diff --git a/apps/web-antd/src/locales/langs/en-US/abp.json b/apps/web-antd/src/locales/langs/en-US/abp.json index 2814509..eb442fe 100644 --- a/apps/web-antd/src/locales/langs/en-US/abp.json +++ b/apps/web-antd/src/locales/langs/en-US/abp.json @@ -204,6 +204,7 @@ "ioTPlatformName": "PlatformName", "ioTPlatformDeviceOpenInfo": "DeviceOpenInfo", "platformPassword": "Password", + "firmwareVersion": "FirmwareVersion", "ioTPlatformProductId": "ProductId", "ioTPlatformProductName": "ProductName", "ioTPlatformAccountId": "AccountId", diff --git a/apps/web-antd/src/locales/langs/zh-CN/abp.json b/apps/web-antd/src/locales/langs/zh-CN/abp.json index 81ddb47..3f3f715 100644 --- a/apps/web-antd/src/locales/langs/zh-CN/abp.json +++ b/apps/web-antd/src/locales/langs/zh-CN/abp.json @@ -197,6 +197,7 @@ "ioTPlatformName": "物联网平台类型", "ioTPlatformDeviceOpenInfo": "平台设备信息", "platformPassword": "设备密码", + "firmwareVersion": "固件版本", "ioTPlatformProductId": "产品Id", "ioTPlatformProductName": "产品名称", "ioTPlatformAccountId": "所属账号Id", diff --git a/apps/web-antd/src/views/devicemanagement/deviceinfo/index.vue b/apps/web-antd/src/views/devicemanagement/deviceinfo/index.vue index 9200937..93fe7c4 100644 --- a/apps/web-antd/src/views/devicemanagement/deviceinfo/index.vue +++ b/apps/web-antd/src/views/devicemanagement/deviceinfo/index.vue @@ -349,10 +349,24 @@ const commandTableColumns = computed(() => [ if (record.accessMode === 'r') { return h('span', { style: { color: '#999' } }, '只读属性,无法设置指令'); } + + const dataType = record.ioTPlatformRawFieldDataType; + const isNumeric = isNumericType(dataType); + return h(Input, { value: record.commandValue, - placeholder: '请输入指令内容', + placeholder: isNumeric ? '请输入数字' : '请输入指令内容', + type: 'text', 'onUpdate:value': (val: string) => { + // 如果是数字类型,只允许输入数字(包括小数点和负号) + if (isNumeric && val !== '') { + // 允许数字、小数点、负号 + // 正则表达式:允许负号开头,然后是数字,可以有小数点和小数部分 + const numericRegex = /^-?\d*\.?\d*$/; + if (!numericRegex.test(val)) { + return; // 不符合格式,不更新 + } + } record.commandValue = val; }, }); @@ -452,12 +466,77 @@ interface ThingModelProperty { loading?: boolean; // 是否正在加载 selected?: boolean; // 是否选中 accessMode?: string; // 访问模式:rw-读写,r-只读 + ioTPlatformRawFieldDataType?: string; // 平台原始字段数据类型,如:INT32, STRING 等 } const thingModelProperties = ref([]); const thingModelLoading = ref(false); // 筛选关键词 const filterKeyword = ref(''); + +// 判断是否为数字类型 +const isNumericType = (dataType: string | undefined): boolean => { + if (!dataType) return false; + const upperType = dataType.toUpperCase(); + return ( + upperType.includes('INT') || + upperType.includes('FLOAT') || + upperType.includes('DOUBLE') || + upperType === 'NUMBER' || + upperType === 'DECIMAL' + ); +}; + +// 根据数据类型转换值 +const convertValueByType = ( + value: string, + dataType: string | undefined, +): any => { + if (!value || value.trim() === '') { + return value; + } + + if (!dataType) { + return value; + } + + const upperType = dataType.toUpperCase(); + + // 数字类型 + if (isNumericType(dataType)) { + // 尝试转换为数字 + const numValue = Number(value); + if (isNaN(numValue)) { + return value; // 如果转换失败,返回原值 + } + + // 根据具体类型进行转换 + if (upperType.includes('INT')) { + return Number.parseInt(value, 10); + } else if ( + upperType.includes('FLOAT') || + upperType.includes('DOUBLE') || + upperType === 'DECIMAL' + ) { + return Number.parseFloat(value); + } + return numValue; + } + + // 布尔类型 + if (upperType === 'BOOL' || upperType === 'BOOLEAN') { + if (value.toLowerCase() === 'true' || value === '1') { + return true; + } + if (value.toLowerCase() === 'false' || value === '0') { + return false; + } + return value; // 无法转换时返回原值 + } + + // 字符串类型或其他类型,直接返回 + return value; +}; // 过滤后的物模型属性列表 const filteredThingModelProperties = computed(() => { if (!filterKeyword.value.trim()) { @@ -507,6 +586,7 @@ const fetchThingModelProperties = async (row: Record) => { loading: false, selected: false, accessMode: item.accessMode || '', // 保存访问模式 + ioTPlatformRawFieldDataType: item.ioTPlatformRawFieldDataType || '', // 保存数据类型 })); } catch (error) { console.error('获取平台物模型属性失败:', error); @@ -547,7 +627,12 @@ const submitBatchCommand = async () => { // 将选中的属性组成键值对(键为标识符,值为指令内容) const commandContent: Record = {}; selectedProperties.forEach((prop) => { - commandContent[prop.ioTPlatformRawFieldName] = prop.commandValue.trim(); + // 根据数据类型转换值 + const convertedValue = convertValueByType( + prop.commandValue.trim(), + prop.ioTPlatformRawFieldDataType, + ); + commandContent[prop.ioTPlatformRawFieldName] = convertedValue; }); try { @@ -1467,7 +1552,12 @@ const sendCommand = async (property: ThingModelProperty) => { property.loading = true; try { const commandContent: Record = {}; - commandContent[property.ioTPlatformRawFieldName] = property.commandValue; + // 根据数据类型转换值 + const convertedValue = convertValueByType( + property.commandValue.trim(), + property.ioTPlatformRawFieldDataType, + ); + commandContent[property.ioTPlatformRawFieldName] = convertedValue; const result = await postAggregationDeviceDeviceCommandForApiAsync({ body: { diff --git a/apps/web-antd/src/views/devicemanagement/deviceinfo/schema.ts b/apps/web-antd/src/views/devicemanagement/deviceinfo/schema.ts index d1120c5..cb09d0e 100644 --- a/apps/web-antd/src/views/devicemanagement/deviceinfo/schema.ts +++ b/apps/web-antd/src/views/devicemanagement/deviceinfo/schema.ts @@ -185,6 +185,11 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [ title: $t('abp.deviceInfos.platformPassword'), minWidth: '150', }, + { + field: 'firmwareVersion', + title: $t('abp.deviceInfos.firmwareVersion'), + minWidth: '150', + }, { field: 'ioTPlatformResponse', title: $t('abp.deviceInfos.ioTPlatformResponse'),