重构设备操作界面

This commit is contained in:
ChenYi 2025-12-25 11:26:14 +08:00
parent f208976dd8
commit 2ff8a447cf
4 changed files with 735 additions and 359 deletions

View File

@ -750,6 +750,10 @@ export const CTWingAccountListInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
phoneNumber: { phoneNumber: {
type: 'string', type: 'string',
description: '手机号码', description: '手机号码',
@ -1091,6 +1095,10 @@ export const CTWingPrivateProductInfoListInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
ctWingAccountId: { ctWingAccountId: {
type: 'string', type: 'string',
description: 'CTWing账户Id', description: 'CTWing账户Id',
@ -2238,6 +2246,10 @@ export const DeviceTableModelDataInfoPageInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
ioTDataType: { ioTDataType: {
type: 'string', type: 'string',
description: `数据类型,用于构建存储路径 description: `数据类型,用于构建存储路径
@ -2528,6 +2540,10 @@ export const DeviceThingModelCommandInfoPageInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
deviceThingModelId: { deviceThingModelId: {
type: 'string', type: 'string',
description: '设备端物模型Id', description: '设备端物模型Id',
@ -2550,10 +2566,6 @@ export const DeviceThingModelCommandInfoPageInputSchema = {
type: 'string', type: 'string',
description: '物联网平台中对应产品物模型属性或者事件类型 JiShe.ServicePro.Core.DataDictionaryTypeConst', description: '物联网平台中对应产品物模型属性或者事件类型 JiShe.ServicePro.Core.DataDictionaryTypeConst',
nullable: true nullable: true
},
isPage: {
type: 'boolean',
description: '是否分页'
} }
}, },
additionalProperties: false, additionalProperties: false,
@ -2793,6 +2805,10 @@ export const DeviceThingModelPageInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
ioTPlatform: { ioTPlatform: {
'$ref': '#/components/schemas/IoTPlatformTypeEnum' '$ref': '#/components/schemas/IoTPlatformTypeEnum'
}, },
@ -2810,10 +2826,6 @@ export const DeviceThingModelPageInputSchema = {
type: 'string', type: 'string',
description: '物联网平台中对应产品物模型属性或者事件类型 JiShe.ServicePro.Core.DataDictionaryTypeConst', description: '物联网平台中对应产品物模型属性或者事件类型 JiShe.ServicePro.Core.DataDictionaryTypeConst',
nullable: true nullable: true
},
isPage: {
type: 'boolean',
description: '是否分页'
} }
}, },
additionalProperties: false additionalProperties: false
@ -3070,6 +3082,10 @@ export const DeviceThingModelPropertyPageInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
deviceThingModelId: { deviceThingModelId: {
type: 'string', type: 'string',
description: '设备端物模型Id', description: '设备端物模型Id',
@ -3092,10 +3108,6 @@ export const DeviceThingModelPropertyPageInputSchema = {
type: 'string', type: 'string',
description: '物联网平台中对应产品物模型属性或者事件类型 JiShe.ServicePro.Core.DataDictionaryTypeConst', description: '物联网平台中对应产品物模型属性或者事件类型 JiShe.ServicePro.Core.DataDictionaryTypeConst',
nullable: true nullable: true
},
isPage: {
type: 'boolean',
description: '是否分页'
} }
}, },
additionalProperties: false, additionalProperties: false,
@ -3236,6 +3248,10 @@ export const DeviceTreeModelDataInfoInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
ioTDataType: { ioTDataType: {
type: 'string', type: 'string',
description: `数据类型,用于构建存储路径 description: `数据类型,用于构建存储路径
@ -4431,6 +4447,10 @@ export const GetOrganizationUnitRoleInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
organizationUnitId: { organizationUnitId: {
type: 'string', type: 'string',
format: 'uuid' format: 'uuid'
@ -4499,6 +4519,10 @@ export const GetOrganizationUnitUserInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
organizationUnitId: { organizationUnitId: {
type: 'string', type: 'string',
format: 'uuid' format: 'uuid'
@ -4608,6 +4632,10 @@ export const GetUnAddRoleInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
organizationUnitId: { organizationUnitId: {
type: 'string', type: 'string',
format: 'uuid' format: 'uuid'
@ -4680,6 +4708,10 @@ export const GetUnAddUserInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
organizationUnitId: { organizationUnitId: {
type: 'string', type: 'string',
format: 'uuid' format: 'uuid'
@ -5576,6 +5608,10 @@ export const IoTPlatformThingModelPageInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
ioTPlatform: { ioTPlatform: {
'$ref': '#/components/schemas/IoTPlatformTypeEnum' '$ref': '#/components/schemas/IoTPlatformTypeEnum'
}, },
@ -5899,6 +5935,10 @@ export const MeterReadingPacketInfoPageInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
ioTDataType: { ioTDataType: {
type: 'string', type: 'string',
description: `数据类型,用于构建存储路径 description: `数据类型,用于构建存储路径
@ -6704,6 +6744,10 @@ export const OneNetAccountListInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
phoneNumber: { phoneNumber: {
type: 'string', type: 'string',
description: '手机号码', description: '手机号码',
@ -6817,6 +6861,10 @@ export const OneNetProductInfoListInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
oneNETAccountId: { oneNETAccountId: {
type: 'string', type: 'string',
description: 'OneNET账户Id', description: 'OneNET账户Id',
@ -6948,6 +6996,10 @@ export const PageDeviceInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
deviceAddress: { deviceAddress: {
type: 'string', type: 'string',
description: '设备地址', description: '设备地址',
@ -7002,6 +7054,10 @@ export const PageFileObjectInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
startCreationTime: { startCreationTime: {
type: 'string', type: 'string',
description: '开始创建时间', description: '开始创建时间',
@ -7237,6 +7293,10 @@ export const PageLanguageInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
filter: { filter: {
type: 'string', type: 'string',
nullable: true nullable: true
@ -7337,6 +7397,10 @@ export const PageLanguageTextInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
cultureName: { cultureName: {
type: 'string', type: 'string',
description: '语言', description: '语言',
@ -7425,6 +7489,10 @@ export const PageMenuInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
startCreationTime: { startCreationTime: {
type: 'string', type: 'string',
description: '开始创建时间', description: '开始创建时间',
@ -7650,6 +7718,10 @@ export const PageTextTemplateInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
name: { name: {
type: 'string', type: 'string',
description: '名称', description: '名称',
@ -7810,6 +7882,10 @@ export const PagingAuditLogInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
startTime: { startTime: {
type: 'string', type: 'string',
description: '开始时间', description: '开始时间',
@ -8029,6 +8105,10 @@ export const PagingDataDictionaryDetailInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
dataDictionaryId: { dataDictionaryId: {
type: 'string', type: 'string',
format: 'uuid' format: 'uuid'
@ -8131,6 +8211,10 @@ export const PagingDataDictionaryInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
filter: { filter: {
type: 'string', type: 'string',
nullable: true nullable: true
@ -8294,6 +8378,10 @@ export const PagingIdentitySecurityLogInputSchema = {
format: 'int32', format: 'int32',
readOnly: true readOnly: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
sorting: { sorting: {
type: 'string', type: 'string',
description: '排序', description: '排序',
@ -8456,6 +8544,10 @@ export const PagingNotificationInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
title: { title: {
type: 'string', type: 'string',
description: '标题', description: '标题',
@ -8640,6 +8732,10 @@ export const PagingNotificationSubscriptionInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
notificationId: { notificationId: {
type: 'string', type: 'string',
format: 'uuid' format: 'uuid'
@ -8798,6 +8894,10 @@ export const PagingRoleListInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
filter: { filter: {
type: 'string', type: 'string',
nullable: true nullable: true
@ -8833,6 +8933,10 @@ export const PagingTenantInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
filter: { filter: {
type: 'string', type: 'string',
nullable: true nullable: true
@ -8868,6 +8972,10 @@ export const PagingUserListInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
filter: { filter: {
type: 'string', type: 'string',
description: '关键字', description: '关键字',
@ -9082,6 +9190,10 @@ export const QueryCTWingAepReceiveMessageInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
ioTDataType: { ioTDataType: {
type: 'string', type: 'string',
description: `数据类型,用于构建存储路径 description: `数据类型,用于构建存储路径
@ -9295,6 +9407,10 @@ export const QueryOneNETReceiveMessageInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
ioTDataType: { ioTDataType: {
type: 'string', type: 'string',
description: `数据类型,用于构建存储路径 description: `数据类型,用于构建存储路径
@ -9696,6 +9812,10 @@ export const SelectDataDictionaryDetailInputSchema = {
</example>`, </example>`,
nullable: true nullable: true
}, },
isPage: {
type: 'boolean',
description: '是否分页'
},
dataDictionaryId: { dataDictionaryId: {
type: 'string', type: 'string',
format: 'uuid' format: 'uuid'

View File

@ -622,6 +622,10 @@ export type CTWingAccountListInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -848,6 +852,10 @@ export type CTWingPrivateProductInfoListInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* CTWing账户Id * CTWing账户Id
*/ */
@ -1238,6 +1246,10 @@ export type DeviceTableModelDataInfoPageInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
* JiShe.ServicePro.Consts.IoTDBDataTypeConst * JiShe.ServicePro.Consts.IoTDBDataTypeConst
@ -1417,6 +1429,10 @@ export type DeviceThingModelCommandInfoPageInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* Id * Id
*/ */
@ -1434,10 +1450,6 @@ export type DeviceThingModelCommandInfoPageInput = {
* JiShe.ServicePro.Core.DataDictionaryTypeConst * JiShe.ServicePro.Core.DataDictionaryTypeConst
*/ */
filedType?: (string) | null; filedType?: (string) | null;
/**
*
*/
isPage?: boolean;
}; };
/** /**
@ -1577,6 +1589,10 @@ export type DeviceThingModelPageInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
ioTPlatform?: IoTPlatformTypeEnum; ioTPlatform?: IoTPlatformTypeEnum;
/** /**
* *
@ -1590,10 +1606,6 @@ export type DeviceThingModelPageInput = {
* JiShe.ServicePro.Core.DataDictionaryTypeConst * JiShe.ServicePro.Core.DataDictionaryTypeConst
*/ */
filedType?: (string) | null; filedType?: (string) | null;
/**
*
*/
isPage?: boolean;
}; };
/** /**
@ -1757,6 +1769,10 @@ export type DeviceThingModelPropertyPageInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* Id * Id
*/ */
@ -1774,10 +1790,6 @@ export type DeviceThingModelPropertyPageInput = {
* JiShe.ServicePro.Core.DataDictionaryTypeConst * JiShe.ServicePro.Core.DataDictionaryTypeConst
*/ */
filedType?: (string) | null; filedType?: (string) | null;
/**
*
*/
isPage?: boolean;
}; };
/** /**
@ -1876,6 +1888,10 @@ export type DeviceTreeModelDataInfoInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
* JiShe.ServicePro.Consts.IoTDBDataTypeConst * JiShe.ServicePro.Consts.IoTDBDataTypeConst
@ -2321,6 +2337,10 @@ export type GetOrganizationUnitRoleInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
organizationUnitId?: string; organizationUnitId?: string;
}; };
@ -2354,6 +2374,10 @@ export type GetOrganizationUnitUserInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
organizationUnitId?: string; organizationUnitId?: string;
filter?: (string) | null; filter?: (string) | null;
}; };
@ -2405,6 +2429,10 @@ export type GetUnAddRoleInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
organizationUnitId?: string; organizationUnitId?: string;
filter?: (string) | null; filter?: (string) | null;
}; };
@ -2439,6 +2467,10 @@ export type GetUnAddUserInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
organizationUnitId?: string; organizationUnitId?: string;
filter?: (string) | null; filter?: (string) | null;
}; };
@ -2828,6 +2860,10 @@ export type IoTPlatformThingModelPageInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
ioTPlatform?: IoTPlatformTypeEnum; ioTPlatform?: IoTPlatformTypeEnum;
/** /**
* *
@ -3040,6 +3076,10 @@ export type MeterReadingPacketInfoPageInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
* JiShe.ServicePro.Consts.IoTDBDataTypeConst * JiShe.ServicePro.Consts.IoTDBDataTypeConst
@ -3369,6 +3409,10 @@ export type OneNetAccountListInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -3589,6 +3633,10 @@ export type OneNetProductInfoListInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* OneNET账户Id * OneNET账户Id
*/ */
@ -3688,6 +3736,10 @@ export type PageDeviceInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -3730,6 +3782,10 @@ export type PageFileObjectInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -3837,6 +3893,10 @@ export type PageLanguageInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
filter?: (string) | null; filter?: (string) | null;
}; };
@ -3906,6 +3966,10 @@ export type PageLanguageTextInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -3966,6 +4030,10 @@ export type PageMenuInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -4110,6 +4178,10 @@ export type PageTextTemplateInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -4201,6 +4273,10 @@ export type PagingAuditLogInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -4301,6 +4377,10 @@ export type PagingDataDictionaryDetailInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
dataDictionaryId?: string; dataDictionaryId?: string;
filter?: (string) | null; filter?: (string) | null;
}; };
@ -4362,6 +4442,10 @@ export type PagingDataDictionaryInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
filter?: (string) | null; filter?: (string) | null;
}; };
@ -4425,6 +4509,10 @@ export type PagingIdentitySecurityLogInput = {
* *
*/ */
readonly skipCount?: number; readonly skipCount?: number;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -4505,6 +4593,10 @@ export type PagingNotificationInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -4617,6 +4709,10 @@ export type PagingNotificationSubscriptionInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
notificationId?: string; notificationId?: string;
/** /**
* Id * Id
@ -4713,6 +4809,10 @@ export type PagingRoleListInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
filter?: (string) | null; filter?: (string) | null;
}; };
@ -4736,6 +4836,10 @@ export type PagingTenantInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
filter?: (string) | null; filter?: (string) | null;
}; };
@ -4759,6 +4863,10 @@ export type PagingUserListInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
*/ */
@ -4846,6 +4954,10 @@ export type QueryCTWingAepReceiveMessageInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
* JiShe.ServicePro.Consts.IoTDBDataTypeConst * JiShe.ServicePro.Consts.IoTDBDataTypeConst
@ -5002,6 +5114,10 @@ export type QueryOneNETReceiveMessageInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
/** /**
* *
* JiShe.ServicePro.Consts.IoTDBDataTypeConst * JiShe.ServicePro.Consts.IoTDBDataTypeConst
@ -5213,6 +5329,10 @@ export type SelectDataDictionaryDetailInput = {
* </example> * </example>
*/ */
sorting?: (string) | null; sorting?: (string) | null;
/**
*
*/
isPage?: boolean;
dataDictionaryId?: string; dataDictionaryId?: string;
filter?: (string) | null; filter?: (string) | null;
typeCode?: (string) | null; typeCode?: (string) | null;

View File

@ -3,16 +3,18 @@ import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table'; import type { VxeGridProps } from '#/adapter/vxe-table';
import { computed, h, nextTick, ref, watch } from 'vue'; import { computed, h, nextTick, ref, watch } from 'vue';
import { useRouter, useRoute } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { import {
Button, Button,
Checkbox,
Input, Input,
message as Message, message as Message,
Modal, Modal,
Popover, Popover,
Table,
Tag, Tag,
} from 'ant-design-vue'; } from 'ant-design-vue';
@ -23,23 +25,24 @@ import {
postAggregationDeviceCreateAsync, postAggregationDeviceCreateAsync,
postAggregationDeviceDeleteAsync, postAggregationDeviceDeleteAsync,
postAggregationDeviceDeviceCommandForApiAsync, postAggregationDeviceDeviceCommandForApiAsync,
postAggregationDeviceGetDevicePropertyValueForApiAsync,
postAggregationDeviceRepushDeviceInfoToIoTplatform, postAggregationDeviceRepushDeviceInfoToIoTplatform,
postDeviceInfoCacheDeviceDataToRedis,
postDeviceInfoBindingDeviceThingModel, postDeviceInfoBindingDeviceThingModel,
postDeviceInfoCacheDeviceDataToRedis,
postDeviceInfoPage, postDeviceInfoPage,
postIoTplatformThingModelInfoPageAsync,
} from '#/api-client'; } from '#/api-client';
import { Icon } from '#/components/icon'; import { Icon } from '#/components/icon';
import { Loading } from '#/components/Loading'; import { Loading } from '#/components/Loading';
import { TableAction } from '#/components/table-action'; import { TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import IoTPlatformThingModelDataSelect from '#/views/thingmodelinfo/IoTPlatformThingModelDataSelect.vue';
import { import {
addDeviceFormSchema, addDeviceFormSchema,
batchAddDeviceFormSchema, batchAddDeviceFormSchema,
bindDeviceThingModelFormSchema,
commandFormSchema, commandFormSchema,
editDeviceFormSchemaEdit, editDeviceFormSchemaEdit,
bindDeviceThingModelFormSchema,
querySchema, querySchema,
tableSchema, tableSchema,
} from './schema'; } from './schema';
@ -94,7 +97,7 @@ const gridOptions: VxeGridProps<any> = {
: formValues || {}; : formValues || {};
// 使API使formValues // 使API使formValues
const finalFormValues = { ...(formValues || {}), ...currentFormValues }; const finalFormValues = { ...formValues, ...currentFormValues };
const { data } = await postDeviceInfoPage({ const { data } = await postDeviceInfoPage({
body: { body: {
@ -131,9 +134,15 @@ const gridOptions: VxeGridProps<any> = {
const currentProductId = row?.ioTPlatformProductId; const currentProductId = row?.ioTPlatformProductId;
// ID // ID
if (firstProductId && currentProductId && firstProductId !== currentProductId) { if (
firstProductId &&
currentProductId &&
firstProductId !== currentProductId
) {
// ID // ID
Message.warning('只能选择同一种产品的设备进行批量绑定,当前设备的产品与已选设备的产品不一致'); Message.warning(
'只能选择同一种产品的设备进行批量绑定,当前设备的产品与已选设备的产品不一致',
);
// //
setTimeout(() => { setTimeout(() => {
@ -146,7 +155,6 @@ const gridOptions: VxeGridProps<any> = {
} }
} }
}, 100); }, 100);
return;
} }
} }
}, },
@ -160,13 +168,15 @@ const gridOptions: VxeGridProps<any> = {
// ID // ID
const productIds = records const productIds = records
.map((r: any) => r.ioTPlatformProductId) .map((r: any) => r.ioTPlatformProductId)
.filter((id: any) => id); .filter(Boolean);
if (productIds.length > 0) { if (productIds.length > 0) {
const uniqueProductIds = [...new Set(productIds)]; const uniqueProductIds = [...new Set(productIds)];
if (uniqueProductIds.length > 1) { if (uniqueProductIds.length > 1) {
// ID // ID
Message.warning('只能选择同一种产品的设备进行批量绑定,当前页面包含多种产品'); Message.warning(
'只能选择同一种产品的设备进行批量绑定,当前页面包含多种产品',
);
// //
setTimeout(() => { setTimeout(() => {
@ -179,7 +189,6 @@ const gridOptions: VxeGridProps<any> = {
} }
} }
}, 100); }, 100);
return;
} }
} }
}, },
@ -206,9 +215,11 @@ watch(
if (newQuery.ioTPlatformDeviceOpenInfo) { if (newQuery.ioTPlatformDeviceOpenInfo) {
// ID // ID
filterValues.ioTPlatformProductId = newQuery.ioTPlatformDeviceOpenInfo; filterValues.ioTPlatformProductId =
newQuery.ioTPlatformDeviceOpenInfo;
// //
filterValues.ioTPlatformDeviceOpenInfo = newQuery.ioTPlatformDeviceOpenInfo; filterValues.ioTPlatformDeviceOpenInfo =
newQuery.ioTPlatformDeviceOpenInfo;
} }
// //
@ -224,7 +235,7 @@ watch(
}, 200); // ApiSelect }, 200); // ApiSelect
} }
}, },
{ immediate: true } { immediate: true },
); );
// ioTPlatformDeviceOpenInfo // ioTPlatformDeviceOpenInfo
@ -237,7 +248,10 @@ watch(
// ioTPlatformDeviceOpenInfo // ioTPlatformDeviceOpenInfo
if (ioTPlatformProductId) { if (ioTPlatformProductId) {
console.log('检测到产品选择变化:', ioTPlatformProductId); console.log('检测到产品选择变化:', ioTPlatformProductId);
gridApi?.formApi?.setFieldValue('ioTPlatformDeviceOpenInfo', ioTPlatformProductId); gridApi?.formApi?.setFieldValue(
'ioTPlatformDeviceOpenInfo',
ioTPlatformProductId,
);
console.log('已设置ioTPlatformDeviceOpenInfo为:', ioTPlatformProductId); console.log('已设置ioTPlatformDeviceOpenInfo为:', ioTPlatformProductId);
} else { } else {
console.log('清空产品选择'); console.log('清空产品选择');
@ -245,7 +259,7 @@ watch(
} }
} }
}, },
{ deep: true } { deep: true },
); );
const cacheRefreshLoading = ref(false); const cacheRefreshLoading = ref(false);
@ -253,71 +267,174 @@ const pageLoading = ref(false);
const loadingTip = ref('缓存刷新中...'); const loadingTip = ref('缓存刷新中...');
const commandRow: Record<string, any> = ref({}); const commandRow: Record<string, any> = ref({});
// //
const bindRows: Array<Record<string, any>> = ref([]); const commandTableColumns = computed(() => [
// -
interface CommandProperty {
id: string; //
propertyId: string; // ID
propertyName: string; //
platformFieldName: string; //
standardFieldName: string; //
value: string; //
}
const commandProperties = ref<CommandProperty[]>([
{ {
id: `prop-${Date.now()}`, title: '',
propertyId: '', key: 'selected',
propertyName: '', width: 50,
platformFieldName: '', fixed: 'left' as const,
standardFieldName: '', customRender: ({ record }: any) => {
value: '', return h(Checkbox, {
checked: record.selected,
'onUpdate:checked': (checked: boolean) => {
record.selected = checked;
},
});
},
},
{
title: '平台物模型属性标识符',
dataIndex: 'ioTPlatformRawFieldName',
key: 'ioTPlatformRawFieldName',
width: 200,
},
{
title: '标准物模型属性名称',
dataIndex: 'standardFieldDisplayName',
key: 'standardFieldDisplayName',
width: 200,
},
{
title: '指令内容',
dataIndex: 'commandValue',
key: 'commandValue',
width: 200,
customRender: ({ record }: any) => {
return h(Input, {
value: record.commandValue,
placeholder: '请输入指令内容',
'onUpdate:value': (val: string) => {
record.commandValue = val;
},
});
},
},
{
title: '返回结果',
dataIndex: 'result',
key: 'result',
width: 250,
customRender: ({ record }: any) => {
// result
const resultText = record.result
? (typeof record.result === 'string'
? record.result
: String(record.result))
: '-';
const resultStr = String(resultText);
const isError = resultStr.includes('失败') || resultStr.includes('失败:');
return h(
'div',
{
style: {
color:
resultText === '-' ? '#666' : isError ? '#ff4d4f' : '#52c41a',
wordBreak: 'break-all',
},
},
resultStr,
);
},
},
{
title: '操作',
key: 'action',
width: 200,
fixed: 'right' as const,
customRender: ({ record }: any) => {
return h(
'div',
{
style: {
display: 'flex',
gap: '8px',
},
},
[
h(
Button,
{
type: 'primary',
size: 'small',
loading: record.loading,
onClick: () => sendCommand(record),
},
'发送指令',
),
h(
Button,
{
size: 'small',
loading: record.loading,
onClick: () => readData(record),
},
'抄读数据',
),
],
);
},
}, },
]); ]);
// - //
const addCommandProperty = () => { const bindRows: Array<Record<string, any>> = ref([]);
commandProperties.value.push({
id: `prop-${Date.now()}-${Math.random()}`, //
propertyId: '', interface ThingModelProperty {
propertyName: '', id: string; // ID
platformFieldName: '', ioTPlatformRawFieldName: string; //
standardFieldName: '', standardFieldDisplayName: string; //
value: '', commandValue: string; //
result: string; //
loading?: boolean; //
selected?: boolean; //
}
const thingModelProperties = ref<ThingModelProperty[]>([]);
const thingModelLoading = ref(false);
//
const fetchThingModelProperties = async (row: Record<string, any>) => {
if (!row.ioTPlatform || !row.ioTPlatformProductId) {
Message.warning('设备缺少平台或产品信息,无法获取物模型属性');
return;
}
thingModelLoading.value = true;
try {
const requestBody: any = {
pageIndex: 1,
pageSize: 1000, //
IsPage: false, //
ioTPlatform:
typeof row.ioTPlatform === 'string'
? Number.parseInt(row.ioTPlatform)
: row.ioTPlatform,
ioTPlatformProductId: String(row.ioTPlatformProductId),
};
const { data } = await postIoTplatformThingModelInfoPageAsync({
body: requestBody,
}); });
};
// - const items = Array.isArray(data?.items) ? data!.items : [];
const removeCommandProperty = (id: string) => { thingModelProperties.value = items.map((item: any) => ({
const index = commandProperties.value.findIndex((p) => p.id === id); id: item.id || '',
if (index > -1) { ioTPlatformRawFieldName: item.ioTPlatformRawFieldName || '',
commandProperties.value.splice(index, 1); standardFieldDisplayName: item.standardFieldDisplayName || '',
} commandValue: '',
// result: '',
if (commandProperties.value.length === 0) { loading: false,
addCommandProperty(); selected: false,
} }));
}; } catch (error) {
console.error('获取平台物模型属性失败:', error);
// Message.error('获取平台物模型属性失败');
const handlePropertyChange = (item: any, property: CommandProperty) => { thingModelProperties.value = [];
if (item) { } finally {
property.propertyId = item.id || item.value || ''; thingModelLoading.value = false;
property.propertyName =
item.standardFieldDisplayName ||
item.ioTPlatformRawFieldName ||
item.label ||
'';
// 使使
property.platformFieldName = item.ioTPlatformRawFieldName || item.standardFieldName || '';
property.standardFieldName = item.standardFieldName || '';
} else {
property.propertyId = '';
property.propertyName = '';
property.platformFieldName = '';
property.standardFieldName = '';
} }
}; };
@ -330,30 +447,79 @@ const [UserModal, userModalApi] = useVbenModal({
}, },
}); });
//
const submitBatchCommand = async () => {
//
const selectedProperties = thingModelProperties.value.filter(
(prop) =>
prop.selected &&
prop.ioTPlatformRawFieldName &&
prop.commandValue &&
prop.commandValue.trim() !== '',
);
if (selectedProperties.length === 0) {
Message.warning('请至少选择一个已填写指令内容的属性');
return;
}
//
const commandContent: Record<string, any> = {};
selectedProperties.forEach((prop) => {
commandContent[prop.ioTPlatformRawFieldName] = prop.commandValue.trim();
});
try {
commandModalApi.setState({ loading: true, confirmLoading: true });
//
const result = await postAggregationDeviceDeviceCommandForApiAsync({
body: {
id: commandRow.value.id,
commandContent,
},
});
if (result.data) {
//
selectedProperties.forEach((prop) => {
prop.result =
typeof result.data === 'string'
? result.data
: (result.data
? JSON.stringify(result.data)
: '指令下发成功');
});
Message.success(`成功发送 ${selectedProperties.length} 个指令`);
} else {
selectedProperties.forEach((prop) => {
prop.result = '指令下发失败';
});
Message.error('指令下发失败');
}
} catch (error) {
console.error('批量指令发送失败:', error);
selectedProperties.forEach((prop) => {
prop.result = `指令下发失败: ${(error as Error).message}`;
});
Message.error('指令下发失败');
} finally {
commandModalApi.setState({ loading: false, confirmLoading: false });
}
};
const [CommandModal, commandModalApi] = useVbenModal({ const [CommandModal, commandModalApi] = useVbenModal({
draggable: true, draggable: true,
onConfirm: submitCommand, onConfirm: submitBatchCommand,
onBeforeClose: () => { onBeforeClose: () => {
commandRow.value = {}; commandRow.value = {};
// thingModelProperties.value = [];
commandProperties.value = [
{
id: `prop-${Date.now()}`,
propertyId: '',
propertyName: '',
platformFieldName: '',
standardFieldName: '',
value: '',
},
];
return true; return true;
}, },
onOpenChange: (isOpen: boolean) => { onOpenChange: async (isOpen: boolean) => {
if (isOpen && commandRow.value) { if (isOpen && commandRow.value) {
// - //
if (commandProperties.value.length === 0) { await fetchThingModelProperties(commandRow.value);
addCommandProperty();
}
} }
}, },
}); });
@ -455,15 +621,21 @@ const [BindForm, bindFormApi] = useVbenForm({
wrapperClass: 'grid-cols-1', wrapperClass: 'grid-cols-1',
handleValuesChange: async (values, changedFields) => { handleValuesChange: async (values, changedFields) => {
// //
if (changedFields.includes('isNeedConfigDevicMdoel') && values.isNeedConfigDevicMdoel) { if (
changedFields.includes('isNeedConfigDevicMdoel') &&
values.isNeedConfigDevicMdoel
) {
console.log('开关打开,准备触发设备物模型下拉框重新加载'); console.log('开关打开,准备触发设备物模型下拉框重新加载');
await nextTick(); await nextTick();
setTimeout(async () => { setTimeout(async () => {
try { try {
const productId = values._ioTPlatformProductId || values.ioTPlatformProductId; const productId =
values._ioTPlatformProductId || values.ioTPlatformProductId;
console.log('手动触发下拉框重新加载产品ID:', productId); console.log('手动触发下拉框重新加载产品ID:', productId);
if (productId) { if (productId) {
const fieldRef = bindFormApi.getFieldComponentRef('deviceThingModelDataId'); const fieldRef = bindFormApi.getFieldComponentRef(
'deviceThingModelDataId',
);
if (fieldRef && typeof fieldRef.updateParam === 'function') { if (fieldRef && typeof fieldRef.updateParam === 'function') {
fieldRef.updateParam({ fieldRef.updateParam({
query: { query: {
@ -682,24 +854,16 @@ const openAddModal = async () => {
userModalApi.open(); userModalApi.open();
}; };
const openCommandModal = (row: Record<string, any>) => { const openCommandModal = async (row: Record<string, any>) => {
commandRow.value = row; commandRow.value = row;
// thingModelProperties.value = [];
commandProperties.value = [
{
id: `prop-${Date.now()}`,
propertyId: '',
propertyName: '',
platformFieldName: '',
standardFieldName: '',
value: '',
},
];
commandModalApi.open(); commandModalApi.open();
}; };
// //
const openBindModal = async (rowOrRows?: Record<string, any> | Array<Record<string, any>>) => { const openBindModal = async (
rowOrRows?: Array<Record<string, any>> | Record<string, any>,
) => {
// //
let selectedRows: Array<Record<string, any>> = []; let selectedRows: Array<Record<string, any>> = [];
@ -749,7 +913,7 @@ const openBindModal = async (rowOrRows?: Record<string, any> | Array<Record<stri
if (selectedRows.length > 1) { if (selectedRows.length > 1) {
const productIds = selectedRows const productIds = selectedRows
.map((row) => row.ioTPlatformProductId) .map((row) => row.ioTPlatformProductId)
.filter((id) => id); // .filter(Boolean); //
if (productIds.length === 0) { if (productIds.length === 0) {
Message.error('选中的设备中没有有效的产品ID无法进行绑定'); Message.error('选中的设备中没有有效的产品ID无法进行绑定');
@ -759,7 +923,9 @@ const openBindModal = async (rowOrRows?: Record<string, any> | Array<Record<stri
// ID // ID
const uniqueProductIds = [...new Set(productIds)]; const uniqueProductIds = [...new Set(productIds)];
if (uniqueProductIds.length > 1) { if (uniqueProductIds.length > 1) {
Message.error(`选中的设备包含 ${uniqueProductIds.length} 种不同的产品,请只选择同一种产品的设备进行批量绑定`); Message.error(
`选中的设备包含 ${uniqueProductIds.length} 种不同的产品,请只选择同一种产品的设备进行批量绑定`,
);
return; return;
} }
} }
@ -773,7 +939,9 @@ const openBindModal = async (rowOrRows?: Record<string, any> | Array<Record<stri
console.log('设置表单值产品ID:', productId, '类型:', typeof productId); console.log('设置表单值产品ID:', productId, '类型:', typeof productId);
if (!productId) { if (!productId) {
console.warn('警告:设备行数据中没有 ioTPlatformProductId 字段,请检查表格数据是否包含该字段'); console.warn(
'警告:设备行数据中没有 ioTPlatformProductId 字段,请检查表格数据是否包含该字段',
);
} }
bindModalApi.open(); bindModalApi.open();
@ -787,83 +955,107 @@ const openBindModal = async (rowOrRows?: Record<string, any> | Array<Record<stri
const formValues = await bindFormApi.getValues(); const formValues = await bindFormApi.getValues();
console.log('表单值设置完成,当前表单值:', formValues); console.log('表单值设置完成,当前表单值:', formValues);
console.log('表单值中的 _ioTPlatformProductId:', formValues._ioTPlatformProductId); console.log(
'表单值中的 _ioTPlatformProductId:',
formValues._ioTPlatformProductId,
);
}; };
// //
async function submitCommand() { const sendCommand = async (property: ThingModelProperty) => {
// - if (!property.commandValue || property.commandValue.trim() === '') {
const invalidProperties = commandProperties.value.filter( Message.warning('请输入指令内容');
(p) => !p.propertyId || !p.value || p.value.trim() === '',
);
if (invalidProperties.length > 0) {
Message.error('请完整填写所有属性名称和指令值');
return; return;
} }
// - if (!property.ioTPlatformRawFieldName) {
const validProperties = commandProperties.value.filter( Message.warning('该属性缺少平台字段名,无法发送指令');
(p) => {
const key = p.platformFieldName || p.standardFieldName || p.propertyName;
return key && p.value && p.value.trim() !== '';
},
);
if (validProperties.length === 0) {
Message.error('请至少添加一个有效的属性-值对');
return; return;
} }
property.loading = true;
try { try {
commandModalApi.setState({ loading: true, confirmLoading: true });
// -
const commandContent: Record<string, any> = {}; const commandContent: Record<string, any> = {};
commandProperties.value.forEach((prop) => { commandContent[property.ioTPlatformRawFieldName] = property.commandValue;
if (prop.value && prop.value.trim() !== '') {
// 使使使
const key = prop.platformFieldName || prop.standardFieldName || prop.propertyName;
if (key) {
commandContent[key] = prop.value;
}
}
});
//
const result = await postAggregationDeviceDeviceCommandForApiAsync({ const result = await postAggregationDeviceDeviceCommandForApiAsync({
body: { body: {
id: commandRow.value.id, id: commandRow.value.id,
commandContent: commandContent, commandContent,
}, },
}); });
if (result.data) { if (result.data) {
// result
property.result =
typeof result.data === 'string'
? result.data
: (result.data
? JSON.stringify(result.data)
: '指令下发成功');
Message.success('指令下发成功'); Message.success('指令下发成功');
commandModalApi.close();
commandRow.value = {};
//
commandProperties.value = [
{
id: `prop-${Date.now()}`,
propertyId: '',
propertyName: '',
platformFieldName: '',
standardFieldName: '',
value: '',
},
];
} else { } else {
property.result = '指令下发失败';
Message.error('指令下发失败'); Message.error('指令下发失败');
} }
} catch (error) { } catch (error) {
console.error('指令发送失败:', error); console.error('指令发送失败:', error);
property.result = `指令下发失败: ${(error as Error).message}`;
Message.error('指令下发失败'); Message.error('指令下发失败');
} finally { } finally {
commandModalApi.setState({ loading: false, confirmLoading: false }); property.loading = false;
} }
};
//
const readData = async (property: ThingModelProperty) => {
if (!property.ioTPlatformRawFieldName) {
Message.warning('该属性缺少平台字段名,无法抄读数据');
return;
} }
if (!commandRow.value.id) {
Message.warning('设备ID不存在无法抄读数据');
return;
}
property.loading = true;
try {
const result = await postAggregationDeviceGetDevicePropertyValueForApiAsync(
{
body: {
id: String(commandRow.value.id),
propertyList: [property.ioTPlatformRawFieldName],
},
},
);
if (result.data !== undefined && result.data !== null) {
//
const propertyValue = (result.data as any)[
property.ioTPlatformRawFieldName
];
if (propertyValue !== undefined && propertyValue !== null) {
property.result =
typeof propertyValue === 'string'
? propertyValue
: JSON.stringify(propertyValue);
Message.success('抄读数据成功');
} else {
property.result = '未获取到数据';
Message.warning('未获取到该属性的数据');
}
} else {
property.result = '抄读数据失败';
}
} catch (error) {
console.error('抄读数据失败:', error);
property.result = `抄读数据失败: ${(error as Error).message}`;
} finally {
property.loading = false;
}
};
// //
async function submitBindDeviceThingModel() { async function submitBindDeviceThingModel() {
const formValues = await bindFormApi.getValues(); const formValues = await bindFormApi.getValues();
@ -885,9 +1077,7 @@ async function submitBindDeviceThingModel() {
} }
// ID // ID
const deviceIds = bindRows.value const deviceIds = bindRows.value.map((row) => row.id).filter(Boolean); //
.map((row) => row.id)
.filter((id) => id); //
if (deviceIds.length === 0) { if (deviceIds.length === 0) {
Message.error('选中的设备中没有有效的设备ID'); Message.error('选中的设备中没有有效的设备ID');
@ -914,7 +1104,6 @@ async function submitBindDeviceThingModel() {
} }
} catch (error) { } catch (error) {
console.error('绑定设备端物模型失败:', error); console.error('绑定设备端物模型失败:', error);
Message.error('绑定设备端物模型失败');
} finally { } finally {
bindModalApi.setState({ loading: false, confirmLoading: false }); bindModalApi.setState({ loading: false, confirmLoading: false });
} }
@ -1168,7 +1357,10 @@ const openBatchBindModal = async () => {
console.log('通过 grid.getCheckboxRecords 获取:', checkboxRecords); console.log('通过 grid.getCheckboxRecords 获取:', checkboxRecords);
} else if (typeof gridInstance.getCheckboxReserveRecords === 'function') { } else if (typeof gridInstance.getCheckboxReserveRecords === 'function') {
checkboxRecords = gridInstance.getCheckboxReserveRecords(); checkboxRecords = gridInstance.getCheckboxReserveRecords();
console.log('通过 grid.getCheckboxReserveRecords 获取:', checkboxRecords); console.log(
'通过 grid.getCheckboxReserveRecords 获取:',
checkboxRecords,
);
} }
// 访 // 访
@ -1182,7 +1374,10 @@ const openBatchBindModal = async () => {
const store = gridInstance.$store; const store = gridInstance.$store;
if (store.checkboxRecords) { if (store.checkboxRecords) {
checkboxRecords = store.checkboxRecords; checkboxRecords = store.checkboxRecords;
console.log('通过 grid.$store.checkboxRecords 获取:', checkboxRecords); console.log(
'通过 grid.$store.checkboxRecords 获取:',
checkboxRecords,
);
} }
} }
} }
@ -1192,12 +1387,18 @@ const openBatchBindModal = async () => {
const store = gridApi.store as any; const store = gridApi.store as any;
if (store.checkboxRecords) { if (store.checkboxRecords) {
checkboxRecords = store.checkboxRecords; checkboxRecords = store.checkboxRecords;
console.log('通过 gridApi.store.checkboxRecords 获取:', checkboxRecords); console.log(
'通过 gridApi.store.checkboxRecords 获取:',
checkboxRecords,
);
} }
} }
// 3 gridApi // 3 gridApi
if (checkboxRecords.length === 0 && typeof (gridApi as any).getCheckboxRecords === 'function') { if (
checkboxRecords.length === 0 &&
typeof (gridApi as any).getCheckboxRecords === 'function'
) {
checkboxRecords = (gridApi as any).getCheckboxRecords(); checkboxRecords = (gridApi as any).getCheckboxRecords();
console.log('通过 gridApi.getCheckboxRecords 获取:', checkboxRecords); console.log('通过 gridApi.getCheckboxRecords 获取:', checkboxRecords);
} }
@ -1213,7 +1414,7 @@ const openBatchBindModal = async () => {
// //
const productIds = checkboxRecords const productIds = checkboxRecords
.map((row) => row.ioTPlatformProductId) .map((row) => row.ioTPlatformProductId)
.filter((id) => id); // .filter(Boolean); //
if (productIds.length === 0) { if (productIds.length === 0) {
Message.error('选中的设备中没有有效的产品ID无法进行绑定'); Message.error('选中的设备中没有有效的产品ID无法进行绑定');
@ -1223,7 +1424,9 @@ const openBatchBindModal = async () => {
// ID // ID
const uniqueProductIds = [...new Set(productIds)]; const uniqueProductIds = [...new Set(productIds)];
if (uniqueProductIds.length > 1) { if (uniqueProductIds.length > 1) {
Message.error(`选中的设备包含 ${uniqueProductIds.length} 种不同的产品,请只选择同一种产品的设备进行批量绑定`); Message.error(
`选中的设备包含 ${uniqueProductIds.length} 种不同的产品,请只选择同一种产品的设备进行批量绑定`,
);
return; return;
} }
@ -1338,10 +1541,10 @@ const toolbarActions = computed(() => [
{{ $t('abp.deviceInfos.viewData') }} {{ $t('abp.deviceInfos.viewData') }}
</Button> </Button>
<Button size="small" type="link" @click="openCommandModal.bind(null, row)()"> <Button size="small" type="link" @click="openCommandModal.bind(null, row)()">
{{ $t('abp.IoTDBBase.Command') }} 设备操作
</Button> </Button>
<Button size="small" type="link" @click="openBindModal.bind(null, row)()"> <Button size="small" type="link" @click="openBindModal.bind(null, row)()">
绑定设备端物模型 绑定物模型
</Button> </Button>
<Popover trigger="hover" placement="bottomRight" :overlay-style="{ minWidth: '120px' }"> <Popover trigger="hover" placement="bottomRight" :overlay-style="{ minWidth: '120px' }">
<template #content> <template #content>
@ -1376,93 +1579,20 @@ const toolbarActions = computed(() => [
<UserModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]"> <UserModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]">
<component :is="editRow.id ? EditForm : AddForm" /> <component :is="editRow.id ? EditForm : AddForm" />
</UserModal> </UserModal>
<CommandModal :title="$t('abp.IoTDBBase.Command')" class="w-[800px]"> <CommandModal title="设备操作" class="w-[1200px]">
<div class="command-form-container"> <div v-if="thingModelLoading" style="padding: 40px; text-align: center">
<div <Loading :loading="true" tip="加载物模型属性中..." />
v-for="(property, index) in commandProperties"
:key="property.id"
class="command-property-item"
style="margin-bottom: 16px; padding: 16px; border: 1px solid #d9d9d9; border-radius: 4px; background: #fafafa"
>
<div class="flex items-center justify-between mb-2">
<span class="text-sm font-medium" style="color: #666">
属性-值对 {{ index + 1 }}
</span>
<Button
v-if="commandProperties.length > 1"
type="text"
danger
size="small"
@click="removeCommandProperty(property.id)"
>
<template #icon>
<Icon icon="ant-design:delete-outlined" />
</template>
删除
</Button>
</div>
<div class="flex gap-4" style="align-items: flex-start">
<div style="flex: 1; min-width: 0; max-width: 50%">
<label class="block mb-2 text-sm" style="color: #333">
平台物模型属性 <span style="color: #ff4d4f">*</span>
</label>
<IoTPlatformThingModelDataSelect
:value="property.propertyId"
:ioTPlatform="
commandRow.ioTPlatform
? Number.parseInt(String(commandRow.ioTPlatform))
: null
"
:ioTPlatformProductId="commandRow.ioTPlatformProductId || null"
placeholder="请选择物模型属性"
style="width: 100%"
@update:value="
(val) => {
property.propertyId = val || '';
}
"
@item-change="(item) => handlePropertyChange(item, property)"
/>
</div>
<div style="flex: 1; min-width: 0">
<label class="block mb-2 text-sm" style="color: #333">
指令值 <span style="color: #ff4d4f">*</span>
</label>
<Input
v-model:value="property.value"
placeholder="请输入指令值"
style="width: 100%"
/>
</div>
</div>
<div v-if="property.propertyName" class="mt-2 text-xs" style="color: #999">
已选择属性: {{ property.propertyName }}
<span v-if="property.platformFieldName" style="margin-left: 8px; color: #666">
(平台字段: {{ property.platformFieldName }})
</span>
</div>
</div>
<div class="mt-4">
<Button type="dashed" block @click="addCommandProperty">
<template #icon>
<Icon icon="ant-design:plus-outlined" />
</template>
新增属性-值对
</Button>
</div>
</div> </div>
<Table v-else :columns="commandTableColumns" :data-source="thingModelProperties" :pagination="false"
:scroll="{ x: 1000, y: 500 }" row-key="id" size="small" />
</CommandModal> </CommandModal>
<BindModal :title="`绑定设备端物模型${bindRows.length > 0 ? ` (已选择 ${bindRows.length} 个设备)` : ''}`" class="w-[600px]"> <BindModal :title="`绑定设备端物模型${bindRows.length > 0 ? ` (已选择 ${bindRows.length} 个设备)` : ''}`" class="w-[600px]">
<div v-if="bindRows.length > 0" class="mb-4 p-3 bg-blue-50 rounded border border-blue-200"> <div v-if="bindRows.length > 0" class="mb-4 rounded border border-blue-200 bg-blue-50 p-3">
<div class="text-sm font-medium text-blue-800 mb-2"> <div class="mb-2 text-sm font-medium text-blue-800">
已选择 {{ bindRows.length }} 个设备 已选择 {{ bindRows.length }} 个设备
</div> </div>
<div class="text-xs text-blue-600 max-h-32 overflow-y-auto"> <div class="max-h-32 overflow-y-auto text-xs text-blue-600">
<div <div v-for="(row, index) in bindRows" :key="row.id || index" class="mb-1">
v-for="(row, index) in bindRows"
:key="row.id || index"
class="mb-1"
>
{{ index + 1 }}. {{ row.deviceName || row.deviceAddress || row.id }} {{ index + 1 }}. {{ row.deviceName || row.deviceAddress || row.id }}
</div> </div>
</div> </div>

View File

@ -193,7 +193,7 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
title: $t('common.action'), title: $t('common.action'),
field: 'action', field: 'action',
fixed: 'right', fixed: 'right',
width: '280', width: '260',
slots: { default: 'action' }, slots: { default: 'action' },
}, },
]); ]);
@ -330,10 +330,12 @@ export const addDeviceFormSchema: any = computed(() => [
const accountId = formValues?.ioTPlatformAccountId; const accountId = formValues?.ioTPlatformAccountId;
return { return {
api: platform && accountId api:
platform && accountId
? postAggregationIoTplatformGetIoTplatformProductInfoAsync ? postAggregationIoTplatformGetIoTplatformProductInfoAsync
: null, : null,
params: platform && accountId params:
platform && accountId
? { ? {
body: { body: {
ioTPlatformType: ioTPlatformType:
@ -586,10 +588,12 @@ export const editDeviceFormSchemaEdit: any = computed(() => [
const accountId = formValues?.ioTPlatformAccountId; const accountId = formValues?.ioTPlatformAccountId;
return { return {
api: platform && accountId api:
platform && accountId
? postAggregationIoTplatformGetIoTplatformProductInfoAsync ? postAggregationIoTplatformGetIoTplatformProductInfoAsync
: null, : null,
params: platform && accountId params:
platform && accountId
? { ? {
body: { body: {
ioTPlatformType: ioTPlatformType:
@ -784,10 +788,12 @@ export const batchAddDeviceFormSchema: any = computed(() => [
const accountId = formValues?.ioTPlatformAccountId; const accountId = formValues?.ioTPlatformAccountId;
return { return {
api: platform && accountId api:
platform && accountId
? postAggregationIoTplatformGetIoTplatformProductInfoAsync ? postAggregationIoTplatformGetIoTplatformProductInfoAsync
: null, : null,
params: platform && accountId params:
platform && accountId
? { ? {
body: { body: {
ioTPlatformType: ioTPlatformType: