1213 lines
37 KiB
TypeScript
1213 lines
37 KiB
TypeScript
import { computed } from 'vue';
|
||
|
||
import { z } from '@vben/common-ui';
|
||
|
||
import dayjs from 'dayjs';
|
||
|
||
import {
|
||
getCommonGetSelectList,
|
||
postAggregationIoTplatformGetIoTplatformProductInfoAsync,
|
||
postAggregationIoTplatformGetIoTplatformProductThingModelInfoAsync,
|
||
postOneNetProductListAsync,
|
||
} from '#/api-client';
|
||
import { $t } from '#/locales';
|
||
|
||
/** 表格中扩展字段可能为对象或 JSON 字符串,统一展示为字符串 */
|
||
function formatFieldExtensionCell(cellValue: unknown): string {
|
||
if (cellValue == null || cellValue === '') {
|
||
return '';
|
||
}
|
||
if (typeof cellValue === 'string') {
|
||
return cellValue;
|
||
}
|
||
if (typeof cellValue === 'object') {
|
||
try {
|
||
return JSON.stringify(cellValue);
|
||
} catch {
|
||
return String(cellValue);
|
||
}
|
||
}
|
||
return String(cellValue);
|
||
}
|
||
|
||
/** 表单中的扩展字段统一转换为可编辑文本 */
|
||
function formatFieldExtensionFormValue(fieldValue: unknown): string {
|
||
if (fieldValue == null || fieldValue === '') {
|
||
return '';
|
||
}
|
||
if (typeof fieldValue === 'string') {
|
||
return fieldValue;
|
||
}
|
||
try {
|
||
return JSON.stringify(fieldValue, null, 2);
|
||
} catch {
|
||
return String(fieldValue);
|
||
}
|
||
}
|
||
|
||
export const querySchema = computed(() => [
|
||
{
|
||
component: 'ApiSelect',
|
||
fieldName: 'ioTPlatform',
|
||
label: $t('abp.deviceInfos.ioTPlatform'),
|
||
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'),
|
||
dependencies: {
|
||
show(values: any) {
|
||
return !!values.ioTPlatform;
|
||
},
|
||
triggerFields: ['ioTPlatform'],
|
||
},
|
||
componentProps: (formValues: any) => {
|
||
const platform = formValues?.ioTPlatform;
|
||
|
||
return {
|
||
api: platform
|
||
? postAggregationIoTplatformGetIoTplatformProductInfoAsync
|
||
: null,
|
||
params: {
|
||
body: {
|
||
// 聚合服务要求 JSON 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 [];
|
||
},
|
||
};
|
||
},
|
||
},
|
||
{
|
||
component: 'ApiSelect',
|
||
fieldName: 'accessMode',
|
||
label: $t('abp.thingModelInfos.AccessMode'),
|
||
componentProps: {
|
||
api: getCommonGetSelectList,
|
||
params: {
|
||
query: {
|
||
typeName: 'DevicePropertyAccessMode',
|
||
},
|
||
},
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: true,
|
||
allowClear: true,
|
||
placeholder: `${$t('common.pleaseSelect')}${$t('abp.thingModelInfos.AccessMode')}`,
|
||
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: 'identifierType',
|
||
label: $t('abp.thingModelInfos.IdentifierType'),
|
||
componentProps: {
|
||
api: getCommonGetSelectList,
|
||
params: {
|
||
query: {
|
||
typeName: 'ThingModelIdentifierTypeEnum',
|
||
},
|
||
},
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: true,
|
||
allowClear: true,
|
||
placeholder: `${$t('common.pleaseSelect')}${$t('abp.thingModelInfos.IdentifierType')}`,
|
||
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: 'SearchKeyWords',
|
||
label: $t('common.SearchKeyWords'),
|
||
},
|
||
]);
|
||
|
||
export const tableSchema = computed(() => [
|
||
{
|
||
field: 'ioTPlatformProductId',
|
||
title: $t('abp.thingModelInfos.ioTPlatformProduct'),
|
||
minWidth: 150,
|
||
showOverflow: 'tooltip',
|
||
fixed: 'left',
|
||
},
|
||
{
|
||
field: 'filedTypeName',
|
||
title: $t('abp.thingModelInfos.FiledType'),
|
||
minWidth: 120,
|
||
showOverflow: 'tooltip',
|
||
formatter: ({ cellValue }: { cellValue: any }) => {
|
||
const typeMap: Record<string, string> = {
|
||
Property: '属性',
|
||
Service: '服务',
|
||
Event: '事件',
|
||
};
|
||
return typeMap[cellValue] || cellValue;
|
||
},
|
||
},
|
||
{
|
||
field: 'ioTPlatformRawFieldName',
|
||
title: $t('abp.thingModelInfos.IoTPlatformRawFieldName'),
|
||
minWidth: 150,
|
||
showOverflow: 'tooltip',
|
||
},
|
||
{
|
||
field: 'standardFieldName',
|
||
title: $t('abp.thingModelInfos.StandardFieldName'),
|
||
minWidth: 150,
|
||
showOverflow: 'tooltip',
|
||
},
|
||
{
|
||
field: 'ioTPlatformRawFieldExtension',
|
||
title: $t('abp.thingModelInfos.IoTPlatformRawFieldExtension'),
|
||
minWidth: 120,
|
||
showOverflow: 'tooltip',
|
||
formatter: ({ cellValue }: { cellValue: unknown }) =>
|
||
formatFieldExtensionCell(cellValue),
|
||
},
|
||
{
|
||
field: 'standardFieldDisplayName',
|
||
title: $t('abp.thingModelInfos.StandardFieldDisplayName'),
|
||
minWidth: 150,
|
||
showOverflow: 'tooltip',
|
||
},
|
||
{
|
||
field: 'standardFieldValueType',
|
||
title: $t('abp.thingModelInfos.StandardFieldValueType'),
|
||
minWidth: 120,
|
||
showOverflow: 'tooltip',
|
||
formatter: ({ cellValue }: { cellValue: any }) => {
|
||
const typeMap: Record<string, string> = {
|
||
String: '字符串',
|
||
Int32: '整数',
|
||
Int64: '长整数',
|
||
Float: '浮点数',
|
||
Double: '双精度',
|
||
Boolean: '布尔值',
|
||
DateTime: '日期时间',
|
||
Object: 'JSON对象',
|
||
Array: '数组',
|
||
Struct: '结构体',
|
||
};
|
||
return typeMap[cellValue] || cellValue;
|
||
},
|
||
},
|
||
{
|
||
field: 'standardFieldFieldExtension',
|
||
title: $t('abp.thingModelInfos.StandardFieldFieldExtension'),
|
||
minWidth: 120,
|
||
showOverflow: 'tooltip',
|
||
formatter: ({ cellValue }: { cellValue: unknown }) =>
|
||
formatFieldExtensionCell(cellValue),
|
||
},
|
||
{
|
||
field: 'isValueNeedConvert',
|
||
title: $t('abp.thingModelInfos.IsValueNeedConvert'),
|
||
minWidth: 120,
|
||
slots: { default: 'isValueNeedConvert' },
|
||
},
|
||
{
|
||
field: 'accessMode',
|
||
title: $t('abp.thingModelInfos.AccessMode'),
|
||
minWidth: 120,
|
||
slots: { default: 'accessMode' },
|
||
},
|
||
{
|
||
field: 'identifierType',
|
||
title: $t('abp.thingModelInfos.IdentifierType'),
|
||
minWidth: 120,
|
||
showOverflow: 'tooltip',
|
||
slots: { default: 'identifierType' },
|
||
},
|
||
{
|
||
field: 'isOperableIdentifier',
|
||
title: $t('abp.thingModelInfos.IsOperableIdentifier'),
|
||
minWidth: 150,
|
||
formatter: ({ cellValue }: { cellValue: any }) => {
|
||
return cellValue === true ? '是' : '否';
|
||
},
|
||
},
|
||
{
|
||
field: 'creationTime',
|
||
title: $t('common.creationTime'),
|
||
minWidth: 180,
|
||
formatter: ({ cellValue }: { cellValue: any }) => {
|
||
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : '-';
|
||
},
|
||
},
|
||
{
|
||
field: 'action',
|
||
title: $t('common.action'),
|
||
width: 200,
|
||
fixed: 'right',
|
||
slots: { default: 'action' },
|
||
},
|
||
]);
|
||
|
||
// 添加物模型表单schema
|
||
export const getAddThingModelFormSchema = (
|
||
getPlatform: () => number | string | undefined,
|
||
getProductId: () => string | undefined,
|
||
) =>
|
||
computed(() => [
|
||
{
|
||
component: 'ApiSelect',
|
||
fieldName: 'filedType',
|
||
label: $t('abp.thingModelInfos.FiledType'),
|
||
rules: z.preprocess(
|
||
(v) => (v == null ? '' : v),
|
||
z.string().min(1, $t('common.required')),
|
||
),
|
||
componentProps: {
|
||
api: getCommonGetSelectList,
|
||
params: {
|
||
query: {
|
||
typeName: 'DataDictionaryTypeConst',
|
||
},
|
||
},
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: true,
|
||
allowClear: true,
|
||
placeholder:
|
||
$t('common.pleaseSelect') + $t('abp.thingModelInfos.FiledType'),
|
||
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: 'standardFieldValueType',
|
||
label: $t('abp.thingModelInfos.StandardFieldValueType'),
|
||
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') +
|
||
$t('abp.thingModelInfos.StandardFieldValueType'),
|
||
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: '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();
|
||
// 选择后自动回填标准物模型扩展参数:extendedAttributeValue
|
||
formValues.standardFieldFieldExtension = formatFieldExtensionFormValue(
|
||
item?.extendedAttributeValue,
|
||
);
|
||
},
|
||
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: 'Textarea',
|
||
fieldName: 'standardFieldFieldExtension',
|
||
label: $t('abp.thingModelInfos.StandardFieldFieldExtension'),
|
||
componentProps: {
|
||
rows: 4,
|
||
placeholder: '请选择标准物模型后自动回填扩展参数(JSON格式)',
|
||
},
|
||
},
|
||
{
|
||
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', 'filedType'],
|
||
trigger: async (_formValues: any, formApi: any) => {
|
||
// 当 filedType 变化时,清空字段值,强制组件重新加载
|
||
if (formApi && typeof formApi.setFieldValue === 'function') {
|
||
await formApi.setFieldValue('ioTPlatformRawFieldName', undefined);
|
||
}
|
||
},
|
||
componentProps: (formValues: any) => {
|
||
// 优先从表单值获取(这是最可靠的方式,因为值是在打开弹窗时设置的)
|
||
let platform = formValues?._ioTPlatform;
|
||
let productId = formValues?._ioTPlatformProductId;
|
||
const filedType = formValues?.filedType;
|
||
|
||
// 如果表单值中没有,尝试从其他字段获取
|
||
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,
|
||
filedType,
|
||
hasApi: !!(platform && productId),
|
||
fromForm: {
|
||
_ioTPlatform: formValues?._ioTPlatform,
|
||
_ioTPlatformProductId: formValues?._ioTPlatformProductId,
|
||
ioTPlatform: formValues?.ioTPlatform,
|
||
ioTPlatformProductId: formValues?.ioTPlatformProductId,
|
||
filedType: formValues?.filedType,
|
||
},
|
||
});
|
||
|
||
return {
|
||
api:
|
||
platform && productId
|
||
? postAggregationIoTplatformGetIoTplatformProductThingModelInfoAsync
|
||
: null,
|
||
params:
|
||
platform && productId
|
||
? {
|
||
body: {
|
||
ioTPlatformType:
|
||
typeof platform === 'string'
|
||
? Number.parseInt(platform)
|
||
: platform,
|
||
ioTPlatformProductId: String(productId),
|
||
// 确保 FiledType 参数始终存在(即使为空),以便触发接口重新请求
|
||
FiledType: filedType ? String(filedType) : undefined,
|
||
},
|
||
}
|
||
: {},
|
||
// 添加 key 确保 filedType 变化时组件重新渲染
|
||
key: `platform-${platform}-product-${productId}-type-${filedType || 'none'}`,
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: !!(platform && productId), // 当有平台和产品ID时立即加载
|
||
allowClear: true,
|
||
showSearch: 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',
|
||
label: $t('abp.thingModelInfos.IsValueNeedConvert'),
|
||
defaultValue: false,
|
||
componentProps: {
|
||
style: { width: 'auto' },
|
||
},
|
||
},
|
||
{
|
||
component: 'ApiSelect',
|
||
fieldName: 'accessMode',
|
||
label: $t('abp.thingModelInfos.AccessMode'),
|
||
componentProps: {
|
||
api: getCommonGetSelectList,
|
||
params: {
|
||
query: {
|
||
typeName: 'DevicePropertyAccessMode',
|
||
},
|
||
},
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: true,
|
||
allowClear: true,
|
||
placeholder:
|
||
$t('common.pleaseSelect') + $t('abp.thingModelInfos.AccessMode'),
|
||
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: 'isOperableIdentifier',
|
||
label: $t('abp.thingModelInfos.IsOperableIdentifier'),
|
||
defaultValue: false,
|
||
componentProps: {
|
||
style: { width: 'auto' },
|
||
},
|
||
},
|
||
{
|
||
component: 'ApiSelect',
|
||
fieldName: 'identifierType',
|
||
label: $t('abp.thingModelInfos.IdentifierType'),
|
||
componentProps: {
|
||
api: getCommonGetSelectList,
|
||
params: {
|
||
query: {
|
||
typeName: 'ThingModelIdentifierTypeEnum',
|
||
},
|
||
},
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: true,
|
||
allowClear: true,
|
||
placeholder:
|
||
$t('common.pleaseSelect') + $t('abp.thingModelInfos.IdentifierType'),
|
||
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: '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(() => [
|
||
{
|
||
component: 'ApiSelect',
|
||
fieldName: 'filedType',
|
||
label: $t('abp.thingModelInfos.FiledType'),
|
||
rules: z.preprocess(
|
||
(v) => (v == null ? '' : v),
|
||
z.string().min(1, $t('common.required')),
|
||
),
|
||
componentProps: {
|
||
api: getCommonGetSelectList,
|
||
params: {
|
||
query: {
|
||
typeName: 'DataDictionaryTypeConst',
|
||
},
|
||
},
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: true,
|
||
disabled: true, // 编辑时禁用
|
||
placeholder:
|
||
$t('common.pleaseSelect') + $t('abp.thingModelInfos.FiledType'),
|
||
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: 'standardFieldValueType',
|
||
label: $t('abp.thingModelInfos.StandardFieldValueType'),
|
||
rules: z.preprocess(
|
||
(v) => (v == null ? '' : v),
|
||
z.string().min(1, $t('common.required')),
|
||
),
|
||
componentProps: {
|
||
api: getCommonGetSelectList,
|
||
params: {
|
||
query: {
|
||
typeName: 'StandardThingModelDataTypeEnum',
|
||
},
|
||
},
|
||
optionsPropName: 'options',
|
||
immediate: true,
|
||
allowClear: true,
|
||
disabled: true, // 编辑时禁用
|
||
placeholder:
|
||
$t('common.pleaseSelect') +
|
||
$t('abp.thingModelInfos.StandardFieldValueType'),
|
||
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;
|
||
}
|
||
// 转换选项值以匹配列表中的小写值
|
||
return items.map((item: any) => ({
|
||
...item,
|
||
// 使用secondValue的小写版本作为value,保持label为原始value
|
||
value: item.secondValue || item.value,
|
||
label: item.value, // 显示文本
|
||
}));
|
||
},
|
||
},
|
||
},
|
||
{
|
||
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', 'filedType'],
|
||
trigger: async (_formValues: any, formApi: any) => {
|
||
// 当 filedType 变化时,清空字段值,强制组件重新加载
|
||
if (formApi && typeof formApi.setFieldValue === 'function') {
|
||
await formApi.setFieldValue('ioTPlatformRawFieldName', undefined);
|
||
}
|
||
},
|
||
componentProps: (formValues: any) => {
|
||
// 优先从表单值获取(这是最可靠的方式,因为值是在打开弹窗时设置的)
|
||
let platform = formValues?._ioTPlatform;
|
||
let productId = formValues?._ioTPlatformProductId;
|
||
const filedType = formValues?.filedType;
|
||
|
||
// 如果表单值中没有,尝试从其他字段获取
|
||
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,
|
||
filedType,
|
||
hasApi: !!(platform && productId),
|
||
fromForm: {
|
||
_ioTPlatform: formValues?._ioTPlatform,
|
||
_ioTPlatformProductId: formValues?._ioTPlatformProductId,
|
||
ioTPlatform: formValues?.ioTPlatform,
|
||
ioTPlatformProductId: formValues?.ioTPlatformProductId,
|
||
filedType: formValues?.filedType,
|
||
},
|
||
});
|
||
|
||
return {
|
||
api:
|
||
platform && productId
|
||
? postAggregationIoTplatformGetIoTplatformProductThingModelInfoAsync
|
||
: null,
|
||
params:
|
||
platform && productId
|
||
? {
|
||
body: {
|
||
ioTPlatformType:
|
||
typeof platform === 'string'
|
||
? Number.parseInt(platform)
|
||
: platform,
|
||
ioTPlatformProductId: String(productId),
|
||
// 确保 FiledType 参数始终存在(即使为空),以便触发接口重新请求
|
||
FiledType: filedType ? String(filedType) : undefined,
|
||
},
|
||
}
|
||
: {},
|
||
// 添加 key 确保 filedType 变化时组件重新渲染
|
||
key: `platform-${platform}-product-${productId}-type-${filedType || 'none'}`,
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: !!(platform && productId), // 当有平台和产品ID时立即加载
|
||
allowClear: true,
|
||
showSearch: 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',
|
||
label: $t('abp.thingModelInfos.IsValueNeedConvert'),
|
||
componentProps: {
|
||
style: { width: 'auto' },
|
||
},
|
||
},
|
||
{
|
||
component: 'ApiSelect',
|
||
fieldName: 'accessMode',
|
||
label: $t('abp.thingModelInfos.AccessMode'),
|
||
componentProps: {
|
||
api: getCommonGetSelectList,
|
||
params: {
|
||
query: {
|
||
typeName: 'DevicePropertyAccessMode',
|
||
},
|
||
},
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: true,
|
||
allowClear: true,
|
||
placeholder:
|
||
$t('common.pleaseSelect') + $t('abp.thingModelInfos.AccessMode'),
|
||
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: 'isOperableIdentifier',
|
||
label: $t('abp.thingModelInfos.IsOperableIdentifier'),
|
||
componentProps: {
|
||
style: { width: 'auto' },
|
||
},
|
||
},
|
||
{
|
||
component: 'ApiSelect',
|
||
fieldName: 'identifierType',
|
||
label: $t('abp.thingModelInfos.IdentifierType'),
|
||
componentProps: {
|
||
api: getCommonGetSelectList,
|
||
params: {
|
||
query: {
|
||
typeName: 'ThingModelIdentifierTypeEnum',
|
||
},
|
||
},
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: true,
|
||
allowClear: true,
|
||
placeholder:
|
||
$t('common.pleaseSelect') + $t('abp.thingModelInfos.IdentifierType'),
|
||
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: '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
|
||
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 [];
|
||
},
|
||
},
|
||
},
|
||
]);
|
||
|
||
// 复制标准模型(按物模型类型多选)表单 schema
|
||
export const copyStandardThingModelFormSchema = computed(() => [
|
||
{
|
||
component: 'ApiSelect',
|
||
fieldName: 'filedTypes',
|
||
label: '选择要复制的物模型类型',
|
||
rules: z.preprocess(
|
||
(v) => (v == null ? [] : v),
|
||
z.array(z.string()).min(1, '请至少选择一个物模型类型'),
|
||
),
|
||
componentProps: {
|
||
api: getCommonGetSelectList,
|
||
params: {
|
||
query: {
|
||
// 与物模型字段类型相同的数据字典(Property / Service / Event)
|
||
typeName: 'DataDictionaryTypeConst',
|
||
},
|
||
},
|
||
labelField: 'value',
|
||
valueField: 'key',
|
||
optionsPropName: 'options',
|
||
immediate: true,
|
||
allowClear: true,
|
||
mode: 'multiple',
|
||
placeholder: '请选择要复制的物模型类型(可多选)',
|
||
maxTagCount: 'responsive',
|
||
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 [];
|
||
},
|
||
},
|
||
},
|
||
]);
|