Compare commits

..

3 Commits

Author SHA1 Message Date
ChenYi
5fe1af6a75 OneNET物模型管理实现 2025-10-23 13:54:19 +08:00
ChenYi
328e4b2c2f 复制产品模型已实现 2025-10-23 11:48:10 +08:00
ChenYi
f349409516 增加查询过滤 2025-10-23 11:20:10 +08:00
7 changed files with 184 additions and 16 deletions

View File

@ -1190,10 +1190,15 @@ export const CopyAnotherProductInputSchema = {
type: 'string',
description: '平台产品ID',
nullable: true
},
sourceProductId: {
type: 'string',
description: '源产品ID',
nullable: true
}
},
additionalProperties: false,
description: '根据数据ID复制已存在物模型信息'
description: '复制已存在产品设备物模型信息'
} as const;
export const CopyStandardThingModelInputSchema = {

View File

@ -517,7 +517,7 @@ export const postThingModelInfoFindByPlatformProductIdAsync = <ThrowOnError exte
};
/**
* ID复制已存在物模型信
*
*/
export const postThingModelInfoCopyAnotherThingModelAsync = <ThrowOnError extends boolean = false>(options?: Options<PostThingModelInfoCopyAnotherThingModelAsyncData, ThrowOnError>) => {
return (options?.client ?? client).post<PostThingModelInfoCopyAnotherThingModelAsyncResponse, PostThingModelInfoCopyAnotherThingModelAsyncError, ThrowOnError>({
@ -537,7 +537,7 @@ export const postThingModelInfoCopyStandardThingModel = <ThrowOnError extends bo
};
/**
*
*
*/
export const postThingModelInfoPageAsync = <ThrowOnError extends boolean = false>(options?: Options<PostThingModelInfoPageAsyncData, ThrowOnError>) => {
return (options?.client ?? client).post<PostThingModelInfoPageAsyncResponse, PostThingModelInfoPageAsyncError, ThrowOnError>({

View File

@ -201,7 +201,7 @@ export type ControllerInterfaceApiDescriptionModel = {
};
/**
* ID复制已存在物模型信
*
*/
export type CopyAnotherProductInput = {
ioTPlatform?: IoTPlatformTypeEnum;
@ -209,6 +209,10 @@ export type CopyAnotherProductInput = {
* ID
*/
ioTPlatformProductId?: (string) | null;
/**
* ID
*/
sourceProductId?: (string) | null;
};
/**

View File

@ -224,7 +224,9 @@
"StandardFieldName": "StandardFieldName",
"StandardFieldDisplayName": "StandardFieldDisplayName",
"IsValueNeedConvert": "IsValueNeedConvert",
"StandardFieldValueType": "StandardFieldValueType"
"StandardFieldValueType": "StandardFieldValueType",
"copyStandardThingModel": "CopyStandardThingModel",
"copyAnotherThingModelModal": "CopyAnotherThingModelModal"
},
"IoTDBBase": {
"IoTDataType": "IoTDataType",

View File

@ -217,7 +217,9 @@
"StandardFieldName": "标准物模型编码",
"StandardFieldDisplayName": "标准物模型名称",
"IsValueNeedConvert": "是否需要值类型转换",
"StandardFieldValueType": "标准物模型值类型"
"StandardFieldValueType": "标准物模型值类型",
"copyStandardThingModel": "复制标准模型",
"copyAnotherThingModelModal": "复制已有模型"
},
"IoTDBBase": {
"IoTDataType": "数据类型",

View File

@ -11,6 +11,7 @@ import { message as Message, Modal, Tag } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
postThingModelInfoCopyAnotherThingModelAsync,
postThingModelInfoCopyStandardThingModel,
postThingModelInfoCreateAsync,
postThingModelInfoDeleteAsync,
@ -22,6 +23,7 @@ import { $t } from '#/locales';
import {
addThingModelFormSchema,
copyThingModelFormSchema,
editThingModelFormSchema,
querySchema,
tableSchema,
@ -75,12 +77,16 @@ const gridOptions: VxeGridProps<any> = {
ajax: {
query: async ({ page }, formValues) => {
const { data } = await postThingModelInfoPageAsync({
body: {
query: {
pageIndex: page.currentPage,
pageSize: page.pageSize,
ioTPlatform: Number.parseInt(props.ioTPlatform) as 1 | 2,
ioTPlatformProductId: props.productId,
...formValues,
},
});
//
hasData.value = data?.items && data.items.length > 0;
return data;
},
},
@ -91,6 +97,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
const editRow: Record<string, any> = ref({});
//
const hasData = ref(true);
const [ThingModelModal, thingModelModalApi] = useVbenModal({
draggable: true,
footer: true,
@ -113,6 +123,20 @@ const [ThingModelModal, thingModelModalApi] = useVbenModal({
},
});
const [CopyModal, copyModalApi] = useVbenModal({
draggable: true,
footer: true,
showCancelButton: true,
showConfirmButton: true,
onConfirm: submitCopy,
onBeforeClose: () => {
return true;
},
onCancel: () => {
copyModalApi.close();
},
});
const [AddForm, addFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
@ -143,11 +167,27 @@ const [EditForm, editFormApi] = useVbenForm({
wrapperClass: 'grid-cols-2',
});
const [CopyForm, copyFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 110,
componentProps: {
class: 'w-4/5',
},
},
layout: 'horizontal',
schema: copyThingModelFormSchema.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
// props
watch(
() => [props.visible, props.productId, props.ioTPlatform],
async ([visible, productId, ioTPlatform]) => {
console.log('物模型模态框props变化:', { visible, productId, ioTPlatform });
console.log('所有props:', props);
if (visible && productId) {
//
setTimeout(async () => {
@ -233,6 +273,54 @@ const openAddModal = async () => {
thingModelModalApi.open();
};
//
const openCopyAnotherThingModelModal = async () => {
console.log('打开复制模态框当前props:', {
productId: props.productId,
productName: props.productName,
ioTPlatform: props.ioTPlatform
});
copyModalApi.open();
};
//
async function submitCopy() {
const { valid } = await copyFormApi.validate();
if (!valid) return;
const formValues = await copyFormApi.getValues();
console.log('复制提交参数:', {
formValues,
props: {
productId: props.productId,
productName: props.productName,
ioTPlatform: props.ioTPlatform
}
});
try {
const resp = await postThingModelInfoCopyAnotherThingModelAsync({
body: {
ioTPlatform: Number.parseInt(props.ioTPlatform) as 1 | 2,
ioTPlatformProductId: props.productId,
sourceProductId: formValues.ioTPlatformProductId,
},
});
if (resp.data) {
Message.success('复制模型成功');
copyModalApi.close();
gridApi.reload();
} else {
Message.error('复制模型失败');
}
} catch (error) {
console.error('复制模型失败:', error);
Message.error('复制模型失败');
}
}
//
async function onDel(record: any) {
try {
@ -277,6 +365,7 @@ function closeModal() {
emit('update:visible', false);
emit('close');
}
</script>
<template>
@ -295,12 +384,20 @@ function closeModal() {
auth: ['AbpIdentity.Users.Create'],
},
{
label: '复制标准模型',
label: $t('abp.thingModelInfos.copyStandardThingModel'),
type: 'default',
icon: 'ant-design:copy-outlined',
onClick: copyStandardThingModel,
auth: ['AbpIdentity.Users.Create'],
},
{
label: $t('abp.thingModelInfos.copyAnotherThingModelModal'),
type: 'default',
icon: 'ant-design:copy-outlined',
onClick: openCopyAnotherThingModelModal,
auth: ['AbpIdentity.Users.Create'],
ifShow: !hasData,
},
]" />
</template>
@ -340,5 +437,10 @@ function closeModal() {
<ThingModelModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]">
<component :is="editRow.id ? EditForm : AddForm" />
</ThingModelModal>
<!-- 复制已有模型模态框 -->
<CopyModal title="复制已有模型" class="w-[600px]">
<CopyForm />
</CopyModal>
</Modal>
</template>

View File

@ -4,7 +4,10 @@ import { z } from '@vben/common-ui';
import dayjs from 'dayjs';
import { getCommonGetSelectList } from '#/api-client';
import {
getCommonGetSelectList,
postOneNetProductListAsync,
} from '#/api-client';
import { $t } from '#/locales';
export const querySchema = computed(() => [
@ -217,7 +220,7 @@ export const addThingModelFormSchema = computed(() => [
return [];
},
},
},
},
{
component: 'Switch',
fieldName: 'isValueNeedConvert',
@ -251,7 +254,8 @@ export const editThingModelFormSchema = computed(() => [
optionsPropName: 'options',
immediate: true,
disabled: true, // 编辑时禁用
placeholder: $t('common.pleaseSelect') + $t('abp.thingModelInfos.FiledType'),
placeholder:
$t('common.pleaseSelect') + $t('abp.thingModelInfos.FiledType'),
afterFetch: (res: any) => {
// 确保返回的是数组格式
if (Array.isArray(res)) {
@ -277,7 +281,8 @@ export const editThingModelFormSchema = computed(() => [
),
componentProps: {
// disabled: true, // 编辑时禁用
placeholder: $t('common.pleaseInput') +
placeholder:
$t('common.pleaseInput') +
$t('abp.thingModelInfos.IoTPlatformRawFieldName'),
},
},
@ -298,7 +303,9 @@ export const editThingModelFormSchema = computed(() => [
.toString()
.toUpperCase();
},
placeholder: $t('common.pleaseInput') + $t('abp.thingModelInfos.StandardFieldDisplayName'),
placeholder:
$t('common.pleaseInput') +
$t('abp.thingModelInfos.StandardFieldDisplayName'),
}),
},
{
@ -308,7 +315,8 @@ export const editThingModelFormSchema = computed(() => [
rules: z.string().min(1, $t('common.required')),
componentProps: {
disabled: true, // 编辑时禁用
placeholder: $t('common.pleaseSelect') + $t('abp.thingModelInfos.StandardFieldName')
placeholder:
$t('common.pleaseSelect') + $t('abp.thingModelInfos.StandardFieldName'),
},
},
{
@ -330,7 +338,8 @@ export const editThingModelFormSchema = computed(() => [
immediate: true,
allowClear: true,
disabled: true, // 编辑时禁用
placeholder: $t('common.pleaseSelect') +
placeholder:
$t('common.pleaseSelect') +
$t('abp.thingModelInfos.StandardFieldValueType'),
afterFetch: (res: any) => {
let items = [];
@ -350,7 +359,7 @@ export const editThingModelFormSchema = computed(() => [
}));
},
},
},
},
{
component: 'Switch',
fieldName: 'isValueNeedConvert',
@ -360,3 +369,47 @@ export const editThingModelFormSchema = computed(() => [
},
},
]);
// 复制已有模型表单schema
export const copyThingModelFormSchema = computed(() => [
{
component: 'ApiSelect',
fieldName: 'ioTPlatformProductId',
label: '选择要复制的产品',
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, '请选择要复制的产品'),
),
componentProps: {
api: postOneNetProductListAsync,
params: {
query: {
pageIndex: 1,
pageSize: 1000,
},
},
labelField: 'productName',
valueField: 'ioTPlatformProductId',
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 && Array.isArray(res.data.items)) {
return res.data.items;
}
return [];
},
},
},
]);