Compare commits

..

2 Commits

Author SHA1 Message Date
ChenYi
9ef2ebd13a 修改 2025-12-18 22:05:55 +08:00
ChenYi
6e9791711a 完善设备端物模型界面 2025-12-18 17:14:47 +08:00
4 changed files with 320 additions and 22 deletions

View File

@ -0,0 +1,88 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { postDeviceThingModelManagementCommandPageAsync } from '#/api-client';
import { $t } from '#/locales';
defineOptions({
name: 'DeviceThingModelCommandModal',
});
const deviceThingModelId = ref<string>('');
const deviceModelName = ref<string>('');
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: [],
showDefaultActions: false,
},
gridOptions: {
columns: [
{
field: 'commandName',
title: '指令名称',
minWidth: 160,
showOverflow: 'tooltip',
},
{
field: 'identifier',
title: '标识符',
minWidth: 140,
showOverflow: 'tooltip',
},
{
field: 'action',
title: $t('common.action'),
width: 200,
fixed: 'right',
slots: { default: 'action' },
},
],
height: 400,
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }) => {
if (!deviceThingModelId.value) {
return { items: [], totalCount: 0 };
}
const { data } = await postDeviceThingModelManagementCommandPageAsync({
body: {
pageIndex: page.currentPage,
pageSize: page.pageSize,
deviceThingModelId: deviceThingModelId.value,
},
});
return data || { items: [], totalCount: 0 };
},
},
},
},
});
const [Modal, modalApi] = useVbenModal({
onOpenChange(isOpen: boolean) {
if (isOpen) {
const data = modalApi.getData<Record<string, any>>();
deviceThingModelId.value = data?.deviceThingModelId || '';
deviceModelName.value = data?.deviceModelName || '';
if (gridApi && gridApi.reload) {
gridApi.reload();
}
}
},
});
</script>
<template>
<Modal :title="`指令管理 - ${deviceModelName || ''}`" class="w-[900px]">
<Grid>
<!-- 这里后续可以加 toolbar-actions新增指令编辑删除等 -->
</Grid>
</Modal>
</template>

View File

@ -0,0 +1,94 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { postDeviceThingModelManagementPropertyPageAsync } from '#/api-client';
import { $t } from '#/locales';
defineOptions({
name: 'DeviceThingModelPropertyModal',
});
const deviceThingModelId = ref<string>('');
const deviceModelName = ref<string>('');
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: [],
showDefaultActions: false,
},
gridOptions: {
columns: [
{
field: 'propertyName',
title: '属性名称',
minWidth: 160,
showOverflow: 'tooltip',
},
{
field: 'identifier',
title: '标识符',
minWidth: 140,
showOverflow: 'tooltip',
},
{
field: 'dataType',
title: '数据类型',
minWidth: 120,
showOverflow: 'tooltip',
},
{
field: 'action',
title: $t('common.action'),
width: 200,
fixed: 'right',
slots: { default: 'action' },
},
],
height: 400,
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }) => {
if (!deviceThingModelId.value) {
return { items: [], totalCount: 0 };
}
const { data } = await postDeviceThingModelManagementPropertyPageAsync({
body: {
pageIndex: page.currentPage,
pageSize: page.pageSize,
deviceThingModelId: deviceThingModelId.value,
},
});
return data || { items: [], totalCount: 0 };
},
},
},
},
});
const [Modal, modalApi] = useVbenModal({
onOpenChange(isOpen: boolean) {
if (isOpen) {
const data = modalApi.getData<Record<string, any>>();
deviceThingModelId.value = data?.deviceThingModelId || '';
deviceModelName.value = data?.deviceModelName || '';
if (gridApi && gridApi.reload) {
gridApi.reload();
}
}
},
});
</script>
<template>
<Modal :title="`属性管理 - ${deviceModelName || ''}`" class="w-[900px]">
<Grid>
<!-- 这里后续可以加 toolbar-actions新增属性快速复制平台端物模型 -->
</Grid>
</Modal>
</template>

View File

