Compare commits
3 Commits
9a9420f423
...
4d7ee72d24
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d7ee72d24 | ||
|
|
15dbbc6825 | ||
|
|
ee179e1f6d |
@ -2071,6 +2071,39 @@ export const FileLoadBalancerOptionsSchema = {
|
|||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const FileObjectDtoSchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: 'string',
|
||||||
|
description: '主键Id',
|
||||||
|
format: 'uuid'
|
||||||
|
},
|
||||||
|
creationTime: {
|
||||||
|
type: 'string',
|
||||||
|
description: '创建时间',
|
||||||
|
format: 'date-time'
|
||||||
|
},
|
||||||
|
fileSize: {
|
||||||
|
type: 'integer',
|
||||||
|
description: '文件大小',
|
||||||
|
format: 'int64'
|
||||||
|
},
|
||||||
|
contentType: {
|
||||||
|
type: 'string',
|
||||||
|
description: '文件名称',
|
||||||
|
nullable: true
|
||||||
|
},
|
||||||
|
fileName: {
|
||||||
|
type: 'string',
|
||||||
|
description: '文件名称',
|
||||||
|
nullable: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
additionalProperties: false,
|
||||||
|
description: '文件'
|
||||||
|
} as const;
|
||||||
|
|
||||||
export const FileQoSOptionsSchema = {
|
export const FileQoSOptionsSchema = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
@ -3362,11 +3395,11 @@ export const IoTDBDynamicObjectPagedResultDtoSchema = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const IoTPlatformTypeEnumSchema = {
|
export const IoTPlatformTypeEnumSchema = {
|
||||||
enum: [0, 1, 2],
|
enum: [1, 2],
|
||||||
type: 'integer',
|
type: 'integer',
|
||||||
description: '物联网平台类型枚举',
|
description: '物联网平台类型枚举',
|
||||||
format: 'int32',
|
format: 'int32',
|
||||||
'说明:': '无=0,电信CTWing=1,移动OneNET=2'
|
'说明:': '电信CTWing=1,移动OneNET=2'
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const LanguageInfoSchema = {
|
export const LanguageInfoSchema = {
|
||||||
@ -4429,6 +4462,11 @@ export const OneNETProductInfoDtoSchema = {
|
|||||||
description: 'OneNET账户Id',
|
description: 'OneNET账户Id',
|
||||||
nullable: true
|
nullable: true
|
||||||
},
|
},
|
||||||
|
oneNETAccountName: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'OneNET账户',
|
||||||
|
nullable: true
|
||||||
|
},
|
||||||
ioTPlatformProductId: {
|
ioTPlatformProductId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: '物联网平台对应的产品Id',
|
description: '物联网平台对应的产品Id',
|
||||||
@ -4444,14 +4482,15 @@ export const OneNETProductInfoDtoSchema = {
|
|||||||
description: '产品访问密钥',
|
description: '产品访问密钥',
|
||||||
nullable: true
|
nullable: true
|
||||||
},
|
},
|
||||||
deviceThingModelUrl: {
|
deviceThingModelFileId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: '设备物模型文件管理地址',
|
description: '设备物模型文件Id',
|
||||||
nullable: true
|
nullable: true
|
||||||
},
|
},
|
||||||
isEncrypted: {
|
deviceThingModelFileName: {
|
||||||
type: 'boolean',
|
type: 'string',
|
||||||
description: '通信是否加密'
|
description: '设备物模型文件名称',
|
||||||
|
nullable: true
|
||||||
},
|
},
|
||||||
isEnabled: {
|
isEnabled: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
@ -4655,32 +4694,38 @@ export const OneNetAccountModifyInputSchema = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const OneNetProductInfoInsertInputSchema = {
|
export const OneNetProductInfoInsertInputSchema = {
|
||||||
|
required: ['communicationAddress', 'ioTPlatformProductId', 'oneNETAccountId', 'productAccesskey'],
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
oneNETAccountId: {
|
oneNETAccountId: {
|
||||||
|
minLength: 1,
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'OneNET 账号ID',
|
description: 'OneNET 账号ID'
|
||||||
nullable: true
|
|
||||||
},
|
},
|
||||||
ioTPlatformProductId: {
|
ioTPlatformProductId: {
|
||||||
|
minLength: 1,
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: '物联网平台对应的产品Id',
|
description: '物联网平台对应的产品Id'
|
||||||
nullable: true
|
|
||||||
},
|
},
|
||||||
productAccesskey: {
|
productAccesskey: {
|
||||||
|
minLength: 1,
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: '产品访问密钥',
|
description: '产品访问密钥'
|
||||||
nullable: true
|
|
||||||
},
|
},
|
||||||
communicationAddress: {
|
communicationAddress: {
|
||||||
|
minLength: 1,
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: '通讯服务地址',
|
description: '通讯服务地址'
|
||||||
nullable: true
|
|
||||||
},
|
},
|
||||||
communicationAddressTLS: {
|
communicationAddressTLS: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'TLS通讯服务地址',
|
description: 'TLS通讯服务地址',
|
||||||
nullable: true
|
nullable: true
|
||||||
|
},
|
||||||
|
deviceThingModelUrl: {
|
||||||
|
type: 'string',
|
||||||
|
description: '物模型文件链接',
|
||||||
|
nullable: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
@ -4733,11 +4778,48 @@ export const OneNetProductInfoListInputSchema = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const OneNetProductInfoModifyInputSchema = {
|
export const OneNetProductInfoModifyInputSchema = {
|
||||||
|
required: ['communicationAddress', 'ioTPlatformProductId', 'oneNETAccountId', 'productAccesskey'],
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
description: '产品数据ID',
|
||||||
format: 'uuid'
|
format: 'uuid'
|
||||||
|
},
|
||||||
|
oneNETAccountId: {
|
||||||
|
minLength: 1,
|
||||||
|
type: 'string',
|
||||||
|
description: 'OneNET 账号ID'
|
||||||
|
},
|
||||||
|
ioTPlatformProductId: {
|
||||||
|
minLength: 1,
|
||||||
|
type: 'string',
|
||||||
|
description: '物联网平台对应的产品Id'
|
||||||
|
},
|
||||||
|
productAccesskey: {
|
||||||
|
minLength: 1,
|
||||||
|
type: 'string',
|
||||||
|
description: '产品访问密钥'
|
||||||
|
},
|
||||||
|
communicationAddress: {
|
||||||
|
minLength: 1,
|
||||||
|
type: 'string',
|
||||||
|
description: '通讯服务地址'
|
||||||
|
},
|
||||||
|
communicationAddressTLS: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'TLS通讯服务地址',
|
||||||
|
nullable: true
|
||||||
|
},
|
||||||
|
deviceThingModelFileId: {
|
||||||
|
type: 'string',
|
||||||
|
description: '设备物模型文件Id',
|
||||||
|
nullable: true
|
||||||
|
},
|
||||||
|
deviceThingModelFileName: {
|
||||||
|
type: 'string',
|
||||||
|
description: '设备物模型文件名称',
|
||||||
|
nullable: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
|
|||||||
@ -917,6 +917,32 @@ export type FileLoadBalancerOptions = {
|
|||||||
expiry?: number;
|
expiry?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件
|
||||||
|
*/
|
||||||
|
export type FileObjectDto = {
|
||||||
|
/**
|
||||||
|
* 主键Id
|
||||||
|
*/
|
||||||
|
id?: string;
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
creationTime?: string;
|
||||||
|
/**
|
||||||
|
* 文件大小
|
||||||
|
*/
|
||||||
|
fileSize?: number;
|
||||||
|
/**
|
||||||
|
* 文件名称
|
||||||
|
*/
|
||||||
|
contentType?: (string) | null;
|
||||||
|
/**
|
||||||
|
* 文件名称
|
||||||
|
*/
|
||||||
|
fileName?: (string) | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type FileQoSOptions = {
|
export type FileQoSOptions = {
|
||||||
exceptionsAllowedBeforeBreaking?: number;
|
exceptionsAllowedBeforeBreaking?: number;
|
||||||
durationOfBreak?: number;
|
durationOfBreak?: number;
|
||||||
@ -1380,7 +1406,7 @@ export type IoTDBDynamicObjectPagedResultDto = {
|
|||||||
/**
|
/**
|
||||||
* 物联网平台类型枚举
|
* 物联网平台类型枚举
|
||||||
*/
|
*/
|
||||||
export type IoTPlatformTypeEnum = 0 | 1 | 2;
|
export type IoTPlatformTypeEnum = 1 | 2;
|
||||||
|
|
||||||
export type IStringValueType = {
|
export type IStringValueType = {
|
||||||
readonly name?: (string) | null;
|
readonly name?: (string) | null;
|
||||||
@ -2107,6 +2133,10 @@ export type OneNETProductInfoDto = {
|
|||||||
* OneNET账户Id
|
* OneNET账户Id
|
||||||
*/
|
*/
|
||||||
oneNETAccountId?: (string) | null;
|
oneNETAccountId?: (string) | null;
|
||||||
|
/**
|
||||||
|
* OneNET账户
|
||||||
|
*/
|
||||||
|
oneNETAccountName?: (string) | null;
|
||||||
/**
|
/**
|
||||||
* 物联网平台对应的产品Id
|
* 物联网平台对应的产品Id
|
||||||
*/
|
*/
|
||||||
@ -2120,13 +2150,13 @@ export type OneNETProductInfoDto = {
|
|||||||
*/
|
*/
|
||||||
productAccesskey?: (string) | null;
|
productAccesskey?: (string) | null;
|
||||||
/**
|
/**
|
||||||
* 设备物模型文件管理地址
|
* 设备物模型文件Id
|
||||||
*/
|
*/
|
||||||
deviceThingModelUrl?: (string) | null;
|
deviceThingModelFileId?: (string) | null;
|
||||||
/**
|
/**
|
||||||
* 通信是否加密
|
* 设备物模型文件名称
|
||||||
*/
|
*/
|
||||||
isEncrypted?: boolean;
|
deviceThingModelFileName?: (string) | null;
|
||||||
/**
|
/**
|
||||||
* 是否启用
|
* 是否启用
|
||||||
*/
|
*/
|
||||||
@ -2200,23 +2230,27 @@ export type OneNetProductInfoInsertInput = {
|
|||||||
/**
|
/**
|
||||||
* OneNET 账号ID
|
* OneNET 账号ID
|
||||||
*/
|
*/
|
||||||
oneNETAccountId?: (string) | null;
|
oneNETAccountId: string;
|
||||||
/**
|
/**
|
||||||
* 物联网平台对应的产品Id
|
* 物联网平台对应的产品Id
|
||||||
*/
|
*/
|
||||||
ioTPlatformProductId?: (string) | null;
|
ioTPlatformProductId: string;
|
||||||
/**
|
/**
|
||||||
* 产品访问密钥
|
* 产品访问密钥
|
||||||
*/
|
*/
|
||||||
productAccesskey?: (string) | null;
|
productAccesskey: string;
|
||||||
/**
|
/**
|
||||||
* 通讯服务地址
|
* 通讯服务地址
|
||||||
*/
|
*/
|
||||||
communicationAddress?: (string) | null;
|
communicationAddress: string;
|
||||||
/**
|
/**
|
||||||
* TLS通讯服务地址
|
* TLS通讯服务地址
|
||||||
*/
|
*/
|
||||||
communicationAddressTLS?: (string) | null;
|
communicationAddressTLS?: (string) | null;
|
||||||
|
/**
|
||||||
|
* 物模型文件链接
|
||||||
|
*/
|
||||||
|
deviceThingModelUrl?: (string) | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type OneNetProductInfoListInput = {
|
export type OneNetProductInfoListInput = {
|
||||||
@ -2257,7 +2291,38 @@ export type OneNetProductInfoListInput = {
|
|||||||
* 修改OneNET产品
|
* 修改OneNET产品
|
||||||
*/
|
*/
|
||||||
export type OneNetProductInfoModifyInput = {
|
export type OneNetProductInfoModifyInput = {
|
||||||
|
/**
|
||||||
|
* 产品数据ID
|
||||||
|
*/
|
||||||
id?: string;
|
id?: string;
|
||||||
|
/**
|
||||||
|
* OneNET 账号ID
|
||||||
|
*/
|
||||||
|
oneNETAccountId: string;
|
||||||
|
/**
|
||||||
|
* 物联网平台对应的产品Id
|
||||||
|
*/
|
||||||
|
ioTPlatformProductId: string;
|
||||||
|
/**
|
||||||
|
* 产品访问密钥
|
||||||
|
*/
|
||||||
|
productAccesskey: string;
|
||||||
|
/**
|
||||||
|
* 通讯服务地址
|
||||||
|
*/
|
||||||
|
communicationAddress: string;
|
||||||
|
/**
|
||||||
|
* TLS通讯服务地址
|
||||||
|
*/
|
||||||
|
communicationAddressTLS?: (string) | null;
|
||||||
|
/**
|
||||||
|
* 设备物模型文件Id
|
||||||
|
*/
|
||||||
|
deviceThingModelFileId?: (string) | null;
|
||||||
|
/**
|
||||||
|
* 设备物模型文件名称
|
||||||
|
*/
|
||||||
|
deviceThingModelFileName?: (string) | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4529,7 +4594,7 @@ export type PostFilesUploadData = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PostFilesUploadResponse = (unknown);
|
export type PostFilesUploadResponse = (Array<FileObjectDto>);
|
||||||
|
|
||||||
export type PostFilesUploadError = (RemoteServiceErrorResponse);
|
export type PostFilesUploadError = (RemoteServiceErrorResponse);
|
||||||
|
|
||||||
|
|||||||
@ -269,12 +269,13 @@
|
|||||||
"ProductCount": "ProductCount",
|
"ProductCount": "ProductCount",
|
||||||
"OneNETAccountId": "OneNETAccountId",
|
"OneNETAccountId": "OneNETAccountId",
|
||||||
"OneNETProductId": "OneNETProductId",
|
"OneNETProductId": "OneNETProductId",
|
||||||
"ProductKey": "ProductKey",
|
|
||||||
"ProductSecret": "ProductSecret",
|
|
||||||
"IoTPlatformProductId": "IoTPlatformProductId",
|
"IoTPlatformProductId": "IoTPlatformProductId",
|
||||||
"ProductName": "ProductName",
|
"ProductName": "ProductName",
|
||||||
"ProductAccesskey": "ProductAccesskey",
|
"ProductAccesskey": "ProductAccesskey",
|
||||||
"IsEncrypted": "IsEncrypted",
|
"IsEncrypted": "IsEncrypted",
|
||||||
"BelongingProductName": "BelongingProductName"
|
"BelongingProductName": "Belonging ProductName",
|
||||||
|
"CommunicationAddress": "Communication Address",
|
||||||
|
"CommunicationAddressTLS": "TLS Communication Address",
|
||||||
|
"DeviceThingModelFileName": "DeviceThingModelFileName"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -271,12 +271,13 @@
|
|||||||
"ProductCount": "产品数量",
|
"ProductCount": "产品数量",
|
||||||
"OneNETAccountId": "OneNET账户Id",
|
"OneNETAccountId": "OneNET账户Id",
|
||||||
"OneNETProductId": "OneNET产品Id",
|
"OneNETProductId": "OneNET产品Id",
|
||||||
"ProductKey": "产品密钥",
|
|
||||||
"ProductSecret": "产品密钥",
|
|
||||||
"IoTPlatformProductId": "物联网平台对应的产品Id",
|
"IoTPlatformProductId": "物联网平台对应的产品Id",
|
||||||
"ProductName": "产品名称",
|
"ProductName": "产品名称",
|
||||||
"ProductAccesskey": "产品访问密钥",
|
"ProductAccesskey": "产品密钥",
|
||||||
"IsEncrypted": "是否加密",
|
"IsEncrypted": "是否加密",
|
||||||
"BelongingProductName": "所属产品"
|
"BelongingProductName": "所属产品",
|
||||||
|
"CommunicationAddress": "通讯地址",
|
||||||
|
"CommunicationAddressTLS": "TLS通讯地址",
|
||||||
|
"DeviceThingModelFileName": "物模型文件"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
import type { VbenFormProps } from '#/adapter/form';
|
import type { VbenFormProps } from '#/adapter/form';
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
import { h, ref } from 'vue';
|
import { h, ref, nextTick } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
@ -16,6 +16,8 @@ import {
|
|||||||
postOneNetProductDeleteAsync,
|
postOneNetProductDeleteAsync,
|
||||||
postOneNetProductListAsync,
|
postOneNetProductListAsync,
|
||||||
postOneNetProductModifyAsync,
|
postOneNetProductModifyAsync,
|
||||||
|
postFilesUpload,
|
||||||
|
postFilesDownload,
|
||||||
} from '#/api-client';
|
} from '#/api-client';
|
||||||
import { TableAction } from '#/components/table-action';
|
import { TableAction } from '#/components/table-action';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
@ -25,6 +27,7 @@ import {
|
|||||||
editProductFormSchemaEdit,
|
editProductFormSchemaEdit,
|
||||||
querySchema,
|
querySchema,
|
||||||
tableSchema,
|
tableSchema,
|
||||||
|
setFileSelectedCallback,
|
||||||
} from './schema';
|
} from './schema';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -69,13 +72,41 @@ const gridOptions: VxeGridProps<any> = {
|
|||||||
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
|
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
|
||||||
|
|
||||||
const editRow: Record<string, any> = ref({});
|
const editRow: Record<string, any> = ref({});
|
||||||
|
// 声明文件变量,用于存储选择的文件
|
||||||
|
let selectedFile: File | null = null;
|
||||||
|
|
||||||
|
// 设置文件选择回调
|
||||||
|
setFileSelectedCallback((file) => {
|
||||||
|
selectedFile = file;
|
||||||
|
});
|
||||||
const [UserModal, userModalApi] = useVbenModal({
|
const [UserModal, userModalApi] = useVbenModal({
|
||||||
draggable: true,
|
draggable: true,
|
||||||
|
footer: true,
|
||||||
|
showCancelButton: true,
|
||||||
|
showConfirmButton: true,
|
||||||
onConfirm: submit,
|
onConfirm: submit,
|
||||||
onBeforeClose: () => {
|
onBeforeClose: () => {
|
||||||
// 只在确认提交后重置,而不是每次关闭都重置
|
// 只在确认提交后重置,而不是每次关闭都重置
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
onOpen: () => {
|
||||||
|
// 重置文件选择
|
||||||
|
selectedFile = null;
|
||||||
|
},
|
||||||
|
onOpenChange: (isOpen: boolean) => {
|
||||||
|
if (isOpen && editRow.value.id) {
|
||||||
|
// 编辑模式下,模态框打开后设置表单值
|
||||||
|
nextTick(() => {
|
||||||
|
editFormApi.setValues({ ...editRow.value });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
// 取消时也重置文件选择
|
||||||
|
selectedFile = null;
|
||||||
|
// 关闭模态框
|
||||||
|
userModalApi.close();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const [AddForm, addFormApi] = useVbenForm({
|
const [AddForm, addFormApi] = useVbenForm({
|
||||||
@ -122,6 +153,45 @@ async function submit() {
|
|||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
|
|
||||||
const formValues = await formApi.getValues();
|
const formValues = await formApi.getValues();
|
||||||
|
|
||||||
|
// 提交前校验
|
||||||
|
if (!formValues.deviceThingModelFileName) {
|
||||||
|
Message.error('请选择设备模型文件');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有文件需要上传,先上传
|
||||||
|
if (selectedFile) {
|
||||||
|
try {
|
||||||
|
userModalApi.setState({ loading: true, confirmLoading: true });
|
||||||
|
const result = await postFilesUpload({ body: { files: [selectedFile] } });
|
||||||
|
if (result.status === 204 || result.status === 200) {
|
||||||
|
const fileInfo = result.data?.[0];
|
||||||
|
if (fileInfo && fileInfo.id) {
|
||||||
|
formValues.deviceThingModelFileId = fileInfo.id;
|
||||||
|
// 文件名已在表单中
|
||||||
|
} else {
|
||||||
|
Message.error('文件上传成功但未获取到文件ID');
|
||||||
|
userModalApi.setState({ loading: false, confirmLoading: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Message.error('文件上传失败');
|
||||||
|
userModalApi.setState({ loading: false, confirmLoading: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
Message.error('文件上传失败');
|
||||||
|
userModalApi.setState({ loading: false, confirmLoading: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空全局变量,防止下次误用
|
||||||
|
selectedFile = null;
|
||||||
|
|
||||||
|
// 继续后续表单提交逻辑
|
||||||
|
|
||||||
const fetchParams: any = isEdit
|
const fetchParams: any = isEdit
|
||||||
? {
|
? {
|
||||||
id: editRow.value.id,
|
id: editRow.value.id,
|
||||||
@ -132,7 +202,6 @@ async function submit() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
userModalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
const resp = await api({ body: fetchParams });
|
const resp = await api({ body: fetchParams });
|
||||||
if (resp.data) {
|
if (resp.data) {
|
||||||
Message.success(
|
Message.success(
|
||||||
@ -154,12 +223,15 @@ async function submit() {
|
|||||||
async function onEdit(record: any) {
|
async function onEdit(record: any) {
|
||||||
editRow.value = record;
|
editRow.value = record;
|
||||||
userModalApi.open();
|
userModalApi.open();
|
||||||
editFormApi.setValues({ ...record });
|
// 重置文件选择状态
|
||||||
|
selectedFile = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const openAddModal = async () => {
|
const openAddModal = async () => {
|
||||||
editRow.value = {};
|
editRow.value = {};
|
||||||
userModalApi.open();
|
userModalApi.open();
|
||||||
|
// 重置文件选择状态
|
||||||
|
selectedFile = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 删除函数
|
// 删除函数
|
||||||
@ -168,6 +240,8 @@ async function onDel(record: any) {
|
|||||||
const resp = await postOneNetProductDeleteAsync({ body: { id: record.id } });
|
const resp = await postOneNetProductDeleteAsync({ body: { id: record.id } });
|
||||||
if (resp.data) {
|
if (resp.data) {
|
||||||
Message.success($t('common.deleteSuccess'));
|
Message.success($t('common.deleteSuccess'));
|
||||||
|
// 重置文件选择
|
||||||
|
selectedFile = null;
|
||||||
gridApi.reload();
|
gridApi.reload();
|
||||||
} else {
|
} else {
|
||||||
Message.error($t('common.deleteFail'));
|
Message.error($t('common.deleteFail'));
|
||||||
@ -176,6 +250,32 @@ async function onDel(record: any) {
|
|||||||
Message.error($t('common.deleteFail'));
|
Message.error($t('common.deleteFail'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 下载文件函数
|
||||||
|
async function onDownloadFile(record: any) {
|
||||||
|
if (!record.deviceThingModelFileId) {
|
||||||
|
Message.error('文件ID不存在,无法下载');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data } = await postFilesDownload({
|
||||||
|
body: { id: record.deviceThingModelFileId },
|
||||||
|
responseType: 'blob',
|
||||||
|
});
|
||||||
|
const url = window.URL.createObjectURL(new Blob([data as Blob]));
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.setAttribute('download', record.deviceThingModelFileName || 'device-model-file');
|
||||||
|
document.body.append(link);
|
||||||
|
link.click();
|
||||||
|
link.remove();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
Message.success('文件下载成功');
|
||||||
|
} catch (error) {
|
||||||
|
Message.error('文件下载失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -205,6 +305,17 @@ async function onDel(record: any) {
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #deviceThingModelFileName="{ row }">
|
||||||
|
<a
|
||||||
|
v-if="row.deviceThingModelFileName && row.deviceThingModelFileId"
|
||||||
|
@click="onDownloadFile(row)"
|
||||||
|
style="color: #1890ff; cursor: pointer; text-decoration: underline;"
|
||||||
|
>
|
||||||
|
{{ row.deviceThingModelFileName }}
|
||||||
|
</a>
|
||||||
|
<span v-else>{{ row.deviceThingModelFileName || '-' }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #action="{ row }">
|
<template #action="{ row }">
|
||||||
<TableAction
|
<TableAction
|
||||||
:actions="[
|
:actions="[
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
import { computed } from 'vue';
|
import { computed, h } from 'vue';
|
||||||
|
|
||||||
import { z } from '@vben/common-ui';
|
import { z } from '@vben/common-ui';
|
||||||
|
|
||||||
|
import { postOneNetAccountListAsync, postFilesUpload } from '#/api-client';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
import { postOneNetAccountListAsync } from '#/api-client';
|
|
||||||
|
|
||||||
export const querySchema = computed(() => [
|
export const querySchema = computed(() => [
|
||||||
{
|
{
|
||||||
@ -18,7 +18,12 @@ export const querySchema = computed(() => [
|
|||||||
export const tableSchema: any = computed((): VxeGridProps['columns'] => [
|
export const tableSchema: any = computed((): VxeGridProps['columns'] => [
|
||||||
{ title: $t('common.seq'), type: 'seq', width: 50 },
|
{ title: $t('common.seq'), type: 'seq', width: 50 },
|
||||||
{
|
{
|
||||||
field: 'oneNETProductId',
|
field: 'oneNETAccountName',
|
||||||
|
title: $t('abp.OneNETManagement.BelongingAccountName'),
|
||||||
|
minWidth: '150',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'ioTPlatformProductId',
|
||||||
title: $t('abp.OneNETManagement.OneNETProductId'),
|
title: $t('abp.OneNETManagement.OneNETProductId'),
|
||||||
minWidth: '150',
|
minWidth: '150',
|
||||||
},
|
},
|
||||||
@ -28,22 +33,28 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
|
|||||||
minWidth: '150',
|
minWidth: '150',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'productKey',
|
field: 'productAccesskey',
|
||||||
title: $t('abp.OneNETManagement.ProductKey'),
|
title: $t('abp.OneNETManagement.ProductAccesskey'),
|
||||||
minWidth: '150',
|
minWidth: '150',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'productSecret',
|
field: 'communicationAddress',
|
||||||
title: $t('abp.OneNETManagement.ProductSecret'),
|
title: $t('abp.OneNETManagement.CommunicationAddress'),
|
||||||
minWidth: '150',
|
minWidth: '150',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'accountName',
|
field: 'communicationAddressTLS',
|
||||||
title: $t('abp.OneNETManagement.AccountName'),
|
title: $t('abp.OneNETManagement.CommunicationAddressTLS'),
|
||||||
minWidth: '150',
|
minWidth: '150',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'enabled',
|
field: 'deviceThingModelFileName',
|
||||||
|
title: $t('abp.OneNETManagement.DeviceThingModelFileName'),
|
||||||
|
minWidth: '150',
|
||||||
|
slots: { default: 'deviceThingModelFileName' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'isEnabled',
|
||||||
title: $t('common.isEnable'),
|
title: $t('common.isEnable'),
|
||||||
minWidth: '150',
|
minWidth: '150',
|
||||||
slots: { default: 'isEnable' },
|
slots: { default: 'isEnable' },
|
||||||
@ -57,6 +68,16 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 全局变量存储选择的文件
|
||||||
|
export let selectedFile: File | null = null;
|
||||||
|
|
||||||
|
// 文件选择回调函数
|
||||||
|
let _onFileSelected: ((file: File) => void) | null = null;
|
||||||
|
|
||||||
|
export function setFileSelectedCallback(callback: (file: File) => void) {
|
||||||
|
_onFileSelected = callback;
|
||||||
|
}
|
||||||
|
|
||||||
export const addProductFormSchema: any = computed(() => [
|
export const addProductFormSchema: any = computed(() => [
|
||||||
{
|
{
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
@ -74,32 +95,25 @@ export const addProductFormSchema: any = computed(() => [
|
|||||||
valueField: 'oneNETAccountId',
|
valueField: 'oneNETAccountId',
|
||||||
immediate: true,
|
immediate: true,
|
||||||
afterFetch: (res: any) => {
|
afterFetch: (res: any) => {
|
||||||
console.log('ApiSelect afterFetch res:', res);
|
|
||||||
|
|
||||||
// 如果是 Axios 响应对象,提取 data
|
// 如果是 Axios 响应对象,提取 data
|
||||||
if (res && res.data) {
|
if (res && res.data) {
|
||||||
console.log('提取 res.data:', res.data);
|
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
|
|
||||||
// 确保返回的是数组格式
|
// 确保返回的是数组格式
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
console.log('返回数组,长度:', data.length);
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
// 如果是包装在 items 中的,提取出来
|
// 如果是包装在 items 中的,提取出来
|
||||||
if (data && Array.isArray(data.items)) {
|
if (data && Array.isArray(data.items)) {
|
||||||
console.log('返回items数组,长度:', data.items.length);
|
|
||||||
return data.items;
|
return data.items;
|
||||||
}
|
}
|
||||||
// 如果是包装在 data 中的,提取出来
|
// 如果是包装在 data 中的,提取出来
|
||||||
if (data && Array.isArray(data.data)) {
|
if (data && Array.isArray(data.data)) {
|
||||||
console.log('返回data数组,长度:', data.data.length);
|
|
||||||
return data.data;
|
return data.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果都不是,返回空数组
|
// 如果都不是,返回空数组
|
||||||
console.log('没有找到数组数据,返回空数组');
|
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
placeholder: `${$t('common.pleaseSelect')}${$t('abp.OneNETManagement.BelongingAccountName')}`,
|
placeholder: `${$t('common.pleaseSelect')}${$t('abp.OneNETManagement.BelongingAccountName')}`,
|
||||||
@ -110,7 +124,7 @@ export const addProductFormSchema: any = computed(() => [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
fieldName: 'oneNETProductId',
|
fieldName: 'ioTPlatformProductId',
|
||||||
label: $t('abp.OneNETManagement.OneNETProductId'),
|
label: $t('abp.OneNETManagement.OneNETProductId'),
|
||||||
rules: z.string().min(1, {
|
rules: z.string().min(1, {
|
||||||
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.OneNETProductId')}`,
|
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.OneNETProductId')}`,
|
||||||
@ -118,73 +132,86 @@ export const addProductFormSchema: any = computed(() => [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
fieldName: 'productName',
|
fieldName: 'productAccesskey',
|
||||||
label: $t('abp.OneNETManagement.ProductName'),
|
label: $t('abp.OneNETManagement.ProductAccesskey'),
|
||||||
rules: z.string().min(1, {
|
rules: z.string().min(1, {
|
||||||
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.ProductName')}`,
|
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.ProductAccesskey')}`,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
fieldName: 'productKey',
|
fieldName: 'communicationAddress',
|
||||||
label: $t('abp.OneNETManagement.ProductKey'),
|
label: $t('abp.OneNETManagement.CommunicationAddress'),
|
||||||
rules: z.string().min(1, {
|
rules: z.string().min(1, {
|
||||||
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.ProductKey')}`,
|
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.CommunicationAddress')}`,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
fieldName: 'productSecret',
|
fieldName: 'communicationAddressTLS',
|
||||||
label: $t('abp.OneNETManagement.ProductSecret'),
|
label: $t('abp.OneNETManagement.CommunicationAddressTLS'),
|
||||||
rules: z.string().min(1, {
|
rules: z.string().min(1, {
|
||||||
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.ProductSecret')}`,
|
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.CommunicationAddressTLS')}`,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: 'Switch',
|
component: 'Input',
|
||||||
|
fieldName: 'deviceThingModelFileName',
|
||||||
|
label: $t('abp.OneNETManagement.DeviceThingModelFileName'),
|
||||||
componentProps: {
|
componentProps: {
|
||||||
class: 'w-auto',
|
placeholder: '请选择文件',
|
||||||
|
readonly: true,
|
||||||
|
addonAfter: h('button', {
|
||||||
|
type: 'button',
|
||||||
|
style: 'border: none; background: #1890ff; color: white; padding: 4px 8px; border-radius: 4px; cursor: pointer;',
|
||||||
|
onClick: () => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'file';
|
||||||
|
input.accept = '.json,.xlsx,.xls';
|
||||||
|
input.onchange = (e: any) => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
// 只显示文件名,不上传
|
||||||
|
const currentInput = document.querySelector('input[placeholder="请选择文件"]') as HTMLInputElement;
|
||||||
|
if (currentInput) {
|
||||||
|
currentInput.value = file.name;
|
||||||
|
// 触发change事件
|
||||||
|
currentInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||||||
|
currentInput.dispatchEvent(new Event('change', { bubbles: true }));
|
||||||
|
|
||||||
|
// 存储文件对象到全局变量,用于后续上传
|
||||||
|
selectedFile = file;
|
||||||
|
// 调用回调函数
|
||||||
|
if (_onFileSelected) {
|
||||||
|
_onFileSelected(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('文件已选择:', file.name, '大小:', file.size, '字节');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
input.click();
|
||||||
|
}
|
||||||
|
}, '选择文件'),
|
||||||
|
},
|
||||||
|
rules: z.string().min(1, {
|
||||||
|
message: `${$t('common.pleaseSelect')}${$t('abp.OneNETManagement.DeviceThingModelFileName')}`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'deviceThingModelFileId',
|
||||||
|
label: '',
|
||||||
|
componentProps: {
|
||||||
|
type: 'hidden',
|
||||||
},
|
},
|
||||||
fieldName: 'enabled',
|
|
||||||
label: $t('common.isEnable'),
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const editProductFormSchemaEdit: any = computed(() => [
|
export const editProductFormSchemaEdit: any = computed(() => [
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'oneNETProductId',
|
|
||||||
label: $t('abp.OneNETManagement.OneNETProductId'),
|
|
||||||
disabled: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'productName',
|
|
||||||
label: $t('abp.OneNETManagement.ProductName'),
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.ProductName')}`,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'productKey',
|
|
||||||
label: $t('abp.OneNETManagement.ProductKey'),
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.ProductKey')}`,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'productSecret',
|
|
||||||
label: $t('abp.OneNETManagement.ProductSecret'),
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.ProductSecret')}`,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
fieldName: 'accountName',
|
fieldName: 'oneNETAccountId',
|
||||||
label: $t('abp.OneNETManagement.AccountName'),
|
label: $t('abp.OneNETManagement.BelongingAccountName'),
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: postOneNetAccountListAsync,
|
api: postOneNetAccountListAsync,
|
||||||
params: {
|
params: {
|
||||||
@ -196,47 +223,124 @@ export const editProductFormSchemaEdit: any = computed(() => [
|
|||||||
labelField: 'accountName',
|
labelField: 'accountName',
|
||||||
valueField: 'oneNETAccountId',
|
valueField: 'oneNETAccountId',
|
||||||
immediate: true,
|
immediate: true,
|
||||||
|
disabled: true, // 编辑时禁用
|
||||||
afterFetch: (res: any) => {
|
afterFetch: (res: any) => {
|
||||||
console.log('ApiSelect afterFetch res:', res);
|
|
||||||
|
|
||||||
// 如果是 Axios 响应对象,提取 data
|
// 如果是 Axios 响应对象,提取 data
|
||||||
if (res && res.data) {
|
if (res && res.data) {
|
||||||
console.log('提取 res.data:', res.data);
|
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
|
|
||||||
// 确保返回的是数组格式
|
// 确保返回的是数组格式
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
console.log('返回数组,长度:', data.length);
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
// 如果是包装在 items 中的,提取出来
|
// 如果是包装在 items 中的,提取出来
|
||||||
if (data && Array.isArray(data.items)) {
|
if (data && Array.isArray(data.items)) {
|
||||||
console.log('返回items数组,长度:', data.items.length);
|
|
||||||
return data.items;
|
return data.items;
|
||||||
}
|
}
|
||||||
// 如果是包装在 data 中的,提取出来
|
// 如果是包装在 data 中的,提取出来
|
||||||
if (data && Array.isArray(data.data)) {
|
if (data && Array.isArray(data.data)) {
|
||||||
console.log('返回data数组,长度:', data.data.length);
|
|
||||||
return data.data;
|
return data.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果都不是,返回空数组
|
// 如果都不是,返回空数组
|
||||||
console.log('没有找到数组数据,返回空数组');
|
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
placeholder: `${$t('common.pleaseSelect')}${$t('abp.OneNETManagement.AccountName')}`,
|
placeholder: `${$t('common.pleaseSelect')}${$t('abp.OneNETManagement.BelongingAccountName')}`,
|
||||||
},
|
},
|
||||||
rules: z.string().min(1, {
|
rules: z.string().min(1, {
|
||||||
message: `${$t('common.pleaseSelect')}${$t('abp.OneNETManagement.AccountName')}`,
|
message: `${$t('common.pleaseSelect')}${$t('abp.OneNETManagement.BelongingAccountName')}`,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: 'Switch',
|
component: 'Input',
|
||||||
|
fieldName: 'ioTPlatformProductId',
|
||||||
|
label: $t('abp.OneNETManagement.OneNETProductId'),
|
||||||
|
disabled: true,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
class: 'w-auto',
|
readonly: true, // 编辑时只读
|
||||||
|
},
|
||||||
|
rules: z.string().min(1, {
|
||||||
|
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.OneNETProductId')}`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'productAccesskey',
|
||||||
|
label: $t('abp.OneNETManagement.ProductAccesskey'),
|
||||||
|
disabled: true,
|
||||||
|
componentProps: {
|
||||||
|
readonly: true, // 编辑时只读
|
||||||
|
},
|
||||||
|
rules: z.string().min(1, {
|
||||||
|
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.ProductAccesskey')}`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'communicationAddress',
|
||||||
|
label: $t('abp.OneNETManagement.CommunicationAddress'),
|
||||||
|
rules: z.string().min(1, {
|
||||||
|
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.CommunicationAddress')}`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'communicationAddressTLS',
|
||||||
|
label: $t('abp.OneNETManagement.CommunicationAddressTLS'),
|
||||||
|
rules: z.string().min(1, {
|
||||||
|
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.OneNETManagement.CommunicationAddressTLS')}`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'deviceThingModelFileName',
|
||||||
|
label: $t('abp.OneNETManagement.DeviceThingModelFileName'),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择文件',
|
||||||
|
readonly: true,
|
||||||
|
addonAfter: h('button', {
|
||||||
|
type: 'button',
|
||||||
|
style: 'border: none; background: #1890ff; color: white; padding: 4px 8px; border-radius: 4px; cursor: pointer;',
|
||||||
|
onClick: () => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'file';
|
||||||
|
input.accept = '.json,.xlsx,.xls';
|
||||||
|
input.onchange = (e: any) => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
// 只显示文件名,不上传
|
||||||
|
const currentInput = document.querySelector('input[placeholder="请选择文件"]') as HTMLInputElement;
|
||||||
|
if (currentInput) {
|
||||||
|
currentInput.value = file.name;
|
||||||
|
// 触发change事件
|
||||||
|
currentInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||||||
|
currentInput.dispatchEvent(new Event('change', { bubbles: true }));
|
||||||
|
|
||||||
|
// 存储文件对象到全局变量,用于后续上传
|
||||||
|
selectedFile = file;
|
||||||
|
// 调用回调函数
|
||||||
|
if (_onFileSelected) {
|
||||||
|
_onFileSelected(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('文件已选择:', file.name, '大小:', file.size, '字节');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
input.click();
|
||||||
|
}
|
||||||
|
}, '选择文件'),
|
||||||
|
},
|
||||||
|
rules: z.string().min(1, {
|
||||||
|
message: `${$t('common.pleaseSelect')}${$t('abp.OneNETManagement.DeviceThingModelFileName')}`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'deviceThingModelFileId',
|
||||||
|
label: '',
|
||||||
|
componentProps: {
|
||||||
|
type: 'hidden',
|
||||||
},
|
},
|
||||||
fieldName: 'enabled',
|
|
||||||
label: $t('common.isEnable'),
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -9,9 +9,12 @@ import { $t } from '#/locales';
|
|||||||
|
|
||||||
import { addFormSchema } from './schema';
|
import { addFormSchema } from './schema';
|
||||||
import { postFilesUpload } from '#/api-client/index';
|
import { postFilesUpload } from '#/api-client/index';
|
||||||
|
import { useUserStore } from '@vben/stores';
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
const emit = defineEmits(['reload']);
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
// 创建上传图标
|
// 创建上传图标
|
||||||
const UploadIcon = createIconifyIcon('mdi:upload');
|
const UploadIcon = createIconifyIcon('mdi:upload');
|
||||||
const FolderIcon = createIconifyIcon('mdi:folder');
|
const FolderIcon = createIconifyIcon('mdi:folder');
|
||||||
@ -144,51 +147,40 @@ const handleUpload = async () => {
|
|||||||
|
|
||||||
uploading.value = true;
|
uploading.value = true;
|
||||||
try {
|
try {
|
||||||
// 获取表单数据
|
|
||||||
const formValues = await formApi.getValues();
|
|
||||||
console.log('Form values:', formValues);
|
|
||||||
console.log('File list:', fileList.value);
|
console.log('File list:', fileList.value);
|
||||||
|
|
||||||
// 创建一个FormData对象,包含所有文件
|
// 提取文件对象
|
||||||
const uploadFormData = new FormData();
|
const files = fileList.value
|
||||||
|
.map(fileInfo => fileInfo.originFileObj)
|
||||||
|
.filter(file => file !== null && file !== undefined);
|
||||||
|
|
||||||
// 添加所有文件到FormData
|
console.log('Extracted files:', files);
|
||||||
fileList.value.forEach((fileInfo, index) => {
|
|
||||||
if (fileInfo.originFileObj) {
|
|
||||||
console.log(`Adding file ${index}:`, fileInfo.name, fileInfo.originFileObj);
|
|
||||||
uploadFormData.append('files', fileInfo.originFileObj);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 添加表单其他数据(如果有的话)
|
// 上传文件 - 使用正确的API格式
|
||||||
if (formValues) {
|
console.log('Sending request to /Files/Upload...');
|
||||||
Object.keys(formValues).forEach(key => {
|
|
||||||
if (formValues[key] !== undefined && formValues[key] !== null) {
|
|
||||||
console.log(`Adding form field ${key}:`, formValues[key]);
|
|
||||||
uploadFormData.append(key, formValues[key]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打印FormData内容(调试用)
|
|
||||||
for (let [key, value] of uploadFormData.entries()) {
|
|
||||||
console.log(`FormData entry: ${key} =`, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传文件
|
|
||||||
const result = await postFilesUpload({
|
const result = await postFilesUpload({
|
||||||
body: uploadFormData as any,
|
body: {
|
||||||
|
files: files
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${userStore.userInfo?.token}`,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Upload result:', result);
|
console.log('Upload result:', result);
|
||||||
|
console.log('Response status:', result.status);
|
||||||
|
console.log('Response data:', result.data);
|
||||||
|
console.log('Response headers:', result.headers);
|
||||||
|
|
||||||
// 检查上传结果
|
// 检查上传结果
|
||||||
if (result.status === 204 || result.status === 200) {
|
if (result.status === 204 || result.status === 200) {
|
||||||
message.success(`文件上传成功!共上传 ${fileList.value.length} 个文件`);
|
message.success(`文件上传成功!共上传 ${fileList.value.length} 个文件`);
|
||||||
|
fileList.value = [];
|
||||||
|
console.log('Emitting reload event...');
|
||||||
emit('reload');
|
emit('reload');
|
||||||
modalApi.close();
|
modalApi.close();
|
||||||
} else {
|
} else {
|
||||||
message.error('文件上传失败,请重试');
|
message.error(`文件上传失败,状态码: ${result.status}`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Upload error:', error);
|
console.error('Upload error:', error);
|
||||||
|
|||||||
@ -73,6 +73,11 @@ const [AddVbenModal, addModalApi] = useVbenModal({
|
|||||||
connectedComponent: AddModal,
|
connectedComponent: AddModal,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleReload = () => {
|
||||||
|
console.log('Reloading file list...');
|
||||||
|
gridApi.reload();
|
||||||
|
};
|
||||||
|
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
addModalApi.open();
|
addModalApi.open();
|
||||||
};
|
};
|
||||||
@ -144,7 +149,7 @@ const handleDown = async (row: any) => {
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
<AddVbenModal @reload="gridApi.reload" />
|
<AddVbenModal @reload="handleReload" />
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
@ -69,13 +69,5 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
export const addFormSchema = computed(() => [
|
export const addFormSchema = computed(() => [
|
||||||
// 文件上传现在在AddModal中处理
|
// 文件上传现在在AddModal中处理,不需要表单字段
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'note',
|
|
||||||
label: $t('common.note'),
|
|
||||||
componentProps: {
|
|
||||||
placeholder: '请输入备注信息',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user