fix(iot): 修复场景联动动态列表 key 与校验问题
- 新增 getStableObjectKey,统一处理对象列表 v-for 稳定 key - 场景联动触发器、执行器、条件组、条件项改用稳定对象 key - 保持场景规则 API 类型不包含 UI 专用 _key 字段 - 修复场景联动触发器/执行器校验与地图详情跳转pull/348/head
parent
aeff25209d
commit
6fb45f1ded
|
|
@ -24,7 +24,7 @@ export namespace RuleSceneApi {
|
||||||
operator?: string;
|
operator?: string;
|
||||||
value?: any;
|
value?: any;
|
||||||
cronExpression?: string;
|
cronExpression?: string;
|
||||||
conditionGroups?: TriggerCondition[][];
|
conditionGroups?: TriggerCondition[][]; // 后端结构:List<List<TriggerCondition>>;外层「或」、组内「且」
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 场景联动规则的触发条件 */
|
/** 场景联动规则的触发条件 */
|
||||||
|
|
|
||||||
|
|
@ -19,21 +19,29 @@ export namespace MesDvMaintenRecordLineApi {
|
||||||
|
|
||||||
/** 查询设备保养记录明细分页 */
|
/** 查询设备保养记录明细分页 */
|
||||||
export function getMaintenRecordLinePage(params: PageParam) {
|
export function getMaintenRecordLinePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<MesDvMaintenRecordLineApi.MaintenRecordLine>>('/mes/dv/mainten-record-line/page', { params });
|
return requestClient.get<
|
||||||
|
PageResult<MesDvMaintenRecordLineApi.MaintenRecordLine>
|
||||||
|
>('/mes/dv/mainten-record-line/page', { params });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询设备保养记录明细详情 */
|
/** 查询设备保养记录明细详情 */
|
||||||
export function getMaintenRecordLine(id: number) {
|
export function getMaintenRecordLine(id: number) {
|
||||||
return requestClient.get<MesDvMaintenRecordLineApi.MaintenRecordLine>(`/mes/dv/mainten-record-line/get?id=${id}`);
|
return requestClient.get<MesDvMaintenRecordLineApi.MaintenRecordLine>(
|
||||||
|
`/mes/dv/mainten-record-line/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增设备保养记录明细 */
|
/** 新增设备保养记录明细 */
|
||||||
export function createMaintenRecordLine(data: MesDvMaintenRecordLineApi.MaintenRecordLine) {
|
export function createMaintenRecordLine(
|
||||||
|
data: MesDvMaintenRecordLineApi.MaintenRecordLine,
|
||||||
|
) {
|
||||||
return requestClient.post('/mes/dv/mainten-record-line/create', data);
|
return requestClient.post('/mes/dv/mainten-record-line/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改设备保养记录明细 */
|
/** 修改设备保养记录明细 */
|
||||||
export function updateMaintenRecordLine(data: MesDvMaintenRecordLineApi.MaintenRecordLine) {
|
export function updateMaintenRecordLine(
|
||||||
|
data: MesDvMaintenRecordLineApi.MaintenRecordLine,
|
||||||
|
) {
|
||||||
return requestClient.put('/mes/dv/mainten-record-line/update', data);
|
return requestClient.put('/mes/dv/mainten-record-line/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,19 +111,22 @@ function initMap() {
|
||||||
// 信息窗口打开后绑定链接点击事件
|
// 信息窗口打开后绑定链接点击事件
|
||||||
infoWindow.addEventListener('open', () => {
|
infoWindow.addEventListener('open', () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const link = document.querySelector('.device-link');
|
const link = document.querySelector(
|
||||||
if (link) {
|
'.BMap_bubble_content .device-link',
|
||||||
link.addEventListener('click', (e) => {
|
);
|
||||||
e.preventDefault();
|
if (!link) {
|
||||||
const deviceId = (e.target as HTMLElement).dataset.id;
|
return;
|
||||||
if (deviceId) {
|
|
||||||
router.push({
|
|
||||||
name: 'IoTDeviceDetail',
|
|
||||||
params: { id: deviceId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
link.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (device.id === undefined || device.id === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
router.push({
|
||||||
|
name: 'IoTDeviceDetail',
|
||||||
|
params: { id: device.id },
|
||||||
|
});
|
||||||
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
|
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
import { getStableObjectKey } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { Button, Tag } from 'ant-design-vue';
|
import { Button, Tag } from 'ant-design-vue';
|
||||||
|
|
@ -183,7 +184,7 @@ function removeConditionGroup() {
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div
|
<div
|
||||||
v-for="(subGroup, subGroupIndex) in trigger.conditionGroups"
|
v-for="(subGroup, subGroupIndex) in trigger.conditionGroups"
|
||||||
:key="`sub-group-${subGroupIndex}`"
|
:key="getStableObjectKey(subGroup)"
|
||||||
class="relative"
|
class="relative"
|
||||||
>
|
>
|
||||||
<!-- 子条件组容器(橙色主题) -->
|
<!-- 子条件组容器(橙色主题) -->
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
IotRuleSceneTriggerConditionTypeEnum,
|
IotRuleSceneTriggerConditionTypeEnum,
|
||||||
} from '@vben/constants';
|
} from '@vben/constants';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
import { getStableObjectKey } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
@ -105,7 +106,7 @@ function updateCondition(
|
||||||
<div v-else class="space-y-4">
|
<div v-else class="space-y-4">
|
||||||
<div
|
<div
|
||||||
v-for="(condition, conditionIndex) in subGroup"
|
v-for="(condition, conditionIndex) in subGroup"
|
||||||
:key="`condition-${conditionIndex}`"
|
:key="getStableObjectKey(condition)"
|
||||||
class="relative"
|
class="relative"
|
||||||
>
|
>
|
||||||
<!-- 条件配置 -->
|
<!-- 条件配置 -->
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { nextTick } from 'vue';
|
||||||
|
|
||||||
import { IotRuleSceneTriggerTypeEnum } from '@vben/constants';
|
import { IotRuleSceneTriggerTypeEnum } from '@vben/constants';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
import { getStableObjectKey } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { Button, Tag } from 'ant-design-vue';
|
import { Button, Tag } from 'ant-design-vue';
|
||||||
|
|
@ -96,7 +97,7 @@ function updateConditionGroup(
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(group, groupIndex) in conditionGroups"
|
v-for="(group, groupIndex) in conditionGroups"
|
||||||
:key="`group-${groupIndex}`"
|
:key="getStableObjectKey(group)"
|
||||||
class="relative"
|
class="relative"
|
||||||
>
|
>
|
||||||
<!-- 条件组容器(橙色主题) -->
|
<!-- 条件组容器(橙色主题) -->
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
IotRuleSceneActionTypeEnum,
|
IotRuleSceneActionTypeEnum,
|
||||||
} from '@vben/constants';
|
} from '@vben/constants';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
import { getStableObjectKey } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { Button, Card, Empty, Form, Select, Tag } from 'ant-design-vue';
|
import { Button, Card, Empty, Form, Select, Tag } from 'ant-design-vue';
|
||||||
|
|
@ -183,7 +184,7 @@ function onActionTypeChange(action: RuleSceneApi.Action, type: number) {
|
||||||
<div v-else class="space-y-[24px]">
|
<div v-else class="space-y-[24px]">
|
||||||
<div
|
<div
|
||||||
v-for="(action, index) in actions"
|
v-for="(action, index) in actions"
|
||||||
:key="`action-${index}`"
|
:key="getStableObjectKey(action)"
|
||||||
class="rounded-lg border border-blue-200 bg-blue-50/40 shadow-sm transition-shadow hover:shadow-md dark:border-blue-900/40 dark:bg-blue-950/20"
|
class="rounded-lg border border-blue-200 bg-blue-50/40 shadow-sm transition-shadow hover:shadow-md dark:border-blue-900/40 dark:bg-blue-950/20"
|
||||||
>
|
>
|
||||||
<!-- 执行器头部(蓝色主题) -->
|
<!-- 执行器头部(蓝色主题) -->
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
isDeviceTrigger,
|
isDeviceTrigger,
|
||||||
} from '@vben/constants';
|
} from '@vben/constants';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
import { getStableObjectKey } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { Button, Card, Empty, Form, Tag } from 'ant-design-vue';
|
import { Button, Card, Empty, Form, Tag } from 'ant-design-vue';
|
||||||
|
|
@ -131,7 +132,7 @@ onMounted(() => {
|
||||||
<div v-if="triggers.length > 0" class="space-y-[24px]">
|
<div v-if="triggers.length > 0" class="space-y-[24px]">
|
||||||
<div
|
<div
|
||||||
v-for="(triggerItem, index) in triggers"
|
v-for="(triggerItem, index) in triggers"
|
||||||
:key="`trigger-${index}`"
|
:key="getStableObjectKey(triggerItem)"
|
||||||
class="rounded-[8px] border border-green-200 bg-green-50/40 shadow-sm transition-shadow hover:shadow-md dark:border-green-900/40 dark:bg-green-950/20"
|
class="rounded-[8px] border border-green-200 bg-green-50/40 shadow-sm transition-shadow hover:shadow-md dark:border-green-900/40 dark:bg-green-950/20"
|
||||||
>
|
>
|
||||||
<!-- 触发器头部(绿色主题) -->
|
<!-- 触发器头部(绿色主题) -->
|
||||||
|
|
|
||||||
|
|
@ -103,12 +103,14 @@ function buildEmptyFormData(): RuleSceneApi.SceneRule {
|
||||||
|
|
||||||
/** 回显时兜底,保证触发器/执行器数组不为空 */
|
/** 回显时兜底,保证触发器/执行器数组不为空 */
|
||||||
function normalizeFormData(result: any): RuleSceneApi.SceneRule {
|
function normalizeFormData(result: any): RuleSceneApi.SceneRule {
|
||||||
|
const triggers: RuleSceneApi.Trigger[] = result.triggers?.length
|
||||||
|
? result.triggers
|
||||||
|
: buildEmptyFormData().triggers!;
|
||||||
|
const actions: RuleSceneApi.Action[] = result.actions || [];
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
triggers: result.triggers?.length
|
triggers,
|
||||||
? result.triggers
|
actions,
|
||||||
: buildEmptyFormData().triggers,
|
|
||||||
actions: result.actions || [],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,7 @@ export namespace RuleSceneApi {
|
||||||
operator?: string;
|
operator?: string;
|
||||||
value?: any;
|
value?: any;
|
||||||
cronExpression?: string;
|
cronExpression?: string;
|
||||||
// 后端结构:List<List<TriggerCondition>>;外层「或」、组内「且」
|
conditionGroups?: TriggerCondition[][]; // 后端结构:List<List<TriggerCondition>>;外层「或」、组内「且」
|
||||||
conditionGroups?: TriggerCondition[][];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 场景联动规则的触发条件 */
|
/** 场景联动规则的触发条件 */
|
||||||
|
|
|
||||||
|
|
@ -19,21 +19,29 @@ export namespace MesDvMaintenRecordLineApi {
|
||||||
|
|
||||||
/** 查询设备保养记录明细分页 */
|
/** 查询设备保养记录明细分页 */
|
||||||
export function getMaintenRecordLinePage(params: PageParam) {
|
export function getMaintenRecordLinePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<MesDvMaintenRecordLineApi.MaintenRecordLine>>('/mes/dv/mainten-record-line/page', { params });
|
return requestClient.get<
|
||||||
|
PageResult<MesDvMaintenRecordLineApi.MaintenRecordLine>
|
||||||
|
>('/mes/dv/mainten-record-line/page', { params });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询设备保养记录明细详情 */
|
/** 查询设备保养记录明细详情 */
|
||||||
export function getMaintenRecordLine(id: number) {
|
export function getMaintenRecordLine(id: number) {
|
||||||
return requestClient.get<MesDvMaintenRecordLineApi.MaintenRecordLine>(`/mes/dv/mainten-record-line/get?id=${id}`);
|
return requestClient.get<MesDvMaintenRecordLineApi.MaintenRecordLine>(
|
||||||
|
`/mes/dv/mainten-record-line/get?id=${id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增设备保养记录明细 */
|
/** 新增设备保养记录明细 */
|
||||||
export function createMaintenRecordLine(data: MesDvMaintenRecordLineApi.MaintenRecordLine) {
|
export function createMaintenRecordLine(
|
||||||
|
data: MesDvMaintenRecordLineApi.MaintenRecordLine,
|
||||||
|
) {
|
||||||
return requestClient.post('/mes/dv/mainten-record-line/create', data);
|
return requestClient.post('/mes/dv/mainten-record-line/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改设备保养记录明细 */
|
/** 修改设备保养记录明细 */
|
||||||
export function updateMaintenRecordLine(data: MesDvMaintenRecordLineApi.MaintenRecordLine) {
|
export function updateMaintenRecordLine(
|
||||||
|
data: MesDvMaintenRecordLineApi.MaintenRecordLine,
|
||||||
|
) {
|
||||||
return requestClient.put('/mes/dv/mainten-record-line/update', data);
|
return requestClient.put('/mes/dv/mainten-record-line/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,13 +117,13 @@ function initMap() {
|
||||||
}
|
}
|
||||||
link.addEventListener('click', (e) => {
|
link.addEventListener('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const deviceId = (e.target as HTMLElement).dataset.id;
|
if (device.id === undefined || device.id === null) {
|
||||||
if (deviceId) {
|
return;
|
||||||
router.push({
|
|
||||||
name: 'IoTDeviceDetail',
|
|
||||||
params: { id: deviceId },
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
router.push({
|
||||||
|
name: 'IoTDeviceDetail',
|
||||||
|
params: { id: device.id },
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
|
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
import { getStableObjectKey } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { ElButton, ElTag } from 'element-plus';
|
import { ElButton, ElTag } from 'element-plus';
|
||||||
|
|
@ -180,7 +181,7 @@ function removeConditionGroup() {
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div
|
<div
|
||||||
v-for="(subGroup, subGroupIndex) in trigger.conditionGroups"
|
v-for="(subGroup, subGroupIndex) in trigger.conditionGroups"
|
||||||
:key="`sub-group-${subGroupIndex}`"
|
:key="getStableObjectKey(subGroup)"
|
||||||
class="relative"
|
class="relative"
|
||||||
>
|
>
|
||||||
<!-- 子条件组容器 -->
|
<!-- 子条件组容器 -->
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
IotRuleSceneTriggerConditionTypeEnum,
|
IotRuleSceneTriggerConditionTypeEnum,
|
||||||
} from '@vben/constants';
|
} from '@vben/constants';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
import { getStableObjectKey } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { ElButton } from 'element-plus';
|
import { ElButton } from 'element-plus';
|
||||||
|
|
@ -105,7 +106,7 @@ function updateCondition(
|
||||||
<div v-else class="space-y-4">
|
<div v-else class="space-y-4">
|
||||||
<div
|
<div
|
||||||
v-for="(condition, conditionIndex) in subGroup"
|
v-for="(condition, conditionIndex) in subGroup"
|
||||||
:key="`condition-${conditionIndex}`"
|
:key="getStableObjectKey(condition)"
|
||||||
class="relative"
|
class="relative"
|
||||||
>
|
>
|
||||||
<!-- 条件配置 -->
|
<!-- 条件配置 -->
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { nextTick } from 'vue';
|
||||||
|
|
||||||
import { IotRuleSceneTriggerTypeEnum } from '@vben/constants';
|
import { IotRuleSceneTriggerTypeEnum } from '@vben/constants';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
import { getStableObjectKey } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { ElButton, ElTag } from 'element-plus';
|
import { ElButton, ElTag } from 'element-plus';
|
||||||
|
|
@ -96,7 +97,7 @@ function updateConditionGroup(
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(group, groupIndex) in conditionGroups"
|
v-for="(group, groupIndex) in conditionGroups"
|
||||||
:key="`group-${groupIndex}`"
|
:key="getStableObjectKey(group)"
|
||||||
class="relative"
|
class="relative"
|
||||||
>
|
>
|
||||||
<!-- 条件组容器(橙色主题) -->
|
<!-- 条件组容器(橙色主题) -->
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
IotRuleSceneActionTypeEnum,
|
IotRuleSceneActionTypeEnum,
|
||||||
} from '@vben/constants';
|
} from '@vben/constants';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
import { getStableObjectKey } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import {
|
import {
|
||||||
|
|
@ -199,7 +200,7 @@ function onActionTypeChange(action: RuleSceneApi.Action, type: number) {
|
||||||
<div v-else class="space-y-[24px]">
|
<div v-else class="space-y-[24px]">
|
||||||
<div
|
<div
|
||||||
v-for="(action, index) in actions"
|
v-for="(action, index) in actions"
|
||||||
:key="`action-${index}`"
|
:key="getStableObjectKey(action)"
|
||||||
class="rounded-lg border-2 border-blue-200 bg-blue-50 shadow-sm transition-shadow hover:shadow-md"
|
class="rounded-lg border-2 border-blue-200 bg-blue-50 shadow-sm transition-shadow hover:shadow-md"
|
||||||
>
|
>
|
||||||
<!-- 执行器头部 - 蓝色主题 -->
|
<!-- 执行器头部 - 蓝色主题 -->
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
isDeviceTrigger,
|
isDeviceTrigger,
|
||||||
} from '@vben/constants';
|
} from '@vben/constants';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
import { getStableObjectKey } from '@vben/utils';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import { ElButton, ElCard, ElEmpty, ElFormItem, ElTag } from 'element-plus';
|
import { ElButton, ElCard, ElEmpty, ElFormItem, ElTag } from 'element-plus';
|
||||||
|
|
@ -164,7 +165,7 @@ onMounted(() => {
|
||||||
<div v-if="triggers.length > 0" class="space-y-[24px]">
|
<div v-if="triggers.length > 0" class="space-y-[24px]">
|
||||||
<div
|
<div
|
||||||
v-for="(triggerItem, index) in triggers"
|
v-for="(triggerItem, index) in triggers"
|
||||||
:key="`trigger-${index}`"
|
:key="getStableObjectKey(triggerItem)"
|
||||||
class="rounded-[8px] border-2 border-green-200 bg-green-50 shadow-sm transition-shadow hover:shadow-md"
|
class="rounded-[8px] border-2 border-green-200 bg-green-50 shadow-sm transition-shadow hover:shadow-md"
|
||||||
>
|
>
|
||||||
<!-- 触发器头部 - 绿色主题 -->
|
<!-- 触发器头部 - 绿色主题 -->
|
||||||
|
|
|
||||||
|
|
@ -103,12 +103,14 @@ function buildEmptyFormData(): RuleSceneApi.SceneRule {
|
||||||
|
|
||||||
/** 回显时兜底,保证触发器/执行器数组不为空 */
|
/** 回显时兜底,保证触发器/执行器数组不为空 */
|
||||||
function normalizeFormData(result: any): RuleSceneApi.SceneRule {
|
function normalizeFormData(result: any): RuleSceneApi.SceneRule {
|
||||||
|
const triggers: RuleSceneApi.Trigger[] = result.triggers?.length
|
||||||
|
? result.triggers
|
||||||
|
: buildEmptyFormData().triggers!;
|
||||||
|
const actions: RuleSceneApi.Action[] = result.actions || [];
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
triggers: result.triggers?.length
|
triggers,
|
||||||
? result.triggers
|
actions,
|
||||||
: buildEmptyFormData().triggers,
|
|
||||||
actions: result.actions || [],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { buildShortUUID } from './uuid';
|
||||||
|
|
||||||
export function bindMethods<T extends object>(instance: T): void {
|
export function bindMethods<T extends object>(instance: T): void {
|
||||||
const prototype = Object.getPrototypeOf(instance);
|
const prototype = Object.getPrototypeOf(instance);
|
||||||
const propertyNames = Object.getOwnPropertyNames(prototype);
|
const propertyNames = Object.getOwnPropertyNames(prototype);
|
||||||
|
|
@ -114,3 +116,22 @@ export function jsonParse(str: string) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const stableObjectKeyMap = new WeakMap<object, string>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为对象引用生成稳定 key,不写入对象本身。
|
||||||
|
*
|
||||||
|
* 适用于 v-for 使用对象或数组项作为渲染单位,但不希望把 UI 字段混入业务数据的场景。
|
||||||
|
*/
|
||||||
|
export function getStableObjectKey(
|
||||||
|
item: object,
|
||||||
|
generator: () => string = buildShortUUID,
|
||||||
|
): string {
|
||||||
|
let key = stableObjectKeyMap.get(item);
|
||||||
|
if (!key) {
|
||||||
|
key = generator();
|
||||||
|
stableObjectKeyMap.set(item, key);
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue