From de28c5c4c27b59057b980f7ada2f90d523d5830d Mon Sep 17 00:00:00 2001 From: haohao <1036606149@qq.com> Date: Sun, 4 Jan 2026 12:25:25 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=E3=80=90antd=E3=80=91=E3=80=90iot?= =?UTF-8?q?=E3=80=91=E8=AE=BE=E5=A4=87=E7=AE=A1=E7=90=86=E8=B7=9F=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E5=AF=B9=E9=BD=90=EF=BC=8C=E5=BF=85=E8=A6=81=E7=9A=84?= =?UTF-8?q?=20ReqVO=E3=80=81RespVO=EF=BC=8C=E5=AD=90=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/iot/device/device/index.ts | 151 ++++++----- .../src/views/iot/device/device/data.ts | 33 ++- .../views/iot/device/device/detail/index.vue | 2 +- .../device/device/detail/modules/config.vue | 4 +- .../device/device/detail/modules/header.vue | 4 +- .../iot/device/device/detail/modules/info.vue | 15 +- .../device/detail/modules/simulator.vue | 2 +- .../device/detail/modules/sub-device.vue | 234 +++++++++++++++--- .../src/views/iot/device/device/index.vue | 51 ++-- .../iot/device/device/modules/card-view.vue | 49 +++- .../views/iot/device/device/modules/form.vue | 103 +++++++- .../iot/device/device/modules/group-form.vue | 4 +- .../iot/device/device/modules/import-form.vue | 3 +- .../iot/ota/modules/task/ota-task-form.vue | 4 +- .../src/views/iot/product/product/data.ts | 9 + .../iot/product/product/modules/card-view.vue | 10 + 16 files changed, 537 insertions(+), 141 deletions(-) diff --git a/apps/web-antd/src/api/iot/device/device/index.ts b/apps/web-antd/src/api/iot/device/device/index.ts index a0d4659b0..ce3456252 100644 --- a/apps/web-antd/src/api/iot/device/device/index.ts +++ b/apps/web-antd/src/api/iot/device/device/index.ts @@ -3,39 +3,76 @@ import type { PageParam, PageResult } from '@vben/request'; import { requestClient } from '#/api/request'; export namespace IotDeviceApi { - // TODO @haohao:需要跟后端对齐,必要的 ReqVO、RespVO - /** 设备 */ - export interface Device { - id?: number; // 设备 ID,主键,自增 + /** 设备新增/修改 Request VO */ + export interface DeviceSaveReqVO { + id?: number; // 设备编号 deviceName: string; // 设备名称 + nickname?: string; // 备注名称 + serialNumber?: string; // 设备序列号 + picUrl?: string; // 设备图片 + groupIds?: number[]; // 设备分组编号数组 + productId: number; // 产品编号(必填) + gatewayId?: number; // 网关设备 ID + config?: string; // 设备配置 + locationType: number; // 定位类型(必填) + latitude?: number; // 设备位置的纬度 + longitude?: number; // 设备位置的经度 + } + + /** 设备更新分组 Request VO */ + export interface DeviceUpdateGroupReqVO { + ids: number[]; // 设备编号列表(必填) + groupIds: number[]; // 分组编号列表(必填) + } + + /** 设备分页 Request VO */ + export interface DevicePageReqVO extends PageParam { + deviceName?: string; // 设备名称 + nickname?: string; // 备注名称 + productId?: number; // 产品编号 + deviceType?: number; // 设备类型 + status?: number; // 设备状态 + groupId?: number; // 设备分组编号 + gatewayId?: number; // 网关设备 ID + } + + /** 设备 Response VO */ + export interface DeviceRespVO { + id: number; // 设备编号 + deviceName: string; // 设备名称 + nickname?: string; // 设备备注名称 + serialNumber?: string; // 设备序列号 + picUrl?: string; // 设备图片 + groupIds?: number[]; // 设备分组编号数组 productId: number; // 产品编号 productKey?: string; // 产品标识 deviceType?: number; // 设备类型 - nickname?: string; // 设备备注名称 gatewayId?: number; // 网关设备 ID state?: number; // 设备状态 - status?: number; // 设备状态(兼容字段) onlineTime?: Date; // 最后上线时间 offlineTime?: Date; // 最后离线时间 activeTime?: Date; // 设备激活时间 - createTime?: Date; // 创建时间 - ip?: string; // 设备的 IP 地址 - firmwareVersion?: string; // 设备的固件版本 - deviceSecret?: string; // 设备密钥,用于设备认证,需安全存储 - mqttClientId?: string; // MQTT 客户端 ID - mqttUsername?: string; // MQTT 用户名 - mqttPassword?: string; // MQTT 密码 - authType?: string; // 认证类型 - locationType?: number; // 定位类型 + deviceSecret?: string; // 设备密钥,用于设备认证 + authType?: string; // 认证类型(如一机一密、动态注册) + config?: string; // 设备配置 + locationType?: number; // 定位方式 latitude?: number; // 设备位置的纬度 longitude?: number; // 设备位置的经度 - areaId?: number; // 地区编码 - address?: string; // 设备详细地址 - serialNumber?: string; // 设备序列号 - config?: string; // 设备配置 - groupIds?: number[]; // 添加分组 ID - picUrl?: string; // 设备图片 - location?: string; // 位置信息(格式:经度,纬度) + createTime?: Date; // 创建时间 + } + + /** 设备认证信息 Response VO */ + export interface DeviceAuthInfoRespVO { + clientId: string; // 客户端 ID + username: string; // 用户名 + password: string; // 密码 + } + + /** 设备导入 Response VO */ + export interface DeviceImportRespVO { + createDeviceNames?: string[]; // 创建成功的设备名称列表 + updateDeviceNames?: string[]; // 更新成功的设备名称列表 + failureDeviceNames?: Record; // 失败的设备名称及原因 } /** IoT 设备属性详细 VO */ @@ -56,30 +93,17 @@ export namespace IotDeviceApi { updateTime: Date; // 更新时间 } - /** 设备认证参数 VO */ - export interface DeviceAuthInfo { - clientId: string; // 客户端 ID - username: string; // 用户名 - password: string; // 密码 - } - /** 设备发送消息 Request VO */ export interface DeviceMessageSendReq { deviceId: number; // 设备编号 method: string; // 请求方法 params?: any; // 请求参数 } - - /** 设备分组更新请求 */ - export interface DeviceGroupUpdateReq { - ids: number[]; // 设备 ID 列表 - groupIds: number[]; // 分组 ID 列表 - } } /** 查询设备分页 */ -export function getDevicePage(params: PageParam) { - return requestClient.get>( +export function getDevicePage(params: IotDeviceApi.DevicePageReqVO) { + return requestClient.get>( '/iot/device/page', { params }, ); @@ -87,38 +111,40 @@ export function getDevicePage(params: PageParam) { /** 查询设备详情 */ export function getDevice(id: number) { - return requestClient.get(`/iot/device/get?id=${id}`); + return requestClient.get( + `/iot/device/get?id=${id}`, + ); } /** 新增设备 */ -export function createDevice(data: IotDeviceApi.Device) { - return requestClient.post('/iot/device/create', data); +export function createDevice(data: IotDeviceApi.DeviceSaveReqVO) { + return requestClient.post('/iot/device/create', data); } /** 修改设备 */ -export function updateDevice(data: IotDeviceApi.Device) { - return requestClient.put('/iot/device/update', data); +export function updateDevice(data: IotDeviceApi.DeviceSaveReqVO) { + return requestClient.put('/iot/device/update', data); } /** 修改设备分组 */ -export function updateDeviceGroup(data: IotDeviceApi.DeviceGroupUpdateReq) { - return requestClient.put('/iot/device/update-group', data); +export function updateDeviceGroup(data: IotDeviceApi.DeviceUpdateGroupReqVO) { + return requestClient.put('/iot/device/update-group', data); } /** 删除单个设备 */ export function deleteDevice(id: number) { - return requestClient.delete(`/iot/device/delete?id=${id}`); + return requestClient.delete(`/iot/device/delete?id=${id}`); } /** 删除多个设备 */ export function deleteDeviceList(ids: number[]) { - return requestClient.delete('/iot/device/delete-list', { + return requestClient.delete('/iot/device/delete-list', { params: { ids: ids.join(',') }, }); } /** 导出设备 */ -export function exportDeviceExcel(params: any) { +export function exportDeviceExcel(params: IotDeviceApi.DevicePageReqVO) { return requestClient.download('/iot/device/export-excel', { params }); } @@ -129,16 +155,22 @@ export function getDeviceCount(productId: number) { /** 获取设备的精简信息列表 */ export function getSimpleDeviceList(deviceType?: number, productId?: number) { - return requestClient.get('/iot/device/simple-list', { - params: { deviceType, productId }, - }); + return requestClient.get( + '/iot/device/simple-list', + { + params: { deviceType, productId }, + }, + ); } /** 根据产品编号,获取设备的精简信息列表 */ export function getDeviceListByProductId(productId: number) { - return requestClient.get('/iot/device/simple-list', { - params: { productId }, - }); + return requestClient.get( + '/iot/device/simple-list', + { + params: { productId }, + }, + ); } /** 获取导入模板 */ @@ -148,10 +180,13 @@ export function importDeviceTemplate() { /** 导入设备 */ export function importDevice(file: File, updateSupport: boolean) { - return requestClient.upload('/iot/device/import', { - file, - updateSupport, - }); + return requestClient.upload( + '/iot/device/import', + { + file, + updateSupport, + }, + ); } /** 获取设备属性最新数据 */ @@ -172,7 +207,7 @@ export function getHistoryDevicePropertyList(params: any) { /** 获取设备认证信息 */ export function getDeviceAuthInfo(id: number) { - return requestClient.get( + return requestClient.get( '/iot/device/get-auth-info', { params: { id } }, ); 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 9360c8cdd..70a562449 100644 --- a/apps/web-antd/src/views/iot/device/device/data.ts +++ b/apps/web-antd/src/views/iot/device/device/data.ts @@ -9,8 +9,8 @@ import { getSimpleDeviceList } from '#/api/iot/device/device'; import { getSimpleDeviceGroupList } from '#/api/iot/device/group'; import { getSimpleProductList } from '#/api/iot/product/product'; -/** 新增/修改的表单 */ -export function useFormSchema(): VbenFormSchema[] { +/** 基础表单字段 */ +export function useBasicFormSchema(): VbenFormSchema[] { return [ { component: 'Input', @@ -36,6 +36,14 @@ export function useFormSchema(): VbenFormSchema[] { }, rules: 'required', }, + { + component: 'Input', + fieldName: 'deviceType', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, { fieldName: 'deviceName', label: 'DeviceName', @@ -62,7 +70,7 @@ export function useFormSchema(): VbenFormSchema[] { component: 'ApiSelect', componentProps: { api: () => getSimpleDeviceList(DeviceTypeEnum.GATEWAY), - labelField: 'nickname', + labelField: 'deviceName', valueField: 'id', placeholder: '子设备可选择父设备', }, @@ -71,6 +79,12 @@ export function useFormSchema(): VbenFormSchema[] { show: (values) => values.deviceType === DeviceTypeEnum.GATEWAY_SUB, }, }, + ]; +} + +/** 高级设置表单字段(更多设置) */ +export function useAdvancedFormSchema(): VbenFormSchema[] { + return [ { fieldName: 'nickname', label: '备注名称', @@ -89,6 +103,11 @@ export function useFormSchema(): VbenFormSchema[] { .optional() .or(z.literal('')), }, + { + fieldName: 'picUrl', + label: '设备图片', + component: 'ImageUpload', + }, { fieldName: 'groupIds', label: '设备分组', @@ -278,6 +297,14 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { title: '备注名称', minWidth: 120, }, + { + field: 'picUrl', + title: '设备图片', + width: 100, + cellRender: { + name: 'CellImage', + }, + }, { field: 'productId', title: '所属产品', diff --git a/apps/web-antd/src/views/iot/device/device/detail/index.vue b/apps/web-antd/src/views/iot/device/device/detail/index.vue index 4b549a363..4ba957410 100644 --- a/apps/web-antd/src/views/iot/device/device/detail/index.vue +++ b/apps/web-antd/src/views/iot/device/device/detail/index.vue @@ -31,7 +31,7 @@ const router = useRouter(); const id = Number(route.params.id); const loading = ref(true); const product = ref({} as IotProductApi.Product); -const device = ref({} as IotDeviceApi.Device); +const device = ref({} as IotDeviceApi.DeviceRespVO); const activeTab = ref('info'); const thingModelList = ref([]); diff --git a/apps/web-antd/src/views/iot/device/device/detail/modules/config.vue b/apps/web-antd/src/views/iot/device/device/detail/modules/config.vue index 072a1ff77..72ad3a463 100644 --- a/apps/web-antd/src/views/iot/device/device/detail/modules/config.vue +++ b/apps/web-antd/src/views/iot/device/device/detail/modules/config.vue @@ -12,7 +12,7 @@ import { IotDeviceMessageMethodEnum } from '#/views/iot/utils/constants'; defineOptions({ name: 'DeviceDetailConfig' }); const props = defineProps<{ - device: IotDeviceApi.Device; + device: IotDeviceApi.DeviceRespVO; }>(); const emit = defineEmits<{ @@ -114,7 +114,7 @@ async function updateDeviceConfig() { await updateDevice({ id: props.device.id, config: JSON.stringify(config.value), - } as IotDeviceApi.Device); + } as IotDeviceApi.DeviceSaveReqVO); message.success({ content: '更新成功!' }); // 触发 success 事件 emit('success'); diff --git a/apps/web-antd/src/views/iot/device/device/detail/modules/header.vue b/apps/web-antd/src/views/iot/device/device/detail/modules/header.vue index 8a739a180..1cc42b791 100644 --- a/apps/web-antd/src/views/iot/device/device/detail/modules/header.vue +++ b/apps/web-antd/src/views/iot/device/device/detail/modules/header.vue @@ -12,7 +12,7 @@ import DeviceForm from '../../modules/form.vue'; interface Props { product: IotProductApi.Product; - device: IotDeviceApi.Device; + device: IotDeviceApi.DeviceRespVO; loading?: boolean; } @@ -50,7 +50,7 @@ function goToProductDetail(productId: number | undefined) { } /** 打开编辑表单 */ -function openEditForm(row: IotDeviceApi.Device) { +function openEditForm(row: IotDeviceApi.DeviceRespVO) { formModalApi.setData(row).open(); } 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 71a15301a..d1f5d66b7 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 @@ -24,7 +24,7 @@ import { getDeviceAuthInfo } from '#/api/iot/device/device'; import { DictTag } from '#/components/dict-tag'; interface Props { - device: IotDeviceApi.Device; + device: IotDeviceApi.DeviceRespVO; product: IotProductApi.Product; } @@ -32,8 +32,8 @@ const props = defineProps(); const authDialogVisible = ref(false); const authPasswordVisible = ref(false); -const authInfo = ref( - {} as IotDeviceApi.DeviceAuthInfo, +const authInfo = ref( + {} as IotDeviceApi.DeviceAuthInfoRespVO, ); /** 控制地图显示的标志 */ @@ -75,8 +75,7 @@ function handleAuthInfoDialogClose() { @@ -142,8 +141,7 @@ function handleAuthInfoDialogClose() {