@ -2,7 +2,7 @@
import type { VbenFormProps } from '#/adapter/form'; import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table'; import type { VxeGridProps } from '#/adapter/vxe-table';
import { h, nextTick, ref } from 'vue'; import { h, nextTick, onMounted, ref } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
@ -27,6 +27,9 @@ import {
tableSchema, tableSchema,
} from './schema'; } from './schema';
import DeviceThingModelPropertyModal from './DeviceThingModelPropertyModal.vue';
import DeviceThingModelCommandModal from './DeviceThingModelCommandModal.vue';
defineOptions({ defineOptions({
name: 'DeviceThingModelManagement', name: 'DeviceThingModelManagement',
}); });
@ -73,7 +76,9 @@ const formOptions: VbenFormProps = {
setTimeout(async () => { setTimeout(async () => {
if (gridApi && gridApi.reload) { if (gridApi && gridApi.reload) {
try { try {
await gridApi.reload(); // 使
const latestValues = await gridApi.formApi.getValues();
await gridApi.reload(latestValues);
} catch (error) { } catch (error) {
console.error('重新加载设备端物模型列表时出错:', error); console.error('重新加载设备端物模型列表时出错:', error);
} }
@ -81,6 +86,16 @@ const formOptions: VbenFormProps = {
}, 100); }, 100);
} }
}, },
//
handleSubmit: async (values) => {
if (gridApi && gridApi.reload) {
try {
await gridApi.reload(values);
} catch (error) {
console.error('搜索设备端物模型列表失败:', error);
}
}
},
}; };
const gridOptions: VxeGridProps<any> = { const gridOptions: VxeGridProps<any> = {
@ -101,29 +116,37 @@ const gridOptions: VxeGridProps<any> = {
proxyConfig: { proxyConfig: {
ajax: { ajax: {
query: async ({ page }, formValues) => { query: async ({ page }, formValues) => {
// 使使 //
const currentPlatform = formValues?.ioTPlatform || ioTPlatform.value; const latestFormValues =
const currentProductId = formValues ||
formValues?.ioTPlatformProductId || productId.value; (gridApi && gridApi.formApi
? await gridApi.formApi.getValues()
: {});
if (!currentPlatform || !currentProductId) { // 使使
return { const currentPlatform =
items: [], latestFormValues?.ioTPlatform || ioTPlatform.value;
totalCount: 0, const currentProductId =
}; latestFormValues?.ioTPlatformProductId || productId.value;
}
try { try {
const { data } = await postDeviceThingModelManagementPageAsync({ const { data } = await postDeviceThingModelManagementPageAsync({
// 使 JSON Body
body: { body: {
pageIndex: page.currentPage, pageIndex: page.currentPage,
pageSize: page.pageSize, pageSize: page.pageSize,
...(currentPlatform && {
ioTPlatform: ioTPlatform:
typeof currentPlatform === 'string' typeof currentPlatform === 'string'
? Number.parseInt(currentPlatform) ? Number.parseInt(currentPlatform)
: currentPlatform, : currentPlatform,
}),
...(currentProductId && {
ioTPlatformProductId: String(currentProductId), ioTPlatformProductId: String(currentProductId),
searchKeyWords: formValues?.SearchKeyWords, }),
...(latestFormValues?.SearchKeyWords && {
searchKeyWords: latestFormValues.SearchKeyWords,
}),
}, },
}); });
@ -144,6 +167,16 @@ const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
const editRow: Record<string, any> = ref({}); const editRow: Record<string, any> = ref({});
// 使
const [PropertyModal, propertyModalApi] = useVbenModal({
connectedComponent: DeviceThingModelPropertyModal,
});
// 使
const [CommandModal, commandModalApi] = useVbenModal({
connectedComponent: DeviceThingModelCommandModal,
});
const [ThingModelModal, thingModelModalApi] = useVbenModal({ const [ThingModelModal, thingModelModalApi] = useVbenModal({
draggable: true, draggable: true,
footer: true, footer: true,
@ -157,7 +190,12 @@ const [ThingModelModal, thingModelModalApi] = useVbenModal({
if (isOpen && editRow.value.id) { if (isOpen && editRow.value.id) {
// //
nextTick(() => { nextTick(() => {
editFormApi.setValues({ ...editRow.value }); const values: any = { ...editRow.value };
//
if (values.ioTPlatform !== undefined && values.ioTPlatform !== null) {
values.ioTPlatform = String(values.ioTPlatform);
}
editFormApi.setValues(values);
}); });
} }
}, },
@ -223,7 +261,11 @@ async function submit() {
); );
thingModelModalApi.close(); thingModelModalApi.close();
editRow.value = {}; editRow.value = {};
gridApi.reload(); // 使
if (gridApi && gridApi.reload && gridApi.formApi) {
const latestValues = await gridApi.formApi.getValues();
await gridApi.reload(latestValues);
}
} else { } else {
Message.error( Message.error(
isEdit ? $t('common.editFail') : $t('common.addFail'), isEdit ? $t('common.editFail') : $t('common.addFail'),
@ -242,6 +284,26 @@ async function onEdit(record: any) {
thingModelModalApi.open(); thingModelModalApi.open();
} }
//
async function openPropertyModal(record: any) {
editRow.value = record;
propertyModalApi.setData({
deviceThingModelId: record.id,
deviceModelName: record.deviceModelName,
});
propertyModalApi.open();
}
//
async function openCommandModal(record: any) {
editRow.value = record;
commandModalApi.setData({
deviceThingModelId: record.id,
deviceModelName: record.deviceModelName,
});
commandModalApi.open();
}
const openAddModal = async () => { const openAddModal = async () => {
editRow.value = {}; editRow.value = {};
thingModelModalApi.open(); thingModelModalApi.open();
@ -264,6 +326,40 @@ async function onDel(record: any) {
Message.error($t('common.deleteFail')); Message.error($t('common.deleteFail'));
} }
} }
// ID
onMounted(async () => {
await nextTick();
setTimeout(async () => {
if (!gridApi || !gridApi.reload) return;
try {
//
const formValues = await gridApi.formApi.getValues();
const newValues: any = { ...formValues };
if (route.query.ioTPlatform && !formValues.ioTPlatform) {
newValues.ioTPlatform = route.query.ioTPlatform;
}
if (route.query.productId && !formValues.ioTPlatformProductId) {
newValues.ioTPlatformProductId = route.query.productId;
}
if (
newValues.ioTPlatform !== formValues.ioTPlatform ||
newValues.ioTPlatformProductId !== formValues.ioTPlatformProductId
) {
await gridApi.formApi.setValues(newValues);
await nextTick();
}
// ID
await gridApi.reload(newValues);
} catch (error) {
console.error('初始化加载设备端物模型列表失败:', error);
}
}, 300);
});
</script> </script>
<template> <template>
@ -306,6 +402,20 @@ async function onDel(record: any) {
auth: ['AbpIdentity.Users.Update'], auth: ['AbpIdentity.Users.Update'],
onClick: onEdit.bind(null, row), onClick: onEdit.bind(null, row),
}, },
{
label: '属性管理',
type: 'link',
size: 'small',
auth: ['AbpIdentity.Users.Update'],
onClick: openPropertyModal.bind(null, row),
},
{
label: '指令管理',
type: 'link',
size: 'small',
auth: ['AbpIdentity.Users.Update'],
onClick: openCommandModal.bind(null, row),
},
{ {
label: $t('common.delete'), label: $t('common.delete'),
icon: 'ant-design:delete-outlined', icon: 'ant-design:delete-outlined',
@ -322,6 +432,12 @@ async function onDel(record: any) {
</template> </template>
</Grid> </Grid>
<!-- 属性管理弹窗独立组件 -->
<PropertyModal />
<!-- 指令管理弹窗独立组件 -->
<CommandModal />
<ThingModelModal <ThingModelModal
:title="editRow.id ? $t('common.edit') : $t('common.add')" :title="editRow.id ? $t('common.edit') : $t('common.add')"
class="w-[800px]" class="w-[800px]"