From 241cf767885e7a965e4fe209f1d91587faf787ad Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 24 May 2026 00:32:35 +0800 Subject: [PATCH] =?UTF-8?q?fix(iot):=20=E4=BF=AE=E5=A4=8D=2021=20=E5=A4=84?= =?UTF-8?q?=20bug=EF=BC=88P1=C3=9715=20+=20P2=C3=976=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 经 codex 4 轮复评定稿,antd / ele 两端同步。 P1(场景规则 / 物模型 / Modbus / Redis sink / 路由): - B7/B8 隐藏路由 path 与 activePath 对齐 vue3 源(产品 / OTA 固件详情) - B9 移除后端不存在的 deleteSceneRuleList 封装 - B10 物模型 number specs 恢复 min/max/step/unit 校验 - B11 物模型新增枚举项补 dataType: ENUM - B12 物模型 struct 非空校验绑 fieldPath,array 嵌套显式覆盖 property.dataSpecs.dataSpecsList,确保父表单 validate 触发 - B13 struct 与 input-output-param 编辑回填 cloneDeep,取消不污染原对象 - B14 Modbus Client 模式 ip/port/timeout/retryInterval 改 dependencies 条件必填 - B19 Redis sink 补 dataStructure(默认 Stream)+ Hash/ZSet 条件字段 - B20 仅 ALERT_RECOVER 强校验 alertConfigId,ALERT_TRIGGER 放行 - B21 conditionGroups 递归校验 · 设备状态/属性 param 必填 · CURRENT_TIME 按 operator 区分:TODAY 免、BETWEEN_TIME 双段、其它单段 · 触发器 / 条件 / 执行器 deviceId 改显式 null/undefined 判断, 保留「全部设备 = 0」(后端 action 支持广播执行) - B22 事件上报条件改回普通 Input,允许标量值或留空 - B23 antd 当前时间条件 :value / @update:value 绑定 + Dayjs 类型 normalize; 归一逻辑抽到 @vben/utils.formatDayjs(packages/@core/base/shared/utils/date.ts), 供所有 app 复用 - B24 设备控制动作切换无条件清依赖,去掉 isInitialized 冗余守卫 - B26 JSON 参数输入先全部校验通过后再写入父表单 P2(产品 / 设备 / 物模型展示 / 数据源): - B28 产品 deviceType 去默认值,强制用户显式选择 - B30 设备列表 DeviceName 加点击详情 slot - B31 设备卡片显示备注名称(nickname || deviceName) - B32 设备详情 hasLocation 改用 != null,合法 0 坐标不再判空 - B41 物模型数据定义展示顺序改为 name-value - B46 数据源 getData() 剔除仅 UI 用的 identifierLoading 临时字段 --- apps/web-antd/src/api/iot/rule/scene/index.ts | 7 -- .../web-antd/src/router/routes/modules/iot.ts | 9 +- .../src/views/iot/device/device/data.ts | 1 + .../iot/device/device/detail/modules/info.vue | 4 +- .../detail/modules/modbus-config-form.vue | 27 ++-- .../src/views/iot/device/device/index.vue | 5 + .../iot/device/device/modules/card-view.vue | 11 +- .../src/views/iot/product/product/data.ts | 1 - .../data/rule/modules/source-config-form.vue | 6 +- .../sink/config/redis-stream-config-form.vue | 53 +++++++- .../configs/current-time-condition-config.vue | 33 ++--- .../form/configs/device-control-config.vue | 32 ++--- .../configs/main-condition-inner-config.vue | 31 ++--- .../scene/form/inputs/json-params-input.vue | 55 ++++---- .../src/views/iot/rule/scene/modules/form.vue | 97 ++++++++++++++- .../modules/components/data-definition.vue | 6 +- .../thingmodel/modules/data-specs/array.vue | 1 + .../thingmodel/modules/data-specs/enum.vue | 7 +- .../thingmodel/modules/data-specs/number.vue | 87 ++++++++++++- .../thingmodel/modules/data-specs/struct.vue | 35 +++++- .../thingmodel/modules/input-output-param.vue | 8 +- .../src/views/mes/md/workstation/data.ts | 12 +- .../web-antd/src/views/mes/utils/constants.ts | 117 ++++++++++++++++++ apps/web-ele/src/api/iot/rule/scene/index.ts | 7 -- apps/web-ele/src/router/routes/modules/iot.ts | 9 +- .../src/views/iot/device/device/data.ts | 1 + .../iot/device/device/detail/modules/info.vue | 4 +- .../detail/modules/modbus-config-form.vue | 27 ++-- .../src/views/iot/device/device/index.vue | 5 + .../iot/device/device/modules/card-view.vue | 11 +- .../src/views/iot/product/product/data.ts | 1 - .../data/rule/modules/source-config-form.vue | 6 +- .../sink/config/redis-stream-config-form.vue | 66 +++++++++- .../form/configs/device-control-config.vue | 32 ++--- .../configs/main-condition-inner-config.vue | 38 +++--- .../scene/form/inputs/json-params-input.vue | 55 ++++---- .../src/views/iot/rule/scene/modules/form.vue | 97 ++++++++++++++- .../modules/components/data-definition.vue | 6 +- .../thingmodel/modules/data-specs/array.vue | 1 + .../thingmodel/modules/data-specs/enum.vue | 7 +- .../thingmodel/modules/data-specs/number.vue | 87 ++++++++++++- .../thingmodel/modules/data-specs/struct.vue | 35 +++++- .../thingmodel/modules/input-output-param.vue | 8 +- .../src/views/mes/md/workstation/data.ts | 12 +- apps/web-ele/src/views/mes/utils/constants.ts | 117 ++++++++++++++++++ packages/constants/src/dict-enum.ts | 17 +++ 46 files changed, 1012 insertions(+), 282 deletions(-) diff --git a/apps/web-antd/src/api/iot/rule/scene/index.ts b/apps/web-antd/src/api/iot/rule/scene/index.ts index acbfbac42..fd522a324 100644 --- a/apps/web-antd/src/api/iot/rule/scene/index.ts +++ b/apps/web-antd/src/api/iot/rule/scene/index.ts @@ -80,13 +80,6 @@ export function deleteSceneRule(id: number) { return requestClient.delete(`/iot/scene-rule/delete?id=${id}`); } -/** 批量删除场景联动规则 */ -export function deleteSceneRuleList(ids: number[]) { - return requestClient.delete('/iot/scene-rule/delete-list', { - params: { ids: ids.join(',') }, - }); -} - /** 更新场景联动规则状态 */ export function updateSceneRuleStatus(id: number, status: number) { return requestClient.put(`/iot/scene-rule/update-status`, { diff --git a/apps/web-antd/src/router/routes/modules/iot.ts b/apps/web-antd/src/router/routes/modules/iot.ts index ec0191863..a1d2203b9 100644 --- a/apps/web-antd/src/router/routes/modules/iot.ts +++ b/apps/web-antd/src/router/routes/modules/iot.ts @@ -12,7 +12,7 @@ const routes: RouteRecordRaw[] = [ }, children: [ { - path: 'product/detail/:id', + path: 'product/product/detail/:id', name: 'IoTProductDetail', meta: { title: '产品详情', @@ -30,14 +30,13 @@ const routes: RouteRecordRaw[] = [ component: () => import('#/views/iot/device/device/detail/index.vue'), }, { - path: 'ota/firmware/detail/:id', + path: 'ota/operation/firmware/detail/:id', name: 'IoTOtaFirmwareDetail', meta: { title: '固件详情', - activePath: '/iot/ota', + activePath: '/iot/operation/ota/firmware', }, - component: () => - import('#/views/iot/ota/firmware/detail/index.vue'), + component: () => import('#/views/iot/ota/firmware/detail/index.vue'), }, ], }, diff --git a/apps/web-antd/src/views/iot/device/device/data.ts b/apps/web-antd/src/views/iot/device/device/data.ts index 3eb5ebb1b..1908033ef 100644 --- a/apps/web-antd/src/views/iot/device/device/data.ts +++ b/apps/web-antd/src/views/iot/device/device/data.ts @@ -276,6 +276,7 @@ export function useGridColumns(): VxeTableGridOptions['colu field: 'deviceName', title: 'DeviceName', minWidth: 150, + slots: { default: 'deviceName' }, }, { field: 'nickname', diff --git a/apps/web-antd/src/views/iot/device/device/detail/modules/info.vue b/apps/web-antd/src/views/iot/device/device/detail/modules/info.vue index ded227804..234ad1b33 100644 --- a/apps/web-antd/src/views/iot/device/device/detail/modules/info.vue +++ b/apps/web-antd/src/views/iot/device/device/detail/modules/info.vue @@ -36,9 +36,9 @@ const authInfo = ref( ); const mapDialogRef = ref>(); -/** 是否有位置信息 */ +/** 是否有位置信息(合法经纬度 0 不应视为空) */ const hasLocation = computed(() => { - return !!(props.device.longitude && props.device.latitude); + return props.device.longitude != null && props.device.latitude != null; }); /** 打开地图弹窗 */ diff --git a/apps/web-antd/src/views/iot/device/device/detail/modules/modbus-config-form.vue b/apps/web-antd/src/views/iot/device/device/detail/modules/modbus-config-form.vue index 669b01fbf..fe3a7afdb 100644 --- a/apps/web-antd/src/views/iot/device/device/detail/modules/modbus-config-form.vue +++ b/apps/web-antd/src/views/iot/device/device/detail/modules/modbus-config-form.vue @@ -58,11 +58,13 @@ const [Form, formApi] = useVbenForm({ componentProps: { placeholder: '请输入 Modbus 服务器 IP 地址', }, + // Client 模式专有字段:必填;Server 模式不显示也不校验 dependencies: { triggerFields: [''], - show: () => isClient.value, // Client 模式专有字段:IP 地址 + show: () => isClient.value, + rules: () => + isClient.value ? z.string().min(1, '请输入 IP 地址') : null, }, - rules: z.string().min(1, '请输入 IP 地址').optional(), }, { fieldName: 'port', @@ -76,9 +78,12 @@ const [Form, formApi] = useVbenForm({ }, dependencies: { triggerFields: [''], - show: () => isClient.value, // Client 模式专有字段:端口 + show: () => isClient.value, + rules: () => + isClient.value + ? z.number({ message: '请输入端口' }).min(1).max(65_535) + : null, }, - rules: z.number().min(1).max(65_535).optional(), defaultValue: 502, }, { @@ -106,9 +111,12 @@ const [Form, formApi] = useVbenForm({ }, dependencies: { triggerFields: [''], - show: () => isClient.value, // Client 模式专有字段:连接超时 + show: () => isClient.value, + rules: () => + isClient.value + ? z.number({ message: '请输入连接超时时间' }).min(1000) + : null, }, - rules: z.number().min(1000).optional(), defaultValue: 3000, }, { @@ -123,9 +131,12 @@ const [Form, formApi] = useVbenForm({ }, dependencies: { triggerFields: [''], - show: () => isClient.value, // Client 模式专有字段:重试间隔 + show: () => isClient.value, + rules: () => + isClient.value + ? z.number({ message: '请输入重试间隔' }).min(1000) + : null, }, - rules: z.number().min(1000).optional(), defaultValue: 10_000, }, { diff --git a/apps/web-antd/src/views/iot/device/device/index.vue b/apps/web-antd/src/views/iot/device/device/index.vue index 682fcac25..3d2db1277 100644 --- a/apps/web-antd/src/views/iot/device/device/index.vue +++ b/apps/web-antd/src/views/iot/device/device/index.vue @@ -430,6 +430,11 @@ onMounted(async () => { + diff --git a/apps/web-antd/src/views/iot/rule/scene/form/configs/current-time-condition-config.vue b/apps/web-antd/src/views/iot/rule/scene/form/configs/current-time-condition-config.vue index bbe7913c5..df03b53a3 100644 --- a/apps/web-antd/src/views/iot/rule/scene/form/configs/current-time-condition-config.vue +++ b/apps/web-antd/src/views/iot/rule/scene/form/configs/current-time-condition-config.vue @@ -1,11 +1,14 @@ diff --git a/apps/web-antd/src/views/iot/thingmodel/modules/data-specs/array.vue b/apps/web-antd/src/views/iot/thingmodel/modules/data-specs/array.vue index 4ab4ba7e1..1e88342b9 100644 --- a/apps/web-antd/src/views/iot/thingmodel/modules/data-specs/array.vue +++ b/apps/web-antd/src/views/iot/thingmodel/modules/data-specs/array.vue @@ -68,5 +68,6 @@ function handleChange(val: any) { diff --git a/apps/web-antd/src/views/iot/thingmodel/modules/data-specs/enum.vue b/apps/web-antd/src/views/iot/thingmodel/modules/data-specs/enum.vue index aca1e5fc5..35a84aabe 100644 --- a/apps/web-antd/src/views/iot/thingmodel/modules/data-specs/enum.vue +++ b/apps/web-antd/src/views/iot/thingmodel/modules/data-specs/enum.vue @@ -2,6 +2,7 @@ diff --git a/apps/web-ele/src/views/iot/thingmodel/modules/data-specs/enum.vue b/apps/web-ele/src/views/iot/thingmodel/modules/data-specs/enum.vue index 22030d2ce..f3ebfcb16 100644 --- a/apps/web-ele/src/views/iot/thingmodel/modules/data-specs/enum.vue +++ b/apps/web-ele/src/views/iot/thingmodel/modules/data-specs/enum.vue @@ -2,6 +2,7 @@