1063 lines
30 KiB
Vue
1063 lines
30 KiB
Vue
<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>
|