Compare commits

..

No commits in common. "e860a539fa80af076b26673282b07eeca6743361" and "45240cac7e16fb4678b4287616e00cf3cb680cb2" have entirely different histories.

8 changed files with 149 additions and 1164 deletions

View File

@ -464,29 +464,6 @@ export const BatchCreateDeviceAggregationInputSchema = {
description: '批量创建设备信息'
} as const;
export const BindingDeviceThingModelInputSchema = {
type: 'object',
properties: {
devieDataId: {
type: 'string',
description: '设备数据Id',
format: 'uuid'
},
isNeedConfigDevicMdoel: {
type: 'boolean',
description: '是否需要配置设备模型默认false'
},
deviceThingModelDataId: {
type: 'string',
description: '设备物模型数据Id',
format: 'uuid',
nullable: true
}
},
additionalProperties: false,
description: '绑定设备物模型输入'
} as const;
export const BuildAnalysisScriptInputSchema = {
type: 'object',
properties: {
@ -3078,6 +3055,11 @@ export const DeviceThingModelPropertyUpdateInputSchema = {
description: '设备端物模型Id',
format: 'uuid'
},
filedType: {
type: 'string',
description: '物联网平台中对应产品物模型属性或者事件类型 JiShe.ServicePro.Core.DataDictionaryTypeConst',
nullable: true
},
ioTPlatformRawFieldName: {
minLength: 1,
type: 'string',
@ -5214,7 +5196,6 @@ export const IoTDBDynamicObjectPagedResultDtoSchema = {
} as const;
export const IoTPlatformProductInfoInputSchema = {
required: ['ioTPlatformType'],
type: 'object',
properties: {
ioTPlatformType: {
@ -5246,23 +5227,6 @@ export const IoTPlatformProductInfoOutputSchema = {
description: '平台产品信息'
} as const;
export const IoTPlatformProductPropertyInfoInputSchema = {
required: ['ioTPlatformProductId', 'ioTPlatformType'],
type: 'object',
properties: {
ioTPlatformType: {
'$ref': '#/components/schemas/IoTPlatformTypeEnum'
},
ioTPlatformProductId: {
minLength: 1,
type: 'string',
description: '物联网平台中对应的产品Id'
}
},
additionalProperties: false,
description: '产品属性信息输入'
} as const;
export const IoTPlatformThingModelCreateInputSchema = {
type: 'object',
properties: {
@ -5302,20 +5266,6 @@ export const IoTPlatformThingModelCreateInputSchema = {
isValueNeedConvert: {
type: 'boolean',
description: '是否需要值类型转换'
},
ioTPlatformRawFieldDataType: {
type: 'string',
description: '物联网平台中对应的产品物模型属性或者事件数据类型int等/>',
nullable: true
},
isSpecialIdentifier: {
type: 'boolean',
description: '是否是特殊物模型标识符'
},
ioTPlatformRawFieldExtension: {
type: 'string',
description: '物联网平台中对应产品物模型标识符扩展,用于扩展结构体类型',
nullable: true
}
},
additionalProperties: false
@ -5413,11 +5363,6 @@ export const IoTPlatformThingModelInfoDtoSchema = {
description: '物联网平台中对应的产品物模型属性或者事件名称',
nullable: true
},
ioTPlatformRawFieldDataType: {
type: 'string',
description: '物联网平台中对应的产品物模型属性或者事件数据类型int等JiShe.ServicePro.Core.OneNETAllThingModel',
nullable: true
},
standardFieldName: {
type: 'string',
description: '管理后台产品标准的物模型属性或者事件名称',
@ -5558,20 +5503,6 @@ export const IoTPlatformThingModelUpdateInputSchema = {
type: 'boolean',
description: '是否需要值类型转换'
},
ioTPlatformRawFieldDataType: {
type: 'string',
description: '物联网平台中对应的产品物模型属性或者事件数据类型int等/>',
nullable: true
},
isSpecialIdentifier: {
type: 'boolean',
description: '是否是特殊物模型标识符'
},
ioTPlatformRawFieldExtension: {
type: 'string',
description: '物联网平台中对应产品物模型标识符扩展,用于扩展结构体类型',
nullable: true
},
id: {
type: 'string',
format: 'uuid'

File diff suppressed because one or more lines are too long

View File

@ -172,24 +172,6 @@ export type BatchCreateDeviceAggregationInput = {
deviceSourceTypeEnum?: DeviceSourceTypeEnum;
};
/**
*
*/
export type BindingDeviceThingModelInput = {
/**
* Id
*/
devieDataId?: string;
/**
* false
*/
isNeedConfigDevicMdoel?: boolean;
/**
* Id
*/
deviceThingModelDataId?: (string) | null;
};
/**
*
*/
@ -1770,6 +1752,10 @@ export type DeviceThingModelPropertyUpdateInput = {
* Id
*/
deviceThingModelId: string;
/**
* JiShe.ServicePro.Core.DataDictionaryTypeConst
*/
filedType?: (string) | null;
/**
*
*/
@ -2600,7 +2586,7 @@ export type IoTDBDynamicObjectPagedResultDto = {
*
*/
export type IoTPlatformProductInfoInput = {
ioTPlatformType: IoTPlatformTypeEnum;
ioTPlatformType?: IoTPlatformTypeEnum;
};
/**
@ -2618,17 +2604,6 @@ export type IoTPlatformProductInfoOutput = {
productName?: (string) | null;
};
/**
*
*/
export type IoTPlatformProductPropertyInfoInput = {
ioTPlatformType: IoTPlatformTypeEnum;
/**
* Id
*/
ioTPlatformProductId: string;
};
export type IoTPlatformThingModelCreateInput = {
ioTPlatform?: IoTPlatformTypeEnum;
/**
@ -2659,18 +2634,6 @@ export type IoTPlatformThingModelCreateInput = {
*
*/
isValueNeedConvert?: boolean;
/**
* int等/>
*/
ioTPlatformRawFieldDataType?: (string) | null;
/**
*
*/
isSpecialIdentifier?: boolean;
/**
*
*/
ioTPlatformRawFieldExtension?: (string) | null;
};
/**
@ -2724,10 +2687,6 @@ export type IoTPlatformThingModelInfoDto = {
*
*/
ioTPlatformRawFieldName?: (string) | null;
/**
* int等JiShe.ServicePro.Core.OneNETAllThingModel
*/
ioTPlatformRawFieldDataType?: (string) | null;
/**
*
*/
@ -2824,18 +2783,6 @@ export type IoTPlatformThingModelUpdateInput = {
*
*/
isValueNeedConvert?: boolean;
/**
* int等/>
*/
ioTPlatformRawFieldDataType?: (string) | null;
/**
*
*/
isSpecialIdentifier?: boolean;
/**
*
*/
ioTPlatformRawFieldExtension?: (string) | null;
id?: string;
};
@ -5969,16 +5916,6 @@ export type PostDeviceInfoCacheDeviceDataToRedisResponse = (boolean);
export type PostDeviceInfoCacheDeviceDataToRedisError = unknown;
export type PostDeviceInfoBindingDeviceThingModelData = {
query?: {
input?: BindingDeviceThingModelInput;
};
};
export type PostDeviceInfoBindingDeviceThingModelResponse = (boolean);
export type PostDeviceInfoBindingDeviceThingModelError = unknown;
export type PostDeviceThingModelManagementCreateAsyncData = {
query?: {
input?: DeviceThingModelCreateInput;
@ -6301,16 +6238,6 @@ export type PostAggregationIoTplatformGetIoTplatformProductInfoAsyncResponse = (
export type PostAggregationIoTplatformGetIoTplatformProductInfoAsyncError = unknown;
export type PostAggregationIoTplatformGetIoTplatformProductPropertyInfoAsyncData = {
query?: {
input?: IoTPlatformProductPropertyInfoInput;
};
};
export type PostAggregationIoTplatformGetIoTplatformProductPropertyInfoAsyncResponse = (Array<SelectResult>);
export type PostAggregationIoTplatformGetIoTplatformProductPropertyInfoAsyncError = unknown;
export type PostIoTplatformThingModelInfoCreateAsyncData = {
query?: {
input?: IoTPlatformThingModelCreateInput;

View File

@ -9,7 +9,6 @@ import { Page, useVbenModal } from '@vben/common-ui';
import {
Button,
Input,
message as Message,
Modal,
Popover,
@ -25,21 +24,18 @@ import {
postAggregationDeviceDeviceCommandForApiAsync,
postAggregationDeviceRepushDeviceInfoToIoTplatform,
postDeviceInfoCacheDeviceDataToRedis,
postDeviceInfoBindingDeviceThingModel,
postDeviceInfoPage,
} from '#/api-client';
import { Icon } from '#/components/icon';
import { Loading } from '#/components/Loading';
import { TableAction } from '#/components/table-action';
import { $t } from '#/locales';
import IoTPlatformThingModelDataSelect from '#/views/thingmodelinfo/IoTPlatformThingModelDataSelect.vue';
import {
addDeviceFormSchema,
batchAddDeviceFormSchema,
commandFormSchema,
editDeviceFormSchemaEdit,
bindDeviceThingModelFormSchema,
querySchema,
tableSchema,
} from './schema';
@ -163,75 +159,6 @@ const cacheRefreshLoading = ref(false);
const pageLoading = ref(false);
const loadingTip = ref('缓存刷新中...');
const commandRow: Record<string, any> = ref({});
//
const bindRow: Record<string, any> = ref({});
// -
interface CommandProperty {
id: string; //
propertyId: string; // ID
propertyName: string; //
platformFieldName: string; //
standardFieldName: string; //
value: string; //
}
const commandProperties = ref<CommandProperty[]>([
{
id: `prop-${Date.now()}`,
propertyId: '',
propertyName: '',
platformFieldName: '',
standardFieldName: '',
value: '',
},
]);
// -
const addCommandProperty = () => {
commandProperties.value.push({
id: `prop-${Date.now()}-${Math.random()}`,
propertyId: '',
propertyName: '',
platformFieldName: '',
standardFieldName: '',
value: '',
});
};
// -
const removeCommandProperty = (id: string) => {
const index = commandProperties.value.findIndex((p) => p.id === id);
if (index > -1) {
commandProperties.value.splice(index, 1);
}
//
if (commandProperties.value.length === 0) {
addCommandProperty();
}
};
//
const handlePropertyChange = (item: any, property: CommandProperty) => {
if (item) {
property.propertyId = item.id || item.value || '';
property.propertyName =
item.standardFieldDisplayName ||
item.ioTPlatformRawFieldName ||
item.label ||
'';
// 使使
property.platformFieldName = item.ioTPlatformRawFieldName || item.standardFieldName || '';
property.standardFieldName = item.standardFieldName || '';
} else {
property.propertyId = '';
property.propertyName = '';
property.platformFieldName = '';
property.standardFieldName = '';
}
};
const [UserModal, userModalApi] = useVbenModal({
draggable: true,
onConfirm: submit,
@ -246,35 +173,6 @@ const [CommandModal, commandModalApi] = useVbenModal({
onConfirm: submitCommand,
onBeforeClose: () => {
commandRow.value = {};
//
commandProperties.value = [
{
id: `prop-${Date.now()}`,
propertyId: '',
propertyName: '',
platformFieldName: '',
standardFieldName: '',
value: '',
},
];
return true;
},
onOpenChange: (isOpen: boolean) => {
if (isOpen && commandRow.value) {
// -
if (commandProperties.value.length === 0) {
addCommandProperty();
}
}
},
});
//
const [BindModal, bindModalApi] = useVbenModal({
draggable: true,
onConfirm: submitBindDeviceThingModel,
onBeforeClose: () => {
bindRow.value = {};
return true;
},
});
@ -330,21 +228,6 @@ const [CommandForm, commandFormApi] = useVbenForm({
showDefaultActions: false,
});
const [BindForm, bindFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 160,
componentProps: {
class: 'w-full',
},
},
layout: 'horizontal',
schema: bindDeviceThingModelFormSchema.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-1',
});
const [BatchAddForm, batchAddFormApi] = useVbenForm({
//
collapsed: false,
@ -571,78 +454,24 @@ const openAddModal = async () => {
const openCommandModal = (row: Record<string, any>) => {
commandRow.value = row;
//
commandProperties.value = [
{
id: `prop-${Date.now()}`,
propertyId: '',
propertyName: '',
platformFieldName: '',
standardFieldName: '',
value: '',
},
];
commandModalApi.open();
};
//
const openBindModal = async (row: Record<string, any>) => {
bindRow.value = row;
bindModalApi.open();
// 使ID
await nextTick();
await bindFormApi.setValues({
isNeedConfigDevicMdoel: false,
deviceThingModelDataId: undefined,
_ioTPlatformProductId: row.ioTPlatformProductId,
});
};
//
async function submitCommand() {
// -
const invalidProperties = commandProperties.value.filter(
(p) => !p.propertyId || !p.value || p.value.trim() === '',
);
const { valid } = await commandFormApi.validate();
if (!valid) return;
if (invalidProperties.length > 0) {
Message.error('请完整填写所有属性名称和指令值');
return;
}
// -
const validProperties = commandProperties.value.filter(
(p) => {
const key = p.platformFieldName || p.standardFieldName || p.propertyName;
return key && p.value && p.value.trim() !== '';
},
);
if (validProperties.length === 0) {
Message.error('请至少添加一个有效的属性-值对');
return;
}
const formValues = await commandFormApi.getValues();
try {
commandModalApi.setState({ loading: true, confirmLoading: true });
// -
const commandContent: Record<string, any> = {};
commandProperties.value.forEach((prop) => {
if (prop.value && prop.value.trim() !== '') {
// 使使使
const key = prop.platformFieldName || prop.standardFieldName || prop.propertyName;
if (key) {
commandContent[key] = prop.value;
}
}
});
//
const result = await postAggregationDeviceDeviceCommandForApiAsync({
body: {
id: commandRow.value.id,
commandContent: commandContent,
Id: commandRow.value.id,
CommandContent: formValues.CommandContent,
},
});
@ -650,17 +479,6 @@ async function submitCommand() {
Message.success('指令下发成功');
commandModalApi.close();
commandRow.value = {};
//
commandProperties.value = [
{
id: `prop-${Date.now()}`,
propertyId: '',
propertyName: '',
platformFieldName: '',
standardFieldName: '',
value: '',
},
];
} else {
Message.error('指令下发失败');
}
@ -672,54 +490,6 @@ async function submitCommand() {
}
}
//
async function submitBindDeviceThingModel() {
const formValues = await bindFormApi.getValues();
//
const isNeedConfig = !!formValues.isNeedConfigDevicMdoel;
const deviceThingModelDataId = formValues.deviceThingModelDataId as
| string
| undefined;
if (isNeedConfig && !deviceThingModelDataId) {
Message.error('请先选择设备端物模型');
return;
}
if (!bindRow.value?.id) {
Message.error('设备信息缺失,无法绑定设备端物模型');
return;
}
try {
bindModalApi.setState({ loading: true, confirmLoading: true });
const result = await postDeviceInfoBindingDeviceThingModel({
query: {
input: {
devieDataId: bindRow.value.id,
isNeedConfigDevicMdoel: isNeedConfig,
deviceThingModelDataId: isNeedConfig ? deviceThingModelDataId : null,
},
},
});
if (result) {
Message.success('绑定设备端物模型成功');
bindModalApi.close();
bindRow.value = {};
gridApi.reload();
} else {
Message.error('绑定设备端物模型失败');
}
} catch (error) {
console.error('绑定设备端物模型失败:', error);
Message.error('绑定设备端物模型失败');
} finally {
bindModalApi.setState({ loading: false, confirmLoading: false });
}
}
//
async function submitBatchAdd() {
const { valid } = await batchAddFormApi.validate();
@ -1049,9 +819,6 @@ const toolbarActions = computed(() => [
<Button size="small" type="link" @click="openCommandModal.bind(null, row)()">
{{ $t('abp.IoTDBBase.Command') }}
</Button>
<Button size="small" type="link" @click="openBindModal.bind(null, row)()">
绑定设备端物模型
</Button>
<Popover trigger="hover" placement="bottomRight" :overlay-style="{ minWidth: '120px' }">
<template #content>
<div style="display: flex; flex-direction: column; gap: 4px">
@ -1085,85 +852,9 @@ const toolbarActions = computed(() => [
<UserModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]">
<component :is="editRow.id ? EditForm : AddForm" />
</UserModal>
<CommandModal :title="$t('abp.IoTDBBase.Command')" class="w-[800px]">
<div class="command-form-container">
<div
v-for="(property, index) in commandProperties"
:key="property.id"
class="command-property-item"
style="margin-bottom: 16px; padding: 16px; border: 1px solid #d9d9d9; border-radius: 4px; background: #fafafa"
>
<div class="flex items-center justify-between mb-2">
<span class="text-sm font-medium" style="color: #666">
属性-值对 {{ index + 1 }}
</span>
<Button
v-if="commandProperties.length > 1"
type="text"
danger
size="small"
@click="removeCommandProperty(property.id)"
>
<template #icon>
<Icon icon="ant-design:delete-outlined" />
</template>
删除
</Button>
</div>
<div class="flex gap-4" style="align-items: flex-start">
<div style="flex: 1; min-width: 0; max-width: 50%">
<label class="block mb-2 text-sm" style="color: #333">
平台物模型属性 <span style="color: #ff4d4f">*</span>
</label>
<IoTPlatformThingModelDataSelect
:value="property.propertyId"
:ioTPlatform="
commandRow.ioTPlatform
? Number.parseInt(String(commandRow.ioTPlatform))
: null
"
:ioTPlatformProductId="commandRow.ioTPlatformProductId || null"
placeholder="请选择物模型属性"
style="width: 100%"
@update:value="
(val) => {
property.propertyId = val || '';
}
"
@item-change="(item) => handlePropertyChange(item, property)"
/>
</div>
<div style="flex: 1; min-width: 0">
<label class="block mb-2 text-sm" style="color: #333">
指令值 <span style="color: #ff4d4f">*</span>
</label>
<Input
v-model:value="property.value"
placeholder="请输入指令值"
style="width: 100%"
/>
</div>
</div>
<div v-if="property.propertyName" class="mt-2 text-xs" style="color: #999">
已选择属性: {{ property.propertyName }}
<span v-if="property.platformFieldName" style="margin-left: 8px; color: #666">
(平台字段: {{ property.platformFieldName }})
</span>
</div>
</div>
<div class="mt-4">
<Button type="dashed" block @click="addCommandProperty">
<template #icon>
<Icon icon="ant-design:plus-outlined" />
</template>
新增属性-值对
</Button>
</div>
</div>
<CommandModal :title="$t('abp.IoTDBBase.Command')" class="w-[600px]">
<CommandForm />
</CommandModal>
<BindModal title="绑定设备端物模型" class="w-[600px]">
<BindForm />
</BindModal>
<BatchAddModal title="批量添加设备" class="w-[800px]">
<BatchAddForm />
<template #footer>

View File

@ -10,7 +10,6 @@ import {
getCommonGetSelectList,
postCtWingAccountListAsync,
postCtWingProductListAsync,
postIoTplatformThingModelInfoFindByPlatformProductIdAsync,
postOneNetAccountListAsync,
postOneNetProductListAsync,
} from '#/api-client';
@ -40,7 +39,7 @@ export const querySchema = computed(() => [
allowClear: true,
placeholder: `${$t('common.pleaseSelect')}${$t('abp.deviceInfos.ioTPlatform')}`,
afterFetch: (res: any) => {
console.log('产品选择器API调用 - 平台类型:', res);
console.log('产品选择器API调用 - 平台类型:',res);
// 确保返回的是数组格式
if (Array.isArray(res)) {
@ -65,14 +64,8 @@ export const querySchema = computed(() => [
label: $t('common.BelongingProductName'),
dependencies: {
show(values: any) {
const shouldShow =
values.ioTPlatform === 2 || values.ioTPlatform === '2';
console.log(
'OneNET产品选择器显示检查 - 平台类型:',
values.ioTPlatform,
'是否显示:',
shouldShow,
);
const shouldShow = values.ioTPlatform === 2 || values.ioTPlatform === '2';
console.log('OneNET产品选择器显示检查 - 平台类型:', values.ioTPlatform, '是否显示:', shouldShow);
return shouldShow; // OneNET平台
},
triggerFields: ['ioTPlatform'],
@ -120,14 +113,8 @@ export const querySchema = computed(() => [
label: $t('common.BelongingProductName'),
dependencies: {
show(values: any) {
const shouldShow =
values.ioTPlatform === 1 || values.ioTPlatform === '1';
console.log(
'CTWing产品选择器显示检查 - 平台类型:',
values.ioTPlatform,
'是否显示:',
shouldShow,
);
const shouldShow = values.ioTPlatform === 1 || values.ioTPlatform === '1';
console.log('CTWing产品选择器显示检查 - 平台类型:', values.ioTPlatform, '是否显示:', shouldShow);
return shouldShow; // CTWing平台
},
triggerFields: ['ioTPlatform'],
@ -239,7 +226,7 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
title: $t('common.action'),
field: 'action',
fixed: 'right',
width: '280',
width: '180',
slots: { default: 'action' },
},
]);
@ -527,76 +514,6 @@ export const addDeviceFormSchema: any = computed(() => [
},
]);
// 设备绑定设备端物模型表单
export const bindDeviceThingModelFormSchema: any = computed(() => [
{
component: 'Switch',
fieldName: 'isNeedConfigDevicMdoel',
label: '是否需要配置设备模型',
defaultValue: false,
componentProps: {
style: { width: 'auto' },
},
},
{
component: 'ApiSelect',
fieldName: 'deviceThingModelDataId',
label: '设备物模型',
// 仅在需要配置设备模型时显示
dependencies: {
show(values: any) {
return !!values.isNeedConfigDevicMdoel;
},
triggerFields: ['isNeedConfigDevicMdoel', '_ioTPlatformProductId'],
},
// 选择设备端物模型
componentProps: (formValues: any) => {
const productId =
formValues?._ioTPlatformProductId || formValues?.ioTPlatformProductId;
return {
api: productId
? postIoTplatformThingModelInfoFindByPlatformProductIdAsync
: null,
params: productId
? {
query: {
input: {
id: String(productId),
},
},
}
: {},
// 平台物模型信息里的显示字段(优先显示标准字段显示名)
labelField: 'standardFieldDisplayName',
valueField: 'id',
optionsPropName: 'options',
immediate: !!productId,
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 [];
},
};
},
// 规则在提交中按开关手动校验,这里设为可选
rules: z.string().optional(),
},
]);
export const editDeviceFormSchemaEdit: any = computed(() => [
{
component: 'ApiSelect',
@ -876,7 +793,20 @@ export const editDeviceFormSchemaEdit: any = computed(() => [
]);
export const commandFormSchema: any = computed(() => [
// 指令表单不再使用schema字段改为在模板中动态渲染
{
component: 'Textarea',
fieldName: 'CommandContent',
label: $t('abp.IoTDBBase.Command'),
componentProps: {
rows: 8,
placeholder: $t('common.pleaseInput') + $t('abp.IoTDBBase.Command'),
showCount: true,
maxLength: 1000,
},
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('abp.IoTDBBase.Command')}`,
}),
},
]);
export const batchAddDeviceFormSchema: any = computed(() => [

View File

@ -175,7 +175,7 @@ async function loadPropertyOptions() {
const items = data?.items || [];
propertyOptions.value = items.map((item: any) => ({
label: `${item.standardFieldDisplayName || item.standardFieldName} (${item.standardFieldName})`,
value: item.ioTPlatformRawFieldName
value: item.standardFieldName || '',
}));
} catch (error) {
console.error('加载属性列表失败:', error);

View File

@ -23,9 +23,9 @@ import { TableAction } from '#/components/table-action';
import { $t } from '#/locales';
import {
getAddThingModelFormSchema,
addThingModelFormSchema,
copyThingModelFormSchema,
getEditThingModelFormSchema,
editThingModelFormSchema,
querySchema,
tableSchema,
} from './schema';
@ -178,69 +178,12 @@ const [ThingModelModal, thingModelModalApi] = useVbenModal({
onBeforeClose: () => {
return true;
},
onOpenChange: async (isOpen: boolean) => {
if (isOpen) {
// ID
await nextTick();
const formApi = editRow.value.id ? editFormApi : addFormApi;
const isEdit = !!editRow.value.id;
//
let platformValue: 1 | 2;
let productIdValue: string;
if (isEdit) {
// editRow.value
platformValue = editRow.value.ioTPlatform
? (typeof editRow.value.ioTPlatform === 'string'
? Number.parseInt(editRow.value.ioTPlatform)
: editRow.value.ioTPlatform) as 1 | 2
: Number.parseInt(ioTPlatform.value) as 1 | 2;
productIdValue = editRow.value.ioTPlatformProductId || productId.value;
} else {
//
const formValues = gridApi?.formApi ? await gridApi.formApi.getValues() : {};
platformValue = formValues.ioTPlatform
? (typeof formValues.ioTPlatform === 'string'
? Number.parseInt(formValues.ioTPlatform)
: formValues.ioTPlatform) as 1 | 2
: Number.parseInt(ioTPlatform.value) as 1 | 2;
productIdValue = formValues.ioTPlatformProductId || productId.value;
//
if (formValues.ioTPlatform) {
ioTPlatform.value = String(formValues.ioTPlatform);
}
if (formValues.ioTPlatformProductId) {
productId.value = String(formValues.ioTPlatformProductId);
}
}
console.log('设置表单值:', {
isEdit,
platformValue,
productIdValue,
editRowValue: isEdit ? editRow.value : null,
onOpenChange: (isOpen: boolean) => {
if (isOpen && editRow.value.id) {
//
nextTick(() => {
editFormApi.setValues({ ...editRow.value });
});
await formApi.setValues({
...(isEdit ? editRow.value : {}),
_ioTPlatform: platformValue,
_ioTPlatformProductId: productIdValue,
});
//
setTimeout(() => {
const fieldRef = formApi.getFieldComponentRef('ioTPlatformRawFieldName');
if (fieldRef && typeof fieldRef.updateParam === 'function') {
fieldRef.updateParam({
body: {
ioTPlatformType: platformValue,
ioTPlatformProductId: productIdValue,
},
});
}
}, 100);
}
},
onCancel: () => {
@ -262,24 +205,10 @@ const [CopyModal, copyModalApi] = useVbenModal({
},
});
// schemaID
// 使 _ioTPlatform _ioTPlatformProductId
const addThingModelFormSchema = getAddThingModelFormSchema(
() => {
//
return ioTPlatform.value ? Number.parseInt(ioTPlatform.value) as 1 | 2 : undefined;
},
() => {
//
return productId.value || undefined;
},
);
const [AddForm, addFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 150,
labelClass: 'whitespace-nowrap',
labelWidth: 110,
componentProps: {
class: 'w-4/5',
},
@ -291,29 +220,10 @@ const [AddForm, addFormApi] = useVbenForm({
wrapperClass: 'grid-cols-2',
});
// schemaID editRow
const editThingModelFormSchema = getEditThingModelFormSchema(
() => {
// editRow
if (editRow.value?.ioTPlatform) {
return typeof editRow.value.ioTPlatform === 'string'
? Number.parseInt(editRow.value.ioTPlatform)
: editRow.value.ioTPlatform;
}
// 使
return ioTPlatform.value ? Number.parseInt(ioTPlatform.value) as 1 | 2 : undefined;
},
() => {
// editRow
return editRow.value?.ioTPlatformProductId || productId.value || undefined;
},
);
const [EditForm, editFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 150,
labelClass: 'whitespace-nowrap',
labelWidth: 110,
componentProps: {
class: 'w-4/5',
},
@ -459,75 +369,12 @@ async function submit() {
async function onEdit(record: any) {
editRow.value = record;
// ID
const platformValue = record.ioTPlatform
? (typeof record.ioTPlatform === 'string'
? Number.parseInt(record.ioTPlatform)
: record.ioTPlatform) as 1 | 2
: Number.parseInt(ioTPlatform.value) as 1 | 2;
const productIdValue = record.ioTPlatformProductId || productId.value;
thingModelModalApi.open();
await nextTick();
setTimeout(async () => {
await editFormApi.setValues({
...record,
_ioTPlatform: platformValue,
_ioTPlatformProductId: productIdValue,
});
//
const fieldRef = editFormApi.getFieldComponentRef('ioTPlatformRawFieldName');
if (fieldRef && typeof fieldRef.updateParam === 'function') {
fieldRef.updateParam({
body: {
ioTPlatformType: platformValue,
ioTPlatformProductId: productIdValue,
},
});
}
}, 100);
}
const openAddModal = async () => {
editRow.value = {};
// ID
const formValues = gridApi?.formApi ? await gridApi.formApi.getValues() : {};
const platformValue = formValues.ioTPlatform
? (typeof formValues.ioTPlatform === 'string'
? Number.parseInt(formValues.ioTPlatform)
: formValues.ioTPlatform) as 1 | 2
: Number.parseInt(ioTPlatform.value) as 1 | 2;
const productIdValue = formValues.ioTPlatformProductId || productId.value;
//
if (formValues.ioTPlatform) {
ioTPlatform.value = String(formValues.ioTPlatform);
}
if (formValues.ioTPlatformProductId) {
productId.value = String(formValues.ioTPlatformProductId);
}
thingModelModalApi.open();
//
await nextTick();
setTimeout(async () => {
await addFormApi.setValues({
_ioTPlatform: platformValue,
_ioTPlatformProductId: productIdValue,
});
//
const fieldRef = addFormApi.getFieldComponentRef('ioTPlatformRawFieldName');
if (fieldRef && typeof fieldRef.updateParam === 'function') {
fieldRef.updateParam({
body: {
ioTPlatformType: platformValue,
ioTPlatformProductId: productIdValue,
},
});
}
}, 100);
};
//

View File

@ -7,7 +7,6 @@ import dayjs from 'dayjs';
import {
getCommonGetSelectList,
postAggregationIoTplatformGetIoTplatformProductInfoAsync,
postAggregationIoTplatformGetIoTplatformProductPropertyInfoAsync,
postOneNetProductListAsync,
} from '#/api-client';
import { $t } from '#/locales';
@ -180,7 +179,7 @@ export const tableSchema = computed(() => [
]);
// 添加物模型表单schema
export const getAddThingModelFormSchema = (getPlatform: () => number | string | undefined, getProductId: () => string | undefined) => computed(() => [
export const addThingModelFormSchema = computed(() => [
{
component: 'ApiSelect',
fieldName: 'filedType',
@ -218,6 +217,57 @@ export const getAddThingModelFormSchema = (getPlatform: () => number | string |
},
},
},
{
component: 'Input',
fieldName: 'ioTPlatformRawFieldName',
label: $t('abp.thingModelInfos.IoTPlatformRawFieldName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
placeholder:
$t('common.pleaseInput') +
$t('abp.thingModelInfos.IoTPlatformRawFieldName'),
},
},
{
component: 'StandardThingModelCodeSelect',
fieldName: 'standardFieldDisplayName',
label: $t('abp.thingModelInfos.StandardFieldDisplayName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: (formValues: any) => ({
// 传入联动的类型编码(运行时具体值)
typeCode: formValues?.filedType ?? null,
onResolve: (item: any | null) => {
// 选择后自动回填:名称=displayText值类型=extendedAttribute(转大写)
formValues.standardFieldDisplayName = item?.displayText ?? '';
formValues.standardFieldName = item?.code ?? '';
formValues.standardFieldValueType = (item?.extendedAttribute ?? '')
.toString()
.toUpperCase();
},
placeholder:
$t('common.pleaseSelect') + $t('abp.thingModelInfos.StandardFieldName'),
}),
},
{
component: 'Input',
fieldName: 'standardFieldName',
label: $t('abp.thingModelInfos.StandardFieldName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
placeholder:
$t('common.pleaseInput') +
$t('abp.thingModelInfos.StandardFieldDisplayName'),
},
},
{
component: 'ApiSelect',
fieldName: 'standardFieldValueType',
@ -256,168 +306,6 @@ export const getAddThingModelFormSchema = (getPlatform: () => number | string |
},
},
},
{
component: 'StandardThingModelCodeSelect',
fieldName: 'standardFieldDisplayName',
label: $t('abp.thingModelInfos.StandardFieldDisplayName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: (formValues: any) => ({
// 传入联动的类型编码(运行时具体值)
typeCode: formValues?.filedType ?? null,
onResolve: (item: any | null) => {
// 选择后自动回填:名称=displayText值类型=extendedAttribute(转大写)
formValues.standardFieldDisplayName = item?.displayText ?? '';
formValues.standardFieldName = item?.code ?? '';
formValues.standardFieldValueType = (item?.extendedAttribute ?? '')
.toString()
.toUpperCase();
},
placeholder:
$t('common.pleaseSelect') + $t('abp.thingModelInfos.StandardFieldName'),
}),
},
{
component: 'Input',
fieldName: 'standardFieldName',
label: $t('abp.thingModelInfos.StandardFieldName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
placeholder:
$t('common.pleaseInput') +
$t('abp.thingModelInfos.StandardFieldDisplayName'),
},
},
{
component: 'ApiSelect',
fieldName: 'ioTPlatformRawFieldName',
label: $t('abp.thingModelInfos.IoTPlatformRawFieldName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
dependencies: {
triggerFields: ['_ioTPlatform', '_ioTPlatformProductId'],
componentProps: (formValues: any) => {
// 优先从表单值获取(这是最可靠的方式,因为值是在打开弹窗时设置的)
let platform = formValues?._ioTPlatform;
let productId = formValues?._ioTPlatformProductId;
// 如果表单值中没有,尝试从其他字段获取
if (!platform && formValues?.ioTPlatform) {
platform = typeof formValues.ioTPlatform === 'string'
? Number.parseInt(formValues.ioTPlatform)
: formValues.ioTPlatform;
}
if (!productId && formValues?.ioTPlatformProductId) {
productId = formValues.ioTPlatformProductId;
}
// 如果还是没有,尝试从外部函数获取(作为后备方案)
if (!platform) {
const externalPlatform = getPlatform();
if (externalPlatform) {
platform = typeof externalPlatform === 'string'
? Number.parseInt(externalPlatform)
: externalPlatform;
}
}
if (!productId) {
const externalProductId = getProductId();
if (externalProductId) {
productId = String(externalProductId);
}
}
// 确保平台类型是数字
if (platform && typeof platform === 'string') {
platform = Number.parseInt(platform);
}
// 调试信息
console.log('平台物模型编码下拉框配置:', {
platform,
productId,
hasApi: !!(platform && productId),
fromForm: {
_ioTPlatform: formValues?._ioTPlatform,
_ioTPlatformProductId: formValues?._ioTPlatformProductId,
ioTPlatform: formValues?.ioTPlatform,
ioTPlatformProductId: formValues?.ioTPlatformProductId,
},
});
return {
api:
platform && productId
? postAggregationIoTplatformGetIoTplatformProductPropertyInfoAsync
: null,
params:
platform && productId
? {
body: {
ioTPlatformType:
typeof platform === 'string'
? Number.parseInt(platform)
: platform,
ioTPlatformProductId: String(productId),
},
}
: {},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: !!(platform && productId), // 当有平台和产品ID时立即加载
allowClear: true,
placeholder:
$t('common.pleaseSelect') +
$t('abp.thingModelInfos.IoTPlatformRawFieldName'),
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;
}
// 存储原始数据映射,用于后续查找 secondValue
const optionMap = new Map();
items.forEach((item: any) => {
if (item.key) {
optionMap.set(item.key, item.secondValue);
}
});
(formValues as any)._platformPropertyMap = optionMap;
return items;
},
onChange: (value: string) => {
// 选择后自动设置平台物模型数值类型为选中项的 secondValue
const optionMap = (formValues as any)._platformPropertyMap;
if (optionMap && value) {
let secondValue = optionMap.get(value);
if (secondValue) {
// 兼容 BOOL / BOOLEAN 差异,统一转换为后端 / 枚举使用的 BOOLEAN
if (
typeof secondValue === 'string' &&
secondValue.toUpperCase() === 'BOOL'
) {
secondValue = 'BOOLEAN';
}
formValues.ioTPlatformRawFieldDataType = secondValue;
}
}
},
};
},
},
},
{
component: 'Switch',
fieldName: 'isValueNeedConvert',
@ -427,60 +315,10 @@ export const getAddThingModelFormSchema = (getPlatform: () => number | string |
style: { width: 'auto' },
},
},
{
component: 'ApiSelect',
fieldName: 'ioTPlatformRawFieldDataType',
label: '平台物模型值类型',
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'StandardThingModelDataTypeEnum',
},
},
labelField: 'value',
valueField: 'secondValue',
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: 'Switch',
fieldName: 'isSpecialIdentifier',
label: '是否特殊物模型标识符',
defaultValue: false,
componentProps: {
style: { width: 'auto' },
},
},
{
component: 'Textarea',
fieldName: 'ioTPlatformRawFieldExtension',
label: '平台物模型值类型扩展',
componentProps: {
rows: 4,
placeholder: '请输入平台原始字段扩展信息用于扩展结构体类型JSON格式',
},
},
]);
// 编辑物模型表单schema
export const getEditThingModelFormSchema = (getPlatform: () => number | string | undefined, getProductId: () => string | undefined) => computed(() => [
export const editThingModelFormSchema = computed(() => [
{
component: 'ApiSelect',
fieldName: 'filedType',
@ -518,6 +356,54 @@ export const getEditThingModelFormSchema = (getPlatform: () => number | string |
},
},
},
{
component: 'Input',
fieldName: 'ioTPlatformRawFieldName',
label: $t('abp.thingModelInfos.IoTPlatformRawFieldName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: {
// disabled: true, // 编辑时禁用
placeholder:
$t('common.pleaseInput') +
$t('abp.thingModelInfos.IoTPlatformRawFieldName'),
},
},
{
component: 'StandardThingModelCodeSelect',
fieldName: 'standardFieldDisplayName',
label: $t('abp.thingModelInfos.StandardFieldDisplayName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: (formValues: any) => ({
typeCode: formValues?.filedType ?? null,
disabled: true, // 编辑时禁用
onResolve: (item: any | null) => {
formValues.standardFieldDisplayName = item?.displayText ?? '';
formValues.standardFieldValueType = (item?.extendedAttribute ?? '')
.toString()
.toUpperCase();
},
placeholder:
$t('common.pleaseInput') +
$t('abp.thingModelInfos.StandardFieldDisplayName'),
}),
},
{
component: 'Input',
fieldName: 'standardFieldName',
label: $t('abp.thingModelInfos.StandardFieldName'),
rules: z.string().min(1, $t('common.required')),
componentProps: {
disabled: true, // 编辑时禁用
placeholder:
$t('common.pleaseSelect') + $t('abp.thingModelInfos.StandardFieldName'),
},
},
{
component: 'ApiSelect',
fieldName: 'standardFieldValueType',
@ -559,164 +445,6 @@ export const getEditThingModelFormSchema = (getPlatform: () => number | string |
},
},
},
{
component: 'StandardThingModelCodeSelect',
fieldName: 'standardFieldDisplayName',
label: $t('abp.thingModelInfos.StandardFieldDisplayName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
componentProps: (formValues: any) => ({
typeCode: formValues?.filedType ?? null,
disabled: true, // 编辑时禁用
onResolve: (item: any | null) => {
formValues.standardFieldDisplayName = item?.displayText ?? '';
formValues.standardFieldValueType = (item?.extendedAttribute ?? '')
.toString()
.toUpperCase();
},
placeholder:
$t('common.pleaseInput') +
$t('abp.thingModelInfos.StandardFieldDisplayName'),
}),
},
{
component: 'Input',
fieldName: 'standardFieldName',
label: $t('abp.thingModelInfos.StandardFieldName'),
rules: z.string().min(1, $t('common.required')),
componentProps: {
disabled: true, // 编辑时禁用
placeholder:
$t('common.pleaseSelect') + $t('abp.thingModelInfos.StandardFieldName'),
},
},
{
component: 'ApiSelect',
fieldName: 'ioTPlatformRawFieldName',
label: $t('abp.thingModelInfos.IoTPlatformRawFieldName'),
rules: z.preprocess(
(v) => (v == null ? '' : v),
z.string().min(1, $t('common.required')),
),
dependencies: {
triggerFields: ['_ioTPlatform', '_ioTPlatformProductId'],
componentProps: (formValues: any) => {
// 优先从表单值获取(这是最可靠的方式,因为值是在打开弹窗时设置的)
let platform = formValues?._ioTPlatform;
let productId = formValues?._ioTPlatformProductId;
// 如果表单值中没有,尝试从其他字段获取
if (!platform && formValues?.ioTPlatform) {
platform = typeof formValues.ioTPlatform === 'string'
? Number.parseInt(formValues.ioTPlatform)
: formValues.ioTPlatform;
}
if (!productId && formValues?.ioTPlatformProductId) {
productId = formValues.ioTPlatformProductId;
}
// 如果还是没有,尝试从外部函数获取(作为后备方案)
if (!platform) {
const externalPlatform = getPlatform();
if (externalPlatform) {
platform = typeof externalPlatform === 'string'
? Number.parseInt(externalPlatform)
: externalPlatform;
}
}
if (!productId) {
const externalProductId = getProductId();
if (externalProductId) {
productId = String(externalProductId);
}
}
// 确保平台类型是数字
if (platform && typeof platform === 'string') {
platform = Number.parseInt(platform);
}
// 调试信息
console.log('平台物模型编码下拉框配置:', {
platform,
productId,
hasApi: !!(platform && productId),
fromForm: {
_ioTPlatform: formValues?._ioTPlatform,
_ioTPlatformProductId: formValues?._ioTPlatformProductId,
ioTPlatform: formValues?.ioTPlatform,
ioTPlatformProductId: formValues?.ioTPlatformProductId,
},
});
return {
api:
platform && productId
? postAggregationIoTplatformGetIoTplatformProductPropertyInfoAsync
: null,
params:
platform && productId
? {
body: {
ioTPlatformType:
typeof platform === 'string'
? Number.parseInt(platform)
: platform,
ioTPlatformProductId: String(productId),
},
}
: {},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: !!(platform && productId), // 当有平台和产品ID时立即加载
allowClear: true,
placeholder:
$t('common.pleaseSelect') +
$t('abp.thingModelInfos.IoTPlatformRawFieldName'),
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;
}
// 存储原始数据映射,用于后续查找 secondValue
const optionMap = new Map();
items.forEach((item: any) => {
if (item.key) {
optionMap.set(item.key, item.secondValue);
}
});
(formValues as any)._platformPropertyMap = optionMap;
return items;
},
onChange: (value: string) => {
// 选择后自动设置平台物模型数值类型为选中项的 secondValue
const optionMap = (formValues as any)._platformPropertyMap;
if (optionMap && value) {
let secondValue = optionMap.get(value);
if (secondValue) {
// 兼容 BOOL / BOOLEAN 差异,统一转换为后端 / 枚举使用的 BOOLEAN
if (
typeof secondValue === 'string' &&
secondValue.toUpperCase() === 'BOOL'
) {
secondValue = 'BOOLEAN';
}
formValues.ioTPlatformRawFieldDataType = secondValue;
}
}
},
};
},
},
},
{
component: 'Switch',
fieldName: 'isValueNeedConvert',
@ -725,55 +453,6 @@ export const getEditThingModelFormSchema = (getPlatform: () => number | string |
style: { width: 'auto' },
},
},
{
component: 'ApiSelect',
fieldName: 'ioTPlatformRawFieldDataType',
label: '平台物模型值类型',
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'StandardThingModelDataTypeEnum',
},
},
labelField: 'value',
valueField: 'secondValue',
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: 'Switch',
fieldName: 'isSpecialIdentifier',
label: '是否特殊物模型标识符',
componentProps: {
style: { width: 'auto' },
},
},
{
component: 'Textarea',
fieldName: 'ioTPlatformRawFieldExtension',
label: '平台物模型值类型扩展',
componentProps: {
rows: 4,
placeholder: '请输入平台原始字段扩展信息用于扩展结构体类型JSON格式',
},
},
]);
// 复制已有模型表单schema