平台的物模型操作完善
This commit is contained in:
parent
8f4cd47a4f
commit
095b521259
@ -5352,6 +5352,28 @@ export const GetPermissionInputSchema = {
|
|||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const GetPlatformThingModelServiceInputSchema = {
|
||||||
|
required: ['id'],
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
minLength: 1,
|
||||||
|
type: 'string'
|
||||||
|
},
|
||||||
|
standardFieldName: {
|
||||||
|
type: 'string',
|
||||||
|
description: '管理后台产品标准的物模型属性或者事件名称',
|
||||||
|
nullable: true
|
||||||
|
},
|
||||||
|
isGetOperateService: {
|
||||||
|
type: 'boolean',
|
||||||
|
description: '是否只获取操作服务'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
additionalProperties: false,
|
||||||
|
description: '获取平台物模型服务列表入参'
|
||||||
|
} as const;
|
||||||
|
|
||||||
export const GetQRCodeOutputSchema = {
|
export const GetQRCodeOutputSchema = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
|
|||||||
@ -2893,6 +2893,21 @@ export type GetPermissionInput = {
|
|||||||
providerKey?: (string) | null;
|
providerKey?: (string) | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取平台物模型服务列表入参
|
||||||
|
*/
|
||||||
|
export type GetPlatformThingModelServiceInput = {
|
||||||
|
id: string;
|
||||||
|
/**
|
||||||
|
* 管理后台产品标准的物模型属性或者事件名称
|
||||||
|
*/
|
||||||
|
standardFieldName?: (string) | null;
|
||||||
|
/**
|
||||||
|
* 是否只获取操作服务
|
||||||
|
*/
|
||||||
|
isGetOperateService?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type GetQRCodeOutput = {
|
export type GetQRCodeOutput = {
|
||||||
/**
|
/**
|
||||||
* base64 二维码
|
* base64 二维码
|
||||||
@ -7770,7 +7785,7 @@ export type PostIoTplatformThingModelInfoUpdateOperableIdentifierError = unknown
|
|||||||
|
|
||||||
export type PostIoTplatformThingModelInfoGetIoTplatformThingModelServiceData = {
|
export type PostIoTplatformThingModelInfoGetIoTplatformThingModelServiceData = {
|
||||||
query?: {
|
query?: {
|
||||||
input?: StringIdInput;
|
input?: GetPlatformThingModelServiceInput;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -816,7 +816,10 @@ function isOperateBreakerServiceItem(item: {
|
|||||||
/** 拉合闸类型参数:与物模型 InputData 标识符 / 展示名对应 */
|
/** 拉合闸类型参数:与物模型 InputData 标识符 / 展示名对应 */
|
||||||
function isBreakerOperateTypeField(f: ServiceParamField): boolean {
|
function isBreakerOperateTypeField(f: ServiceParamField): boolean {
|
||||||
const n = f.name.trim().toLowerCase();
|
const n = f.name.trim().toLowerCase();
|
||||||
if (f.label.includes('拉合闸类型')) {
|
if (f.label.includes('拉合闸类型') || f.label.includes('操作类型')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (n === 'operatetype' || n === 'operate_type') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (n === 'operatecommandtype') {
|
if (n === 'operatecommandtype') {
|
||||||
@ -858,11 +861,6 @@ const valveCommandTypeOptions = ref<Array<{ label: string; value: string }>>(
|
|||||||
);
|
);
|
||||||
const valveCommandTypeLoading = ref(false);
|
const valveCommandTypeLoading = ref(false);
|
||||||
|
|
||||||
const breakerOperateTypeOptions = ref<Array<{ label: string; value: string }>>(
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
const breakerOperateTypeLoading = ref(false);
|
|
||||||
|
|
||||||
function normalizeServiceThirdValue(raw: unknown): ServiceParamField[] {
|
function normalizeServiceThirdValue(raw: unknown): ServiceParamField[] {
|
||||||
if (raw === null || raw === undefined || raw === '') {
|
if (raw === null || raw === undefined || raw === '') {
|
||||||
return [];
|
return [];
|
||||||
@ -993,6 +991,10 @@ const serviceCallSelectOptions = computed(() =>
|
|||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const breakerOperateTypeOptions = computed(() =>
|
||||||
|
extractBreakerOperateTypeOptionsFromSecondValue(currentServiceItem.value),
|
||||||
|
);
|
||||||
|
|
||||||
function shouldUseValveCommandTypeSelectForField(f: ServiceParamField): boolean {
|
function shouldUseValveCommandTypeSelectForField(f: ServiceParamField): boolean {
|
||||||
if (!isValveControlServiceItem(currentServiceItem.value)) {
|
if (!isValveControlServiceItem(currentServiceItem.value)) {
|
||||||
return false;
|
return false;
|
||||||
@ -1009,6 +1011,96 @@ function shouldUseBreakerOperateTypeSelectForField(
|
|||||||
return isBreakerOperateTypeField(f);
|
return isBreakerOperateTypeField(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseJsonMaybe(raw: unknown): unknown {
|
||||||
|
if (typeof raw !== 'string') {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
const s = raw.trim();
|
||||||
|
if (!s) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JSON.parse(s) as unknown;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toSecondValueSelectOptions(
|
||||||
|
list: unknown[],
|
||||||
|
): Array<{ label: string; value: string }> {
|
||||||
|
return list
|
||||||
|
.map((x: any) => {
|
||||||
|
if (!x || typeof x !== 'object') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const value = String(
|
||||||
|
x.key ?? x.id ?? x.value ?? x.Identifier ?? x.identifier ?? '',
|
||||||
|
).trim();
|
||||||
|
const label = String(
|
||||||
|
x.label ?? x.name ?? x.text ?? x.value ?? x.Name ?? x.name ?? value,
|
||||||
|
).trim();
|
||||||
|
if (!value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return { label: label || value, value };
|
||||||
|
})
|
||||||
|
.filter(Boolean) as Array<{ label: string; value: string }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractBreakerOperateTypeOptionsFromSecondValue(item: {
|
||||||
|
secondValue?: null | string;
|
||||||
|
} | null): Array<{ label: string; value: string }> {
|
||||||
|
if (!item) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const parsed = parseJsonMaybe(item.secondValue);
|
||||||
|
if (!parsed) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
return toSecondValueSelectOptions(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof parsed === 'object') {
|
||||||
|
const obj = parsed as Record<string, unknown>;
|
||||||
|
const candidateLists = [
|
||||||
|
obj.operateType,
|
||||||
|
obj.OperateType,
|
||||||
|
obj.operateTypeList,
|
||||||
|
obj.operateTypes,
|
||||||
|
obj.OperateTypeList,
|
||||||
|
obj.OperateTypes,
|
||||||
|
obj.options,
|
||||||
|
obj.list,
|
||||||
|
obj.items,
|
||||||
|
obj.data,
|
||||||
|
];
|
||||||
|
for (const c of candidateLists) {
|
||||||
|
if (Array.isArray(c)) {
|
||||||
|
const options = toSecondValueSelectOptions(c);
|
||||||
|
if (options.length > 0) {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// secondValue 也可能是键值映射:{ "1":"拉闸", "2":"合闸" }
|
||||||
|
if (c && typeof c === 'object' && !Array.isArray(c)) {
|
||||||
|
const mapped = Object.entries(c as Record<string, unknown>).map(
|
||||||
|
([k, v]) => ({
|
||||||
|
label: String(v ?? k),
|
||||||
|
value: String(k),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
if (mapped.length > 0) {
|
||||||
|
return mapped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
function mapSelectListToOptions(list: any[]): Array<{ label: string; value: string }> {
|
function mapSelectListToOptions(list: any[]): Array<{ label: string; value: string }> {
|
||||||
return list
|
return list
|
||||||
.map((x: any) => ({
|
.map((x: any) => ({
|
||||||
@ -1035,7 +1127,6 @@ watch(
|
|||||||
() => currentServiceItem.value,
|
() => currentServiceItem.value,
|
||||||
async (item) => {
|
async (item) => {
|
||||||
valveCommandTypeOptions.value = [];
|
valveCommandTypeOptions.value = [];
|
||||||
breakerOperateTypeOptions.value = [];
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1056,21 +1147,6 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOperateBreakerServiceItem(item)) {
|
|
||||||
breakerOperateTypeLoading.value = true;
|
|
||||||
try {
|
|
||||||
const { data } = await getCommonGetSelectList({
|
|
||||||
query: { typeName: DEVICE_THING_MODE_COMMAND_TYPE_ENUM },
|
|
||||||
} as any);
|
|
||||||
breakerOperateTypeOptions.value = mapSelectListToOptions(
|
|
||||||
unwrapSelectListResponse(data),
|
|
||||||
);
|
|
||||||
} catch {
|
|
||||||
breakerOperateTypeOptions.value = [];
|
|
||||||
} finally {
|
|
||||||
breakerOperateTypeLoading.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1107,8 +1183,6 @@ const [ServiceCallModal, serviceCallModalApi] = useVbenModal({
|
|||||||
serviceCallFormValues.value = {};
|
serviceCallFormValues.value = {};
|
||||||
valveCommandTypeOptions.value = [];
|
valveCommandTypeOptions.value = [];
|
||||||
valveCommandTypeLoading.value = false;
|
valveCommandTypeLoading.value = false;
|
||||||
breakerOperateTypeOptions.value = [];
|
|
||||||
breakerOperateTypeLoading.value = false;
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
onOpenChange: async (isOpen: boolean) => {
|
onOpenChange: async (isOpen: boolean) => {
|
||||||
@ -1126,6 +1200,22 @@ const [ServiceCallModal, serviceCallModalApi] = useVbenModal({
|
|||||||
|
|
||||||
const serviceCallModalState = serviceCallModalApi.useStore();
|
const serviceCallModalState = serviceCallModalApi.useStore();
|
||||||
|
|
||||||
|
/** 服务入参:部分字段需为数值(如 Quantity),避免以字符串提交 */
|
||||||
|
function coerceServiceCallParamValue(
|
||||||
|
fieldName: string,
|
||||||
|
raw: string,
|
||||||
|
): { ok: true; value: unknown } | { ok: false; message: string } {
|
||||||
|
const key = fieldName.trim();
|
||||||
|
if (key.toLowerCase() === 'quantity') {
|
||||||
|
const n = Number(raw);
|
||||||
|
if (Number.isNaN(n)) {
|
||||||
|
return { ok: false, message: '数量(Quantity)需填写有效数字' };
|
||||||
|
}
|
||||||
|
return { ok: true, value: n };
|
||||||
|
}
|
||||||
|
return { ok: true, value: raw };
|
||||||
|
}
|
||||||
|
|
||||||
async function submitDeviceServiceCall() {
|
async function submitDeviceServiceCall() {
|
||||||
const row = serviceCallRow.value;
|
const row = serviceCallRow.value;
|
||||||
if (!row?.id) {
|
if (!row?.id) {
|
||||||
@ -1149,7 +1239,12 @@ async function submitDeviceServiceCall() {
|
|||||||
for (const f of serviceParamFields.value) {
|
for (const f of serviceParamFields.value) {
|
||||||
const v = (serviceCallFormValues.value[f.name] ?? '').trim();
|
const v = (serviceCallFormValues.value[f.name] ?? '').trim();
|
||||||
if (v !== '') {
|
if (v !== '') {
|
||||||
serviceParams[f.name] = v;
|
const coerced = coerceServiceCallParamValue(f.name, v);
|
||||||
|
if (!coerced.ok) {
|
||||||
|
Message.warning(coerced.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
serviceParams[f.name] = coerced.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -2861,7 +2956,6 @@ const toolbarActions = computed(() => [
|
|||||||
v-else-if="shouldUseBreakerOperateTypeSelectForField(f)"
|
v-else-if="shouldUseBreakerOperateTypeSelectForField(f)"
|
||||||
v-model:value="serviceCallFormValues[f.name]"
|
v-model:value="serviceCallFormValues[f.name]"
|
||||||
:options="breakerOperateTypeOptions"
|
:options="breakerOperateTypeOptions"
|
||||||
:loading="breakerOperateTypeLoading"
|
|
||||||
allow-clear
|
allow-clear
|
||||||
class="min-w-0 flex-1"
|
class="min-w-0 flex-1"
|
||||||
size="small"
|
size="small"
|
||||||
|
|||||||
@ -7,17 +7,19 @@ import { useRoute } from 'vue-router';
|
|||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { message as Message, Tag } from 'ant-design-vue';
|
import { Button, Input, Select, message as Message, Tag } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
getCommonGetSelectList,
|
getCommonGetSelectList,
|
||||||
postAggregationIoTplatformUpdateIoTplatformProductThingModelInfoAsync,
|
postAggregationIoTplatformUpdateIoTplatformProductThingModelInfoAsync,
|
||||||
|
postIoTplatformThingModelInfoCreateIoTplatformThingModelCommand,
|
||||||
postIoTplatformThingModelInfoCopyAnotherThingModelAsync,
|
postIoTplatformThingModelInfoCopyAnotherThingModelAsync,
|
||||||
postIoTplatformThingModelInfoCopyStandardThingModel,
|
postIoTplatformThingModelInfoCopyStandardThingModel,
|
||||||
postIoTplatformThingModelInfoCreateAsync,
|
postIoTplatformThingModelInfoCreateAsync,
|
||||||
postIoTplatformThingModelInfoDeleteAsync,
|
postIoTplatformThingModelInfoDeleteAsync,
|
||||||
|
postIoTplatformThingModelInfoGetIoTplatformThingModelService,
|
||||||
postIoTplatformThingModelInfoPageAsync,
|
postIoTplatformThingModelInfoPageAsync,
|
||||||
postIoTplatformThingModelInfoUpdateAsync,
|
postIoTplatformThingModelInfoUpdateAsync,
|
||||||
} from '#/api-client';
|
} from '#/api-client';
|
||||||
@ -289,6 +291,14 @@ const [ThingModelModal, thingModelModalApi] = useVbenModal({
|
|||||||
|
|
||||||
await formApi.setValues({
|
await formApi.setValues({
|
||||||
...(isEdit ? editRow.value : {}),
|
...(isEdit ? editRow.value : {}),
|
||||||
|
...(isEdit && {
|
||||||
|
standardFieldFieldExtension: formatFieldExtensionForForm(
|
||||||
|
editRow.value.standardFieldFieldExtension,
|
||||||
|
),
|
||||||
|
ioTPlatformRawFieldExtension: formatFieldExtensionForForm(
|
||||||
|
editRow.value.ioTPlatformRawFieldExtension,
|
||||||
|
),
|
||||||
|
}),
|
||||||
_ioTPlatform: platformValue,
|
_ioTPlatform: platformValue,
|
||||||
_ioTPlatformProductId: productIdValue,
|
_ioTPlatformProductId: productIdValue,
|
||||||
// 确保 identifierType 转换为字符串格式,以便与下拉框的 key 匹配
|
// 确保 identifierType 转换为字符串格式,以便与下拉框的 key 匹配
|
||||||
@ -355,6 +365,105 @@ const [CopyStandardModal, copyStandardModalApi] = useVbenModal({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
type OperateServiceItem = {
|
||||||
|
key?: null | string;
|
||||||
|
value?: null | string;
|
||||||
|
secondValue?: null | string;
|
||||||
|
thirdValue?: unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
const commandEditRow = ref<Record<string, any>>({});
|
||||||
|
const operateServiceLoading = ref(false);
|
||||||
|
const createCommandLoading = ref(false);
|
||||||
|
const operateServiceOptions = ref<OperateServiceItem[]>([]);
|
||||||
|
const operateTypeOptions = ref<Array<{ label: string; value: number }>>([]);
|
||||||
|
const selectedOperateType = ref<number>();
|
||||||
|
const operateIssueCommandText = ref('');
|
||||||
|
|
||||||
|
function normalizeOperateTypeOptions(
|
||||||
|
raw: unknown,
|
||||||
|
): Array<{ label: string; value: number }> {
|
||||||
|
if (raw == null || raw === '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let data: unknown = raw;
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
const s = data.trim();
|
||||||
|
if (!s) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
data = JSON.parse(s) as unknown;
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
return data
|
||||||
|
.map((item: any) => {
|
||||||
|
const valueRaw = item?.key ?? item?.value ?? item?.id ?? item?.operateType;
|
||||||
|
const labelRaw =
|
||||||
|
item?.value ??
|
||||||
|
item?.label ??
|
||||||
|
item?.name ??
|
||||||
|
item?.displayName ??
|
||||||
|
item?.key;
|
||||||
|
const value = Number.parseInt(String(valueRaw ?? ''), 10);
|
||||||
|
if (Number.isNaN(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
label: String(labelRaw ?? value),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(Boolean) as Array<{ label: string; value: number }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof data === 'object') {
|
||||||
|
return Object.entries(data as Record<string, unknown>)
|
||||||
|
.map(([k, v]) => {
|
||||||
|
const value = Number.parseInt(String(k), 10);
|
||||||
|
if (Number.isNaN(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
label: String(v ?? k),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(Boolean) as Array<{ label: string; value: number }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const [OperateCommandModal, operateCommandModalApi] = useVbenModal({
|
||||||
|
draggable: true,
|
||||||
|
footer: true,
|
||||||
|
showCancelButton: true,
|
||||||
|
showConfirmButton: true,
|
||||||
|
confirmText: '添加',
|
||||||
|
onConfirm: submitOperateCommand,
|
||||||
|
onBeforeClose: () => {
|
||||||
|
commandEditRow.value = {};
|
||||||
|
operateServiceOptions.value = [];
|
||||||
|
operateTypeOptions.value = [];
|
||||||
|
selectedOperateType.value = undefined;
|
||||||
|
operateIssueCommandText.value = '';
|
||||||
|
createCommandLoading.value = false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
onOpenChange: async (isOpen: boolean) => {
|
||||||
|
if (!isOpen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await fetchOperateServiceOptions();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// 创建新增表单 schema(传入获取平台和产品ID的函数,作为后备方案)
|
// 创建新增表单 schema(传入获取平台和产品ID的函数,作为后备方案)
|
||||||
// 注意:实际使用时,值会从表单的 _ioTPlatform 和 _ioTPlatformProductId 字段获取
|
// 注意:实际使用时,值会从表单的 _ioTPlatform 和 _ioTPlatformProductId 字段获取
|
||||||
const addThingModelFormSchema = getAddThingModelFormSchema(
|
const addThingModelFormSchema = getAddThingModelFormSchema(
|
||||||
@ -540,6 +649,20 @@ function normalizeFieldExtensionValue(fieldValue: unknown) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatFieldExtensionForForm(fieldValue: unknown) {
|
||||||
|
if (fieldValue == null || fieldValue === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (typeof fieldValue === 'string') {
|
||||||
|
return fieldValue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JSON.stringify(fieldValue, null, 2);
|
||||||
|
} catch {
|
||||||
|
return String(fieldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function parseJsonFieldValue(
|
function parseJsonFieldValue(
|
||||||
fieldValue: unknown,
|
fieldValue: unknown,
|
||||||
fieldLabel: string,
|
fieldLabel: string,
|
||||||
@ -685,6 +808,12 @@ async function onEdit(record: any) {
|
|||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
await editFormApi.setValues({
|
await editFormApi.setValues({
|
||||||
...record,
|
...record,
|
||||||
|
standardFieldFieldExtension: formatFieldExtensionForForm(
|
||||||
|
record.standardFieldFieldExtension,
|
||||||
|
),
|
||||||
|
ioTPlatformRawFieldExtension: formatFieldExtensionForForm(
|
||||||
|
record.ioTPlatformRawFieldExtension,
|
||||||
|
),
|
||||||
_ioTPlatform: platformValue,
|
_ioTPlatform: platformValue,
|
||||||
_ioTPlatformProductId: productIdValue,
|
_ioTPlatformProductId: productIdValue,
|
||||||
// 确保 identifierType 转换为字符串格式,以便与下拉框的 key 匹配
|
// 确保 identifierType 转换为字符串格式,以便与下拉框的 key 匹配
|
||||||
@ -755,6 +884,106 @@ const openAddModal = async () => {
|
|||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function fetchOperateServiceOptions() {
|
||||||
|
if (!commandEditRow.value?.ioTPlatformProductId) {
|
||||||
|
Message.warning('当前物模型数据缺少产品ID,无法加载可操作指令');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!commandEditRow.value?.standardFieldName) {
|
||||||
|
Message.warning('当前物模型数据缺少标准物模型标识符,无法加载可操作指令');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
operateServiceLoading.value = true;
|
||||||
|
try {
|
||||||
|
const { data } = await postIoTplatformThingModelInfoGetIoTplatformThingModelService(
|
||||||
|
{
|
||||||
|
body: {
|
||||||
|
id: String(commandEditRow.value.ioTPlatformProductId),
|
||||||
|
standardFieldName: String(commandEditRow.value.standardFieldName),
|
||||||
|
isGetOperateService: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
operateServiceOptions.value = Array.isArray(data)
|
||||||
|
? (data as OperateServiceItem[])
|
||||||
|
: [];
|
||||||
|
const firstService = operateServiceOptions.value[0];
|
||||||
|
operateTypeOptions.value = normalizeOperateTypeOptions(
|
||||||
|
firstService?.secondValue,
|
||||||
|
);
|
||||||
|
selectedOperateType.value =
|
||||||
|
operateTypeOptions.value.length > 0
|
||||||
|
? operateTypeOptions.value[0]?.value
|
||||||
|
: undefined;
|
||||||
|
if (operateServiceOptions.value.length === 0) {
|
||||||
|
Message.warning('当前属性标识符暂无可操作指令');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取可操作指令列表失败:', error);
|
||||||
|
Message.error('获取可操作指令列表失败');
|
||||||
|
operateServiceOptions.value = [];
|
||||||
|
operateTypeOptions.value = [];
|
||||||
|
selectedOperateType.value = undefined;
|
||||||
|
} finally {
|
||||||
|
operateServiceLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openOperateCommandModal(record: Record<string, any>) {
|
||||||
|
if (!record?.id) {
|
||||||
|
Message.warning('当前物模型数据缺少ID,无法添加默认操作指令');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const filedType = String(record?.filedType ?? '');
|
||||||
|
if (!filedType.includes('Service')) {
|
||||||
|
Message.warning('仅服务类型物模型支持添加默认操作指令');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
commandEditRow.value = record;
|
||||||
|
operateCommandModalApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitOperateCommand() {
|
||||||
|
if (!commandEditRow.value?.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedOperateType.value == null) {
|
||||||
|
Message.warning('请选择操作类型');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let issueCommand = operateIssueCommandText.value.trim();
|
||||||
|
if (!issueCommand) {
|
||||||
|
Message.warning('请填写指令内容');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
createCommandLoading.value = true;
|
||||||
|
try {
|
||||||
|
const resp =
|
||||||
|
await postIoTplatformThingModelInfoCreateIoTplatformThingModelCommand({
|
||||||
|
body: {
|
||||||
|
thingModelDataId: String(commandEditRow.value.id),
|
||||||
|
operateType: selectedOperateType.value,
|
||||||
|
issueCommand,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (resp.data) {
|
||||||
|
Message.success('默认操作指令添加成功');
|
||||||
|
operateCommandModalApi.close();
|
||||||
|
await gridApi.reload();
|
||||||
|
} else {
|
||||||
|
Message.error('默认操作指令添加失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('默认操作指令添加失败:', error);
|
||||||
|
Message.error('默认操作指令添加失败');
|
||||||
|
} finally {
|
||||||
|
createCommandLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 模型刷新
|
// 模型刷新
|
||||||
async function onThingModelRefresh() {
|
async function onThingModelRefresh() {
|
||||||
const formValues = gridApi?.formApi ? await gridApi.formApi.getValues() : {};
|
const formValues = gridApi?.formApi ? await gridApi.formApi.getValues() : {};
|
||||||
@ -1023,6 +1252,14 @@ async function onDel(record: any) {
|
|||||||
confirm: onDel.bind(null, row),
|
confirm: onDel.bind(null, row),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '指令',
|
||||||
|
type: 'link',
|
||||||
|
size: 'small',
|
||||||
|
auth: ['AbpIdentity.Users.Update'],
|
||||||
|
ifShow: String(row.filedType ?? '').includes('Service'),
|
||||||
|
onClick: openOperateCommandModal.bind(null, row),
|
||||||
|
},
|
||||||
]" />
|
]" />
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
@ -1039,5 +1276,50 @@ async function onDel(record: any) {
|
|||||||
<CopyStandardModal title="复制标准模型" class="w-[600px]">
|
<CopyStandardModal title="复制标准模型" class="w-[600px]">
|
||||||
<CopyStandardForm />
|
<CopyStandardForm />
|
||||||
</CopyStandardModal>
|
</CopyStandardModal>
|
||||||
|
|
||||||
|
<OperateCommandModal title="默认操作指令添加" class="w-[640px]">
|
||||||
|
<div v-if="operateServiceLoading" class="py-8 text-center text-gray-500">
|
||||||
|
正在加载可操作指令列表...
|
||||||
|
</div>
|
||||||
|
<div v-else class="space-y-3">
|
||||||
|
<div class="text-xs text-gray-500">
|
||||||
|
属性标识符:{{ commandEditRow.ioTPlatformRawFieldName || '-' }}
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="w-24 flex-shrink-0 text-right text-sm text-gray-600">操作类型</span>
|
||||||
|
<Select
|
||||||
|
v-model:value="selectedOperateType"
|
||||||
|
:options="operateTypeOptions"
|
||||||
|
allow-clear
|
||||||
|
class="min-w-0 flex-1"
|
||||||
|
placeholder="请选择操作类型"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-1">
|
||||||
|
<div class="text-sm font-medium text-gray-700">指令内容</div>
|
||||||
|
<Input.TextArea
|
||||||
|
v-model:value="operateIssueCommandText"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入默认操作指令内容"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="flex w-full items-center justify-end gap-2">
|
||||||
|
<Button @click="operateCommandModalApi.close()">
|
||||||
|
{{ $t('common.cancel') }}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
:loading="createCommandLoading"
|
||||||
|
:disabled="operateServiceLoading"
|
||||||
|
@click="submitOperateCommand"
|
||||||
|
>
|
||||||
|
添加
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</OperateCommandModal>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -828,9 +828,13 @@ export const getEditThingModelFormSchema = (
|
|||||||
disabled: true, // 编辑时禁用
|
disabled: true, // 编辑时禁用
|
||||||
onResolve: (item: any | null) => {
|
onResolve: (item: any | null) => {
|
||||||
formValues.standardFieldDisplayName = item?.displayText ?? '';
|
formValues.standardFieldDisplayName = item?.displayText ?? '';
|
||||||
|
formValues.standardFieldName = item?.code ?? '';
|
||||||
formValues.standardFieldValueType = (item?.extendedAttribute ?? '')
|
formValues.standardFieldValueType = (item?.extendedAttribute ?? '')
|
||||||
.toString()
|
.toString()
|
||||||
.toUpperCase();
|
.toUpperCase();
|
||||||
|
formValues.standardFieldFieldExtension = formatFieldExtensionFormValue(
|
||||||
|
item?.extendedAttributeValue,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
placeholder:
|
placeholder:
|
||||||
$t('common.pleaseInput') +
|
$t('common.pleaseInput') +
|
||||||
@ -849,6 +853,15 @@ export const getEditThingModelFormSchema = (
|
|||||||
$t('abp.thingModelInfos.StandardFieldName'),
|
$t('abp.thingModelInfos.StandardFieldName'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: 'Textarea',
|
||||||
|
fieldName: 'standardFieldFieldExtension',
|
||||||
|
label: $t('abp.thingModelInfos.StandardFieldFieldExtension'),
|
||||||
|
componentProps: {
|
||||||
|
rows: 4,
|
||||||
|
placeholder: '请选择标准物模型后自动回填扩展参数(JSON格式)',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
fieldName: 'ioTPlatformRawFieldName',
|
fieldName: 'ioTPlatformRawFieldName',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user