Commit 509576d5b566866399e6de033bf965a89a64309b

Authored by sqy
1 parent c8d8d83e

'fix:调整场景联动逻辑,加入访问统计'

@@ -11,12 +11,11 @@ import { useMessage } from '/@/hooks/web/useMessage'; @@ -11,12 +11,11 @@ import { useMessage } from '/@/hooks/web/useMessage';
11 * } 11 * }
12 * 12 *
13 */ 13 */
14 -export interface selectionOptions { 14 +interface selectionOptions {
15 rowKey: string; 15 rowKey: string;
16 clickToRowSelect: boolean; 16 clickToRowSelect: boolean;
17 rowSelection: { 17 rowSelection: {
18 onSelect: (_, __, selectedRowKeys: string[]) => void; 18 onSelect: (_, __, selectedRowKeys: string[]) => void;
19 - getCheckboxProps: (record: Recordable) => void;  
20 type: 'radio' | 'checkbox'; 19 type: 'radio' | 'checkbox';
21 }; 20 };
22 } 21 }
@@ -27,8 +26,8 @@ export const useBatchDelete = ( @@ -27,8 +26,8 @@ export const useBatchDelete = (
27 const { createMessage } = useMessage(); 26 const { createMessage } = useMessage();
28 const selectedRowIds = ref<string[]>([]); 27 const selectedRowIds = ref<string[]>([]);
29 const hasBatchDelete = computed(() => selectedRowIds.value.length <= 0); 28 const hasBatchDelete = computed(() => selectedRowIds.value.length <= 0);
30 - // 复选框事件  
31 - const onSelectRow = (_, __, selectedRows) => { 29 + // 复选框选择事件
  30 + const onSelect = (_, __, selectedRows) => {
32 const selectedRowKeys = selectedRows.map((item) => item.id); 31 const selectedRowKeys = selectedRows.map((item) => item.id);
33 selectedRowIds.value = selectedRowKeys; 32 selectedRowIds.value = selectedRowKeys;
34 }; 33 };
@@ -49,20 +48,13 @@ export const useBatchDelete = ( @@ -49,20 +48,13 @@ export const useBatchDelete = (
49 selectedRowIds.value = []; 48 selectedRowIds.value = [];
50 } 49 }
51 }; 50 };
  51 +
52 const selectionOptions: selectionOptions = { 52 const selectionOptions: selectionOptions = {
53 rowKey: 'id', 53 rowKey: 'id',
54 clickToRowSelect: false, 54 clickToRowSelect: false,
55 rowSelection: { 55 rowSelection: {
56 - onSelect: onSelectRow, 56 + onSelect,
57 type: 'checkbox', 57 type: 'checkbox',
58 - getCheckboxProps(record: Recordable) {  
59 - // Demo:status为1的选择框禁用  
60 - if (record.status === 1) {  
61 - return { disabled: true };  
62 - } else {  
63 - return { disabled: false };  
64 - }  
65 - },  
66 }, 58 },
67 }; 59 };
68 return { hasBatchDelete, selectionOptions, handleDeleteOrBatchDelete }; 60 return { hasBatchDelete, selectionOptions, handleDeleteOrBatchDelete };
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 v-bind="$attrs" 4 v-bind="$attrs"
5 @register="registerDrawer" 5 @register="registerDrawer"
6 @ok="handleSubmit" 6 @ok="handleSubmit"
7 - width="100%" 7 + width="50%"
8 showFooter 8 showFooter
9 @close="handleClose" 9 @close="handleClose"
10 :title="title" 10 :title="title"
@@ -65,6 +65,7 @@ @@ -65,6 +65,7 @@
65 :actionData="actionData" 65 :actionData="actionData"
66 :triggerData="triggerData" 66 :triggerData="triggerData"
67 :ref="skipUnwrap.actionItemRefs" 67 :ref="skipUnwrap.actionItemRefs"
  68 + :deviceList="deviceList"
68 @deleteAction="deleteAction" 69 @deleteAction="deleteAction"
69 /> 70 />
70 </template> 71 </template>
@@ -172,6 +173,7 @@ @@ -172,6 +173,7 @@
172 label: item.name, 173 label: item.name,
173 }; 174 };
174 }); 175 });
  176 + deviceList.value = editEntryIdData.value;
175 nextTick(() => { 177 nextTick(() => {
176 setEditFields(skipUnwrap.triggerItemRefs, editEntryIdData); 178 setEditFields(skipUnwrap.triggerItemRefs, editEntryIdData);
177 setEditFields(skipUnwrap.conditionItemRefs, editEntryIdData); 179 setEditFields(skipUnwrap.conditionItemRefs, editEntryIdData);
@@ -285,6 +287,7 @@ @@ -285,6 +287,7 @@
285 287
286 doActions.forEach((action, index) => { 288 doActions.forEach((action, index) => {
287 nextTick(() => { 289 nextTick(() => {
  290 + // 设置执行动作外层值
288 unref(skipUnwrap.actionItemRefs)[index].setFieldsFormValueFun({ 291 unref(skipUnwrap.actionItemRefs)[index].setFieldsFormValueFun({
289 outTarget: action.outTarget, 292 outTarget: action.outTarget,
290 device: action.entityType, 293 device: action.entityType,
@@ -292,76 +295,92 @@ @@ -292,76 +295,92 @@
292 alarm_config: action.alarmProfileId, 295 alarm_config: action.alarmProfileId,
293 alarm_level: action.doContext.alarmLevel, 296 alarm_level: action.doContext.alarmLevel,
294 }); 297 });
  298 + // 如果是设备输出设置脚本值
295 if (action.outTarget === 'DEVICE_OUT') { 299 if (action.outTarget === 'DEVICE_OUT') {
296 unref(skipUnwrap.actionItemRefs)[index].setJsonValue(action.doContext.params); 300 unref(skipUnwrap.actionItemRefs)[index].setJsonValue(action.doContext.params);
297 } 301 }
298 - if (action.doContext.clearRule) { 302 + // 清除告警有值?{数组}
  303 + if (action?.doContext?.clearRule?.length) {
299 unref(skipUnwrap.actionItemRefs)[index].checked = true; 304 unref(skipUnwrap.actionItemRefs)[index].checked = true;
  305 + // 生成对应清除告警的数组长度
  306 + unref(skipUnwrap.actionItemRefs)[index].clearRuleList = [
  307 + ...new Array(action?.doContext?.clearRule?.length).keys(),
  308 + ];
  309 + // 推迟执行时机-DOM渲染完毕在执行
300 nextTick(async () => { 310 nextTick(async () => {
301 - unref(skipUnwrap.actionItemRefs)[index].clearAlarmRef.setFieldsFormValueFun({  
302 - triggered: action.doContext?.clearRule?.triggerCondition?.condition?.spec?.type,  
303 - device: action?.entityType,  
304 - triggerType: action?.doContext?.clearRule?.triggerType,  
305 - type1:  
306 - action?.doContext?.clearRule?.triggerCondition?.condition?.condition[0]?.key  
307 - ?.type,  
308 - type2:  
309 - action?.doContext?.clearRule?.triggerCondition?.condition?.condition[0]?.key?.key,  
310 - operationType:  
311 - action?.doContext?.clearRule?.triggerCondition?.condition?.condition[0]  
312 - ?.valueType,  
313 - detail: action?.doContext?.clearRule?.triggerCondition?.alarmDetails,  
314 - entityId: action?.doContext?.clearRule?.entityId,  
315 - replaceValue:  
316 - action?.doContext?.clearRule?.triggerCondition?.condition?.spec?.predicate  
317 - ?.defaultValue,  
318 - time: action?.doContext?.clearRule?.triggerCondition?.condition?.spec?.predicate  
319 - ?.defaultValue,  
320 - timeUnit: action?.doContext?.clearRule?.triggerCondition?.condition?.spec?.unit,  
321 - });  
322 - // 设置值operationType  
323 -  
324 - unref(skipUnwrap.actionItemRefs)[index].clearAlarmRef.operationType =  
325 - action.doContext.clearRule.triggerCondition.condition.condition[0].valueType; 311 + unref(skipUnwrap.actionItemRefs)[index].refItem.clearRuleRefs.value.map(
  312 + (item, index) => {
  313 + item.setFieldsFormValueFun({
  314 + triggered:
  315 + action.doContext.clearRule[index].triggerCondition.condition.spec.type,
  316 + device: action.doContext.clearRule[index].entityType,
  317 + triggerType: action.doContext.clearRule[index].triggerType,
  318 + type1:
  319 + action.doContext.clearRule[index].triggerCondition.condition.condition[0].key
  320 + .type,
  321 + type2:
  322 + action.doContext.clearRule[index].triggerCondition.condition.condition[0].key
  323 + .key,
  324 + operationType:
  325 + action.doContext.clearRule[index].triggerCondition.condition.condition[0]
  326 + .valueType,
  327 + detail: action.doContext.clearRule[index].triggerCondition.alarmDetails,
  328 + entityId: action.doContext.clearRule[index].entityId,
  329 + replaceValue:
  330 + action.doContext.clearRule[index].triggerCondition.condition.spec.predicate
  331 + .defaultValue,
  332 + time: action.doContext.clearRule[index].triggerCondition.condition.spec
  333 + .predicate.defaultValue,
  334 + timeUnit:
  335 + action.doContext.clearRule[index].triggerCondition.condition.spec.unit,
  336 + });
  337 + // 单独设置operationType值 操作符类型 NUMERIC|String|Boolean|DATE_TIME
  338 + item.operationType =
  339 + action.doContext.clearRule[
  340 + index
  341 + ].triggerCondition.condition.condition[0].valueType;
  342 + }
  343 + );
326 344
327 const ConditionScreeningForm = await unref(skipUnwrap.actionItemRefs)[ 345 const ConditionScreeningForm = await unref(skipUnwrap.actionItemRefs)[
328 index 346 index
329 ].getRefItemConditionScreeningRefs(); 347 ].getRefItemConditionScreeningRefs();
330 348
331 - // // 设置对应条件筛选的个数  
332 - unref(skipUnwrap.actionItemRefs)[index].setConditionScreeningList([  
333 - ...new Array(  
334 - action.doContext.clearRule.triggerCondition.condition.condition.length  
335 - ).keys(),  
336 - ]);  
337 - // 操作符类型 NUMERIC|String|Boolean|DATE_TIME  
338 - const valueType =  
339 - action.doContext.clearRule.triggerCondition?.condition.condition[0].valueType;  
340 -  
341 // 循环设置条件筛选值。TODO:此处设置顺序有问题 349 // 循环设置条件筛选值。TODO:此处设置顺序有问题
342 - nextTick(() => {  
343 - const richTextList = [];  
344 - action.doContext.clearRule.triggerCondition.condition.condition.forEach(  
345 - (item, index) => { 350 + action.doContext.clearRule.map((rule, ruleIndex) => {
  351 + // 生成对应条件筛选的数组个数
  352 + unref(skipUnwrap.actionItemRefs)[index].setConditionScreeningList([
  353 + ...new Array(
  354 + action.doContext.clearRule[
  355 + ruleIndex
  356 + ].triggerCondition.condition.condition.length
  357 + ).keys(),
  358 + ]);
  359 + nextTick(() => {
  360 + const richTextList = [];
  361 + rule.triggerCondition.condition.condition.forEach((item, conditionIndex) => {
346 const formItem = { 362 const formItem = {
347 operation: item.predicate.operation, 363 operation: item.predicate.operation,
348 value: String(item.predicate.value.defaultValue), 364 value: String(item.predicate.value.defaultValue),
349 }; 365 };
350 richTextList.push({ 366 richTextList.push({
351 // 查询中文操作符 367 // 查询中文操作符
352 - operation: findOperation(valueType, item.predicate.operation).label, 368 + operation: findOperation(item.valueType, item.predicate.operation).label,
353 value: String(item.predicate.value.defaultValue), 369 value: String(item.predicate.value.defaultValue),
354 - attribute:  
355 - action.doContext.clearRule.triggerCondition?.condition.condition[0]?.key  
356 - ?.key, 370 + attribute: item?.key?.key,
357 }); 371 });
358 - ConditionScreeningForm.value[index].setFieldsValue(formItem);  
359 - }  
360 - );  
361 - unref(skipUnwrap.actionItemRefs)[index].setRichText(richTextList); 372 + ConditionScreeningForm[ruleIndex].value[conditionIndex].setFieldsValue(
  373 + formItem
  374 + );
  375 + });
  376 + unref(skipUnwrap.actionItemRefs)[index].setRichText(richTextList, ruleIndex);
  377 + });
362 }); 378 });
363 }); 379 });
364 } 380 }
  381 + nextTick(() => {
  382 + setEditFields(skipUnwrap.actionItemRefs, editEntryIdData);
  383 + });
365 }); 384 });
366 }); 385 });
367 } 386 }
1 -import { ref, h } from 'vue'; 1 +import { ref } from 'vue';
2 import { BasicColumn, FormSchema } from '/@/components/Table'; 2 import { BasicColumn, FormSchema } from '/@/components/Table';
3 -import {  
4 - screenLinkOrganizationGetApi,  
5 - screenLinkPagePutApi,  
6 -} from '/@/api/ruleengine/ruleengineApi';  
7 -import { Switch } from 'ant-design-vue';  
8 -import { useMessage } from '/@/hooks/web/useMessage'; 3 +import { screenLinkOrganizationGetApi } from '/@/api/ruleengine/ruleengineApi';
  4 +
9 import { copyTransFun } from '/@/utils/fnUtils'; 5 import { copyTransFun } from '/@/utils/fnUtils';
10 6
11 /** 7 /**
@@ -53,34 +49,7 @@ export const columns: BasicColumn[] = [ @@ -53,34 +49,7 @@ export const columns: BasicColumn[] = [
53 title: '状态', 49 title: '状态',
54 dataIndex: 'status', 50 dataIndex: 'status',
55 width: 120, 51 width: 120,
56 - customRender: ({ record }) => {  
57 - if (!Reflect.has(record, 'pendingStatus')) {  
58 - record.pendingStatus = false;  
59 - }  
60 - return h(Switch, {  
61 - checked: record.status === 1,  
62 - checkedChildren: '启用',  
63 - unCheckedChildren: '禁用',  
64 - loading: record.pendingStatus,  
65 - onChange(checked: boolean) {  
66 - record.pendingStatus = true;  
67 - const newStatus = checked ? 1 : 0;  
68 - const { createMessage } = useMessage();  
69 - screenLinkPagePutApi({ id: record.id, status: newStatus })  
70 - .then(() => {  
71 - record.status = newStatus;  
72 - if (record.status == 1) {  
73 - createMessage.success(`启用成功`);  
74 - } else {  
75 - createMessage.success('禁用成功');  
76 - }  
77 - })  
78 - .finally(() => {  
79 - record.pendingStatus = false;  
80 - });  
81 - },  
82 - });  
83 - }, 52 + slots: { customRender: 'status' },
84 }, 53 },
85 { 54 {
86 title: '描述', 55 title: '描述',
@@ -17,7 +17,6 @@ export const genTriggerOrConditionData = (triggerData) => { @@ -17,7 +17,6 @@ export const genTriggerOrConditionData = (triggerData) => {
17 timeUnit, 17 timeUnit,
18 replaceValue, 18 replaceValue,
19 } = triggerData; 19 } = triggerData;
20 - console.log(time, timeUnit, replaceValue);  
21 const mapPredicate = predicate?.map((item) => { 20 const mapPredicate = predicate?.map((item) => {
22 return { 21 return {
23 key: { 22 key: {
@@ -72,42 +71,58 @@ export const genTriggerOrConditionData = (triggerData) => { @@ -72,42 +71,58 @@ export const genTriggerOrConditionData = (triggerData) => {
72 }; 71 };
73 }; 72 };
74 73
75 -export const genActionData = (conditionData) => { 74 +export const genActionData = (actionData) => {
76 const { 75 const {
77 alarm_config, 76 alarm_config,
78 alarm_level, 77 alarm_level,
79 - detail,  
80 - device,  
81 - doContext,  
82 - operationType,  
83 outTarget, 78 outTarget,
84 - predicate,  
85 - triggerType,  
86 - triggered,  
87 - type1,  
88 - type2,  
89 - schedule,  
90 - entityId, 79 + clearRule: clearRules,
  80 + doContext,
  81 + device,
91 deviceId, 82 deviceId,
92 - time,  
93 - timeUnit,  
94 - } = conditionData;  
95 -  
96 - const mapPredicate = predicate?.map((item) => { 83 + } = actionData;
  84 + const clearRule = clearRules.map((item) => {
  85 + const mapPredicate = item.predicate.map((pred) => {
  86 + return {
  87 + key: {
  88 + type: item.type1,
  89 + key: item.type2,
  90 + },
  91 + valueType: item.operationType,
  92 + // value: null,
  93 + predicate: {
  94 + type: item.operationType,
  95 + operation: pred.operation,
  96 + value: {
  97 + defaultValue: pred.value,
  98 + // userValue: null,
  99 + // dynamicValue: null,
  100 + },
  101 + },
  102 + };
  103 + });
97 return { 104 return {
98 - key: {  
99 - type: type1,  
100 - key: type2,  
101 - },  
102 - valueType: operationType,  
103 - // value: null,  
104 - predicate: {  
105 - type: operationType,  
106 - operation: item.operation,  
107 - value: {  
108 - defaultValue: item.value,  
109 - // userValue: null,  
110 - // dynamicValue: null, 105 + triggerType: item.triggerType,
  106 + entityType: item.device,
  107 + entityId: item.device === 'PART' ? item.entityId : null,
  108 + triggerCondition: {
  109 + alarmDetails: item.detail,
  110 + condition: {
  111 + condition: mapPredicate,
  112 + spec: {
  113 + type: item.triggered,
  114 + unit: item.timeUnit,
  115 + predicate: {
  116 + defaultValue: item.time,
  117 + },
  118 + },
  119 + },
  120 + schedule: {
  121 + type: item.schedule,
  122 + // timezone: 'Asia/Shanghai',
  123 + // daysOfWeek: [2, 3],
  124 + // startsOn: 8700000,
  125 + // endsOn: 30300000,
111 }, 126 },
112 }, 127 },
113 }; 128 };
@@ -116,36 +131,12 @@ export const genActionData = (conditionData) => { @@ -116,36 +131,12 @@ export const genActionData = (conditionData) => {
116 { 131 {
117 alarmProfileId: alarm_config, 132 alarmProfileId: alarm_config,
118 outTarget, 133 outTarget,
119 - entityType: device,  
120 - deviceId: entityId?.length ? entityId : null,  
121 - doContext: mapPredicate?.length 134 + entityType: device ?? 'ALL',
  135 + deviceId: device === 'PART' ? deviceId : null,
  136 + doContext: clearRule?.length
122 ? { 137 ? {
123 alarmLevel: alarm_level, 138 alarmLevel: alarm_level,
124 - clearRule: {  
125 - triggerType,  
126 - triggerCondition: {  
127 - alarmDetails: detail,  
128 - condition: {  
129 - condition: mapPredicate,  
130 - spec: {  
131 - type: triggered,  
132 - unit: timeUnit,  
133 - predicate: {  
134 - defaultValue: time,  
135 - // userValue: null,  
136 - // dynamicValue: null,  
137 - },  
138 - },  
139 - },  
140 - schedule: {  
141 - type: schedule,  
142 - // timezone: 'Asia/Shanghai',  
143 - // daysOfWeek: [2, 3],  
144 - // startsOn: 8700000,  
145 - // endsOn: 30300000,  
146 - },  
147 - },  
148 - }, 139 + clearRule,
149 } 140 }
150 : { 141 : {
151 ...doContext, 142 ...doContext,
@@ -178,6 +169,48 @@ export const operationBoolean = [ @@ -178,6 +169,48 @@ export const operationBoolean = [
178 { label: '不等于', value: Boolean_Operation.NOT_EQUAL }, 169 { label: '不等于', value: Boolean_Operation.NOT_EQUAL },
179 ]; 170 ];
180 171
  172 +export const scheduleOptions = [
  173 + { label: '始终启用', value: 'ANY_TIME' },
  174 + { label: '定时启用', value: 'SPECIFIC_TIME' },
  175 + { label: '自定义启用', value: 'CUSTOM' },
  176 +];
  177 +export const timeUnitOptions = [
  178 + {
  179 + label: '秒',
  180 + value: 'SECONDS',
  181 + },
  182 + {
  183 + label: '分',
  184 + value: 'MINUTES',
  185 + },
  186 + {
  187 + label: '时',
  188 + value: 'HOURS',
  189 + },
  190 + {
  191 + label: '天',
  192 + value: 'DAYS',
  193 + },
  194 +];
  195 +export const options = [
  196 + {
  197 + label: '数字',
  198 + value: 'NUMERIC',
  199 + },
  200 + {
  201 + label: '布尔值',
  202 + value: 'BOOLEAN',
  203 + },
  204 + {
  205 + label: '字符串',
  206 + value: 'STRING',
  207 + },
  208 + {
  209 + label: '时间',
  210 + value: 'DATE_TIME',
  211 + },
  212 +];
  213 +
181 // 查找操作符 214 // 查找操作符
182 export function findOperation(valueType, operation) { 215 export function findOperation(valueType, operation) {
183 switch (valueType) { 216 switch (valueType) {
@@ -5,6 +5,15 @@ @@ -5,6 +5,15 @@
5 <div> 5 <div>
6 <span class="mr-2">启用规则</span> 6 <span class="mr-2">启用规则</span>
7 <RadioGroup v-model:value="schedule" :options="scheduleOptions" /> 7 <RadioGroup v-model:value="schedule" :options="scheduleOptions" />
  8 + <Tooltip title="移除" class="ml-4">
  9 + <Icon
  10 + icon="fluent:delete-off-20-regular"
  11 + size="20"
  12 + class="mr-2 cursor-pointer"
  13 + @click="handleDelete(index)"
  14 + v-if="clearRuleList.length > 1"
  15 + />
  16 + </Tooltip>
8 </div> 17 </div>
9 </template> 18 </template>
10 <BasicForm @register="registerForm"> 19 <BasicForm @register="registerForm">
@@ -29,7 +38,7 @@ @@ -29,7 +38,7 @@
29 </Input> 38 </Input>
30 </template> 39 </template>
31 </BasicForm> 40 </BasicForm>
32 - <Card size="small" :bordered="false" style="border: 2px dashed #797979" v-if="operationType"> 41 + <Card size="small" :bordered="false" style="border: 2px dashed #d9d9d9" v-if="operationType">
33 <ConditionScreening 42 <ConditionScreening
34 :childGetFieldsValue="childGetFieldsValue" 43 :childGetFieldsValue="childGetFieldsValue"
35 ref="conditionScreeningRef" 44 ref="conditionScreeningRef"
@@ -42,11 +51,24 @@ @@ -42,11 +51,24 @@
42 import { ref, provide } from 'vue'; 51 import { ref, provide } from 'vue';
43 import { CollapseContainer } from '/@/components/Container/index'; 52 import { CollapseContainer } from '/@/components/Container/index';
44 import { BasicForm, useForm } from '/@/components/Form/index'; 53 import { BasicForm, useForm } from '/@/components/Form/index';
45 - import { Radio, Card, Select, Input } from 'ant-design-vue'; 54 + import { Radio, Card, Select, Input, Tooltip } from 'ant-design-vue';
46 import { trigger_condition_schema } from '../config/config.data.ts'; 55 import { trigger_condition_schema } from '../config/config.data.ts';
47 import { getAttribute } from '/@/api/ruleengine/ruleengineApi'; 56 import { getAttribute } from '/@/api/ruleengine/ruleengineApi';
48 import ConditionScreening from './ConditionScreening.vue'; 57 import ConditionScreening from './ConditionScreening.vue';
  58 + import { scheduleOptions, timeUnitOptions, options } from '../config/formatData.ts';
49 59
  60 + import { Icon } from '/@/components/Icon';
  61 + defineProps({
  62 + index: {
  63 + type: Number,
  64 + required: true,
  65 + },
  66 + clearRuleList: {
  67 + type: Array,
  68 + default: () => [],
  69 + },
  70 + });
  71 + const emit = defineEmits(['delete']);
50 const RadioGroup = Radio.Group; 72 const RadioGroup = Radio.Group;
51 73
52 const [registerForm, { resetFields, getFieldsValue, updateSchema, setFieldsValue }] = useForm({ 74 const [registerForm, { resetFields, getFieldsValue, updateSchema, setFieldsValue }] = useForm({
@@ -90,52 +112,13 @@ @@ -90,52 +112,13 @@
90 }); 112 });
91 }; 113 };
92 const schedule = ref('ANY_TIME'); 114 const schedule = ref('ANY_TIME');
93 - const scheduleOptions = [  
94 - { label: '始终启用', value: 'ANY_TIME' },  
95 - { label: '定时启用', value: 'SPECIFIC_TIME' },  
96 - { label: '自定义启用', value: 'SPECIFIC_TIME' },  
97 - ];  
98 const operationType = ref<string>(''); 115 const operationType = ref<string>('');
99 - const options = [  
100 - {  
101 - label: '数字',  
102 - value: 'NUMERIC',  
103 - },  
104 - {  
105 - label: '布尔值',  
106 - value: 'BOOLEAN',  
107 - },  
108 - {  
109 - label: '字符串',  
110 - value: 'STRING',  
111 - },  
112 - {  
113 - label: '时间',  
114 - value: 'DATE_TIME',  
115 - },  
116 - ];  
117 -  
118 - const timeUnitOptions = [  
119 - {  
120 - label: '秒',  
121 - value: 'SECONDS',  
122 - },  
123 - {  
124 - label: '分',  
125 - value: 'MINUTES',  
126 - },  
127 - {  
128 - label: '时',  
129 - value: 'HOURS',  
130 - },  
131 - {  
132 - label: '天',  
133 - value: 'DAYS',  
134 - },  
135 - ];  
136 - const childGetFieldsValue = () => getFieldsValue();  
137 provide('operationType', operationType); 116 provide('operationType', operationType);
138 117
  118 + const childGetFieldsValue = () => getFieldsValue();
  119 + const handleDelete = (index: number) => {
  120 + emit('delete', index);
  121 + };
139 defineExpose({ 122 defineExpose({
140 getFieldsValue, 123 getFieldsValue,
141 updateFieldDeviceId, 124 updateFieldDeviceId,
@@ -70,7 +70,7 @@ @@ -70,7 +70,7 @@
70 .basicStyle { 70 .basicStyle {
71 margin-top: 0.5rem; 71 margin-top: 0.5rem;
72 width: 80%; 72 width: 80%;
73 - border: 2px dashed #797979; 73 + border: 1px dashed #d9d9d9;
74 padding: 1rem 0 0.5rem; 74 padding: 1rem 0 0.5rem;
75 border-radius: 0.25rem; 75 border-radius: 0.25rem;
76 } 76 }
@@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
43 </Input> 43 </Input>
44 </template> 44 </template>
45 </BasicForm> 45 </BasicForm>
46 - <Card size="small" :bordered="false" style="border: 2px dashed #797979" v-if="operationType"> 46 + <Card size="small" :bordered="false" style="border: 2px dashed #d9d9d9" v-if="operationType">
47 <ConditionScreening 47 <ConditionScreening
48 :childGetFieldsValue="childGetFieldsValue" 48 :childGetFieldsValue="childGetFieldsValue"
49 ref="conditionScreeningRef" 49 ref="conditionScreeningRef"
@@ -61,6 +61,7 @@ @@ -61,6 +61,7 @@
61 import { trigger_condition_schema } from '../config/config.data.ts'; 61 import { trigger_condition_schema } from '../config/config.data.ts';
62 import { getAttribute } from '/@/api/ruleengine/ruleengineApi'; 62 import { getAttribute } from '/@/api/ruleengine/ruleengineApi';
63 import ConditionScreening from './ConditionScreening.vue'; 63 import ConditionScreening from './ConditionScreening.vue';
  64 + import { scheduleOptions, timeUnitOptions, options } from '../config/formatData.ts';
64 const RadioGroup = Radio.Group; 65 const RadioGroup = Radio.Group;
65 66
66 defineProps({ 67 defineProps({
@@ -128,53 +129,12 @@ @@ -128,53 +129,12 @@
128 }; 129 };
129 130
130 const schedule = ref('ANY_TIME'); 131 const schedule = ref('ANY_TIME');
131 - const scheduleOptions = [  
132 - { label: '始终启用', value: 'ANY_TIME' },  
133 - { label: '定时启用', value: 'SPECIFIC_TIME' },  
134 - { label: '自定义启用', value: 'CUSTOM' },  
135 - ];  
136 const operationType = ref<string>(''); 132 const operationType = ref<string>('');
137 - const timeUnitOptions = [  
138 - {  
139 - label: '秒',  
140 - value: 'SECONDS',  
141 - },  
142 - {  
143 - label: '分',  
144 - value: 'MINUTES',  
145 - },  
146 - {  
147 - label: '时',  
148 - value: 'HOURS',  
149 - },  
150 - {  
151 - label: '天',  
152 - value: 'DAYS',  
153 - },  
154 - ];  
155 - const options = [  
156 - {  
157 - label: '数字',  
158 - value: 'NUMERIC',  
159 - },  
160 - {  
161 - label: '布尔值',  
162 - value: 'BOOLEAN',  
163 - },  
164 - {  
165 - label: '字符串',  
166 - value: 'STRING',  
167 - },  
168 - {  
169 - label: '时间',  
170 - value: 'DATE_TIME',  
171 - },  
172 - ]; 133 + provide('operationType', operationType);
  134 +
173 // 子组件获取父组件的值 135 // 子组件获取父组件的值
174 const childGetFieldsValue = () => getFieldsValue(); 136 const childGetFieldsValue = () => getFieldsValue();
175 137
176 - provide('operationType', operationType);  
177 -  
178 // 获取conditionScreeningForm的组件 138 // 获取conditionScreeningForm的组件
179 const getRefItemConditionScreeningRefs = async () => { 139 const getRefItemConditionScreeningRefs = async () => {
180 await nextTick(); 140 await nextTick();
@@ -32,17 +32,30 @@ @@ -32,17 +32,30 @@
32 </div> 32 </div>
33 </template> 33 </template>
34 <template #clearAlarm> 34 <template #clearAlarm>
35 - <Checkbox v-model:checked="checked"> 清除告警 </Checkbox> 35 + <Checkbox v-model:checked="checked" @change="handleCheckedChange"> 清除告警 </Checkbox>
  36 + <Tooltip title="清除告警与触发器一一对应">
  37 + <QuestionCircleOutlined />
  38 + </Tooltip>
36 </template> 39 </template>
37 </BasicForm> 40 </BasicForm>
38 - <Card  
39 - v-if="checked"  
40 - :bordered="false"  
41 - style="border: 2px dashed #797979"  
42 - :bodyStyle="{ padding: 0 }" 41 + <template v-for="(item, index) in clearRuleList" :key="item">
  42 + <Card
  43 + :bordered="false"
  44 + style="border: 2px dashed #d9d9d9; margin-top: 1rem"
  45 + :bodyStyle="{ padding: 0 }"
  46 + >
  47 + <ClearAlarm
  48 + :clearRuleList="clearRuleList"
  49 + :index="index"
  50 + :ref="refItem.clearRuleRefs"
  51 + @delete="deleteClearRule"
  52 + />
  53 + </Card>
  54 + </template>
  55 +
  56 + <a-button v-if="checked && isAddClearRule" class="mt-4" type="primary" @click="addClearRule"
  57 + >新增清除告警</a-button
43 > 58 >
44 - <ClearAlarm ref="clearAlarmRef" />  
45 - </Card>  
46 </CollapseContainer> 59 </CollapseContainer>
47 </template> 60 </template>
48 <script lang="ts" setup> 61 <script lang="ts" setup>
@@ -57,6 +70,7 @@ @@ -57,6 +70,7 @@
57 import { QuestionCircleOutlined } from '@ant-design/icons-vue'; 70 import { QuestionCircleOutlined } from '@ant-design/icons-vue';
58 import { useUserStore } from '/@/store/modules/user'; 71 import { useUserStore } from '/@/store/modules/user';
59 import ClearAlarm from './ClearAlarm.vue'; 72 import ClearAlarm from './ClearAlarm.vue';
  73 +
60 const props = defineProps({ 74 const props = defineProps({
61 actionIndex: { 75 actionIndex: {
62 type: Number, 76 type: Number,
@@ -70,20 +84,25 @@ @@ -70,20 +84,25 @@
70 type: Array, 84 type: Array,
71 default: () => [], 85 default: () => [],
72 }, 86 },
  87 + deviceList: {
  88 + type: Array,
  89 + required: true,
  90 + },
73 }); 91 });
74 - 92 + const isAddClearRule = computed(() => clearRuleList.value.length < props.triggerData.length);
  93 + const refItem = {
  94 + clearRuleRefs: ref([]),
  95 + };
75 const emit = defineEmits(['deleteAction']); 96 const emit = defineEmits(['deleteAction']);
76 const userStore = useUserStore(); 97 const userStore = useUserStore();
77 - const options = computed(() => {  
78 - return [  
79 - { label: '设备输出', value: 'DEVICE_OUT' },  
80 - {  
81 - label: '告警输出',  
82 - value: 'MSG_NOTIFY',  
83 - disabled: userStore.getOutTarget === 'MSG_NOTIFY' || !props.triggerData.length,  
84 - },  
85 - ];  
86 - }); 98 + const options = computed(() => [
  99 + { label: '设备输出', value: 'DEVICE_OUT' },
  100 + {
  101 + label: '告警输出',
  102 + value: 'MSG_NOTIFY',
  103 + disabled: userStore.getOutTarget === 'MSG_NOTIFY' || !props.triggerData.length,
  104 + },
  105 + ]);
87 const hasDisabled = ref(false); 106 const hasDisabled = ref(false);
88 const outTarget = ref(''); 107 const outTarget = ref('');
89 const changeOutTarget = (value: string) => { 108 const changeOutTarget = (value: string) => {
@@ -101,18 +120,21 @@ @@ -101,18 +120,21 @@
101 120
102 // 获取整个执行动作表单值 121 // 获取整个执行动作表单值
103 const getFieldsValueFunc = () => { 122 const getFieldsValueFunc = () => {
104 - const predicate =  
105 - clearAlarmRef?.value?.conditionScreeningRef?.refItem?.conditionScreeningRefs?.value?.map( 123 + const clearRule = refItem.clearRuleRefs.value.map((item) => {
  124 + const predicate = item.conditionScreeningRef?.refItem?.conditionScreeningRefs?.value?.map(
106 (item) => item.getFieldsValue() 125 (item) => item.getFieldsValue()
107 ); 126 );
108 127
  128 + return {
  129 + ...item.getFieldsValue(),
  130 + predicate,
  131 + schedule: item?.schedule,
  132 + };
  133 + });
109 return { 134 return {
110 ...getFieldsValue(), 135 ...getFieldsValue(),
111 - ...clearAlarmRef?.value?.getFieldsValue(),  
112 - predicate,  
113 doContext: unref(jsonInstance.value).get(), 136 doContext: unref(jsonInstance.value).get(),
114 - schedule: clearAlarmRef?.value?.schedule,  
115 - checked: checked.value, 137 + clearRule,
116 }; 138 };
117 }; 139 };
118 const setFieldsFormValueFun = (fieldsValue) => { 140 const setFieldsFormValueFun = (fieldsValue) => {
@@ -155,6 +177,30 @@ @@ -155,6 +177,30 @@
155 emit('deleteAction', { actionIndex, outTarget }); 177 emit('deleteAction', { actionIndex, outTarget });
156 }; 178 };
157 179
  180 + const clearRuleList = ref([]);
  181 + const handleCheckedChange = (e: Event) => {
  182 + if (!e.target.checked) {
  183 + clearRuleList.value = [];
  184 + } else {
  185 + addClearRule();
  186 + }
  187 + };
  188 + const addClearRule = () => {
  189 + unref(clearRuleList).push(Date.now());
  190 + nextTick(() => {
  191 + setFields(refItem.clearRuleRefs);
  192 + });
  193 + };
  194 +
  195 + function setFields(refs) {
  196 + unref(refs).map((item) => {
  197 + item.updateFieldDeviceId(props.deviceList);
  198 + });
  199 + }
  200 + const deleteClearRule = (index) => {
  201 + unref(clearRuleList).splice(index, 1);
  202 + };
  203 +
158 // json 以及初始化JSON 204 // json 以及初始化JSON
159 const jsoneditorRef = ref(); 205 const jsoneditorRef = ref();
160 const jsonValue = ref({}); 206 const jsonValue = ref({});
@@ -180,20 +226,24 @@ @@ -180,20 +226,24 @@
180 }; 226 };
181 227
182 const operationType = ref<string>(''); 228 const operationType = ref<string>('');
183 - const clearAlarmRef = ref(); 229 + provide('operationType', operationType);
184 230
185 const getRefItemConditionScreeningRefs = async () => { 231 const getRefItemConditionScreeningRefs = async () => {
186 await nextTick(); 232 await nextTick();
187 - return clearAlarmRef.value.conditionScreeningRef.refItem.conditionScreeningRefs; 233 + return refItem.clearRuleRefs.value.map(
  234 + (item) => item.conditionScreeningRef.refItem.conditionScreeningRefs
  235 + );
188 }; 236 };
189 const setConditionScreeningList = (list) => { 237 const setConditionScreeningList = (list) => {
190 - clearAlarmRef.value.conditionScreeningRef.conditionScreeningList = list; 238 + refItem.clearRuleRefs.value.map((item) => {
  239 + item.conditionScreeningRef.conditionScreeningList = list;
  240 + });
191 }; 241 };
192 242
193 - const setRichText = (list) => {  
194 - clearAlarmRef.value.conditionScreeningRef.otherAttribute = list; 243 + const setRichText = (list, index) => {
  244 + refItem.clearRuleRefs.value[index].conditionScreeningRef.otherAttribute = list;
195 }; 245 };
196 - provide('operationType', operationType); 246 +
197 defineExpose({ 247 defineExpose({
198 getFieldsValueFunc, 248 getFieldsValueFunc,
199 setFieldsFormValueFun, 249 setFieldsFormValueFun,
@@ -206,10 +256,11 @@ @@ -206,10 +256,11 @@
206 jsonInstance, 256 jsonInstance,
207 updateEditFieldAlarmConfig, 257 updateEditFieldAlarmConfig,
208 checked, 258 checked,
209 - clearAlarmRef,  
210 getRefItemConditionScreeningRefs, 259 getRefItemConditionScreeningRefs,
211 setConditionScreeningList, 260 setConditionScreeningList,
212 setRichText, 261 setRichText,
  262 + refItem,
  263 + clearRuleList,
213 }); 264 });
214 </script> 265 </script>
215 266
@@ -34,44 +34,60 @@ @@ -34,44 +34,60 @@
34 ]" 34 ]"
35 /> 35 />
36 </template> 36 </template>
  37 +
  38 + <template #status="{ record }">
  39 + <Switch
  40 + :checked="record.status === 1"
  41 + :loading="record.pendingStatus"
  42 + checkedChildren="启用"
  43 + unCheckedChildren="禁用"
  44 + @change="(checked:boolean)=>statusChange(checked,record)"
  45 + />
  46 + </template>
37 </BasicTable> 47 </BasicTable>
38 - <SceneLinkAgeDrawer  
39 - @register="registerDrawer"  
40 - @success="handleSuccess"  
41 - ref="sceneLinkAgeDrawerRef"  
42 - /> 48 + <SceneLinkAgeDrawer @register="registerDrawer" @success="handleSuccess" />
43 </div> 49 </div>
44 </template> 50 </template>
45 <script lang="ts"> 51 <script lang="ts">
46 - import { defineComponent, ref } from 'vue'; 52 + import { defineComponent } from 'vue';
47 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 53 import { BasicTable, useTable, TableAction } from '/@/components/Table';
48 import { useDrawer } from '/@/components/Drawer'; 54 import { useDrawer } from '/@/components/Drawer';
49 - import { screenLinkPageGetApi, screenLinkPageDeleteApi } from '/@/api/ruleengine/ruleengineApi'; 55 + import {
  56 + screenLinkPageGetApi,
  57 + screenLinkPageDeleteApi,
  58 + screenLinkPagePutApi,
  59 + } from '/@/api/ruleengine/ruleengineApi';
50 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 60 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
51 - 61 + import { Switch } from 'ant-design-vue';
52 import { columns, searchFormSchema } from './config/config.data.ts'; 62 import { columns, searchFormSchema } from './config/config.data.ts';
53 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 63 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
54 import { getAuthCache } from '/@/utils/auth'; 64 import { getAuthCache } from '/@/utils/auth';
55 import { authBtn } from '/@/enums/roleEnum'; 65 import { authBtn } from '/@/enums/roleEnum';
56 import SceneLinkAgeDrawer from './SceneLinkAgeDrawer.vue'; 66 import SceneLinkAgeDrawer from './SceneLinkAgeDrawer.vue';
  67 + import { useMessage } from '/@/hooks/web/useMessage';
57 68
58 export default defineComponent({ 69 export default defineComponent({
59 name: 'LinkEdge', 70 name: 'LinkEdge',
60 - components: { BasicTable, SceneLinkAgeDrawer, TableAction }, 71 + components: { BasicTable, SceneLinkAgeDrawer, TableAction, Switch },
61 setup() { 72 setup() {
62 - const sceneLinkAgeDrawerRef: any = ref(null);  
63 const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete( 73 const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
64 screenLinkPageDeleteApi, 74 screenLinkPageDeleteApi,
65 handleSuccess 75 handleSuccess
66 ); 76 );
67 - const handleLog = (log) => {  
68 - console.log(log); 77 + selectionOptions.rowSelection.getCheckboxProps = (record: Recordable) => {
  78 + // Demo:status为1的选择框禁用
  79 + if (record.status === 1) {
  80 + return { disabled: true };
  81 + } else {
  82 + return { disabled: false };
  83 + }
69 }; 84 };
  85 +
70 const userInfo: any = getAuthCache(USER_INFO_KEY); 86 const userInfo: any = getAuthCache(USER_INFO_KEY);
71 const userId = userInfo.userId; 87 const userId = userInfo.userId;
72 const role: string = userInfo.roles[0]; 88 const role: string = userInfo.roles[0];
73 const [registerDrawer, { openDrawer }] = useDrawer(); 89 const [registerDrawer, { openDrawer }] = useDrawer();
74 - const [registerTable, { reload }] = useTable({ 90 + const [registerTable, { reload, setProps }] = useTable({
75 title: '场景联动列表', 91 title: '场景联动列表',
76 api: screenLinkPageGetApi, 92 api: screenLinkPageGetApi,
77 columns, 93 columns,
@@ -114,8 +130,29 @@ @@ -114,8 +130,29 @@
114 function handleSuccess() { 130 function handleSuccess() {
115 reload(); 131 reload();
116 } 132 }
  133 +
  134 + const statusChange = async (checked, record) => {
  135 + // record.pendingStatus = true;
  136 + setProps({
  137 + loading: true,
  138 + });
  139 + const newStatus = checked ? 1 : 0;
  140 + const { createMessage } = useMessage();
  141 + try {
  142 + await screenLinkPagePutApi({ id: record.id, status: newStatus });
  143 + if (newStatus) {
  144 + createMessage.success(`启用成功`);
  145 + } else {
  146 + createMessage.success('禁用成功');
  147 + }
  148 + } finally {
  149 + setProps({
  150 + loading: false,
  151 + });
  152 + reload();
  153 + }
  154 + };
117 return { 155 return {
118 - sceneLinkAgeDrawerRef,  
119 registerTable, 156 registerTable,
120 registerDrawer, 157 registerDrawer,
121 handleAdd, 158 handleAdd,
@@ -127,7 +164,7 @@ @@ -127,7 +164,7 @@
127 authBtn, 164 authBtn,
128 role, 165 role,
129 userId, 166 userId,
130 - handleLog, 167 + statusChange,
131 }; 168 };
132 }, 169 },
133 }); 170 });
@@ -135,6 +135,14 @@ @@ -135,6 +135,14 @@
135 link.rel = 'shortcut icon'; 135 link.rel = 'shortcut icon';
136 link.href = res.icon ?? '/favicon.ico'; 136 link.href = res.icon ?? '/favicon.ico';
137 document.getElementsByTagName('head')[0].appendChild(link); 137 document.getElementsByTagName('head')[0].appendChild(link);
  138 +
  139 + var _hmt = _hmt || [];
  140 + (function () {
  141 + var hm = document.createElement('script');
  142 + hm.src = 'https://hm.baidu.com/hm.js?909f8e22a361b08e4f5ea3918500aede';
  143 + var s = document.getElementsByTagName('script')[0];
  144 + s.parentNode.insertBefore(hm, s);
  145 + })();
138 } 146 }
139 loading.value = false; 147 loading.value = false;
140 } 148 }