2025-12-22 10:33:30 +08:00

1063 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue';
import { useVbenModal, z } from '@vben/common-ui';
import { message as Message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
getCommonGetSelectList,
postAggregationIoTplatformGetIoTplatformProductInfoAsync,
postDeviceThingModelManagementCopyAnotherDeviceThingModelAsync,
postDeviceThingModelManagementCopyIoTplatformThingModelToDeviceAsync,
postDeviceThingModelManagementPageAsync,
postDeviceThingModelManagementPropertyCreateAsync,
postDeviceThingModelManagementPropertyDeleteAsync,
postDeviceThingModelManagementPropertyFindByIdAsync,
postDeviceThingModelManagementPropertyPageAsync,
postDeviceThingModelManagementPropertyUpdateAsync,
} from '#/api-client';
import { TableAction } from '#/components/table-action';
import { $t } from '#/locales';
import IoTPlatformThingModelDataSelect from '../IoTPlatformThingModelDataSelect.vue';
defineOptions({
name: 'DeviceThingModelPropertyModal',
});
const deviceThingModelId = ref<string>('');
const deviceModelName = ref<string>('');
const ioTPlatform = ref<number | string>('');
const ioTPlatformProductId = ref<string>('');
const editRow: Record<string, any> = ref({});
// 属性列表
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: [],
showDefaultActions: false,
},
gridOptions: {
columns: [
{
field: 'filedType',
title: '物模型类型',
minWidth: 160,
showOverflow: 'tooltip',
},
{
field: 'standardFieldDisplayName',
title: '标准属性名称',
minWidth: 160,
showOverflow: 'tooltip',
},
{
field: 'standardFieldName',
title: '标准属性标识符',
minWidth: 160,
showOverflow: 'tooltip',
},
{
field: 'standardFieldValueType',
title: '标准属性值类型',
minWidth: 160,
showOverflow: 'tooltip',
},
{
field: 'ioTPlatformRawFieldName',
title: '平台属性标识符',
minWidth: 160,
showOverflow: 'tooltip',
},
{
field: 'ioTPlatformRawFieldDataType',
title: '平台属性值类型',
minWidth: 160,
showOverflow: 'tooltip',
},
{
field: 'isValueNeedConvert',
title: '值类型是否转换',
minWidth: 120,
showOverflow: 'tooltip',
formatter: ({ cellValue }: { cellValue: any }) => {
return cellValue ? '是' : '否';
},
},
{
field: 'parsingSequence',
title: '解析方式',
minWidth: 140,
showOverflow: 'tooltip',
formatter: ({ cellValue }: { cellValue: any }) => {
if (cellValue === 1) return '正序';
if (cellValue === 2) return '高低位反转';
return cellValue ?? '-';
},
},
{
field: 'nativeSkipNumber',
title: '正序跳过数量',
minWidth: 140,
showOverflow: 'tooltip',
},
{
field: 'nativeTakeNumber',
title: '正序获取数量',
minWidth: 140,
showOverflow: 'tooltip',
},
{
field: 'reversalSkipNumber',
title: '反转跳过数量',
minWidth: 140,
showOverflow: 'tooltip',
},
{
field: 'reversalTakeNumber',
title: '反转获取数量',
minWidth: 140,
showOverflow: 'tooltip',
},
{
field: 'action',
title: $t('common.action'),
width: 200,
fixed: 'right',
slots: { default: 'action' },
},
],
height: 400,
pagerConfig: {},
toolbarConfig: {
custom: true,
},
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 [AddPropertyFormModal, addPropertyFormModalApi] = useVbenModal({
draggable: true,
footer: true,
showCancelButton: true,
showConfirmButton: true,
onConfirm: submitAddProperty,
onBeforeClose: () => {
return true;
},
onOpenChange: (isOpen: boolean) => {
if (isOpen) {
// 新增模式下,清空表单
addPropertyFormApi.resetForm();
}
},
onCancel: () => {
addPropertyFormModalApi.close();
},
});
// 属性编辑弹窗(独立)
const [EditPropertyFormModal, editPropertyFormModalApi] = useVbenModal({
draggable: true,
footer: true,
showCancelButton: true,
showConfirmButton: true,
onConfirm: submitEditProperty,
onBeforeClose: () => {
return true;
},
onOpenChange: (isOpen: boolean) => {
if (isOpen && editRow.value.id) {
// 编辑模式下,加载属性详情
nextTick(async () => {
try {
const { data } =
await postDeviceThingModelManagementPropertyFindByIdAsync({
body: { id: editRow.value.id },
});
if (data) {
const values: any = { ...data };
// 处理解析方式字段(从后端获取的可能是数字,需要转换成字符串)
if (
values.parsingSequence !== undefined &&
values.parsingSequence !== null
) {
// 如果后端返回的是数字,转换为字符串;如果已经是字符串,保持原样
values.parsingSequence = String(values.parsingSequence);
}
editPropertyFormApi.setValues(values);
}
} catch (error) {
console.error('加载属性详情失败:', error);
}
});
}
},
onCancel: () => {
editPropertyFormModalApi.close();
},
});
// 快速复制平台端物模型属性弹窗
const [CopyPropertyModal, copyPropertyModalApi] = useVbenModal({
draggable: true,
footer: true,
showCancelButton: true,
showConfirmButton: true,
onConfirm: submitCopyProperty,
onBeforeClose: () => {
return true;
},
onCancel: () => {
copyPropertyModalApi.close();
},
});
// 快速复制设备端物模型弹窗
const [CopyDeviceThingModelModal, copyDeviceThingModelModalApi] = useVbenModal({
draggable: true,
footer: true,
showCancelButton: true,
showConfirmButton: true,
onConfirm: submitCopyDeviceThingModel,
onBeforeClose: () => {
return true;
},
onCancel: () => {
copyDeviceThingModelModalApi.close();
},
});
// 新增属性表单 schema只包含新增接口需要的字段
const addPropertyFormSchema = computed(() => [
{
component: 'ApiSelect',
fieldName: 'filedType',
label: '物模型类型',
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'DataDictionaryTypeConst',
},
},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: true,
allowClear: true,
placeholder: '请选择物模型类型',
afterFetch: (res: any) => {
if (Array.isArray(res)) return res;
if (res && Array.isArray(res.items)) return res.items;
if (res && Array.isArray(res.data)) return res.data;
return [];
},
},
},
{
component: IoTPlatformThingModelDataSelect,
fieldName: 'ioTPlatformThingModelDataId',
label: '平台端物模型数据选择',
modelPropName: 'value',
dependencies: {
triggerFields: ['filedType'],
},
componentProps: (formValues: any) => ({
filedType: formValues?.filedType || null,
ioTPlatform: ioTPlatform.value,
ioTPlatformProductId: ioTPlatformProductId.value,
placeholder: '请选择平台端物模型数据',
}),
},
{
component: 'ApiSelect',
fieldName: 'parsingSequence',
label: '解析方式',
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'ParsingSequenceTypeEnum',
},
},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: true,
allowClear: true,
placeholder: `${$t('common.pleaseSelect')}解析方式`,
afterFetch: (res: any) => {
let items = [];
if (Array.isArray(res)) {
items = res;
} else if (res && Array.isArray(res.items)) {
items = res.items;
} else if (res && Array.isArray(res.data)) {
items = res.data;
}
// 将 key 转换为字符串,因为表单需要字符串类型
return items.map((item: any) => ({
...item,
key: String(item.key || item.value),
}));
},
},
},
{
component: 'InputNumber',
fieldName: 'nativeSkipNumber',
label: '正序跳过数量',
rules: z.preprocess(
(v) => (v == null ? 0 : v),
z.number().min(0, '正序跳过数量不能小于0'),
),
componentProps: {
min: 0,
placeholder: `${$t('common.pleaseInput')}正序跳过数量`,
},
},
{
component: 'InputNumber',
fieldName: 'nativeTakeNumber',
label: '正序获取数量',
rules: z.preprocess(
(v) => (v == null ? 0 : v),
z.number().min(0, '正序获取数量不能小于0'),
),
componentProps: {
min: 0,
placeholder: `${$t('common.pleaseInput')}正序获取数量`,
},
},
{
component: 'InputNumber',
fieldName: 'reversalSkipNumber',
label: '反转跳过数量',
componentProps: {
min: 0,
placeholder: `${$t('common.pleaseInput')}反转跳过数量`,
},
},
{
component: 'InputNumber',
fieldName: 'reversalTakeNumber',
label: '反转获取数量',
componentProps: {
min: 0,
placeholder: `${$t('common.pleaseInput')}反转获取数量`,
},
},
]);
// 编辑属性表单 schema包含编辑接口需要的所有字段
const editPropertyFormSchema = computed(() => {
return [
{
component: 'Input',
fieldName: 'standardFieldDisplayName',
label: '标准属性名称',
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
placeholder: `${$t('common.pleaseInput')}标准属性名称`,
},
},
{
component: 'Input',
fieldName: 'standardFieldName',
label: '标准属性标识符',
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
placeholder: `${$t('common.pleaseInput')}标准属性标识符`,
},
},
{
component: 'ApiSelect',
fieldName: 'standardFieldValueType',
label: '标准属性值类型',
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'StandardThingModelDataTypeEnum',
},
},
labelField: 'value',
valueField: 'secondValue',
optionsPropName: 'options',
immediate: true,
allowClear: true,
placeholder: `${$t('common.pleaseSelect')}标准属性值类型`,
afterFetch: (res: any) => {
if (Array.isArray(res)) return res;
if (res && Array.isArray(res.items)) return res.items;
if (res && Array.isArray(res.data)) return res.data;
return [];
},
},
},
{
component: 'Input',
fieldName: 'ioTPlatformRawFieldName',
label: '平台属性标识符',
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
placeholder: `${$t('common.pleaseInput')}平台属性标识符`,
},
},
{
component: 'ApiSelect',
fieldName: 'ioTPlatformRawFieldDataType',
label: '平台属性值类型',
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'StandardThingModelDataTypeEnum',
},
},
labelField: 'value',
valueField: 'secondValue',
optionsPropName: 'options',
immediate: true,
allowClear: true,
placeholder: `${$t('common.pleaseSelect')}平台属性值类型`,
afterFetch: (res: any) => {
if (Array.isArray(res)) return res;
if (res && Array.isArray(res.items)) return res.items;
if (res && Array.isArray(res.data)) return res.data;
return [];
},
},
},
{
component: 'Switch',
fieldName: 'isValueNeedConvert',
label: '值类型是否转换',
componentProps: {
checkedChildren: '是',
unCheckedChildren: '否',
style: { width: 'auto' }, // 优化宽度显示
},
},
{
component: 'ApiSelect',
fieldName: 'parsingSequence',
label: '解析方式',
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'ParsingSequenceTypeEnum',
},
},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: true,
allowClear: true,
placeholder: `${$t('common.pleaseSelect')}解析方式`,
afterFetch: (res: any) => {
let items = [];
if (Array.isArray(res)) {
items = res;
} else if (res && Array.isArray(res.items)) {
items = res.items;
} else if (res && Array.isArray(res.data)) {
items = res.data;
}
// 将 key 转换为字符串,因为表单需要字符串类型
return items.map((item: any) => ({
...item,
key: String(item.key || item.value),
}));
},
},
},
{
component: 'InputNumber',
fieldName: 'nativeSkipNumber',
label: '正序跳过数量',
componentProps: {
min: 0,
placeholder: `${$t('common.pleaseInput')}正序跳过数量`,
},
},
{
component: 'InputNumber',
fieldName: 'nativeTakeNumber',
label: '正序获取数量',
componentProps: {
min: 0,
placeholder: `${$t('common.pleaseInput')}正序获取数量`,
},
},
{
component: 'InputNumber',
fieldName: 'reversalSkipNumber',
label: '反转跳过数量',
componentProps: {
min: 0,
placeholder: `${$t('common.pleaseInput')}反转跳过数量`,
},
},
{
component: 'InputNumber',
fieldName: 'reversalTakeNumber',
label: '反转获取数量',
componentProps: {
min: 0,
placeholder: `${$t('common.pleaseInput')}反转获取数量`,
},
},
];
});
// 新增属性表单
const [AddPropertyForm, addPropertyFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 140,
componentProps: {
class: 'w-4/5',
},
},
layout: 'horizontal',
schema: addPropertyFormSchema,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
// 编辑属性表单
const [EditPropertyForm, editPropertyFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 140,
componentProps: {
class: 'w-4/5',
},
},
layout: 'horizontal',
schema: editPropertyFormSchema.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
// 监听 editRow 变化,动态更新编辑表单 schema
watch(
() => editRow.value.id,
() => {
if (editPropertyFormApi && editPropertyFormApi.updateSchema) {
editPropertyFormApi.updateSchema(editPropertyFormSchema.value);
}
},
);
// 快速复制表单(选择平台和产品)
const [CopyPropertyForm, copyPropertyFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 140,
componentProps: {
class: 'w-4/5',
},
},
layout: 'horizontal',
schema: [
{
component: 'ApiSelect',
fieldName: 'ioTPlatform',
label: $t('abp.deviceInfos.ioTPlatform'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'IoTPlatformTypeEnum',
},
},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: true,
allowClear: true,
placeholder:
$t('common.pleaseSelect') + $t('abp.deviceInfos.ioTPlatform'),
afterFetch: (res: any) => {
if (Array.isArray(res)) return res;
if (res && Array.isArray(res.items)) return res.items;
if (res && Array.isArray(res.data)) return res.data;
return [];
},
},
},
{
component: 'ApiSelect',
fieldName: 'ioTPlatformProductId',
label: $t('common.BelongingProductName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
dependencies: {
show(values: any) {
return !!values.ioTPlatform;
},
triggerFields: ['ioTPlatform'],
},
componentProps: (formValues: any) => {
const platform = formValues?.ioTPlatform;
return {
api: platform
? postAggregationIoTplatformGetIoTplatformProductInfoAsync
: null,
params: {
body: {
ioTPlatformType:
typeof platform === 'string'
? Number.parseInt(platform)
: platform,
},
},
labelField: 'productName',
valueField: 'ioTPlatformProductId',
optionsPropName: 'options',
immediate: false,
allowClear: true,
placeholder:
$t('common.pleaseSelect') + $t('common.BelongingProductName'),
afterFetch: (res: any) => {
if (Array.isArray(res)) return res;
if (res && Array.isArray(res.items)) return res.items;
if (res && Array.isArray(res.data)) return res.data;
if (res && res.data && Array.isArray(res.data.items)) {
return res.data.items;
}
return [];
},
};
},
},
],
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
// 快速复制设备端物模型表单
const [CopyDeviceThingModelForm, copyDeviceThingModelFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 140,
componentProps: {
class: 'w-4/5',
},
},
layout: 'horizontal',
schema: [
{
component: 'ApiSelect',
fieldName: 'sourceDeviceThingModelId',
label: '选择设备端物模型',
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
api: postDeviceThingModelManagementPageAsync,
params: {
body: {
pageIndex: 1,
pageSize: 1000,
isPage: false, // 不分页,获取全部数据
},
},
labelField: 'deviceModelName',
valueField: 'id',
optionsPropName: 'options',
immediate: true,
allowClear: true,
placeholder: '请选择要复制的设备端物模型',
afterFetch: (res: any) => {
if (Array.isArray(res)) return res;
if (res && Array.isArray(res.items)) return res.items;
if (res && Array.isArray(res.data)) return res.data;
if (res && res.data && Array.isArray(res.data.items)) {
return res.data.items;
}
return [];
},
},
},
],
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-1',
});
// 打开新增属性弹窗
function openAddPropertyModal() {
addPropertyFormModalApi.open();
}
// 打开编辑属性弹窗
function openEditPropertyModal(record: any) {
editRow.value = record;
editPropertyFormModalApi.open();
}
// 打开快速复制平台端物模型弹窗
function openCopyPropertyModal() {
copyPropertyFormApi.resetForm();
copyPropertyModalApi.open();
}
// 打开快速复制设备端物模型弹窗
function openCopyDeviceThingModelModal() {
copyDeviceThingModelFormApi.resetForm();
copyDeviceThingModelModalApi.open();
}
// 提交新增属性
async function submitAddProperty() {
const { valid } = await addPropertyFormApi.validate();
if (!valid) return;
const formValues = await addPropertyFormApi.getValues();
const fetchParams: any = {
deviceThingModelId: deviceThingModelId.value,
...(formValues.ioTPlatformThingModelDataId && {
ioTPlatformThingModelDataId: String(
formValues.ioTPlatformThingModelDataId,
),
}),
nativeSkipNumber: formValues.nativeSkipNumber || 0,
nativeTakeNumber: formValues.nativeTakeNumber || 0,
parsingSequence:
typeof formValues.parsingSequence === 'string'
? Number.parseInt(formValues.parsingSequence)
: formValues.parsingSequence,
...(formValues.reversalSkipNumber !== undefined &&
formValues.reversalSkipNumber !== null && {
reversalSkipNumber: formValues.reversalSkipNumber,
}),
...(formValues.reversalTakeNumber !== undefined &&
formValues.reversalTakeNumber !== null && {
reversalTakeNumber: formValues.reversalTakeNumber,
}),
};
try {
const resp = await postDeviceThingModelManagementPropertyCreateAsync({
body: fetchParams,
});
if (resp.data) {
Message.success($t('common.addSuccess'));
addPropertyFormModalApi.close();
await nextTick();
if (gridApi && gridApi.reload) {
await gridApi.reload();
}
} else {
Message.error($t('common.addFail'));
}
} catch (error) {
console.error('提交属性失败:', error);
}
}
// 提交编辑属性
async function submitEditProperty() {
const { valid } = await editPropertyFormApi.validate();
if (!valid) return;
const formValues = await editPropertyFormApi.getValues();
const fetchParams: any = {
id: editRow.value.id,
deviceThingModelId: deviceThingModelId.value,
...(formValues.filedType && { filedType: formValues.filedType }),
ioTPlatformRawFieldName: formValues.ioTPlatformRawFieldName,
ioTPlatformRawFieldDataType: formValues.ioTPlatformRawFieldDataType,
standardFieldName: formValues.standardFieldName,
standardFieldValueType: formValues.standardFieldValueType,
standardFieldDisplayName: formValues.standardFieldDisplayName,
...(formValues.isValueNeedConvert !== undefined && {
isValueNeedConvert: formValues.isValueNeedConvert,
}),
nativeSkipNumber: formValues.nativeSkipNumber || 0,
nativeTakeNumber: formValues.nativeTakeNumber || 0,
parsingSequence:
typeof formValues.parsingSequence === 'string'
? Number.parseInt(formValues.parsingSequence)
: formValues.parsingSequence,
...(formValues.reversalSkipNumber !== undefined &&
formValues.reversalSkipNumber !== null && {
reversalSkipNumber: formValues.reversalSkipNumber,
}),
...(formValues.reversalTakeNumber !== undefined &&
formValues.reversalTakeNumber !== null && {
reversalTakeNumber: formValues.reversalTakeNumber,
}),
};
try {
const resp = await postDeviceThingModelManagementPropertyUpdateAsync({
body: fetchParams,
});
if (resp.data) {
Message.success($t('common.editSuccess'));
editPropertyFormModalApi.close();
editRow.value = {};
await nextTick();
if (gridApi && gridApi.reload) {
await gridApi.reload();
}
} else {
Message.error($t('common.editFail'));
}
} catch (error) {
console.error('提交属性失败:', error);
}
}
// 提交快速复制设备端物模型
async function submitCopyDeviceThingModel() {
const { valid } = await copyDeviceThingModelFormApi.validate();
if (!valid) return;
const formValues = await copyDeviceThingModelFormApi.getValues();
if (!formValues.sourceDeviceThingModelId) {
Message.warning('请选择要复制的设备端物模型');
return;
}
try {
const resp =
await postDeviceThingModelManagementCopyAnotherDeviceThingModelAsync({
body: {
ioTPlatform: Number.parseInt(String(ioTPlatform.value)) as 1 | 2,
deviceThingModelId: deviceThingModelId.value,
sourceProductId: formValues.sourceDeviceThingModelId,
},
});
if (resp.data) {
Message.success('快速复制设备端物模型属性成功');
copyDeviceThingModelModalApi.close();
await nextTick();
if (gridApi && gridApi.reload) {
await gridApi.reload();
}
} else {
Message.error('快速复制设备端物模型属性失败');
}
} catch (error) {
console.error('快速复制设备端物模型属性失败:', error);
}
}
// 提交快速复制平台端物模型
async function submitCopyProperty() {
const { valid } = await copyPropertyFormApi.validate();
if (!valid) return;
const formValues = await copyPropertyFormApi.getValues();
if (!formValues.ioTPlatform || !formValues.ioTPlatformProductId) {
Message.warning('请选择平台和产品');
return;
}
try {
const resp =
await postDeviceThingModelManagementCopyIoTplatformThingModelToDeviceAsync(
{
body: {
ioTPlatform: Number.parseInt(String(formValues.ioTPlatform)) as
| 1
| 2,
ioTPlatformProductId: String(formValues.ioTPlatformProductId),
deviceThingModelId: deviceThingModelId.value,
},
},
);
if (resp.data) {
Message.success('快速复制平台端物模型属性成功');
copyPropertyModalApi.close();
await nextTick();
if (gridApi && gridApi.reload) {
await gridApi.reload();
}
} else {
Message.error('快速复制平台端物模型属性失败');
}
} catch (error) {
console.error('快速复制平台端物模型属性失败:', error);
}
}
// 删除属性
async function onDeleteProperty(record: any) {
try {
const resp = await postDeviceThingModelManagementPropertyDeleteAsync({
body: { id: record.id },
});
if (resp.data) {
Message.success($t('common.deleteSuccess'));
await nextTick();
if (gridApi && gridApi.reload) {
await gridApi.reload();
}
} else {
Message.error($t('common.deleteFail'));
}
} catch (error) {
console.error('删除属性失败:', error);
}
}
const [Modal, modalApi] = useVbenModal({
onOpenChange(isOpen: boolean) {
if (isOpen) {
const data = modalApi.getData<Record<string, any>>();
deviceThingModelId.value = data?.deviceThingModelId || '';
deviceModelName.value = data?.deviceModelName || '';
ioTPlatform.value = data?.ioTPlatform || '';
ioTPlatformProductId.value = data?.ioTPlatformProductId || '';
// 使用 nextTick 确保 Grid 组件已完全初始化
nextTick(() => {
if (gridApi && gridApi.reload) {
gridApi.reload();
}
});
}
},
});
</script>
<template>
<Modal :title="`属性管理 - ${deviceModelName || ''}`" class="w-[1200px]">
<Grid>
<template #toolbar-actions>
<TableAction :actions="[
{
label: $t('common.add'),
type: 'primary',
icon: 'ant-design:plus-outlined',
onClick: openAddPropertyModal,
auth: ['AbpIdentity.Users.Create'],
},
{
label: '快速复制平台端物模型',
type: 'default',
icon: 'ant-design:copy-outlined',
onClick: openCopyPropertyModal,
auth: ['AbpIdentity.Users.Create'],
},
{
label: '快速复制设备端物模型',
type: 'default',
icon: 'ant-design:copy-outlined',
onClick: openCopyDeviceThingModelModal,
auth: ['AbpIdentity.Users.Create'],
},
]" />
</template>
<template #action="{ row }">
<TableAction :actions="[
{
label: $t('common.edit'),
type: 'link',
size: 'small',
auth: ['AbpIdentity.Users.Update'],
onClick: openEditPropertyModal.bind(null, row),
},
{
label: $t('common.delete'),
icon: 'ant-design:delete-outlined',
type: 'link',
size: 'small',
auth: ['AbpIdentity.Users.Delete'],
popConfirm: {
title: $t('common.askConfirmDelete'),
confirm: onDeleteProperty.bind(null, row),
},
},
]" />
</template>
</Grid>
<!-- 属性新增弹窗 -->
<AddPropertyFormModal :title="$t('common.add')" class="w-[900px]">
<AddPropertyForm />
</AddPropertyFormModal>
<!-- 属性编辑弹窗 -->
<EditPropertyFormModal :title="$t('common.edit')" class="w-[900px]">
<EditPropertyForm />
</EditPropertyFormModal>
<!-- 快速复制平台端物模型属性弹窗 -->
<CopyPropertyModal title="快速复制平台端物模型属性" class="w-[600px]">
<CopyPropertyForm />
</CopyPropertyModal>
<!-- 快速复制设备端物模型属性弹窗 -->
<CopyDeviceThingModelModal title="快速复制设备端物模型属性" class="w-[600px]">
<CopyDeviceThingModelForm />
</CopyDeviceThingModelModal>
</Modal>
</template>