设备操作优化

This commit is contained in:
ChenYi 2025-12-25 16:41:46 +08:00
parent b0760495ae
commit f54c055199
2 changed files with 180 additions and 2 deletions

View File

@ -42,6 +42,7 @@ import {
batchAddDeviceFormSchema, batchAddDeviceFormSchema,
bindDeviceThingModelFormSchema, bindDeviceThingModelFormSchema,
commandFormSchema, commandFormSchema,
deviceUpgradeFormSchema,
editDeviceFormSchemaEdit, editDeviceFormSchemaEdit,
querySchema, querySchema,
tableSchema, tableSchema,
@ -267,6 +268,9 @@ const pageLoading = ref(false);
const loadingTip = ref('缓存刷新中...'); const loadingTip = ref('缓存刷新中...');
const commandRow: Record<string, any> = ref({}); const commandRow: Record<string, any> = ref({});
//
const upgradeRow: Record<string, any> = ref({});
// //
const commandTableColumns = computed(() => [ const commandTableColumns = computed(() => [
{ {
@ -394,6 +398,21 @@ interface ThingModelProperty {
const thingModelProperties = ref<ThingModelProperty[]>([]); const thingModelProperties = ref<ThingModelProperty[]>([]);
const thingModelLoading = ref(false); const thingModelLoading = ref(false);
//
const filterKeyword = ref('');
//
const filteredThingModelProperties = computed(() => {
if (!filterKeyword.value.trim()) {
return thingModelProperties.value;
}
const keyword = filterKeyword.value.trim().toLowerCase();
return thingModelProperties.value.filter((prop) => {
return (
prop.standardFieldDisplayName?.toLowerCase().includes(keyword) ||
prop.ioTPlatformRawFieldName?.toLowerCase().includes(keyword)
);
});
});
// //
const fetchThingModelProperties = async (row: Record<string, any>) => { const fetchThingModelProperties = async (row: Record<string, any>) => {
@ -514,12 +533,14 @@ const [CommandModal, commandModalApi] = useVbenModal({
onBeforeClose: () => { onBeforeClose: () => {
commandRow.value = {}; commandRow.value = {};
thingModelProperties.value = []; thingModelProperties.value = [];
filterKeyword.value = ''; //
return true; return true;
}, },
onOpenChange: async (isOpen: boolean) => { onOpenChange: async (isOpen: boolean) => {
if (isOpen && commandRow.value) { if (isOpen && commandRow.value) {
// //
await fetchThingModelProperties(commandRow.value); await fetchThingModelProperties(commandRow.value);
filterKeyword.value = ''; //
} }
}, },
}); });
@ -703,6 +724,83 @@ const [BatchAddModal, batchAddModalApi] = useVbenModal({
}, },
}); });
//
const [UpgradeForm, upgradeFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 120,
componentProps: {
class: 'w-full',
},
},
layout: 'horizontal',
schema: deviceUpgradeFormSchema.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-1',
});
//
const submitDeviceUpgrade = async () => {
const { valid } = await upgradeFormApi.validate();
if (!valid) return;
const formValues = await upgradeFormApi.getValues();
try {
upgradeModalApi.setState({ loading: true, confirmLoading: true });
// TODO:
// const result = await postDeviceUpgrade({
// body: {
// deviceId: upgradeRow.value.id,
// targetVersionId: formValues.targetVersionId,
// upgradeDescription: formValues.upgradeDescription,
// },
// });
//
await new Promise((resolve) => setTimeout(resolve, 1000));
Message.success('设备升级任务已提交');
upgradeModalApi.close();
upgradeRow.value = {};
upgradeFormApi.resetForm();
gridApi.reload();
} catch (error) {
console.error('设备升级失败:', error);
Message.error('设备升级失败');
} finally {
upgradeModalApi.setState({ loading: false, confirmLoading: false });
}
};
//
const openUpgradeModal = (row: Record<string, any>) => {
upgradeRow.value = row;
upgradeModalApi.open();
//
nextTick(() => {
upgradeFormApi.setValues({
deviceId: row.id,
deviceName: row.deviceName || row.deviceAddress,
currentVersion: row.firmwareVersion || '未知',
targetVersionId: undefined,
upgradeDescription: '',
});
});
};
const [UpgradeModal, upgradeModalApi] = useVbenModal({
draggable: true,
onConfirm: submitDeviceUpgrade,
onBeforeClose: () => {
upgradeRow.value = {};
upgradeFormApi.resetForm();
return true;
},
});
// //
const batchAddModalState = batchAddModalApi.useStore(); const batchAddModalState = batchAddModalApi.useStore();
@ -1549,6 +1647,10 @@ const toolbarActions = computed(() => [
<Popover trigger="hover" placement="bottomRight" :overlay-style="{ minWidth: '120px' }"> <Popover trigger="hover" placement="bottomRight" :overlay-style="{ minWidth: '120px' }">
<template #content> <template #content>
<div style="display: flex; flex-direction: column; gap: 4px"> <div style="display: flex; flex-direction: column; gap: 4px">
<Button type="text" size="small" @click="openUpgradeModal.bind(null, row)()"
style="padding: 4px 8px; text-align: left">
设备升级
</Button>
<Button type="text" size="small" @click="toDeviceLog.bind(null, row)()" <Button type="text" size="small" @click="toDeviceLog.bind(null, row)()"
style="padding: 4px 8px; text-align: left"> style="padding: 4px 8px; text-align: left">
{{ $t('abp.IoTDBBase.PlatformLog') }} {{ $t('abp.IoTDBBase.PlatformLog') }}
@ -1583,9 +1685,32 @@ const toolbarActions = computed(() => [
<div v-if="thingModelLoading" style="padding: 40px; text-align: center"> <div v-if="thingModelLoading" style="padding: 40px; text-align: center">
<Loading :loading="true" tip="加载物模型属性中..." /> <Loading :loading="true" tip="加载物模型属性中..." />
</div> </div>
<Table v-else :columns="commandTableColumns" :data-source="thingModelProperties" :pagination="false" <div v-else>
:scroll="{ x: 1000, y: 500 }" row-key="id" size="small" /> <div style="margin-bottom: 16px">
<Input
v-model:value="filterKeyword"
placeholder="请输入标准物模型属性名称或平台物模型属性标识符进行筛选"
allow-clear
style="width: 100%"
>
<template #prefix>
<Icon icon="ant-design:search-outlined" />
</template>
</Input>
</div>
<Table
:columns="commandTableColumns"
:data-source="filteredThingModelProperties"
:pagination="false"
:scroll="{ x: 1000, y: 500 }"
row-key="id"
size="small"
/>
</div>
</CommandModal> </CommandModal>
<UpgradeModal title="设备升级" class="w-[600px]">
<UpgradeForm />
</UpgradeModal>
<BindModal :title="`绑定设备端物模型${bindRows.length > 0 ? ` (已选择 ${bindRows.length} 个设备)` : ''}`" class="w-[600px]"> <BindModal :title="`绑定设备端物模型${bindRows.length > 0 ? ` (已选择 ${bindRows.length} 个设备)` : ''}`" class="w-[600px]">
<div v-if="bindRows.length > 0" class="mb-4 rounded border border-blue-200 bg-blue-50 p-3"> <div v-if="bindRows.length > 0" class="mb-4 rounded border border-blue-200 bg-blue-50 p-3">
<div class="mb-2 text-sm font-medium text-blue-800"> <div class="mb-2 text-sm font-medium text-blue-800">

View File

@ -643,6 +643,59 @@ export const commandFormSchema: any = computed(() => [
// 指令表单不再使用schema字段改为在模板中动态渲染 // 指令表单不再使用schema字段改为在模板中动态渲染
]); ]);
// 设备升级表单
export const deviceUpgradeFormSchema: any = computed(() => [
{
component: 'Input',
fieldName: 'deviceId',
label: '设备ID',
componentProps: {
disabled: true,
},
},
{
component: 'Input',
fieldName: 'deviceName',
label: '设备名称',
componentProps: {
disabled: true,
},
},
{
component: 'Input',
fieldName: 'currentVersion',
label: '当前版本',
componentProps: {
disabled: true,
},
},
{
component: 'ApiSelect',
fieldName: 'targetVersionId',
label: '目标版本',
componentProps: {
// TODO: 待接口实现后,替换为实际的版本列表接口
api: null,
placeholder: '请选择目标版本',
allowClear: true,
},
rules: z.string().min(1, {
message: '请选择目标版本',
}),
},
{
component: 'Textarea',
fieldName: 'upgradeDescription',
label: '升级说明',
componentProps: {
rows: 4,
placeholder: '请输入升级说明(可选)',
maxLength: 500,
showCount: true,
},
},
]);
export const batchAddDeviceFormSchema: any = computed(() => [ export const batchAddDeviceFormSchema: any = computed(() => [
{ {
component: 'Textarea', component: 'Textarea',