refactor:【antd】【iot】将 DeviceSaveReqVO 和 DeviceRespVO 合并到 Device,简化设备 API 接口

This commit is contained in:
haohao
2026-01-16 17:38:02 +08:00
committed by xingyu
parent 63265c1a6b
commit ce2bfa5cd2
11 changed files with 114 additions and 171 deletions

View File

@@ -3,49 +3,14 @@ import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request'; import { requestClient } from '#/api/request';
export namespace IotDeviceApi { export namespace IotDeviceApi {
/** 设备新增/修改 Request VO */ /** 设备 */
// TODO @haohao可以降低一些 VO 哈DeviceSaveReqVO、DeviceRespVO 合并成 Device 就好,类似别的模块 export interface Device {
export interface DeviceSaveReqVO {
id?: number; // 设备编号 id?: number; // 设备编号
deviceName: string; // 设备名称 deviceName: string; // 设备名称
nickname?: string; // 备注名称 nickname?: string; // 备注名称
serialNumber?: string; // 设备序列号 serialNumber?: string; // 设备序列号
picUrl?: string; // 设备图片 picUrl?: string; // 设备图片
groupIds?: number[]; // 设备分组编号数组 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 */
// TODO @haohao可以不用 DevicePageReqVO直接 PageParam 即可,简洁一点。这里的强类型,收益不大;
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; // 产品编号 productId: number; // 产品编号
productKey?: string; // 产品标识 productKey?: string; // 产品标识
deviceType?: number; // 设备类型 deviceType?: number; // 设备类型
@@ -57,12 +22,18 @@ export namespace IotDeviceApi {
deviceSecret?: string; // 设备密钥,用于设备认证 deviceSecret?: string; // 设备密钥,用于设备认证
authType?: string; // 认证类型(如一机一密、动态注册) authType?: string; // 认证类型(如一机一密、动态注册)
config?: string; // 设备配置 config?: string; // 设备配置
locationType?: number; // 定位方式 locationType?: number; // 定位类型
latitude?: number; // 设备位置的纬度 latitude?: number; // 设备位置的纬度
longitude?: number; // 设备位置的经度 longitude?: number; // 设备位置的经度
createTime?: Date; // 创建时间 createTime?: Date; // 创建时间
} }
/** 设备更新分组 Request VO */
export interface DeviceUpdateGroupReqVO {
ids: number[]; // 设备编号列表(必填)
groupIds: number[]; // 分组编号列表(必填)
}
/** 设备认证信息 Response VO */ /** 设备认证信息 Response VO */
export interface DeviceAuthInfoRespVO { export interface DeviceAuthInfoRespVO {
clientId: string; // 客户端 ID clientId: string; // 客户端 ID
@@ -104,8 +75,8 @@ export namespace IotDeviceApi {
} }
/** 查询设备分页 */ /** 查询设备分页 */
export function getDevicePage(params: IotDeviceApi.DevicePageReqVO) { export function getDevicePage(params: PageParam) {
return requestClient.get<PageResult<IotDeviceApi.DeviceRespVO>>( return requestClient.get<PageResult<IotDeviceApi.Device>>(
'/iot/device/page', '/iot/device/page',
{ params }, { params },
); );
@@ -113,18 +84,16 @@ export function getDevicePage(params: IotDeviceApi.DevicePageReqVO) {
/** 查询设备详情 */ /** 查询设备详情 */
export function getDevice(id: number) { export function getDevice(id: number) {
return requestClient.get<IotDeviceApi.DeviceRespVO>( return requestClient.get<IotDeviceApi.Device>(`/iot/device/get?id=${id}`);
`/iot/device/get?id=${id}`,
);
} }
/** 新增设备 */ /** 新增设备 */
export function createDevice(data: IotDeviceApi.DeviceSaveReqVO) { export function createDevice(data: IotDeviceApi.Device) {
return requestClient.post<number>('/iot/device/create', data); return requestClient.post<number>('/iot/device/create', data);
} }
/** 修改设备 */ /** 修改设备 */
export function updateDevice(data: IotDeviceApi.DeviceSaveReqVO) { export function updateDevice(data: IotDeviceApi.Device) {
return requestClient.put<boolean>('/iot/device/update', data); return requestClient.put<boolean>('/iot/device/update', data);
} }
@@ -146,7 +115,7 @@ export function deleteDeviceList(ids: number[]) {
} }
/** 导出设备 */ /** 导出设备 */
export function exportDeviceExcel(params: IotDeviceApi.DevicePageReqVO) { export function exportDeviceExcel(params: PageParam) {
return requestClient.download('/iot/device/export-excel', { params }); return requestClient.download('/iot/device/export-excel', { params });
} }
@@ -157,22 +126,16 @@ export function getDeviceCount(productId: number) {
/** 获取设备的精简信息列表 */ /** 获取设备的精简信息列表 */
export function getSimpleDeviceList(deviceType?: number, productId?: number) { export function getSimpleDeviceList(deviceType?: number, productId?: number) {
return requestClient.get<IotDeviceApi.DeviceRespVO[]>( return requestClient.get<IotDeviceApi.Device[]>('/iot/device/simple-list', {
'/iot/device/simple-list', params: { deviceType, productId },
{ });
params: { deviceType, productId },
},
);
} }
/** 根据产品编号,获取设备的精简信息列表 */ /** 根据产品编号,获取设备的精简信息列表 */
export function getDeviceListByProductId(productId: number) { export function getDeviceListByProductId(productId: number) {
return requestClient.get<IotDeviceApi.DeviceRespVO[]>( return requestClient.get<IotDeviceApi.Device[]>('/iot/device/simple-list', {
'/iot/device/simple-list', params: { productId },
{ });
params: { productId },
},
);
} }
/** 获取导入模板 */ /** 获取导入模板 */

View File

@@ -31,7 +31,7 @@ const router = useRouter();
const id = Number(route.params.id); const id = Number(route.params.id);
const loading = ref(true); const loading = ref(true);
const product = ref<IotProductApi.Product>({} as IotProductApi.Product); const product = ref<IotProductApi.Product>({} as IotProductApi.Product);
const device = ref<IotDeviceApi.DeviceRespVO>({} as IotDeviceApi.DeviceRespVO); const device = ref<IotDeviceApi.Device>({} as IotDeviceApi.Device);
const activeTab = ref('info'); const activeTab = ref('info');
const thingModelList = ref<ThingModelData[]>([]); const thingModelList = ref<ThingModelData[]>([]);

View File

@@ -12,7 +12,7 @@ import { IotDeviceMessageMethodEnum } from '#/views/iot/utils/constants';
defineOptions({ name: 'DeviceDetailConfig' }); defineOptions({ name: 'DeviceDetailConfig' });
const props = defineProps<{ const props = defineProps<{
device: IotDeviceApi.DeviceRespVO; device: IotDeviceApi.Device;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
@@ -114,7 +114,7 @@ async function updateDeviceConfig() {
await updateDevice({ await updateDevice({
id: props.device.id, id: props.device.id,
config: JSON.stringify(config.value), config: JSON.stringify(config.value),
} as IotDeviceApi.DeviceSaveReqVO); } as IotDeviceApi.Device);
message.success({ content: '更新成功!' }); message.success({ content: '更新成功!' });
// 触发 success 事件 // 触发 success 事件
emit('success'); emit('success');

View File

@@ -12,7 +12,7 @@ import DeviceForm from '../../modules/form.vue';
interface Props { interface Props {
product: IotProductApi.Product; product: IotProductApi.Product;
device: IotDeviceApi.DeviceRespVO; device: IotDeviceApi.Device;
loading?: boolean; loading?: boolean;
} }
@@ -50,7 +50,7 @@ function goToProductDetail(productId: number | undefined) {
} }
/** 打开编辑表单 */ /** 打开编辑表单 */
function openEditForm(row: IotDeviceApi.DeviceRespVO) { function openEditForm(row: IotDeviceApi.Device) {
formModalApi.setData(row).open(); formModalApi.setData(row).open();
} }
</script> </script>

View File

@@ -24,7 +24,7 @@ import { getDeviceAuthInfo } from '#/api/iot/device/device';
import { DictTag } from '#/components/dict-tag'; import { DictTag } from '#/components/dict-tag';
interface Props { interface Props {
device: IotDeviceApi.DeviceRespVO; device: IotDeviceApi.Device;
product: IotProductApi.Product; product: IotProductApi.Product;
} }

View File

@@ -34,7 +34,7 @@ import DataDefinition from '../../../../thingmodel/modules/components/data-defin
import DeviceDetailsMessage from './message.vue'; import DeviceDetailsMessage from './message.vue';
const props = defineProps<{ const props = defineProps<{
device: IotDeviceApi.DeviceRespVO; device: IotDeviceApi.Device;
product: IotProductApi.Product; product: IotProductApi.Product;
thingModelList: ThingModelData[]; thingModelList: ThingModelData[];
}>(); }>();

View File

@@ -1,17 +1,17 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { PageParam } from '@vben/request';
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { IotDeviceApi } from '#/api/iot/device/device'; import type { IotDeviceApi } from '#/api/iot/device/device';
import type { IotProductApi } from '#/api/iot/product/product'; import type { IotProductApi } from '#/api/iot/product/product';
import { onMounted, reactive, ref, watch } from 'vue'; import { onMounted, ref, watch } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { DeviceTypeEnum, DICT_TYPE } from '@vben/constants'; import { DeviceTypeEnum, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks'; import { getDictOptions } from '@vben/hooks';
import { IconifyIcon } from '@vben/icons';
import { Button, Input, Select, Space } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getDevicePage } from '#/api/iot/device/device'; import { getDevicePage } from '#/api/iot/device/device';
@@ -25,10 +25,6 @@ const props = defineProps<Props>();
const router = useRouter(); const router = useRouter();
const products = ref<IotProductApi.Product[]>([]); // 产品列表 const products = ref<IotProductApi.Product[]>([]); // 产品列表
const queryParams = reactive({
deviceName: '',
status: undefined as number | undefined,
}); // 查询参数
function useGridColumns(): VxeTableGridOptions['columns'] { function useGridColumns(): VxeTableGridOptions['columns'] {
return [ return [
@@ -72,7 +68,35 @@ function useGridColumns(): VxeTableGridOptions['columns'] {
]; ];
} }
const [Grid, gridApi] = useVbenVxeGrid<IotDeviceApi.DeviceRespVO>({ /** 搜索表单 schema */
function useGridFormSchema(): VbenFormSchema[] {
return [
{
fieldName: 'deviceName',
label: 'DeviceName',
component: 'Input',
componentProps: {
placeholder: '请输入 DeviceName',
allowClear: true,
},
},
{
fieldName: 'status',
label: '设备状态',
component: 'Select',
componentProps: {
options: getDictOptions(DICT_TYPE.IOT_DEVICE_STATE, 'number'),
placeholder: '请选择设备状态',
allowClear: true,
},
},
];
}
const [Grid, gridApi] = useVbenVxeGrid<IotDeviceApi.Device>({
formOptions: {
schema: useGridFormSchema(),
},
gridOptions: { gridOptions: {
columns: useGridColumns(), columns: useGridColumns(),
height: 'auto', height: 'auto',
@@ -82,11 +106,14 @@ const [Grid, gridApi] = useVbenVxeGrid<IotDeviceApi.DeviceRespVO>({
}, },
proxyConfig: { proxyConfig: {
ajax: { ajax: {
query: async ({ query: async (
page, {
}: { page,
page: { currentPage: number; pageSize: number }; }: {
}) => { page: { currentPage: number; pageSize: number };
},
formValues?: { deviceName?: string; status?: number },
) => {
if (!props.deviceId) { if (!props.deviceId) {
return { list: [], total: 0 }; return { list: [], total: 0 };
} }
@@ -95,15 +122,15 @@ const [Grid, gridApi] = useVbenVxeGrid<IotDeviceApi.DeviceRespVO>({
pageSize: page.pageSize, pageSize: page.pageSize,
gatewayId: props.deviceId, gatewayId: props.deviceId,
deviceType: DeviceTypeEnum.GATEWAY_SUB, deviceType: DeviceTypeEnum.GATEWAY_SUB,
deviceName: queryParams.deviceName || undefined, deviceName: formValues?.deviceName || undefined,
status: queryParams.status, status: formValues?.status,
} as IotDeviceApi.DevicePageReqVO); } as PageParam);
}, },
}, },
}, },
toolbarConfig: { toolbarConfig: {
refresh: true, refresh: true,
search: false, search: true,
}, },
pagerConfig: { pagerConfig: {
enabled: true, enabled: true,
@@ -111,18 +138,6 @@ const [Grid, gridApi] = useVbenVxeGrid<IotDeviceApi.DeviceRespVO>({
}, },
}); });
/** 搜索操作 */
function handleQuery() {
gridApi.query();
}
/** 重置搜索 */
function resetQuery() {
queryParams.deviceName = '';
queryParams.status = undefined;
handleQuery();
}
/** 获取产品名称 */ /** 获取产品名称 */
function getProductName(productId: number) { function getProductName(productId: number) {
const product = products.value.find((p) => p.id === productId); const product = products.value.find((p) => p.id === productId);
@@ -139,7 +154,7 @@ watch(
() => props.deviceId, () => props.deviceId,
(newValue) => { (newValue) => {
if (newValue) { if (newValue) {
handleQuery(); gridApi.query();
} }
}, },
); );
@@ -151,49 +166,13 @@ onMounted(async () => {
// 如果设备ID存在则查询列表 // 如果设备ID存在则查询列表
if (props.deviceId) { if (props.deviceId) {
handleQuery(); gridApi.query();
} }
}); });
</script> </script>
<template> <template>
<Page auto-content-height> <Page auto-content-height>
<!-- 搜索区域 -->
<!-- TODO @haohao这个 search 能不能融合到 Grid -->
<div class="mb-4 flex flex-wrap items-center gap-3">
<Input
v-model:value="queryParams.deviceName"
placeholder="请输入设备名称"
style="width: 200px"
allow-clear
@press-enter="handleQuery"
/>
<Select
v-model:value="queryParams.status"
allow-clear
placeholder="请选择设备状态"
style="width: 160px"
>
<Select.Option
v-for="dict in getDictOptions(DICT_TYPE.IOT_DEVICE_STATE, 'number')"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</Select.Option>
</Select>
<Space>
<Button type="primary" @click="handleQuery">
<IconifyIcon icon="ep:search" class="mr-5px" />
搜索
</Button>
<Button @click="resetQuery">
<IconifyIcon icon="ep:refresh-right" class="mr-5px" />
重置
</Button>
</Space>
</div>
<!-- 子设备列表 --> <!-- 子设备列表 -->
<Grid> <Grid>
<template #product="{ row }"> <template #product="{ row }">

View File

@@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { PageParam } from '@vben/request';
import type { IotDeviceApi } from '#/api/iot/device/device'; import type { IotDeviceApi } from '#/api/iot/device/device';
import type { IotDeviceGroupApi } from '#/api/iot/device/group'; import type { IotDeviceGroupApi } from '#/api/iot/device/group';
import type { IotProductApi } from '#/api/iot/product/product'; import type { IotProductApi } from '#/api/iot/product/product';
@@ -68,7 +70,7 @@ const [DeviceImportFormModal, deviceImportFormModalApi] = useVbenModal({
destroyOnClose: true, destroyOnClose: true,
}); });
const queryParams = ref<Partial<IotDeviceApi.DevicePageReqVO>>({ const queryParams = ref<Partial<PageParam>>({
deviceName: '', deviceName: '',
nickname: '', nickname: '',
productId: undefined, productId: undefined,
@@ -118,7 +120,7 @@ async function handleExport() {
...queryParams.value, ...queryParams.value,
pageNo: 1, pageNo: 1,
pageSize: 999_999, pageSize: 999_999,
} as IotDeviceApi.DevicePageReqVO); } as PageParam);
downloadFileFromBlobPart({ fileName: '物联网设备.xls', source: data }); downloadFileFromBlobPart({ fileName: '物联网设备.xls', source: data });
} }
@@ -147,12 +149,12 @@ function handleCreate() {
} }
/** 编辑设备 */ /** 编辑设备 */
function handleEdit(row: IotDeviceApi.DeviceRespVO) { function handleEdit(row: IotDeviceApi.Device) {
deviceFormModalApi.setData(row).open(); deviceFormModalApi.setData(row).open();
} }
/** 删除设备 */ /** 删除设备 */
async function handleDelete(row: IotDeviceApi.DeviceRespVO) { async function handleDelete(row: IotDeviceApi.Device) {
const hideLoading = message.loading({ const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.deviceName]), content: $t('ui.actionMessage.deleting', [row.deviceName]),
duration: 0, duration: 0,
@@ -203,12 +205,12 @@ function handleImport() {
function handleRowCheckboxChange({ function handleRowCheckboxChange({
records, records,
}: { }: {
records: IotDeviceApi.DeviceRespVO[]; records: IotDeviceApi.Device[];
}) { }) {
checkedIds.value = records.map((item) => item.id!); checkedIds.value = records.map((item) => item.id!);
} }
const [Grid, gridApi] = useVbenVxeGrid<IotDeviceApi.DeviceRespVO>({ const [Grid, gridApi] = useVbenVxeGrid<IotDeviceApi.Device>({
gridOptions: { gridOptions: {
checkboxConfig: { checkboxConfig: {
highlight: true, highlight: true,
@@ -228,7 +230,7 @@ const [Grid, gridApi] = useVbenVxeGrid<IotDeviceApi.DeviceRespVO>({
pageNo: page.currentPage, pageNo: page.currentPage,
pageSize: page.pageSize, pageSize: page.pageSize,
...queryParams.value, ...queryParams.value,
} as IotDeviceApi.DevicePageReqVO); } as PageParam);
}, },
}, },
}, },

View File

@@ -1,4 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { PageParam } from '@vben/request';
import type { IotDeviceApi } from '#/api/iot/device/device'; import type { IotDeviceApi } from '#/api/iot/device/device';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
@@ -46,9 +48,9 @@ const emit = defineEmits<{
}>(); }>();
const loading = ref(false); const loading = ref(false);
const list = ref<IotDeviceApi.DeviceRespVO[]>([]); const list = ref<IotDeviceApi.Device[]>([]);
const total = ref(0); const total = ref(0);
const queryParams = ref<Partial<IotDeviceApi.DevicePageReqVO>>({ const queryParams = ref<Partial<PageParam>>({
pageNo: 1, pageNo: 1,
pageSize: 12, pageSize: 12,
}); });
@@ -66,7 +68,7 @@ async function getList() {
const data = await getDevicePage({ const data = await getDevicePage({
...queryParams.value, ...queryParams.value,
...props.searchParams, ...props.searchParams,
} as IotDeviceApi.DevicePageReqVO); } as PageParam);
list.value = data.list || []; list.value = data.list || [];
total.value = data.total || 0; total.value = data.total || 0;
} finally { } finally {
@@ -192,7 +194,7 @@ onMounted(() => {
<Button <Button
size="small" size="small"
class="action-btn action-btn-detail" class="action-btn action-btn-detail"
@click="emit('detail', item.id)" @click="emit('detail', item.id!)"
> >
<IconifyIcon icon="lucide:eye" class="mr-1" /> <IconifyIcon icon="lucide:eye" class="mr-1" />
详情 详情
@@ -200,7 +202,7 @@ onMounted(() => {
<Button <Button
size="small" size="small"
class="action-btn action-btn-data" class="action-btn action-btn-data"
@click="emit('model', item.id)" @click="emit('model', item.id!)"
> >
<IconifyIcon icon="lucide:database" class="mr-1" /> <IconifyIcon icon="lucide:database" class="mr-1" />
数据 数据

View File

@@ -2,7 +2,7 @@
import type { IotDeviceApi } from '#/api/iot/device/device'; import type { IotDeviceApi } from '#/api/iot/device/device';
import type { IotProductApi } from '#/api/iot/product/product'; import type { IotProductApi } from '#/api/iot/product/product';
import { computed, nextTick, onMounted, ref } from 'vue'; import { computed, nextTick, onMounted, ref, watch } from 'vue';
import { useVbenModal } from '@vben/common-ui'; import { useVbenModal } from '@vben/common-ui';
@@ -18,7 +18,7 @@ import { useAdvancedFormSchema, useBasicFormSchema } from '../data';
defineOptions({ name: 'IoTDeviceForm' }); defineOptions({ name: 'IoTDeviceForm' });
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
const formData = ref<IotDeviceApi.DeviceRespVO>(); const formData = ref<IotDeviceApi.Device>();
const products = ref<IotProductApi.Product[]>([]); const products = ref<IotProductApi.Product[]>([]);
const activeKey = ref<string[]>([]); const activeKey = ref<string[]>([]);
@@ -97,7 +97,7 @@ const [Modal, modalApi] = useVbenModal({
const data = { const data = {
...basicValues, ...basicValues,
...advancedValues, ...advancedValues,
} as IotDeviceApi.DeviceSaveReqVO; } as IotDeviceApi.Device;
try { try {
await (formData.value?.id ? updateDevice(data) : createDevice(data)); await (formData.value?.id ? updateDevice(data) : createDevice(data));
// 关闭并提示 // 关闭并提示
@@ -115,11 +115,8 @@ const [Modal, modalApi] = useVbenModal({
return; return;
} }
// 加载数据 // 加载数据
const data = modalApi.getData<IotDeviceApi.DeviceRespVO>(); const data = modalApi.getData<IotDeviceApi.Device>();
if (!data || !data.id) { if (!data || !data.id) {
// 新增:确保 Collapse 折叠
// TODO @haohao是不是 activeKey 在上面的 112 到 115 就已经处理了哈;
activeKey.value = [];
return; return;
} }
// 编辑模式:加载数据 // 编辑模式:加载数据
@@ -127,29 +124,29 @@ const [Modal, modalApi] = useVbenModal({
try { try {
formData.value = await getDevice(data.id); formData.value = await getDevice(data.id);
await formApi.setValues(formData.value); await formApi.setValues(formData.value);
// 如果存在高级字段数据,自动展开 Collapse
// TODO @haohao默认不用展开哈
if (
formData.value?.nickname ||
formData.value?.picUrl ||
formData.value?.groupIds?.length ||
formData.value?.serialNumber ||
formData.value?.locationType !== undefined
) {
activeKey.value = ['advanced'];
// 等待 Collapse 展开后表单挂载
await nextTick();
await nextTick();
if (advancedFormApi.isMounted) {
await advancedFormApi.setValues(formData.value);
}
}
} finally { } finally {
modalApi.unlock(); modalApi.unlock();
} }
}, },
}); });
/** 监听 Collapse 展开,自动设置高级表单的值 */
watch(
activeKey,
async (newKeys) => {
// 当用户手动展开 Collapse 且存在表单数据时,设置高级表单的值
if (newKeys.includes('advanced') && formData.value) {
// 等待表单挂载
await nextTick();
await nextTick();
if (advancedFormApi.isMounted) {
await advancedFormApi.setValues(formData.value);
}
}
},
{ immediate: false },
);
/** 初始化产品列表 */ /** 初始化产品列表 */
onMounted(async () => { onMounted(async () => {
products.value = await getSimpleProductList(); products.value = await getSimpleProductList();

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import type { DeviceRespVO, IotDeviceApi } from '#/api/iot/device/device'; import type { IotDeviceApi } from '#/api/iot/device/device';
import type { OtaTask } from '#/api/iot/ota/task'; import type { OtaTask } from '#/api/iot/ota/task';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
@@ -57,7 +57,7 @@ const formRules = {
}, },
], ],
}; };
const devices = ref<IotDeviceApi.DeviceRespVO[]>([]); const devices = ref<IotDeviceApi.Device[]>([]);
/** 设备选项 */ /** 设备选项 */
const deviceOptions = computed(() => { const deviceOptions = computed(() => {