Commit d120cec6b5bc02b60991e751d875a932b44988f5

Authored by sqy
1 parent e18453a8

'调整配置文件'

  1 +import { ref, h } from 'vue';
  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';
  9 +import { copyTransFun } from '/@/utils/fnUtils';
  10 +
  11 +/**
  12 + * 所使用的枚举值
  13 + */
  14 +
  15 +export enum TriggerEnum {
  16 + IS_DEVICE_ACT = 'DEVICE_TRIGGER',
  17 + IS_TIME_ACT = 'SCHEDULE_TRIGGER',
  18 + IS_SCENE_ACT = 'SCENE_TRIGGER',
  19 + IS_HAND_ACT = 'HAND_ACT',
  20 + IS_MSG_NOTIFY = 'MSG_NOTIFY',
  21 + IS_DEVICE_STATUS = 'DEVICE_STATUS',
  22 + IS_TIME_ALL = 'SCHEDULE_TRIGGER',
  23 +}
  24 +export const isDevice = (type: string) => {
  25 + return type === TriggerEnum.IS_DEVICE_ACT;
  26 +};
  27 +
  28 +export const isTime = (type: string) => {
  29 + return type === TriggerEnum.IS_TIME_ACT;
  30 +};
  31 +
  32 +export const columns: BasicColumn[] = [
  33 + {
  34 + title: '场景联动名称',
  35 + dataIndex: 'name',
  36 + width: 200,
  37 + },
  38 + {
  39 + title: '触发方式',
  40 + dataIndex: 'triggerType',
  41 + format: (_: string, record: Recordable) => {
  42 + return record.triggers[0]?.triggerType == 'DEVICE_TRIGGER'
  43 + ? '设备触发'
  44 + : record.triggers[0]?.triggerType == 'SCHEDULE_TRIGGER'
  45 + ? '定时触发'
  46 + : record.triggers[0]?.triggerType == 'SCENE_TRIGGER'
  47 + ? '场景触发'
  48 + : '手动触发';
  49 + },
  50 + width: 200,
  51 + },
  52 + {
  53 + title: '状态',
  54 + dataIndex: 'status',
  55 + 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 + },
  84 + },
  85 + {
  86 + title: '描述',
  87 + dataIndex: 'description',
  88 + width: 200,
  89 + },
  90 + {
  91 + title: '创建者',
  92 + dataIndex: 'creatorName',
  93 + width: 200,
  94 + },
  95 + {
  96 + title: '创建时间',
  97 + dataIndex: 'createTime',
  98 + width: 180,
  99 + },
  100 +];
  101 +export const organizationId = ref('');
  102 +export const formSchema: FormSchema[] = [
  103 + {
  104 + field: 'name',
  105 + label: '场景联动名称',
  106 + colProps: { span: 24 },
  107 + required: true,
  108 + component: 'Input',
  109 +
  110 + componentProps: {
  111 + maxLength: 36,
  112 + placeholder: '请输入场景联动名称',
  113 + },
  114 + },
  115 + {
  116 + required: true,
  117 + field: 'organizationId',
  118 + label: '所属组织',
  119 + colProps: { span: 24 },
  120 + component: 'ApiTreeSelect',
  121 + componentProps: {
  122 + api: async () => {
  123 + const data = await screenLinkOrganizationGetApi();
  124 + copyTransFun(data as any as any[]);
  125 + return data;
  126 + },
  127 + onChange(value) {
  128 + organizationId.value = value;
  129 + },
  130 + },
  131 + },
  132 + {
  133 + field: 'description',
  134 + label: '描述',
  135 + colProps: { span: 24 },
  136 + component: 'InputTextArea',
  137 + componentProps: {
  138 + maxLength: 255,
  139 + placeholder: '请输入描述',
  140 + },
  141 + },
  142 +];
  143 +
  144 +export const searchFormSchema: FormSchema[] = [
  145 + {
  146 + field: 'organizationId',
  147 + label: '所属组织',
  148 + colProps: { span: 6 },
  149 + component: 'ApiTreeSelect',
  150 + componentProps: {
  151 + placeholder: '请选择组织',
  152 + api: async () => {
  153 + const data = await screenLinkOrganizationGetApi();
  154 + copyTransFun(data as any as any[]);
  155 + return data;
  156 + },
  157 + },
  158 + },
  159 + {
  160 + field: 'name',
  161 + label: '名称',
  162 + component: 'Input',
  163 + colProps: { span: 6 },
  164 + componentProps: {
  165 + maxLength: 36,
  166 + placeholder: '请输入场景联动名称',
  167 + },
  168 + },
  169 + {
  170 + field: 'status',
  171 + label: '状态',
  172 + component: 'Select',
  173 + componentProps: {
  174 + placeholder: '请选择状态',
  175 + options: [
  176 + { label: '启用', value: '1' },
  177 + { label: '禁用', value: '0' },
  178 + ],
  179 + },
  180 + colProps: { span: 6 },
  181 + },
  182 +];
  183 +// 持续时间
  184 +const isTimeDuration = (type) => {
  185 + return type === 'timeDuration';
  186 +};
  187 +const isReplace = (type) => {
  188 + return type === 'replace';
  189 +};
  190 +// 部分
  191 +const isPart = (type: string) => {
  192 + return type === 'PART';
  193 +};
  194 +
  195 +export const trigger_condition_schema: FormSchema[] = [
  196 + {
  197 + field: 'triggered',
  198 + label: '',
  199 + component: 'Select',
  200 + componentProps: {
  201 + placeholder: '请选择触发类型',
  202 + options: [
  203 + { label: '简单', value: 'SIMPLE' },
  204 + { label: '持续时长', value: 'timeDuration' },
  205 + { label: '重复次数', value: 'replace' },
  206 + ],
  207 + },
  208 + colProps: { span: 6 },
  209 + },
  210 + {
  211 + field: 'device',
  212 + label: '',
  213 + component: 'Select',
  214 + componentProps: {
  215 + placeholder: '请选择设备',
  216 + options: [
  217 + { label: '全部', value: 'ALL' },
  218 + { label: '部分', value: 'PART' },
  219 + ],
  220 + },
  221 + colProps: { span: 6 },
  222 + },
  223 + {
  224 + field: 'entityId',
  225 + label: '',
  226 + component: 'Select',
  227 + componentProps: {
  228 + placeholder: '请选择设备',
  229 + mode: 'multiple',
  230 + },
  231 + ifShow: ({ values }) => isPart(values.device),
  232 + colProps: { span: 6 },
  233 + },
  234 + {
  235 + field: 'time',
  236 + label: '',
  237 + component: 'Input',
  238 + componentProps: {
  239 + placeholder: '请输入持续时间',
  240 + },
  241 + ifShow: ({ values }) => isTimeDuration(values.triggered),
  242 + colProps: { span: 6 },
  243 + },
  244 + {
  245 + field: 'timeUnit',
  246 + label: '',
  247 + component: 'Input',
  248 + componentProps: {
  249 + placeholder: '请输入持续时间单位',
  250 + },
  251 + ifShow: ({ values }) => isTimeDuration(values.triggered),
  252 + colProps: { span: 6 },
  253 + },
  254 + {
  255 + field: 'replaceValue',
  256 + label: '',
  257 + component: 'Input',
  258 + componentProps: {
  259 + placeholder: '事件计数值',
  260 + },
  261 + ifShow: ({ values }) => isReplace(values.triggered),
  262 + colProps: { span: 6 },
  263 + },
  264 + {
  265 + field: 'triggerType',
  266 + label: '',
  267 + component: 'Select',
  268 + componentProps: {
  269 + placeholder: '设备触发',
  270 + options: [
  271 + { label: '设备触发', value: 'DEVICE_TRIGGER' },
  272 + // { label: '定时触发', value: 'SCHEDULE_TRIGGER' },
  273 + // { label: '场景触发', value: 'SCENE_TRIGGER' },
  274 + // { label: '手动触发', value: 'HAND_ACT' },
  275 + ],
  276 + },
  277 + colProps: { span: 6 },
  278 + },
  279 +
  280 + {
  281 + field: 'type1',
  282 + label: '',
  283 + component: 'Select',
  284 + componentProps: {
  285 + placeholder: '属性触发方式',
  286 + options: [{ label: '属性触发', value: 'TIME_SERIES' }],
  287 + },
  288 + ifShow: ({ values }) => isDevice(values.triggerType),
  289 + colProps: { span: 6 },
  290 + },
  291 + {
  292 + field: 'type2',
  293 + label: '',
  294 + component: 'AutoComplete',
  295 + componentProps: {
  296 + placeholder: '请选择属性',
  297 + },
  298 + ifShow: ({ values }) => isDevice(values.triggerType),
  299 + colProps: { span: 6 },
  300 + },
  301 + {
  302 + field: 'operationType',
  303 + label: '',
  304 + component: 'Select',
  305 + slot: 'operationType',
  306 + colProps: { span: 6 },
  307 + },
  308 + {
  309 + field: 'detail',
  310 + label: '',
  311 + component: 'InputTextArea',
  312 + componentProps: {
  313 + placeholder: '请输入详情',
  314 + },
  315 + colProps: {
  316 + span: 13,
  317 + },
  318 + },
  319 +];
  320 +// !!!----------------------------------------------------^_^------------------------------------------------------------!!!
  321 +enum ActionEnum {
  322 + DEVICE_OUT = 'DEVICE_OUT',
  323 + ALARM_OUT = 'MSG_NOTIFY',
  324 +}
  325 +const isDeviceOut = (type: string) => type === ActionEnum.DEVICE_OUT;
  326 +const isAlarmOut = (type: string) => type === ActionEnum.ALARM_OUT;
  327 +
  328 +export const actionSchema: FormSchema[] = [
  329 + {
  330 + field: 'outTarget',
  331 + label: '',
  332 + component: 'Select',
  333 + required: true,
  334 + componentProps: {
  335 + placeholder: '请选择执行动作',
  336 + },
  337 + slot: 'outTarget',
  338 + colProps: { span: 6 },
  339 + },
  340 + {
  341 + field: 'device',
  342 + label: '',
  343 + component: 'Select',
  344 + componentProps: {
  345 + placeholder: '请选择设备',
  346 + options: [
  347 + { label: '全部', value: 'ALL' },
  348 + { label: '部分', value: 'PART' },
  349 + ],
  350 + },
  351 + ifShow: ({ values }) => isDeviceOut(values.outTarget),
  352 + colProps: { span: 6 },
  353 + },
  354 + {
  355 + field: 'deviceId',
  356 + label: '',
  357 + component: 'Select',
  358 + componentProps: {
  359 + placeholder: '请选择设备',
  360 + mode: 'multiple',
  361 + },
  362 + ifShow: ({ values }) => isPart(values.device) && isDeviceOut(values.outTarget),
  363 + colProps: { span: 6 },
  364 + },
  365 + {
  366 + field: 'alarm_config',
  367 + label: '',
  368 + component: 'Select',
  369 + componentProps: {
  370 + placeholder: '请选择告警配置',
  371 + },
  372 + ifShow: ({ values }) => values.outTarget === 'MSG_NOTIFY',
  373 + colProps: { span: 6 },
  374 + },
  375 + {
  376 + field: 'doContext',
  377 + component: 'Input',
  378 + label: '',
  379 + slot: 'doContext',
  380 + show: ({ values }) => isDeviceOut(values.outTarget),
  381 + colProps: {
  382 + span: 24,
  383 + },
  384 + },
  385 + {
  386 + field: 'alarm_level',
  387 + component: 'Select',
  388 + label: '',
  389 + show: ({ values }) => isAlarmOut(values.outTarget),
  390 + componentProps: {
  391 + placeholder: '请选择告警等级',
  392 + options: [
  393 + {
  394 + label: '紧急',
  395 + value: 'CRITICAL',
  396 + },
  397 + {
  398 + label: '重要',
  399 + value: 'MAJOR',
  400 + },
  401 + {
  402 + label: '次要',
  403 + value: 'MINOR',
  404 + },
  405 + {
  406 + label: '警告',
  407 + value: 'WARNING',
  408 + },
  409 + {
  410 + label: '不确定',
  411 + value: 'INDETERMINATE',
  412 + },
  413 + ],
  414 + },
  415 + colProps: {
  416 + span: 6,
  417 + },
  418 + },
  419 + {
  420 + field: 'clear_alarm',
  421 + component: 'Checkbox',
  422 + label: '',
  423 + show: ({ values }) => isAlarmOut(values.outTarget),
  424 + colProps: {
  425 + span: 8,
  426 + },
  427 + slot: 'clearAlarm',
  428 + },
  429 +];
  1 +import { formatToDateTime } from '/@/utils/dateUtil';
  2 +
  3 +// 生成触发器或执行条件JSON数据
  4 +export const genTriggerOrConditionData = (triggerData) => {
  5 + const {
  6 + triggerType,
  7 + entityId,
  8 + type1,
  9 + type2,
  10 + device,
  11 + detail,
  12 + predicate,
  13 + operationType,
  14 + triggered,
  15 + schedule,
  16 + } = triggerData;
  17 + const mapPredicate = predicate?.map((item) => {
  18 + return {
  19 + key: {
  20 + type: type1,
  21 + key: type2,
  22 + },
  23 + valueType: operationType,
  24 + value: null,
  25 + predicate: {
  26 + type: operationType === 'DATE_TIME' ? 'NUMERIC' : operationType,
  27 + operation: item.operation,
  28 + value: {
  29 + defaultValue:
  30 + operationType === 'DATE_TIME' ? Number(formatToDateTime(item.value, 'x')) : item.value,
  31 + userValue: null,
  32 + dynamicValue: null,
  33 + },
  34 + },
  35 + };
  36 + });
  37 + return {
  38 + triggerType,
  39 + entityType: device,
  40 + entityId: entityId?.length ? entityId : null,
  41 + triggerCondition: {
  42 + alarmDetails: detail,
  43 + condition: {
  44 + condition: mapPredicate,
  45 + spec: {
  46 + type: triggered,
  47 + // unit: 'SECONDS',
  48 + // predicate: {
  49 + // defaultValue: 30,
  50 + // userValue: null,
  51 + // dynamicValue: null,
  52 + // },
  53 + },
  54 + },
  55 + schedule: {
  56 + type: schedule,
  57 + // timezone: 'Asia/Shanghai',
  58 + // daysOfWeek: [2, 3],
  59 + // startsOn: 8700000,
  60 + // endsOn: 30300000,
  61 + },
  62 + },
  63 + };
  64 +};
  65 +
  66 +export const genActionData = (conditionData) => {
  67 + const {
  68 + alarm_config,
  69 + alarm_level,
  70 + detail,
  71 + device,
  72 + doContext,
  73 + operationType,
  74 + outTarget,
  75 + predicate,
  76 + triggerType,
  77 + triggered,
  78 + type1,
  79 + type2,
  80 + schedule,
  81 + entityId,
  82 + deviceId,
  83 + checked,
  84 + } = conditionData;
  85 + const mapPredicate = predicate?.map((item) => {
  86 + return {
  87 + key: {
  88 + type: type1,
  89 + key: type2,
  90 + },
  91 + valueType: operationType,
  92 + value: null,
  93 + predicate: {
  94 + type: operationType,
  95 + operation: item.operation,
  96 + value: {
  97 + defaultValue: item.value,
  98 + userValue: null,
  99 + dynamicValue: null,
  100 + },
  101 + },
  102 + };
  103 + });
  104 + return [
  105 + {
  106 + alarmProfileId: alarm_config,
  107 + outTarget,
  108 + entityType: device,
  109 + entityId: entityId?.length ? entityId : null,
  110 + deviceId,
  111 + doContext: mapPredicate?.length
  112 + ? {
  113 + alarmLevel: alarm_level,
  114 + clearRule: {
  115 + triggerType,
  116 + triggerCondition: {
  117 + alarmDetails: detail,
  118 + condition: {
  119 + condition: mapPredicate,
  120 + spec: {
  121 + type: triggered,
  122 + // unit: 'SECONDS',
  123 + // predicate: {
  124 + // defaultValue: 30,
  125 + // userValue: null,
  126 + // dynamicValue: null,
  127 + // },
  128 + },
  129 + },
  130 + schedule: {
  131 + type: schedule,
  132 + // timezone: 'Asia/Shanghai',
  133 + // daysOfWeek: [2, 3],
  134 + // startsOn: 8700000,
  135 + // endsOn: 30300000,
  136 + },
  137 + },
  138 + },
  139 + }
  140 + : {
  141 + ...doContext,
  142 + alarmLevel: outTarget === 'MSG_NOTIFY' ? alarm_level : undefined,
  143 + },
  144 + },
  145 + ];
  146 +};
  147 +
  148 +import { Number_Operation, String_Operation, Boolean_Operation } from '/@/enums/operationEnum';
  149 +
  150 +export const operationNumber_OR_TIME = [
  151 + { label: '等于', value: Number_Operation.EQUAL },
  152 + { label: '不等于', value: Number_Operation.NOT_EQUAL },
  153 + { label: '小于', value: Number_Operation.LESS },
  154 + { label: '小于等于', value: Number_Operation.LESS_OR_EQUAL },
  155 + { label: '大于', value: Number_Operation.GREATER },
  156 + { label: '大于等于', value: Number_Operation.GREATER_OR_EQUAL },
  157 +];
  158 +
  159 +export const operationString = [
  160 + { label: '等于', value: String_Operation.EQUAL },
  161 + { label: '不等于', value: String_Operation.NOT_EQUAL },
  162 + { label: '开始于', value: String_Operation.BEGAN_IN },
  163 + { label: '结束于', value: String_Operation.END_IN },
  164 + { label: '包含', value: String_Operation.INCLUDE },
  165 + { label: '不包含', value: String_Operation.NOT_INCLUDE },
  166 +];
  167 +
  168 +export const operationBoolean = [
  169 + { label: '等于', value: Boolean_Operation.EQUAL },
  170 + { label: '不等于', value: Boolean_Operation.NOT_EQUAL },
  171 +];
  172 +
  173 +// 查找操作符
  174 +export function findOperation(valueType, operation) {
  175 + switch (valueType) {
  176 + case 'NUMERIC' || 'DATE_TIME':
  177 + return operationNumber_OR_TIME.find((item) => item.value === operation);
  178 + case 'STRING':
  179 + return operationString.find((item) => item.value === operation);
  180 + case 'BOOLEAN':
  181 + return operationBoolean.find((item) => item.value === operation);
  182 + }
  183 +}
  184 +
  185 +export function isType(operationType) {
  186 + switch (operationType) {
  187 + case 'NUMERIC':
  188 + return [
  189 + {
  190 + field: 'operation',
  191 + label: '执行操作',
  192 + component: 'Select',
  193 + required: true,
  194 + componentProps: {
  195 + options: operationNumber_OR_TIME,
  196 + },
  197 + colProps: {
  198 + span: 8,
  199 + },
  200 + },
  201 + {
  202 + field: 'value',
  203 + label: '操作值',
  204 + required: true,
  205 + component: 'InputNumber',
  206 + colProps: {
  207 + span: 8,
  208 + },
  209 + },
  210 + ];
  211 + case 'STRING':
  212 + return [
  213 + {
  214 + field: 'ignoreCase',
  215 + label: '忽略大小写',
  216 + component: 'Checkbox',
  217 + labelWidth: 150,
  218 + colProps: {
  219 + span: 7,
  220 + },
  221 + },
  222 + {
  223 + field: 'operation',
  224 + label: '执行操作',
  225 + component: 'Select',
  226 + required: true,
  227 + componentProps: {
  228 + options: operationString,
  229 + },
  230 + colProps: {
  231 + span: 7,
  232 + },
  233 + },
  234 + {
  235 + field: 'value',
  236 + label: '操作值',
  237 + required: true,
  238 + component: 'Input',
  239 + colProps: {
  240 + span: 7,
  241 + },
  242 + },
  243 + ];
  244 + case 'BOOLEAN':
  245 + return [
  246 + {
  247 + field: 'operation',
  248 + label: '执行操作',
  249 + component: 'Select',
  250 + required: true,
  251 + componentProps: {
  252 + options: operationBoolean,
  253 + },
  254 + colProps: {
  255 + span: 8,
  256 + },
  257 + },
  258 + {
  259 + field: 'value',
  260 + label: '操作值',
  261 + component: 'Select',
  262 + required: true,
  263 + componentProps: {
  264 + options: [
  265 + {
  266 + label: '真',
  267 + value: 'true',
  268 + },
  269 + {
  270 + label: '假',
  271 + value: 'false',
  272 + },
  273 + ],
  274 + },
  275 + colProps: {
  276 + span: 8,
  277 + },
  278 + },
  279 + ];
  280 + case 'DATE_TIME':
  281 + return [
  282 + {
  283 + field: 'operation',
  284 + label: '执行操作',
  285 + required: true,
  286 + component: 'Select',
  287 + componentProps: {
  288 + options: operationNumber_OR_TIME,
  289 + },
  290 + colProps: {
  291 + span: 8,
  292 + },
  293 + },
  294 + {
  295 + field: 'value',
  296 + label: '操作值',
  297 + required: true,
  298 + component: 'DatePicker',
  299 + componentProps: {
  300 + showTime: true,
  301 + },
  302 + colProps: {
  303 + span: 8,
  304 + },
  305 + },
  306 + ];
  307 + }
  308 +}
  309 +export function conditionPreView(data, operationType) {
  310 + if (operationType === 'NUMERIC' || operationType === 'DATE_TIME') {
  311 + const { EQUAL, NOT_EQUAL, LESS, LESS_OR_EQUAL, GREATER, GREATER_OR_EQUAL } = Number_Operation;
  312 + return data.map((item) => {
  313 + return {
  314 + operation:
  315 + item?.operation === EQUAL
  316 + ? '等于'
  317 + : item?.operation === NOT_EQUAL
  318 + ? '不等于'
  319 + : item?.operation === LESS
  320 + ? '小于'
  321 + : item?.operation === LESS_OR_EQUAL
  322 + ? '小于等于'
  323 + : item?.operation === GREATER
  324 + ? '大于'
  325 + : item?.operation === GREATER_OR_EQUAL
  326 + ? '大于等于'
  327 + : '',
  328 + value: item.value,
  329 + attribute: item.attribute,
  330 + };
  331 + });
  332 + } else if (operationType === 'STRING') {
  333 + const { EQUAL, NOT_EQUAL, BEGAN_IN, END_IN, INCLUDE, NOT_INCLUDE } = String_Operation;
  334 + return data.map((item) => {
  335 + return {
  336 + operation:
  337 + item?.operation === EQUAL
  338 + ? '等于'
  339 + : item?.operation === NOT_EQUAL
  340 + ? '不等于'
  341 + : item?.operation === BEGAN_IN
  342 + ? '开始于'
  343 + : item?.operation === END_IN
  344 + ? '结束于'
  345 + : item?.operation === INCLUDE
  346 + ? '包含'
  347 + : item?.operation === NOT_INCLUDE
  348 + ? '不包含'
  349 + : '',
  350 + value: item.value,
  351 + attribute: item.attribute,
  352 + };
  353 + });
  354 + } else if (operationType === 'BOOLEAN') {
  355 + const { EQUAL, NOT_EQUAL } = Boolean_Operation;
  356 + return data.map((item) => {
  357 + return {
  358 + operation:
  359 + item?.operation === EQUAL ? '等于' : item?.operation === NOT_EQUAL ? '不等于' : '',
  360 + value: item.value,
  361 + attribute: item.attribute,
  362 + };
  363 + });
  364 + }
  365 +}