From 8587a549c692778b7b9a08e83efc4d139e583bce Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Jan 2026 19:36:51 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat=EF=BC=9A=E3=80=90iot=E3=80=91modbus-tc?= =?UTF-8?q?p=20=E5=8D=8F=E8=AE=AE=E6=8E=A5=E5=85=A5=2020%=EF=BC=9A?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0=EF=BC=8C=E5=9F=BA=E4=BA=8E?= =?UTF-8?q?=20dynamic-forging-wigderson.md=20=E8=A7=84=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/iot/device/modbus/config/index.ts | 29 ++ src/api/iot/device/modbus/point/index.ts | 48 +++ .../device/detail/DeviceModbusConfig.vue | 262 +++++++++++++++ .../device/detail/DeviceModbusConfigForm.vue | 160 +++++++++ .../device/detail/DeviceModbusPointForm.vue | 315 ++++++++++++++++++ src/views/iot/device/device/detail/index.vue | 13 + src/views/iot/utils/constants.ts | 68 ++++ 7 files changed, 895 insertions(+) create mode 100644 src/api/iot/device/modbus/config/index.ts create mode 100644 src/api/iot/device/modbus/point/index.ts create mode 100644 src/views/iot/device/device/detail/DeviceModbusConfig.vue create mode 100644 src/views/iot/device/device/detail/DeviceModbusConfigForm.vue create mode 100644 src/views/iot/device/device/detail/DeviceModbusPointForm.vue diff --git a/src/api/iot/device/modbus/config/index.ts b/src/api/iot/device/modbus/config/index.ts new file mode 100644 index 000000000..fa0e0a802 --- /dev/null +++ b/src/api/iot/device/modbus/config/index.ts @@ -0,0 +1,29 @@ +import request from '@/config/axios' + +/** Modbus 连接配置 VO */ +export interface DeviceModbusConfigVO { + id?: number // 主键 + deviceId: number // 设备编号 + ip: string // Modbus 服务器 IP 地址 + port: number // Modbus 服务器端口 + slaveId: number // 从站地址 + timeout: number // 连接超时时间,单位:毫秒 + retryInterval: number // 重试间隔,单位:毫秒 + status: number // 状态 +} + +/** Modbus 连接配置 API */ +export const DeviceModbusConfigApi = { + /** 获取设备的 Modbus 连接配置 */ + getModbusConfig: async (deviceId: number) => { + return await request.get({ + url: `/iot/device-modbus-config/get`, + params: { deviceId } + }) + }, + + /** 保存 Modbus 连接配置 */ + saveModbusConfig: async (data: DeviceModbusConfigVO) => { + return await request.post({ url: `/iot/device-modbus-config/save`, data }) + } +} diff --git a/src/api/iot/device/modbus/point/index.ts b/src/api/iot/device/modbus/point/index.ts new file mode 100644 index 000000000..5dc05d1c1 --- /dev/null +++ b/src/api/iot/device/modbus/point/index.ts @@ -0,0 +1,48 @@ +import request from '@/config/axios' + +/** Modbus 点位配置 VO */ +export interface DeviceModbusPointVO { + id?: number // 主键 + deviceId: number // 设备编号 + thingModelId: number // 物模型属性编号 + identifier: string // 属性标识符 + name: string // 属性名称 + functionCode: number // Modbus 功能码 + registerAddress: number // 寄存器起始地址 + registerCount: number // 寄存器数量 + byteOrder: string // 字节序 + rawDataType: string // 原始数据类型 + scale: number // 缩放因子 + pollInterval: number // 轮询间隔,单位:毫秒 + status: number // 状态 +} + +/** Modbus 点位配置 API */ +export const DeviceModbusPointApi = { + /** 获取设备的 Modbus 点位分页 */ + getModbusPointPage: async (params: any) => { + return await request.get({ url: `/iot/device-modbus-point/page`, params }) + }, + + /** 获取 Modbus 点位详情 */ + getModbusPoint: async (id: number) => { + return await request.get({ + url: `/iot/device-modbus-point/get?id=${id}` + }) + }, + + /** 创建 Modbus 点位配置 */ + createModbusPoint: async (data: DeviceModbusPointVO) => { + return await request.post({ url: `/iot/device-modbus-point/create`, data }) + }, + + /** 更新 Modbus 点位配置 */ + updateModbusPoint: async (data: DeviceModbusPointVO) => { + return await request.put({ url: `/iot/device-modbus-point/update`, data }) + }, + + /** 删除 Modbus 点位配置 */ + deleteModbusPoint: async (id: number) => { + return await request.delete({ url: `/iot/device-modbus-point/delete?id=${id}` }) + } +} diff --git a/src/views/iot/device/device/detail/DeviceModbusConfig.vue b/src/views/iot/device/device/detail/DeviceModbusConfig.vue new file mode 100644 index 000000000..d380fb2dc --- /dev/null +++ b/src/views/iot/device/device/detail/DeviceModbusConfig.vue @@ -0,0 +1,262 @@ + + + + diff --git a/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue b/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue new file mode 100644 index 000000000..0e9572a60 --- /dev/null +++ b/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue @@ -0,0 +1,160 @@ + + + + diff --git a/src/views/iot/device/device/detail/DeviceModbusPointForm.vue b/src/views/iot/device/device/detail/DeviceModbusPointForm.vue new file mode 100644 index 000000000..db0b7b523 --- /dev/null +++ b/src/views/iot/device/device/detail/DeviceModbusPointForm.vue @@ -0,0 +1,315 @@ + + + + diff --git a/src/views/iot/device/device/detail/index.vue b/src/views/iot/device/device/detail/index.vue index 3ec756b5c..5c44c94b4 100644 --- a/src/views/iot/device/device/detail/index.vue +++ b/src/views/iot/device/device/detail/index.vue @@ -36,6 +36,18 @@ @success="getDeviceData" /> + + + @@ -50,6 +62,7 @@ import DeviceDetailsThingModel from './DeviceDetailsThingModel.vue' import DeviceDetailsMessage from './DeviceDetailsMessage.vue' import DeviceDetailsSimulator from './DeviceDetailsSimulator.vue' import DeviceDetailConfig from './DeviceDetailConfig.vue' +import DeviceModbusConfig from './DeviceModbusConfig.vue' defineOptions({ name: 'IoTDeviceDetail' }) diff --git a/src/views/iot/utils/constants.ts b/src/views/iot/utils/constants.ts index fe6db1881..259f5dcef 100644 --- a/src/views/iot/utils/constants.ts +++ b/src/views/iot/utils/constants.ts @@ -541,3 +541,71 @@ export const JSON_PARAMS_EXAMPLE_VALUES = { [IoTDataSpecsDataTypeEnum.ARRAY]: { display: '[]', value: [] }, DEFAULT: { display: '""', value: '' } } as const + +// ========== Modbus 相关常量 ========== + +/** Modbus 功能码枚举 */ +export const ModbusFunctionCodeEnum = { + READ_COILS: 1, // 读线圈 + READ_DISCRETE_INPUTS: 2, // 读离散输入 + READ_HOLDING_REGISTERS: 3, // 读保持寄存器 + READ_INPUT_REGISTERS: 4 // 读输入寄存器 +} as const + +/** Modbus 功能码选项 */ +export const ModbusFunctionCodeOptions = [ + { value: 1, label: '01 - 读线圈 (Coils)', description: '可读写布尔值' }, + { value: 2, label: '02 - 读离散输入 (Discrete Inputs)', description: '只读布尔值' }, + { value: 3, label: '03 - 读保持寄存器 (Holding Registers)', description: '可读写16位数据' }, + { value: 4, label: '04 - 读输入寄存器 (Input Registers)', description: '只读16位数据' } +] + +/** Modbus 原始数据类型枚举 */ +export const ModbusRawDataTypeEnum = { + INT16: 'INT16', + UINT16: 'UINT16', + INT32: 'INT32', + UINT32: 'UINT32', + FLOAT: 'FLOAT', + DOUBLE: 'DOUBLE', + BOOLEAN: 'BOOLEAN', + STRING: 'STRING' +} as const + +/** Modbus 原始数据类型选项 */ +export const ModbusRawDataTypeOptions = [ + { value: 'INT16', label: 'INT16', description: '有符号16位整数', registerCount: 1 }, + { value: 'UINT16', label: 'UINT16', description: '无符号16位整数', registerCount: 1 }, + { value: 'INT32', label: 'INT32', description: '有符号32位整数', registerCount: 2 }, + { value: 'UINT32', label: 'UINT32', description: '无符号32位整数', registerCount: 2 }, + { value: 'FLOAT', label: 'FLOAT', description: '32位浮点数', registerCount: 2 }, + { value: 'DOUBLE', label: 'DOUBLE', description: '64位浮点数', registerCount: 4 }, + { value: 'BOOLEAN', label: 'BOOLEAN', description: '布尔值', registerCount: 1 }, + { value: 'STRING', label: 'STRING', description: '字符串', registerCount: 0 } +] + +/** Modbus 字节序选项 - 16位 */ +export const ModbusByteOrder16Options = [ + { value: 'AB', label: 'AB', description: '大端序' }, + { value: 'BA', label: 'BA', description: '小端序' } +] + +/** Modbus 字节序选项 - 32位 */ +export const ModbusByteOrder32Options = [ + { value: 'ABCD', label: 'ABCD', description: '大端序' }, + { value: 'CDAB', label: 'CDAB', description: '大端字交换' }, + { value: 'DCBA', label: 'DCBA', description: '小端序' }, + { value: 'BADC', label: 'BADC', description: '小端字交换' } +] + +/** 根据数据类型获取字节序选项 */ +export const getByteOrderOptions = (rawDataType: string) => { + if (['INT32', 'UINT32', 'FLOAT'].includes(rawDataType)) { + return ModbusByteOrder32Options + } + if (rawDataType === 'DOUBLE') { + // 64位暂时复用32位字节序 + return ModbusByteOrder32Options + } + return ModbusByteOrder16Options +} From 56a25258ee7f29935173716b7a2c95e59f7f3e01 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Jan 2026 23:34:43 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat=EF=BC=9A=E3=80=90iot=E3=80=91modbus-tc?= =?UTF-8?q?p=20=E5=8D=8F=E8=AE=AE=E6=8E=A5=E5=85=A5=2040%=EF=BC=9A?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E8=A1=A8=E5=8D=95=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=EF=BC=8C=E5=9F=BA=E4=BA=8E=20dreamy-stirring?= =?UTF-8?q?-kazoo.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../device/detail/DeviceModbusConfig.vue | 40 ++-- .../device/detail/DeviceModbusConfigForm.vue | 43 ++-- .../device/detail/DeviceModbusPointForm.vue | 200 +++++++----------- 3 files changed, 113 insertions(+), 170 deletions(-) diff --git a/src/views/iot/device/device/detail/DeviceModbusConfig.vue b/src/views/iot/device/device/detail/DeviceModbusConfig.vue index d380fb2dc..67fea1c28 100644 --- a/src/views/iot/device/device/detail/DeviceModbusConfig.vue +++ b/src/views/iot/device/device/detail/DeviceModbusConfig.vue @@ -39,6 +39,7 @@ 点位配置 + 新增点位 @@ -106,16 +107,16 @@ @@ -149,6 +150,7 @@ import { ThingModelData } from '@/api/iot/thingmodel' import { DeviceModbusConfigApi, DeviceModbusConfigVO } from '@/api/iot/device/modbus/config' import { DeviceModbusPointApi, DeviceModbusPointVO } from '@/api/iot/device/modbus/point' import { ModbusFunctionCodeOptions } from '@/views/iot/utils/constants' +import { DICT_TYPE } from '@/utils/dict' import DeviceModbusConfigForm from './DeviceModbusConfigForm.vue' import DeviceModbusPointForm from './DeviceModbusPointForm.vue' @@ -163,16 +165,7 @@ const props = defineProps<{ const message = useMessage() // ======================= 连接配置 ======================= -// TODO @AI:默认应该都是空的 -const modbusConfig = ref({ - deviceId: props.device.id, - ip: '', - port: 502, - slaveId: 1, - timeout: 3000, - retryInterval: 1000, - status: 0 // TODO @AI:使用 CommonStatus; -}) +const modbusConfig = ref({} as DeviceModbusConfigVO) /** 获取连接配置 */ const getModbusConfig = async () => { @@ -245,13 +238,16 @@ const handleEditPoint = (row: DeviceModbusPointVO) => { } /** 删除点位 */ -const handleDeletePoint = async (id: number) => { - // TODO @AI:最好点位的名字带上。参考别的模块; - // TODO @AI:参考别的注释。 - await message.confirm('确定要删除该点位配置吗?') - await DeviceModbusPointApi.deleteModbusPoint(id) - message.success('删除成功') - await getPointPage() +const handleDeletePoint = async (id: number, name: string) => { + try { + // 删除的二次确认 + await message.delConfirm('确定要删除点位【' + name + '】吗?') + // 发起删除 + await DeviceModbusPointApi.deleteModbusPoint(id) + message.success('删除成功') + // 刷新列表 + await getPointPage() + } catch {} } /** 初始化 */ diff --git a/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue b/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue index 0e9572a60..cb17230e0 100644 --- a/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue +++ b/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue @@ -11,9 +11,10 @@ - + - - + - -
单位:毫秒
-
- + - -
单位:毫秒
-
- + @@ -74,6 +69,7 @@ From 972eb47610f25d70f436f29cdae656b9ecedc864 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 18 Jan 2026 00:07:23 +0800 Subject: [PATCH 3/7] =?UTF-8?q?feat=EF=BC=9A=E3=80=90iot=E3=80=91modbus-tc?= =?UTF-8?q?p=20=E5=8D=8F=E8=AE=AE=E6=8E=A5=E5=85=A5=20100%=EF=BC=9A?= =?UTF-8?q?=E5=AE=8C=E6=95=B4=E5=AE=9E=E7=8E=B0=EF=BC=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20todo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/iot/device/modbus/point/index.ts | 12 +-- .../device/detail/DeviceModbusConfig.vue | 28 ++++--- .../device/detail/DeviceModbusConfigForm.vue | 29 ++++--- .../device/detail/DeviceModbusPointForm.vue | 77 ++++++++++++------- 4 files changed, 87 insertions(+), 59 deletions(-) diff --git a/src/api/iot/device/modbus/point/index.ts b/src/api/iot/device/modbus/point/index.ts index 5dc05d1c1..0ae51bb94 100644 --- a/src/api/iot/device/modbus/point/index.ts +++ b/src/api/iot/device/modbus/point/index.ts @@ -4,14 +4,14 @@ import request from '@/config/axios' export interface DeviceModbusPointVO { id?: number // 主键 deviceId: number // 设备编号 - thingModelId: number // 物模型属性编号 + thingModelId?: number // 物模型属性编号 identifier: string // 属性标识符 name: string // 属性名称 - functionCode: number // Modbus 功能码 - registerAddress: number // 寄存器起始地址 - registerCount: number // 寄存器数量 - byteOrder: string // 字节序 - rawDataType: string // 原始数据类型 + functionCode?: number // Modbus 功能码 + registerAddress?: number // 寄存器起始地址 + registerCount?: number // 寄存器数量 + byteOrder?: string // 字节序 + rawDataType?: string // 原始数据类型 scale: number // 缩放因子 pollInterval: number // 轮询间隔,单位:毫秒 status: number // 状态 diff --git a/src/views/iot/device/device/detail/DeviceModbusConfig.vue b/src/views/iot/device/device/detail/DeviceModbusConfig.vue index 67fea1c28..f9682f040 100644 --- a/src/views/iot/device/device/detail/DeviceModbusConfig.vue +++ b/src/views/iot/device/device/detail/DeviceModbusConfig.vue @@ -5,7 +5,9 @@
连接配置 - 编辑 + + 编辑 +
@@ -26,9 +28,7 @@ {{ modbusConfig.retryInterval ? `${modbusConfig.retryInterval} ms` : '-' }} - - {{ modbusConfig.status === 0 ? '启用' : '禁用' }} - +
@@ -37,9 +37,8 @@
点位配置 - + - 新增点位
@@ -112,9 +111,20 @@ diff --git a/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue b/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue index cb17230e0..b59a7b507 100644 --- a/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue +++ b/src/views/iot/device/device/detail/DeviceModbusConfigForm.vue @@ -1,6 +1,6 @@