1063 lines
30 KiB
Vue
Raw Normal View History

2025-12-18 22:05:55 +08:00
<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue';
2025-12-18 22:05:55 +08:00
import { useVbenModal, z } from '@vben/common-ui';
2025-12-18 22:05:55 +08:00
import { message as Message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
2025-12-18 22:05:55 +08:00
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';
2025-12-18 22:05:55 +08:00
import { $t } from '#/locales';
2025-12-22 10:33:30 +08:00
import IoTPlatformThingModelDataSelect from '../IoTPlatformThingModelDataSelect.vue';
2025-12-18 22:05:55 +08:00
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({});
2025-12-18 22:05:55 +08:00
// 属性列表
2025-12-18 22:05:55 +08:00
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: [],
showDefaultActions: false,
},
gridOptions: {
columns: [
{
field: 'filedType',
title: '物模型类型',
minWidth: 160,
showOverflow: 'tooltip',
},
2025-12-18 22:05:55 +08:00
{
field: 'standardFieldDisplayName',
title: '标准属性名称',
2025-12-18 22:05:55 +08:00
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,
2025-12-18 22:05:55 +08:00
showOverflow: 'tooltip',
},
{
field: 'isValueNeedConvert',
title: '值类型是否转换',
2025-12-18 22:05:55 +08:00
minWidth: 120,
showOverflow: 'tooltip',
formatter: ({ cellValue }: { cellValue: any }) => {
return cellValue ? '是' : '否';
},
2025-12-18 22:05:55 +08:00
},
{
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',
},
2025-12-18 22:05:55 +08:00
{
field: 'action',
title: $t('common.action'),
width: 200,
fixed: 'right',
slots: { default: 'action' },
},
],
height: 400,
pagerConfig: {},
toolbarConfig: {
custom: true,
},
2025-12-18 22:05:55 +08:00
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,
},
});
2025-12-18 22:05:55 +08:00
return data || { items: [], totalCount: 0 };
},
},
},
},
});
2025-12-22 10:33:30 +08:00
// 属性新增弹窗(独立)
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,
2025-12-22 10:33:30 +08:00
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);
}
2025-12-22 10:33:30 +08:00
editPropertyFormApi.setValues(values);
}
} catch (error) {
console.error('加载属性详情失败:', error);
}
});
}
},
onCancel: () => {
2025-12-22 10:33:30 +08:00
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();
},
});
2025-12-22 10:33:30 +08:00
// 新增属性表单 schema只包含新增接口需要的字段
const addPropertyFormSchema = computed(() => [
{
component: 'ApiSelect',
fieldName: 'filedType',
label: '物模型类型',
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'DataDictionaryTypeConst',
},
},
2025-12-22 10:33:30 +08:00
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',
},
},
2025-12-22 10:33:30 +08:00
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',
},
},
2025-12-22 10:33:30 +08:00
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 [];
},
},
2025-12-22 10:33:30 +08:00
},
{
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',
},
},
2025-12-22 10:33:30 +08:00
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 [];
},
},
2025-12-22 10:33:30 +08:00
},
{
component: 'Switch',
fieldName: 'isValueNeedConvert',
label: '值类型是否转换',
componentProps: {
checkedChildren: '是',
unCheckedChildren: '否',
style: { width: 'auto' }, // 优化宽度显示
},
},
{
component: 'ApiSelect',
fieldName: 'parsingSequence',
label: '解析方式',
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'ParsingSequenceTypeEnum',
},
},
2025-12-22 10:33:30 +08:00
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),
}));
},
},
2025-12-22 10:33:30 +08:00
},
{
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')}反转获取数量`,
},
},
];
});
2025-12-22 10:33:30 +08:00
// 新增属性表单
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',
2025-12-22 10:33:30 +08:00
schema: editPropertyFormSchema.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
2025-12-22 10:33:30 +08:00
// 监听 editRow 变化,动态更新编辑表单 schema
watch(
() => editRow.value.id,
() => {
2025-12-22 10:33:30 +08:00
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() {
2025-12-22 10:33:30 +08:00
addPropertyFormModalApi.open();
}
// 打开编辑属性弹窗
function openEditPropertyModal(record: any) {
editRow.value = record;
2025-12-22 10:33:30 +08:00
editPropertyFormModalApi.open();
}
// 打开快速复制平台端物模型弹窗
function openCopyPropertyModal() {
copyPropertyFormApi.resetForm();
copyPropertyModalApi.open();
}
// 打开快速复制设备端物模型弹窗
function openCopyDeviceThingModelModal() {
copyDeviceThingModelFormApi.resetForm();
copyDeviceThingModelModalApi.open();
}
2025-12-22 10:33:30 +08:00
// 提交新增属性
async function submitAddProperty() {
const { valid } = await addPropertyFormApi.validate();
if (!valid) return;
2025-12-22 10:33:30 +08:00
const formValues = await addPropertyFormApi.getValues();
const fetchParams: any = {
deviceThingModelId: deviceThingModelId.value,
2025-12-22 10:33:30 +08:00
...(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 {
2025-12-22 10:33:30 +08:00
const resp = await postDeviceThingModelManagementPropertyCreateAsync({
body: fetchParams,
});
if (resp.data) {
2025-12-22 10:33:30 +08:00
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 {
2025-12-22 10:33:30 +08:00
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);
}
}
2025-12-18 22:05:55 +08:00
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();
}
});
2025-12-18 22:05:55 +08:00
}
},
});
</script>
<template>
<Modal :title="`属性管理 - ${deviceModelName || ''}`" class="w-[1200px]">
2025-12-18 22:05:55 +08:00
<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>
2025-12-18 22:05:55 +08:00
</Grid>
2025-12-22 10:33:30 +08:00
<!-- 属性新增弹窗 -->
<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>
<!-- 快速复制设备端物模型属性弹窗 -->
2025-12-22 10:33:30 +08:00
<CopyDeviceThingModelModal title="快速复制设备端物模型属性" class="w-[600px]">
<CopyDeviceThingModelForm />
</CopyDeviceThingModelModal>
2025-12-18 22:05:55 +08:00
</Modal>
</template>