设备端物模型属性完善

This commit is contained in:
ChenYi 2025-12-22 10:33:30 +08:00
parent cfbe8f4df0
commit f3ac09394c
6 changed files with 614 additions and 244 deletions

View File

@ -126,6 +126,7 @@ export type ComponentType =
| 'Select' | 'Select'
| 'Space' | 'Space'
| 'StandardThingModelCodeSelect' | 'StandardThingModelCodeSelect'
| 'IoTPlatformThingModelDataSelect'
| 'Switch' | 'Switch'
| 'Textarea' | 'Textarea'
| 'TimePicker' | 'TimePicker'
@ -181,7 +182,14 @@ async function initComponentAdapter() {
StandardThingModelCodeSelect: defineAsyncComponent( StandardThingModelCodeSelect: defineAsyncComponent(
() => () =>
import( import(
'#/views/thingmodelinfo/ioTPlatformThingModelInfo/StandardThingModelCodeSelect.vue' '#/views/thingmodelinfo/StandardThingModelCodeSelect.vue'
) as any,
),
// 自定义平台端物模型选择组件(分页搜索)
IoTPlatformThingModelDataSelect: defineAsyncComponent(
() =>
import(
'#/views/thingmodelinfo/IoTPlatformThingModelDataSelect.vue'
) as any, ) as any,
), ),
// 自定义默认按钮 // 自定义默认按钮

View File

@ -2765,7 +2765,7 @@ export const DeviceThingModelPageInputSchema = {
} as const; } as const;
export const DeviceThingModelPropertyCreateInputSchema = { export const DeviceThingModelPropertyCreateInputSchema = {
required: ['deviceThingModelId', 'ioTPlatformRawFieldDataType', 'ioTPlatformRawFieldName', 'nativeSkipNumber', 'nativeTakeNumber', 'parsingSequence', 'standardFieldDisplayName', 'standardFieldName', 'standardFieldValueType'], required: ['deviceThingModelId', 'nativeSkipNumber', 'nativeTakeNumber', 'parsingSequence'],
type: 'object', type: 'object',
properties: { properties: {
deviceThingModelId: { deviceThingModelId: {
@ -2773,39 +2773,10 @@ export const DeviceThingModelPropertyCreateInputSchema = {
description: '设备端物模型Id', description: '设备端物模型Id',
format: 'uuid' format: 'uuid'
}, },
filedType: { ioTPlatformThingModelDataId: {
type: 'string', type: 'string',
description: '物联网平台中对应产品物模型属性或者事件类型 JiShe.ServicePro.Core.DataDictionaryTypeConst', description: '平台端物模型数据Id',
nullable: true format: 'uuid'
},
ioTPlatformRawFieldName: {
minLength: 1,
type: 'string',
description: '物联网平台中对应的产品物模型属性或者事件名称'
},
ioTPlatformRawFieldDataType: {
minLength: 1,
type: 'string',
description: '物联网平台中对应的产品物模型属性或者事件数据类型JiShe.ServicePro.Core.OneNETAllThingModel'
},
standardFieldName: {
minLength: 1,
type: 'string',
description: '管理后台产品标准的物模型属性或者事件名称'
},
standardFieldValueType: {
minLength: 1,
type: 'string',
description: '标准物模型字段值类型'
},
standardFieldDisplayName: {
minLength: 1,
type: 'string',
description: '标准物模型字段显示名称'
},
isValueNeedConvert: {
type: 'boolean',
description: '是否需要值类型转换'
}, },
nativeSkipNumber: { nativeSkipNumber: {
type: 'integer', type: 'integer',
@ -3075,6 +3046,10 @@ export const DeviceThingModelPropertyUpdateInputSchema = {
required: ['deviceThingModelId', 'id', 'ioTPlatformRawFieldDataType', 'ioTPlatformRawFieldName', 'nativeSkipNumber', 'nativeTakeNumber', 'parsingSequence', 'standardFieldDisplayName', 'standardFieldName', 'standardFieldValueType'], required: ['deviceThingModelId', 'id', 'ioTPlatformRawFieldDataType', 'ioTPlatformRawFieldName', 'nativeSkipNumber', 'nativeTakeNumber', 'parsingSequence', 'standardFieldDisplayName', 'standardFieldName', 'standardFieldValueType'],
type: 'object', type: 'object',
properties: { properties: {
id: {
type: 'string',
format: 'uuid'
},
deviceThingModelId: { deviceThingModelId: {
type: 'string', type: 'string',
description: '设备端物模型Id', description: '设备端物模型Id',
@ -3138,10 +3113,6 @@ export const DeviceThingModelPropertyUpdateInputSchema = {
description: '反转获取数量', description: '反转获取数量',
format: 'int32', format: 'int32',
nullable: true nullable: true
},
id: {
type: 'string',
format: 'uuid'
} }
}, },
additionalProperties: false, additionalProperties: false,

View File

@ -1572,33 +1572,9 @@ export type DeviceThingModelPropertyCreateInput = {
*/ */
deviceThingModelId: string; deviceThingModelId: string;
/** /**
* JiShe.ServicePro.Core.DataDictionaryTypeConst * Id
*/ */
filedType?: (string) | null; ioTPlatformThingModelDataId?: string;
/**
*
*/
ioTPlatformRawFieldName: string;
/**
* JiShe.ServicePro.Core.OneNETAllThingModel
*/
ioTPlatformRawFieldDataType: string;
/**
*
*/
standardFieldName: string;
/**
*
*/
standardFieldValueType: string;
/**
*
*/
standardFieldDisplayName: string;
/**
*
*/
isValueNeedConvert?: boolean;
/** /**
* *
*/ */
@ -1771,6 +1747,7 @@ export type DeviceThingModelPropertyPageInput = {
* *
*/ */
export type DeviceThingModelPropertyUpdateInput = { export type DeviceThingModelPropertyUpdateInput = {
id: string;
/** /**
* Id * Id
*/ */
@ -1820,7 +1797,6 @@ export type DeviceThingModelPropertyUpdateInput = {
* *
*/ */
reversalTakeNumber?: (number) | null; reversalTakeNumber?: (number) | null;
id: string;
}; };
export type DeviceThingModelUpdateInput = { export type DeviceThingModelUpdateInput = {

View File

@ -0,0 +1,198 @@
<script setup lang="ts">
import { ref, watch, computed, h } from 'vue';
import { Select, Divider, Row } from 'ant-design-vue';
import { ChevronLeft, ChevronRight } from '@vben/icons';
import { postIoTplatformThingModelInfoPageAsync } from '#/api-client';
import { $t } from '#/locales';
import { useDebounceFn } from '@vueuse/core';
interface Props {
value?: string;
typeCode?: string | number | null;
filedType?: string | null;
ioTPlatform?: number | string | null;
ioTPlatformProductId?: string | null;
placeholder?: string;
disabled?: boolean;
allowClear?: boolean;
onResolve?: (item: any | null) => void;
}
const props = withDefaults(defineProps<Props>(), {
placeholder: $t('common.pleaseSelect') + $t('abp.thingModelInfos.StandardFieldName'),
disabled: false,
allowClear: true,
});
const emit = defineEmits<{
'update:value': [string | undefined];
change: [string | undefined];
'item-change': [any | null];
}>();
const VNodes = (props: any) => {
return props.vnodes;
};
const options = ref<any[]>([]);
const total = ref(0);
const loading = ref<boolean>(false);
const query = ref({
pageIndex: 1,
pageSize: 10,
filter: '',
});
const maxPage = computed(() => Math.ceil((total.value || 0) / query.value.pageSize) || 1);
const fetchData = async () => {
// ID
if (!props.ioTPlatform || !props.ioTPlatformProductId) {
options.value = [];
total.value = 0;
return;
}
loading.value = true;
try {
const requestBody: any = {
pageIndex: query.value.pageIndex,
pageSize: query.value.pageSize,
...(query.value.filter && { searchKeyWords: query.value.filter }),
...(props.ioTPlatform && {
ioTPlatform:
typeof props.ioTPlatform === 'string'
? Number.parseInt(props.ioTPlatform)
: props.ioTPlatform,
}),
...(props.ioTPlatformProductId && {
ioTPlatformProductId: String(props.ioTPlatformProductId),
}),
...(props.filedType && { filedType: String(props.filedType) }),
...(props.typeCode && !props.filedType && { filedType: String(props.typeCode) }),
};
const { data } = await postIoTplatformThingModelInfoPageAsync({
body: requestBody,
});
const items = Array.isArray(data?.items) ? data!.items : [];
const mappedItems = items.map((item: any) => ({
label: `${item.standardFieldDisplayName || item.ioTPlatformRawFieldName || item.id || ''}`,
value: item.id || '',
...item,
}));
//
if (props.value && props.value.trim() !== '' && !mappedItems.find(item => item.value === props.value)) {
//
mappedItems.unshift({
label: `当前值: ${props.value}`,
value: props.value,
displayText: props.value,
code: props.value,
});
}
options.value = mappedItems;
total.value = (data as any)?.totalCount || 0;
} catch (err) {
console.error('获取标准物模型编码失败:', err);
} finally {
loading.value = false;
}
};
const changePage = (next: number) => {
if (next === 1) {
if (query.value.pageIndex >= maxPage.value) return;
query.value.pageIndex += 1;
} else {
if (query.value.pageIndex <= 1) return;
query.value.pageIndex -= 1;
}
fetchData();
};
const onSearch = useDebounceFn((kw: string) => {
query.value.pageIndex = 1;
query.value.filter = kw;
fetchData();
}, 400);
const onChange = (val?: string) => {
emit('update:value', val);
emit('change', val);
if (val) {
const found = options.value.find((o) => o.value === val) || null;
emit('item-change', found);
props.onResolve && props.onResolve(found);
} else {
emit('item-change', null);
props.onResolve && props.onResolve(null);
}
};
watch(
() => [props.filedType, props.typeCode, props.ioTPlatform, props.ioTPlatformProductId],
() => {
// reset when filedType/typeCode/platform/product changes
query.value.pageIndex = 1;
query.value.filter = '';
options.value = [];
total.value = 0;
// IDfiledType/typeCode
if (props.ioTPlatform && props.ioTPlatformProductId) {
fetchData();
}
},
{ immediate: true },
);
//
watch(
() => props.value,
(newValue) => {
if (newValue && newValue.trim() !== '' && props.ioTPlatform && props.ioTPlatformProductId && !options.value.find(item => item.value === newValue)) {
//
fetchData();
}
},
{ immediate: true },
);
</script>
<template>
<Select
:value="value"
:showSearch="true"
:filter-option="false"
:options="options"
:placeholder="placeholder"
:disabled="disabled"
:allowClear="allowClear"
:loading="loading"
@search="onSearch"
@change="onChange"
>
<template #dropdownRender="{ menuNode: menu }">
<v-nodes :vnodes="menu" />
<Divider style="margin: 4px 0" />
<div @mousedown="(e) => e.preventDefault()">
<Row type="flex" justify="space-around" align="middle">
<ChevronLeft @click="changePage(0)" :class="{ 'text-gray-400': query.pageIndex <= 1 }"
style="cursor: pointer; width: 16px; height: 16px;" />
<div>{{ `${query.pageIndex}/${maxPage}` }}</div>
<ChevronRight @click="changePage(1)" :class="{ 'text-gray-400': query.pageIndex >= maxPage }"
style="cursor: pointer; width: 16px; height: 16px;" />
</Row>
</div>
</template>
</Select>
</template>
<style lang="less" scoped>
.text-gray-400 {
color: #9ca3af;
cursor: not-allowed !important;
}
</style>

View File

@ -22,6 +22,8 @@ import {
import { TableAction } from '#/components/table-action'; import { TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import IoTPlatformThingModelDataSelect from '../IoTPlatformThingModelDataSelect.vue';
defineOptions({ defineOptions({
name: 'DeviceThingModelPropertyModal', name: 'DeviceThingModelPropertyModal',
}); });
@ -155,13 +157,34 @@ const [Grid, gridApi] = useVbenVxeGrid({
}, },
}); });
// / //
const [PropertyFormModal, propertyFormModalApi] = useVbenModal({ const [AddPropertyFormModal, addPropertyFormModalApi] = useVbenModal({
draggable: true, draggable: true,
footer: true, footer: true,
showCancelButton: true, showCancelButton: true,
showConfirmButton: true, showConfirmButton: true,
onConfirm: submitProperty, 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: () => { onBeforeClose: () => {
return true; return true;
}, },
@ -184,19 +207,16 @@ const [PropertyFormModal, propertyFormModalApi] = useVbenModal({
// //
values.parsingSequence = String(values.parsingSequence); values.parsingSequence = String(values.parsingSequence);
} }
propertyFormApi.setValues(values); editPropertyFormApi.setValues(values);
} }
} catch (error) { } catch (error) {
console.error('加载属性详情失败:', error); console.error('加载属性详情失败:', error);
} }
}); });
} else if (isOpen) {
//
propertyFormApi.resetForm();
} }
}, },
onCancel: () => { onCancel: () => {
propertyFormModalApi.close(); editPropertyFormModalApi.close();
}, },
}); });
@ -230,151 +250,273 @@ const [CopyDeviceThingModelModal, copyDeviceThingModelModalApi] = useVbenModal({
}, },
}); });
// schema // schema
const propertyFormSchema = computed(() => { const addPropertyFormSchema = computed(() => [
const isEdit = !!editRow.value.id; {
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 [ return [
{ {
component: 'Input', component: 'Input',
fieldName: 'standardFieldDisplayName', fieldName: 'standardFieldDisplayName',
label: '标准属性名称', label: '标准属性名称',
rules: z.preprocess( rules: z.preprocess(
(v) => (v == null ? '' : v), (v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')), z.string().min(1, $t('common.required')),
), ),
componentProps: { componentProps: {
placeholder: `${$t('common.pleaseInput')}标准属性名称`, placeholder: `${$t('common.pleaseInput')}标准属性名称`,
disabled: isEdit, //
},
}, },
{ },
component: 'Input', {
fieldName: 'standardFieldName', component: 'Input',
label: '标准属性标识符', fieldName: 'standardFieldName',
rules: z.preprocess( label: '标准属性标识符',
(v) => (v == null ? '' : v), rules: z.preprocess(
z.string().min(1, $t('common.required')), (v) => (v == null ? '' : v),
), z.string().min(1, $t('common.required')),
componentProps: { ),
placeholder: `${$t('common.pleaseInput')}标准属性标识符`, componentProps: {
disabled: isEdit, // placeholder: `${$t('common.pleaseInput')}标准属性标识符`,
},
}, },
{ },
component: 'ApiSelect', {
fieldName: 'standardFieldValueType', component: 'ApiSelect',
label: '标准属性值类型', fieldName: 'standardFieldValueType',
rules: z.preprocess( label: '标准属性值类型',
(v) => (v == null ? '' : v), rules: z.preprocess(
z.string().min(1, $t('common.required')), (v) => (v == null ? '' : v),
), z.string().min(1, $t('common.required')),
componentProps: { ),
api: getCommonGetSelectList, componentProps: {
params: { api: getCommonGetSelectList,
query: { params: {
typeName: 'StandardThingModelDataTypeEnum', query: {
}, typeName: 'StandardThingModelDataTypeEnum',
},
labelField: 'value',
valueField: 'secondValue',
optionsPropName: 'options',
immediate: true,
allowClear: true,
disabled: isEdit, //
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 [];
}, },
}, },
}, labelField: 'value',
{ valueField: 'secondValue',
component: 'Input', optionsPropName: 'options',
fieldName: 'ioTPlatformRawFieldName', immediate: true,
label: '平台属性标识符', allowClear: true,
rules: z.preprocess( placeholder: `${$t('common.pleaseSelect')}标准属性值类型`,
(v) => (v == null ? '' : v), afterFetch: (res: any) => {
z.string().min(1, $t('common.required')), if (Array.isArray(res)) return res;
), if (res && Array.isArray(res.items)) return res.items;
componentProps: { if (res && Array.isArray(res.data)) return res.data;
placeholder: `${$t('common.pleaseInput')}平台属性标识符`, return [];
}, },
}, },
{ },
component: 'ApiSelect', {
fieldName: 'ioTPlatformRawFieldDataType', component: 'Input',
label: '平台属性值类型', fieldName: 'ioTPlatformRawFieldName',
rules: z.preprocess( label: '平台属性标识符',
(v) => (v == null ? '' : v), rules: z.preprocess(
z.string().min(1, $t('common.required')), (v) => (v == null ? '' : v),
), z.string().min(1, $t('common.required')),
componentProps: { ),
api: getCommonGetSelectList, componentProps: {
params: { placeholder: `${$t('common.pleaseInput')}平台属性标识符`,
query: { },
typeName: 'StandardThingModelDataTypeEnum', },
}, {
}, component: 'ApiSelect',
labelField: 'value', fieldName: 'ioTPlatformRawFieldDataType',
valueField: 'secondValue', label: '平台属性值类型',
optionsPropName: 'options', rules: z.preprocess(
immediate: true, (v) => (v == null ? '' : v),
allowClear: true, z.string().min(1, $t('common.required')),
placeholder: `${$t('common.pleaseSelect')}平台属性值类型`, ),
afterFetch: (res: any) => { componentProps: {
if (Array.isArray(res)) return res; api: getCommonGetSelectList,
if (res && Array.isArray(res.items)) return res.items; params: {
if (res && Array.isArray(res.data)) return res.data; query: {
return []; typeName: 'StandardThingModelDataTypeEnum',
}, },
}, },
}, labelField: 'value',
{ valueField: 'secondValue',
component: 'Switch', optionsPropName: 'options',
fieldName: 'isValueNeedConvert', immediate: true,
label: '值类型是否转换', allowClear: true,
componentProps: { placeholder: `${$t('common.pleaseSelect')}平台属性值类型`,
checkedChildren: '是', afterFetch: (res: any) => {
unCheckedChildren: '否', if (Array.isArray(res)) return res;
style: { width: 'auto' }, // if (res && Array.isArray(res.items)) return res.items;
if (res && Array.isArray(res.data)) return res.data;
return [];
}, },
}, },
{ },
component: 'ApiSelect', {
fieldName: 'parsingSequence', component: 'Switch',
label: '解析方式', fieldName: 'isValueNeedConvert',
componentProps: { label: '值类型是否转换',
api: getCommonGetSelectList, componentProps: {
params: { checkedChildren: '是',
query: { unCheckedChildren: '否',
typeName: 'ParsingSequenceTypeEnum', style: { width: 'auto' }, //
}, },
}, },
labelField: 'value', {
valueField: 'key', component: 'ApiSelect',
optionsPropName: 'options', fieldName: 'parsingSequence',
immediate: true, label: '解析方式',
allowClear: true, componentProps: {
placeholder: `${$t('common.pleaseSelect')}解析方式`, api: getCommonGetSelectList,
afterFetch: (res: any) => { params: {
let items = []; query: {
if (Array.isArray(res)) { typeName: 'ParsingSequenceTypeEnum',
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),
}));
}, },
}, },
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', component: 'InputNumber',
fieldName: 'nativeSkipNumber', fieldName: 'nativeSkipNumber',
@ -414,8 +556,8 @@ const propertyFormSchema = computed(() => {
]; ];
}); });
// //
const [PropertyForm, propertyFormApi] = useVbenForm({ const [AddPropertyForm, addPropertyFormApi] = useVbenForm({
collapsed: false, collapsed: false,
commonConfig: { commonConfig: {
labelWidth: 140, labelWidth: 140,
@ -424,18 +566,34 @@ const [PropertyForm, propertyFormApi] = useVbenForm({
}, },
}, },
layout: 'horizontal', layout: 'horizontal',
schema: propertyFormSchema.value, schema: addPropertyFormSchema,
showCollapseButton: false, showCollapseButton: false,
showDefaultActions: false, showDefaultActions: false,
wrapperClass: 'grid-cols-2', wrapperClass: 'grid-cols-2',
}); });
// editRow schema //
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( watch(
() => editRow.value.id, () => editRow.value.id,
() => { () => {
if (propertyFormApi && propertyFormApi.updateSchema) { if (editPropertyFormApi && editPropertyFormApi.updateSchema) {
propertyFormApi.updateSchema(propertyFormSchema.value); editPropertyFormApi.updateSchema(editPropertyFormSchema.value);
} }
}, },
); );
@ -588,14 +746,13 @@ const [CopyDeviceThingModelForm, copyDeviceThingModelFormApi] = useVbenForm({
// //
function openAddPropertyModal() { function openAddPropertyModal() {
editRow.value = {}; addPropertyFormModalApi.open();
propertyFormModalApi.open();
} }
// //
function openEditPropertyModal(record: any) { function openEditPropertyModal(record: any) {
editRow.value = record; editRow.value = record;
propertyFormModalApi.open(); editPropertyFormModalApi.open();
} }
// //
@ -610,44 +767,105 @@ function openCopyDeviceThingModelModal() {
copyDeviceThingModelModalApi.open(); copyDeviceThingModelModalApi.open();
} }
// / //
async function submitProperty() { async function submitAddProperty() {
const isEdit = !!editRow.value.id; const { valid } = await addPropertyFormApi.validate();
const { valid } = await propertyFormApi.validate();
if (!valid) return; if (!valid) return;
const formValues = await propertyFormApi.getValues(); const formValues = await addPropertyFormApi.getValues();
const fetchParams: any = { const fetchParams: any = {
...formValues,
deviceThingModelId: deviceThingModelId.value, deviceThingModelId: deviceThingModelId.value,
...(formValues.parsingSequence && { ...(formValues.ioTPlatformThingModelDataId && {
// ioTPlatformThingModelDataId: String(
parsingSequence: Number.parseInt(String(formValues.parsingSequence)), 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,
}), }),
...(isEdit && { id: editRow.value.id }),
}; };
try { try {
const api = isEdit const resp = await postDeviceThingModelManagementPropertyCreateAsync({
? postDeviceThingModelManagementPropertyUpdateAsync body: fetchParams,
: postDeviceThingModelManagementPropertyCreateAsync; });
const resp = await api({ body: fetchParams });
if (resp.data) { if (resp.data) {
Message.success( Message.success($t('common.addSuccess'));
isEdit ? $t('common.editSuccess') : $t('common.addSuccess'), addPropertyFormModalApi.close();
); await nextTick();
propertyFormModalApi.close(); 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 = {}; editRow.value = {};
await nextTick(); await nextTick();
if (gridApi && gridApi.reload) { if (gridApi && gridApi.reload) {
await gridApi.reload(); await gridApi.reload();
} }
} else { } else {
Message.error(isEdit ? $t('common.editFail') : $t('common.addFail')); Message.error($t('common.editFail'));
} }
} catch (error) { } catch (error) {
console.error('提交属性失败:', error); console.error('提交属性失败:', error);
Message.error(isEdit ? $t('common.editFail') : $t('common.addFail'));
} }
} }
@ -685,7 +903,6 @@ async function submitCopyDeviceThingModel() {
} }
} catch (error) { } catch (error) {
console.error('快速复制设备端物模型属性失败:', error); console.error('快速复制设备端物模型属性失败:', error);
Message.error('快速复制设备端物模型属性失败');
} }
} }
@ -727,7 +944,6 @@ async function submitCopyProperty() {
} }
} catch (error) { } catch (error) {
console.error('快速复制平台端物模型属性失败:', error); console.error('快速复制平台端物模型属性失败:', error);
Message.error('快速复制平台端物模型属性失败');
} }
} }
@ -748,7 +964,6 @@ async function onDeleteProperty(record: any) {
} }
} catch (error) { } catch (error) {
console.error('删除属性失败:', error); console.error('删除属性失败:', error);
Message.error($t('common.deleteFail'));
} }
} }
@ -824,10 +1039,15 @@ const [Modal, modalApi] = useVbenModal({
</template> </template>
</Grid> </Grid>
<!-- 属性新增/编辑弹窗 --> <!-- 属性新增弹窗 -->
<PropertyFormModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[900px]"> <AddPropertyFormModal :title="$t('common.add')" class="w-[900px]">
<PropertyForm /> <AddPropertyForm />
</PropertyFormModal> </AddPropertyFormModal>
<!-- 属性编辑弹窗 -->
<EditPropertyFormModal :title="$t('common.edit')" class="w-[900px]">
<EditPropertyForm />
</EditPropertyFormModal>
<!-- 快速复制平台端物模型属性弹窗 --> <!-- 快速复制平台端物模型属性弹窗 -->
<CopyPropertyModal title="快速复制平台端物模型属性" class="w-[600px]"> <CopyPropertyModal title="快速复制平台端物模型属性" class="w-[600px]">
@ -835,10 +1055,7 @@ const [Modal, modalApi] = useVbenModal({
</CopyPropertyModal> </CopyPropertyModal>
<!-- 快速复制设备端物模型属性弹窗 --> <!-- 快速复制设备端物模型属性弹窗 -->
<CopyDeviceThingModelModal <CopyDeviceThingModelModal title="快速复制设备端物模型属性" class="w-[600px]">
title="快速复制设备端物模型属性"
class="w-[600px]"
>
<CopyDeviceThingModelForm /> <CopyDeviceThingModelForm />
</CopyDeviceThingModelModal> </CopyDeviceThingModelModal>
</Modal> </Modal>