Commit 73f83cde71c060cf5bbd33b97afb8462577e4993
Merge branch 'refactor/linkedge' into 'main_dev'
refactor: 重构场景联动 See merge request yunteng/thingskit-front!1020
Showing
55 changed files
with
3254 additions
and
1038 deletions
Too many changes to show.
To preserve performance only 55 of 73 files are displayed.
| @@ -25,7 +25,7 @@ module.exports = defineConfig({ | @@ -25,7 +25,7 @@ module.exports = defineConfig({ | ||
| 25 | 'plugin:jest/recommended', | 25 | 'plugin:jest/recommended', |
| 26 | ], | 26 | ], |
| 27 | rules: { | 27 | rules: { |
| 28 | - 'no-console': 'off', | 28 | + 'no-console': 'error', |
| 29 | 'vue/script-setup-uses-vars': 'error', | 29 | 'vue/script-setup-uses-vars': 'error', |
| 30 | '@typescript-eslint/ban-ts-ignore': 'off', | 30 | '@typescript-eslint/ban-ts-ignore': 'off', |
| 31 | '@typescript-eslint/explicit-function-return-type': 'off', | 31 | '@typescript-eslint/explicit-function-return-type': 'off', |
| 1 | import { DataType } from '../../device/model/modelOfMatterModel'; | 1 | import { DataType } from '../../device/model/modelOfMatterModel'; |
| 2 | -import { DataTypeEnum } from '/@/components/Form/src/externalCompns/components/StructForm/config'; | 2 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; |
| 3 | import { DataSource } from '/@/views/visual/palette/types'; | 3 | import { DataSource } from '/@/views/visual/palette/types'; |
| 4 | 4 | ||
| 5 | export interface AddDataBoardParams { | 5 | export interface AddDataBoardParams { |
| 1 | -import { | ||
| 2 | - DataTypeEnum, | ||
| 3 | - FunctionType, | ||
| 4 | -} from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | 1 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; |
| 2 | +import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | ||
| 5 | 3 | ||
| 6 | export interface Specs { | 4 | export interface Specs { |
| 7 | min: string; | 5 | min: string; |
| @@ -26,7 +24,7 @@ export interface DataType { | @@ -26,7 +24,7 @@ export interface DataType { | ||
| 26 | 24 | ||
| 27 | export interface StructJSON { | 25 | export interface StructJSON { |
| 28 | functionName?: string; | 26 | functionName?: string; |
| 29 | - identifier?: string; | 27 | + identifier: string; |
| 30 | remark?: string; | 28 | remark?: string; |
| 31 | dataType?: DataType; | 29 | dataType?: DataType; |
| 32 | serviceCommand?: string; | 30 | serviceCommand?: string; |
| 1 | import { BasicPageParams } from '/@/api/model/baseModel'; | 1 | import { BasicPageParams } from '/@/api/model/baseModel'; |
| 2 | +import { SceneLinkageDataType } from '/@/views/rule/linkedge/components/SceneLinkageDrawer/type'; | ||
| 2 | 3 | ||
| 3 | export type ScreenLinkPageQueryParam = BasicPageParams & ScreenParams; | 4 | export type ScreenLinkPageQueryParam = BasicPageParams & ScreenParams; |
| 4 | 5 | ||
| @@ -14,97 +15,7 @@ export type ScreenByDeptIdParams = { | @@ -14,97 +15,7 @@ export type ScreenByDeptIdParams = { | ||
| 14 | // organizationId: '2f5c8f2a-196c-4941-8771-290f9da76219'; | 15 | // organizationId: '2f5c8f2a-196c-4941-8771-290f9da76219'; |
| 15 | }; | 16 | }; |
| 16 | 17 | ||
| 17 | -export interface ScreenAddModel { | ||
| 18 | - createTime?: string; | ||
| 19 | - creator?: string; | ||
| 20 | - defaultConfig?: string; | ||
| 21 | - description?: string; | ||
| 22 | - doAction?: [ | ||
| 23 | - { | ||
| 24 | - command: string; | ||
| 25 | - createTime: string; | ||
| 26 | - creator: string; | ||
| 27 | - defaultConfig: string; | ||
| 28 | - description: string; | ||
| 29 | - deviceId: string; | ||
| 30 | - enabled: true; | ||
| 31 | - icon: string; | ||
| 32 | - id: string; | ||
| 33 | - name: string; | ||
| 34 | - outPut: string; | ||
| 35 | - outTarget: string; | ||
| 36 | - roleIds: []; | ||
| 37 | - tenantCode: string; | ||
| 38 | - tenantExpireTime: string; | ||
| 39 | - tenantId: string; | ||
| 40 | - tenantStatus: 'DISABLED'; | ||
| 41 | - updateTime: string; | ||
| 42 | - updater: string; | ||
| 43 | - } | ||
| 44 | - ]; | ||
| 45 | - doCondition?: [ | ||
| 46 | - { | ||
| 47 | - compare: 0; | ||
| 48 | - createTime: string; | ||
| 49 | - creator: string; | ||
| 50 | - defaultConfig: string; | ||
| 51 | - description: string; | ||
| 52 | - deviceId: string; | ||
| 53 | - enabled: true; | ||
| 54 | - icon: string; | ||
| 55 | - id: string; | ||
| 56 | - name: string; | ||
| 57 | - property: string; | ||
| 58 | - roleIds: []; | ||
| 59 | - status: string; | ||
| 60 | - tenantCode: string; | ||
| 61 | - tenantExpireTime: string; | ||
| 62 | - tenantId: string; | ||
| 63 | - tenantStatus: 'DISABLED'; | ||
| 64 | - updateTime: string; | ||
| 65 | - updater: string; | ||
| 66 | - value: string; | ||
| 67 | - } | ||
| 68 | - ]; | ||
| 69 | - enabled?: true; | ||
| 70 | - icon?: string; | ||
| 71 | - id?: string; | ||
| 72 | - name?: string; | ||
| 73 | - organizationId?: string; | ||
| 74 | - roleIds?: [string]; | ||
| 75 | - status?: string; | ||
| 76 | - tenantCode?: string; | ||
| 77 | - tenantExpireTime?: string; | ||
| 78 | - tenantId?: string; | ||
| 79 | - tenantStatus?: 'DISABLED'; | ||
| 80 | - triggers?: [ | ||
| 81 | - { | ||
| 82 | - attributeChoose?: string; | ||
| 83 | - compare?: 0; | ||
| 84 | - createTime?: string; | ||
| 85 | - creator?: string; | ||
| 86 | - defaultConfig?: string; | ||
| 87 | - description?: string; | ||
| 88 | - deviceId?: string; | ||
| 89 | - enabled?: true; | ||
| 90 | - icon?: string; | ||
| 91 | - id?: string; | ||
| 92 | - name?: string; | ||
| 93 | - roleIds?: []; | ||
| 94 | - tenantCode?: string; | ||
| 95 | - tenantExpireTime?: string; | ||
| 96 | - tenantId?: string; | ||
| 97 | - tenantStatus?: 'DISABLED'; | ||
| 98 | - tiggerEvent?: string; | ||
| 99 | - touchWay?: string; | ||
| 100 | - updateTime?: string; | ||
| 101 | - updater?: string; | ||
| 102 | - value?: string; | ||
| 103 | - } | ||
| 104 | - ]; | ||
| 105 | - updateTime?: string; | ||
| 106 | - updater?: string; | ||
| 107 | -} | 18 | +export type ScreenAddModel = SceneLinkageDataType; |
| 108 | 19 | ||
| 109 | export interface IChangeStatus { | 20 | export interface IChangeStatus { |
| 110 | status?: number; | 21 | status?: number; |
| @@ -6,6 +6,7 @@ import { | @@ -6,6 +6,7 @@ import { | ||
| 6 | ScreenByDeptIdParams, | 6 | ScreenByDeptIdParams, |
| 7 | IChangeStatus, | 7 | IChangeStatus, |
| 8 | } from '/@/api/ruleengine/model/ruleengineModel'; | 8 | } from '/@/api/ruleengine/model/ruleengineModel'; |
| 9 | +import { DeviceModel } from '../device/model/deviceModel'; | ||
| 9 | 10 | ||
| 10 | enum ScreenManagerApi { | 11 | enum ScreenManagerApi { |
| 11 | /** | 12 | /** |
| @@ -126,7 +127,7 @@ export const byOrganizationIdGetMasterDevice = (params: { | @@ -126,7 +127,7 @@ export const byOrganizationIdGetMasterDevice = (params: { | ||
| 126 | deviceProfileId?: string; | 127 | deviceProfileId?: string; |
| 127 | }) => { | 128 | }) => { |
| 128 | const { organizationId, deviceProfileId } = params; | 129 | const { organizationId, deviceProfileId } = params; |
| 129 | - return defHttp.get({ | 130 | + return defHttp.get<DeviceModel[]>({ |
| 130 | url: `${ScreenManagerApi.MASTER_GET_DEVICE}`, | 131 | url: `${ScreenManagerApi.MASTER_GET_DEVICE}`, |
| 131 | params: { deviceProfileId, organizationId }, | 132 | params: { deviceProfileId, organizationId }, |
| 132 | }); | 133 | }); |
| @@ -191,6 +191,10 @@ | @@ -191,6 +191,10 @@ | ||
| 191 | <slot name="afterFullScreen"></slot> | 191 | <slot name="afterFullScreen"></slot> |
| 192 | </div> | 192 | </div> |
| 193 | </div> | 193 | </div> |
| 194 | - <div ref="jsonEditorElRef" class="flex-auto"></div> | 194 | + <div |
| 195 | + ref="jsonEditorElRef" | ||
| 196 | + class="flex-auto" | ||
| 197 | + :style="{ backgroundColor: disabled ? '#f0f0f0' : '' }" | ||
| 198 | + ></div> | ||
| 195 | </div> | 199 | </div> |
| 196 | </template> | 200 | </template> |
| @@ -15,6 +15,8 @@ export { default as ApiUpload } from './src/components/ApiUpload.vue'; | @@ -15,6 +15,8 @@ export { default as ApiUpload } from './src/components/ApiUpload.vue'; | ||
| 15 | export { default as StructForm } from './src/externalCompns/components/StructForm/StructForm.vue'; | 15 | export { default as StructForm } from './src/externalCompns/components/StructForm/StructForm.vue'; |
| 16 | export { default as JavaScriptFunctionEditor } from './src/components/JavaScriptFunctionEditor.vue'; | 16 | export { default as JavaScriptFunctionEditor } from './src/components/JavaScriptFunctionEditor.vue'; |
| 17 | 17 | ||
| 18 | +export { ThingsModelForm } from './src/externalCompns/components/ThingsModelForm'; | ||
| 19 | + | ||
| 18 | //注册自定义组件 | 20 | //注册自定义组件 |
| 19 | export { | 21 | export { |
| 20 | JEasyCron, | 22 | JEasyCron, |
| @@ -69,7 +69,7 @@ | @@ -69,7 +69,7 @@ | ||
| 69 | name: 'BasicForm', | 69 | name: 'BasicForm', |
| 70 | components: { FormItem, Form, Row, FormAction }, | 70 | components: { FormItem, Form, Row, FormAction }, |
| 71 | props: basicProps, | 71 | props: basicProps, |
| 72 | - emits: ['advanced-change', 'reset', 'submit', 'register'], | 72 | + emits: ['advanced-change', 'reset', 'submit', 'register', 'fieldValueChange'], |
| 73 | setup(props, { emit, attrs }) { | 73 | setup(props, { emit, attrs }) { |
| 74 | const formModel = reactive<Recordable>({}); | 74 | const formModel = reactive<Recordable>({}); |
| 75 | const modalFn = useModalContext(); | 75 | const modalFn = useModalContext(); |
| @@ -230,6 +230,7 @@ | @@ -230,6 +230,7 @@ | ||
| 230 | 230 | ||
| 231 | function setFormModel(key: string, value: any) { | 231 | function setFormModel(key: string, value: any) { |
| 232 | formModel[key] = value; | 232 | formModel[key] = value; |
| 233 | + emit('fieldValueChange', key, value); | ||
| 233 | const { validateTrigger } = unref(getBindValue); | 234 | const { validateTrigger } = unref(getBindValue); |
| 234 | if (!validateTrigger || validateTrigger === 'change') { | 235 | if (!validateTrigger || validateTrigger === 'change') { |
| 235 | validateFields([key]).catch((_) => {}); | 236 | validateFields([key]).catch((_) => {}); |
| @@ -5,7 +5,8 @@ | @@ -5,7 +5,8 @@ | ||
| 5 | import { BasicModal } from '/@/components/Modal'; | 5 | import { BasicModal } from '/@/components/Modal'; |
| 6 | import { PlusCircleOutlined } from '@ant-design/icons-vue'; | 6 | import { PlusCircleOutlined } from '@ant-design/icons-vue'; |
| 7 | import { FormFieldsEnum, formSchemas } from './config'; | 7 | import { FormFieldsEnum, formSchemas } from './config'; |
| 8 | - import { DataTypeEnum } from '../StructForm/config'; | 8 | + import { DataTypeEnum } from '/@/enums/objectModelEnum'; |
| 9 | + | ||
| 9 | const show = ref(false); | 10 | const show = ref(false); |
| 10 | 11 | ||
| 11 | const props = withDefaults( | 12 | const props = withDefaults( |
| @@ -50,7 +51,7 @@ | @@ -50,7 +51,7 @@ | ||
| 50 | updateSchema([ | 51 | updateSchema([ |
| 51 | { | 52 | { |
| 52 | field: FormFieldsEnum.ZOOM_FACTOR, | 53 | field: FormFieldsEnum.ZOOM_FACTOR, |
| 53 | - ifShow: props.dataType == DataTypeEnum.IS_BOOL ? false : true, | 54 | + ifShow: props.dataType == DataTypeEnum.BOOL ? false : true, |
| 54 | }, | 55 | }, |
| 55 | ]); | 56 | ]); |
| 56 | } | 57 | } |
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | import { Card } from 'ant-design-vue'; | 2 | import { Card } from 'ant-design-vue'; |
| 3 | import { computed, nextTick, onMounted, onUpdated, unref, watch } from 'vue'; | 3 | import { computed, nextTick, onMounted, onUpdated, unref, watch } from 'vue'; |
| 4 | - import { DataTypeEnum } from '../StructForm/config'; | ||
| 5 | import { BasicCreateFormParams } from './type'; | 4 | import { BasicCreateFormParams } from './type'; |
| 6 | import { DynamicProps } from '/#/utils'; | 5 | import { DynamicProps } from '/#/utils'; |
| 7 | import { Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | 6 | import { Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
| 8 | import { BasicForm, FormProps, FormSchema, useForm } from '/@/components/Form'; | 7 | import { BasicForm, FormProps, FormSchema, useForm } from '/@/components/Form'; |
| 8 | + import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 9 | import { ReadAndWriteEnum } from '/@/enums/toolEnum'; | 9 | import { ReadAndWriteEnum } from '/@/enums/toolEnum'; |
| 10 | 10 | ||
| 11 | const props = withDefaults( | 11 | const props = withDefaults( |
| @@ -86,7 +86,7 @@ | @@ -86,7 +86,7 @@ | ||
| 86 | // step: step, | 86 | // step: step, |
| 87 | // formatter: (value: string) => value, | 87 | // formatter: (value: string) => value, |
| 88 | // parser: (string: string) => { | 88 | // parser: (string: string) => { |
| 89 | - // if (dataType === DataTypeEnum.IS_NUMBER_INT) { | 89 | + // if (dataType === DataTypeEnum.NUMBER_INT) { |
| 90 | // return Number(Number(string).toFixed()); | 90 | // return Number(Number(string).toFixed()); |
| 91 | // } | 91 | // } |
| 92 | // return Number(string); | 92 | // return Number(string); |
| @@ -188,19 +188,19 @@ | @@ -188,19 +188,19 @@ | ||
| 188 | dataType: dataType! as unknown as DataTypeEnum, | 188 | dataType: dataType! as unknown as DataTypeEnum, |
| 189 | specs: specs as Partial<Specs>, | 189 | specs: specs as Partial<Specs>, |
| 190 | }; | 190 | }; |
| 191 | - if (type === DataTypeEnum.IS_NUMBER_INT || type === DataTypeEnum.IS_NUMBER_DOUBLE) { | 191 | + if (type === DataTypeEnum.NUMBER_INT || type === DataTypeEnum.NUMBER_DOUBLE) { |
| 192 | schemas.push(createInputNumber(params)); | 192 | schemas.push(createInputNumber(params)); |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | - if (type === DataTypeEnum.IS_BOOL) { | 195 | + if (type === DataTypeEnum.BOOL) { |
| 196 | schemas.push(createSelect(params)); | 196 | schemas.push(createSelect(params)); |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | - if (type === DataTypeEnum.IS_STRING) { | 199 | + if (type === DataTypeEnum.STRING) { |
| 200 | schemas.push(createInput(params)); | 200 | schemas.push(createInput(params)); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | - if (type === DataTypeEnum.IS_STRUCT) { | 203 | + if (type === DataTypeEnum.STRUCT) { |
| 204 | schemas.push(createInputJson(params)); | 204 | schemas.push(createInputJson(params)); |
| 205 | } | 205 | } |
| 206 | } | 206 | } |
| 1 | -import { DataTypeEnum } from '../StructForm/config'; | ||
| 2 | import { Specs } from '/@/api/device/model/modelOfMatterModel'; | 1 | import { Specs } from '/@/api/device/model/modelOfMatterModel'; |
| 2 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 3 | 3 | ||
| 4 | export interface BasicCreateFormParams { | 4 | export interface BasicCreateFormParams { |
| 5 | identifier: string; | 5 | identifier: string; |
| 1 | import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; | 1 | import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; |
| 2 | import { findDictItemByCode } from '/@/api/system/dict'; | 2 | import { findDictItemByCode } from '/@/api/system/dict'; |
| 3 | import { FormSchema } from '/@/components/Table'; | 3 | import { FormSchema } from '/@/components/Table'; |
| 4 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 4 | import { isNullOrUnDef } from '/@/utils/is'; | 5 | import { isNullOrUnDef } from '/@/utils/is'; |
| 5 | import { FormField } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | 6 | import { FormField } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; |
| 6 | 7 | ||
| 7 | -export enum DataTypeEnum { | ||
| 8 | - IS_NUMBER_INT = 'INT', | ||
| 9 | - IS_NUMBER_DOUBLE = 'DOUBLE', | ||
| 10 | - IS_STRING = 'TEXT', | ||
| 11 | - IS_STRUCT = 'STRUCT', | ||
| 12 | - IS_BOOL = 'BOOL', | ||
| 13 | -} | ||
| 14 | - | ||
| 15 | export const validateValueRange = (_rule, value: Record<'min' | 'max', number>, _callback) => { | 8 | export const validateValueRange = (_rule, value: Record<'min' | 'max', number>, _callback) => { |
| 16 | value = value || {}; | 9 | value = value || {}; |
| 17 | const { min, max } = value; | 10 | const { min, max } = value; |
| @@ -77,10 +70,9 @@ export const formSchemas = ( | @@ -77,10 +70,9 @@ export const formSchemas = ( | ||
| 77 | try { | 70 | try { |
| 78 | const record = await findDictItemByCode(params); | 71 | const record = await findDictItemByCode(params); |
| 79 | return hasStructForm | 72 | return hasStructForm |
| 80 | - ? record.filter((item) => item.itemValue !== DataTypeEnum.IS_STRUCT) | 73 | + ? record.filter((item) => item.itemValue !== DataTypeEnum.STRUCT) |
| 81 | : record; | 74 | : record; |
| 82 | } catch (error) { | 75 | } catch (error) { |
| 83 | - console.log(error); | ||
| 84 | return []; | 76 | return []; |
| 85 | } | 77 | } |
| 86 | }, | 78 | }, |
| @@ -91,7 +83,7 @@ export const formSchemas = ( | @@ -91,7 +83,7 @@ export const formSchemas = ( | ||
| 91 | valueField: 'itemValue', | 83 | valueField: 'itemValue', |
| 92 | getPopupContainer: () => document.body, | 84 | getPopupContainer: () => document.body, |
| 93 | onChange: (value: string) => { | 85 | onChange: (value: string) => { |
| 94 | - if (value == DataTypeEnum.IS_STRUCT) { | 86 | + if (value == DataTypeEnum.STRUCT) { |
| 95 | updateSchema({ | 87 | updateSchema({ |
| 96 | field: FormField.SPECS_LIST, | 88 | field: FormField.SPECS_LIST, |
| 97 | componentProps: { | 89 | componentProps: { |
| @@ -114,8 +106,8 @@ export const formSchemas = ( | @@ -114,8 +106,8 @@ export const formSchemas = ( | ||
| 114 | span: 18, | 106 | span: 18, |
| 115 | }, | 107 | }, |
| 116 | ifShow: ({ values }) => | 108 | ifShow: ({ values }) => |
| 117 | - values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_INT || | ||
| 118 | - values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_DOUBLE, | 109 | + values[FormField.TYPE] === DataTypeEnum.NUMBER_INT || |
| 110 | + values[FormField.TYPE] === DataTypeEnum.NUMBER_DOUBLE, | ||
| 119 | rules: [{ validator: validateValueRange }], | 111 | rules: [{ validator: validateValueRange }], |
| 120 | }, | 112 | }, |
| 121 | { | 113 | { |
| @@ -134,8 +126,8 @@ export const formSchemas = ( | @@ -134,8 +126,8 @@ export const formSchemas = ( | ||
| 134 | }, | 126 | }, |
| 135 | }, | 127 | }, |
| 136 | ifShow: ({ values }) => | 128 | ifShow: ({ values }) => |
| 137 | - values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_INT || | ||
| 138 | - values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_DOUBLE, | 129 | + values[FormField.TYPE] === DataTypeEnum.NUMBER_INT || |
| 130 | + values[FormField.TYPE] === DataTypeEnum.NUMBER_DOUBLE, | ||
| 139 | dynamicRules: ({ model }) => { | 131 | dynamicRules: ({ model }) => { |
| 140 | const valueRange = model[FormField.VALUE_RANGE] || {}; | 132 | const valueRange = model[FormField.VALUE_RANGE] || {}; |
| 141 | const { min, max } = valueRange; | 133 | const { min, max } = valueRange; |
| @@ -199,8 +191,8 @@ export const formSchemas = ( | @@ -199,8 +191,8 @@ export const formSchemas = ( | ||
| 199 | }; | 191 | }; |
| 200 | }, | 192 | }, |
| 201 | ifShow: ({ values }) => | 193 | ifShow: ({ values }) => |
| 202 | - values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_INT || | ||
| 203 | - values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_DOUBLE, | 194 | + values[FormField.TYPE] === DataTypeEnum.NUMBER_INT || |
| 195 | + values[FormField.TYPE] === DataTypeEnum.NUMBER_DOUBLE, | ||
| 204 | }, | 196 | }, |
| 205 | { | 197 | { |
| 206 | field: FormField.BOOL_CLOSE, | 198 | field: FormField.BOOL_CLOSE, |
| @@ -214,7 +206,7 @@ export const formSchemas = ( | @@ -214,7 +206,7 @@ export const formSchemas = ( | ||
| 214 | placeholder: '如:关', | 206 | placeholder: '如:关', |
| 215 | }, | 207 | }, |
| 216 | defaultValue: '关', | 208 | defaultValue: '关', |
| 217 | - ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_BOOL, | 209 | + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.BOOL, |
| 218 | dynamicRules: ({ model }) => { | 210 | dynamicRules: ({ model }) => { |
| 219 | const close = model[FormField.BOOL_CLOSE]; | 211 | const close = model[FormField.BOOL_CLOSE]; |
| 220 | const open = model[FormField.BOOL_OPEN]; | 212 | const open = model[FormField.BOOL_OPEN]; |
| @@ -243,7 +235,7 @@ export const formSchemas = ( | @@ -243,7 +235,7 @@ export const formSchemas = ( | ||
| 243 | placeholder: '如:开', | 235 | placeholder: '如:开', |
| 244 | }, | 236 | }, |
| 245 | defaultValue: '开', | 237 | defaultValue: '开', |
| 246 | - ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_BOOL, | 238 | + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.BOOL, |
| 247 | dynamicRules: ({ model }) => { | 239 | dynamicRules: ({ model }) => { |
| 248 | const close = model[FormField.BOOL_CLOSE]; | 240 | const close = model[FormField.BOOL_CLOSE]; |
| 249 | const open = model[FormField.BOOL_OPEN]; | 241 | const open = model[FormField.BOOL_OPEN]; |
| @@ -277,7 +269,7 @@ export const formSchemas = ( | @@ -277,7 +269,7 @@ export const formSchemas = ( | ||
| 277 | suffix: () => '字节', | 269 | suffix: () => '字节', |
| 278 | }; | 270 | }; |
| 279 | }, | 271 | }, |
| 280 | - ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_STRING, | 272 | + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.STRING, |
| 281 | }, | 273 | }, |
| 282 | { | 274 | { |
| 283 | field: FormField.EXTENSION_DESC, | 275 | field: FormField.EXTENSION_DESC, |
| @@ -322,7 +314,7 @@ export const formSchemas = ( | @@ -322,7 +314,7 @@ export const formSchemas = ( | ||
| 322 | valueField: 'value', | 314 | valueField: 'value', |
| 323 | changeEvent: 'update:value', | 315 | changeEvent: 'update:value', |
| 324 | colProps: { span: 24 }, | 316 | colProps: { span: 24 }, |
| 325 | - ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_STRUCT, | 317 | + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.STRUCT, |
| 326 | rules: [{ required: true, validator: validateJSON }], | 318 | rules: [{ required: true, validator: validateJSON }], |
| 327 | }, | 319 | }, |
| 328 | { | 320 | { |
| 1 | -import { DataTypeEnum } from './config'; | ||
| 2 | import { StructJSON } from '/@/api/device/model/modelOfMatterModel'; | 1 | import { StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
| 2 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 3 | import { FormField } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | 3 | import { FormField } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; |
| 4 | 4 | ||
| 5 | export enum OpenModalMode { | 5 | export enum OpenModalMode { |
| 1 | import { cloneDeep } from 'lodash-es'; | 1 | import { cloneDeep } from 'lodash-es'; |
| 2 | -import { DataTypeEnum } from './config'; | ||
| 3 | import { StructFormValue } from './type'; | 2 | import { StructFormValue } from './type'; |
| 4 | import { DataType, ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | 3 | import { DataType, ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
| 5 | import { isArray } from '/@/utils/is'; | 4 | import { isArray } from '/@/utils/is'; |
| 5 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 6 | 6 | ||
| 7 | export function transfromToStructJSON(value: StructFormValue): StructJSON { | 7 | export function transfromToStructJSON(value: StructFormValue): StructJSON { |
| 8 | const { | 8 | const { |
| @@ -24,21 +24,21 @@ export function transfromToStructJSON(value: StructFormValue): StructJSON { | @@ -24,21 +24,21 @@ export function transfromToStructJSON(value: StructFormValue): StructJSON { | ||
| 24 | let dataType = {} as unknown as DataType; | 24 | let dataType = {} as unknown as DataType; |
| 25 | 25 | ||
| 26 | switch (type) { | 26 | switch (type) { |
| 27 | - case DataTypeEnum.IS_NUMBER_INT: | 27 | + case DataTypeEnum.NUMBER_INT: |
| 28 | dataType = { | 28 | dataType = { |
| 29 | type, | 29 | type, |
| 30 | specs: { valueRange, step, unit, unitName }, | 30 | specs: { valueRange, step, unit, unitName }, |
| 31 | }; | 31 | }; |
| 32 | break; | 32 | break; |
| 33 | 33 | ||
| 34 | - case DataTypeEnum.IS_NUMBER_DOUBLE: | 34 | + case DataTypeEnum.NUMBER_DOUBLE: |
| 35 | dataType = { | 35 | dataType = { |
| 36 | type, | 36 | type, |
| 37 | specs: { valueRange, step, unit, unitName }, | 37 | specs: { valueRange, step, unit, unitName }, |
| 38 | }; | 38 | }; |
| 39 | break; | 39 | break; |
| 40 | 40 | ||
| 41 | - case DataTypeEnum.IS_BOOL: | 41 | + case DataTypeEnum.BOOL: |
| 42 | dataType = { | 42 | dataType = { |
| 43 | type, | 43 | type, |
| 44 | specs: { | 44 | specs: { |
| @@ -48,14 +48,14 @@ export function transfromToStructJSON(value: StructFormValue): StructJSON { | @@ -48,14 +48,14 @@ export function transfromToStructJSON(value: StructFormValue): StructJSON { | ||
| 48 | }; | 48 | }; |
| 49 | break; | 49 | break; |
| 50 | 50 | ||
| 51 | - case DataTypeEnum.IS_STRING: | 51 | + case DataTypeEnum.STRING: |
| 52 | dataType = { | 52 | dataType = { |
| 53 | type, | 53 | type, |
| 54 | specs: { length }, | 54 | specs: { length }, |
| 55 | }; | 55 | }; |
| 56 | break; | 56 | break; |
| 57 | 57 | ||
| 58 | - case DataTypeEnum.IS_STRUCT: | 58 | + case DataTypeEnum.STRUCT: |
| 59 | dataType = { | 59 | dataType = { |
| 60 | type, | 60 | type, |
| 61 | specs: specs! as unknown as ModelOfMatterParams[], | 61 | specs: specs! as unknown as ModelOfMatterParams[], |
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { StructJSON } from '/@/api/device/model/modelOfMatterModel'; | ||
| 3 | + import { JsonPreview } from '/@/components/CodeEditor'; | ||
| 4 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 5 | + | ||
| 6 | + defineProps<{ | ||
| 7 | + inputData?: StructJSON[]; | ||
| 8 | + }>(); | ||
| 9 | + | ||
| 10 | + defineEmits(['register']); | ||
| 11 | + | ||
| 12 | + const data = {}; | ||
| 13 | + | ||
| 14 | + const [register] = useModalInner(); | ||
| 15 | +</script> | ||
| 16 | + | ||
| 17 | +<template> | ||
| 18 | + <BasicModal @register="register" title=""> | ||
| 19 | + <!-- --> | ||
| 20 | + <JsonPreview :data="data" /> | ||
| 21 | + </BasicModal> | ||
| 22 | +</template> |
| 1 | +import { FormSchema } from '../../../types/form'; | ||
| 2 | +import { Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | ||
| 3 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 4 | +import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; | ||
| 5 | + | ||
| 6 | +export const getFormSchemas = ({ | ||
| 7 | + structJSON: structJson, | ||
| 8 | + required, | ||
| 9 | + transportType, | ||
| 10 | +}: { | ||
| 11 | + structJSON: StructJSON[]; | ||
| 12 | + required?: boolean; | ||
| 13 | + transportType?: string; | ||
| 14 | +}): FormSchema[] => { | ||
| 15 | + const createInputNumber = ({ identifier, functionName, dataType }: StructJSON): FormSchema => { | ||
| 16 | + const { specs } = dataType || {}; | ||
| 17 | + const { valueRange } = specs! as Specs; | ||
| 18 | + const { max = 2147483647, min = -2147483648 } = valueRange || {}; | ||
| 19 | + return { | ||
| 20 | + field: identifier, | ||
| 21 | + label: functionName, | ||
| 22 | + component: 'InputNumber', | ||
| 23 | + rules: [ | ||
| 24 | + { | ||
| 25 | + required, | ||
| 26 | + message: `${functionName}是必填项`, | ||
| 27 | + }, | ||
| 28 | + { | ||
| 29 | + type: 'number', | ||
| 30 | + trigger: 'change', | ||
| 31 | + validator: (_rule, value) => { | ||
| 32 | + const reg = /^[0-9]*$/; | ||
| 33 | + if (!reg.test(value)) | ||
| 34 | + return Promise.reject(new Error(`${functionName}不是一个有效的数字`)); | ||
| 35 | + if (value < min || value > max) | ||
| 36 | + return Promise.reject(new Error(`${functionName}取值范围在${min}~${max}之间`)); | ||
| 37 | + | ||
| 38 | + return Promise.resolve(value); | ||
| 39 | + }, | ||
| 40 | + }, | ||
| 41 | + ], | ||
| 42 | + componentProps: { | ||
| 43 | + max, | ||
| 44 | + min, | ||
| 45 | + placeholder: `请输入${functionName}`, | ||
| 46 | + }, | ||
| 47 | + } as FormSchema; | ||
| 48 | + }; | ||
| 49 | + | ||
| 50 | + const createInput = ({ identifier, functionName, dataType }: StructJSON): FormSchema => { | ||
| 51 | + const { specs } = dataType || {}; | ||
| 52 | + const { length = 10240 } = specs! as Partial<Specs>; | ||
| 53 | + return { | ||
| 54 | + field: identifier, | ||
| 55 | + label: functionName, | ||
| 56 | + component: 'Input', | ||
| 57 | + rules: [ | ||
| 58 | + { | ||
| 59 | + required, | ||
| 60 | + message: `${functionName}是必填项`, | ||
| 61 | + }, | ||
| 62 | + { | ||
| 63 | + type: 'string', | ||
| 64 | + trigger: 'change', | ||
| 65 | + validator: (_rule, value) => { | ||
| 66 | + if ((value?.length || 0) > length) | ||
| 67 | + return Promise.reject(new Error(`${functionName}数据长度应该小于${length}`)); | ||
| 68 | + | ||
| 69 | + return Promise.resolve(value); | ||
| 70 | + }, | ||
| 71 | + }, | ||
| 72 | + ], | ||
| 73 | + componentProps: { | ||
| 74 | + maxLength: length, | ||
| 75 | + placeholder: `请输入${functionName}`, | ||
| 76 | + }, | ||
| 77 | + } as FormSchema; | ||
| 78 | + }; | ||
| 79 | + | ||
| 80 | + const createSelect = ({ identifier, functionName, dataType }: StructJSON): FormSchema => { | ||
| 81 | + const { specs } = dataType || {}; | ||
| 82 | + const { boolClose, boolOpen } = specs! as Partial<Specs>; | ||
| 83 | + return { | ||
| 84 | + field: identifier, | ||
| 85 | + label: functionName!, | ||
| 86 | + component: 'Select', | ||
| 87 | + rules: [ | ||
| 88 | + { | ||
| 89 | + required, | ||
| 90 | + message: `${functionName}是必填项`, | ||
| 91 | + type: 'number', | ||
| 92 | + }, | ||
| 93 | + ], | ||
| 94 | + componentProps: { | ||
| 95 | + options: [ | ||
| 96 | + { label: `${boolClose}-0`, value: 0 }, | ||
| 97 | + { label: `${boolOpen}-1`, value: 1 }, | ||
| 98 | + ], | ||
| 99 | + placeholder: `请选择${functionName}`, | ||
| 100 | + }, | ||
| 101 | + }; | ||
| 102 | + }; | ||
| 103 | + | ||
| 104 | + const createStructJson = ({ identifier, functionName, dataType }: StructJSON): FormSchema => { | ||
| 105 | + return { | ||
| 106 | + field: identifier, | ||
| 107 | + label: functionName!, | ||
| 108 | + component: 'Input', | ||
| 109 | + changeEvent: 'update:value', | ||
| 110 | + componentProps: () => { | ||
| 111 | + return { | ||
| 112 | + inputData: dataType?.specs || [], | ||
| 113 | + }; | ||
| 114 | + }, | ||
| 115 | + colSlot: identifier, | ||
| 116 | + }; | ||
| 117 | + }; | ||
| 118 | + | ||
| 119 | + const createTCPServiceCommandInput = ({ | ||
| 120 | + serviceCommand, | ||
| 121 | + functionName, | ||
| 122 | + }: StructJSON): FormSchema => { | ||
| 123 | + return { | ||
| 124 | + field: 'serviceCommand', | ||
| 125 | + label: '服务命令', | ||
| 126 | + component: 'Input', | ||
| 127 | + required, | ||
| 128 | + componentProps: { | ||
| 129 | + defaultValue: serviceCommand, | ||
| 130 | + placeholder: `请输入${functionName}`, | ||
| 131 | + }, | ||
| 132 | + }; | ||
| 133 | + }; | ||
| 134 | + | ||
| 135 | + const schemas: FormSchema[] = []; | ||
| 136 | + | ||
| 137 | + for (const item of structJson) { | ||
| 138 | + const { dataType } = item; | ||
| 139 | + const { type } = dataType || {}; | ||
| 140 | + if (transportType === TransportTypeEnum.TCP) { | ||
| 141 | + item.serviceCommand && schemas.push(createTCPServiceCommandInput(item)); | ||
| 142 | + break; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + if (type === DataTypeEnum.BOOL) schemas.push(createSelect(item)); | ||
| 146 | + else if (type === DataTypeEnum.NUMBER_INT) schemas.push(createInputNumber(item)); | ||
| 147 | + else if (type === DataTypeEnum.NUMBER_DOUBLE) schemas.push(createInputNumber(item)); | ||
| 148 | + else if (type === DataTypeEnum.STRING) schemas.push(createInput(item)); | ||
| 149 | + else if (type === DataTypeEnum.STRUCT) schemas.push(createStructJson(item)); | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + return schemas; | ||
| 153 | +}; |
| 1 | +import { ValidatorRule } from 'ant-design-vue/lib/form/interface'; | ||
| 2 | +export { default as ThingsModelForm } from './index.vue'; | ||
| 3 | + | ||
| 4 | +export const validateTCPCustomCommand: ValidatorRule['validator'] = (_rule, value) => { | ||
| 5 | + const reg = /^[\s0-9a-fA-F]+$/; | ||
| 6 | + if (reg.test(value)) return Promise.resolve(); | ||
| 7 | + return Promise.reject('请输入ASCII或HEX服务命令(0~9/A~F)'); | ||
| 8 | +}; | ||
| 9 | + | ||
| 10 | +export const trimBlankSpace = (string: string) => string.replace(/\s/g, ''); |
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { Card } from 'ant-design-vue'; | ||
| 3 | + import { ComponentPublicInstance, computed, nextTick, reactive, unref, watch } from 'vue'; | ||
| 4 | + import { getFormSchemas } from './config'; | ||
| 5 | + import { ThingsModelForm } from '.'; | ||
| 6 | + import { DefineComponentsBasicExpose } from '/#/utils'; | ||
| 7 | + import { StructJSON } from '/@/api/device/model/modelOfMatterModel'; | ||
| 8 | + import { useForm } from '../../../hooks/useForm'; | ||
| 9 | + import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 10 | + import { BasicForm } from '/@/components/Form'; | ||
| 11 | + | ||
| 12 | + const props = withDefaults( | ||
| 13 | + defineProps<{ | ||
| 14 | + value?: Recordable; | ||
| 15 | + inputData?: StructJSON[]; | ||
| 16 | + required?: boolean; | ||
| 17 | + title?: string; | ||
| 18 | + transportType?: string; | ||
| 19 | + disabled?: boolean; | ||
| 20 | + identifier?: string; | ||
| 21 | + }>(), | ||
| 22 | + { | ||
| 23 | + inputData: () => [], | ||
| 24 | + required: true, | ||
| 25 | + } | ||
| 26 | + ); | ||
| 27 | + | ||
| 28 | + const thingsModelFormListElMap = reactive< | ||
| 29 | + Record<string, { el: InstanceType<typeof ThingsModelForm>; structJSON: StructJSON }> | ||
| 30 | + >({}); | ||
| 31 | + | ||
| 32 | + const [register, formActionType] = useForm({ | ||
| 33 | + schemas: getFormSchemas({ | ||
| 34 | + structJSON: props.inputData || [], | ||
| 35 | + required: props.required, | ||
| 36 | + transportType: props.transportType, | ||
| 37 | + }), | ||
| 38 | + showActionButtonGroup: false, | ||
| 39 | + layout: 'inline', | ||
| 40 | + labelWidth: 100, | ||
| 41 | + }); | ||
| 42 | + | ||
| 43 | + const getStructFormItem = computed(() => { | ||
| 44 | + const { inputData } = props; | ||
| 45 | + return inputData.filter((item) => item.dataType?.type === DataTypeEnum.STRUCT); | ||
| 46 | + }); | ||
| 47 | + | ||
| 48 | + const setFormElRef = ( | ||
| 49 | + el: Nullable<Element | ComponentPublicInstance>, | ||
| 50 | + structJSON: StructJSON | ||
| 51 | + ) => { | ||
| 52 | + const _structJSON = unref(getStructFormItem).find( | ||
| 53 | + (item) => item.identifier === structJSON.identifier | ||
| 54 | + ); | ||
| 55 | + | ||
| 56 | + if (_structJSON) | ||
| 57 | + thingsModelFormListElMap[structJSON.identifier!] = { | ||
| 58 | + el: el as InstanceType<typeof ThingsModelForm>, | ||
| 59 | + structJSON, | ||
| 60 | + }; | ||
| 61 | + }; | ||
| 62 | + | ||
| 63 | + const getFieldsValue = () => { | ||
| 64 | + const basicValue = formActionType.getFieldsValue(); | ||
| 65 | + | ||
| 66 | + const structValue: Recordable = {}; | ||
| 67 | + for (const key of Object.keys(thingsModelFormListElMap)) { | ||
| 68 | + const item = thingsModelFormListElMap[key]; | ||
| 69 | + const { el } = item; | ||
| 70 | + structValue[key] = el.getFieldsValue() || {}; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + return { | ||
| 74 | + ...basicValue, | ||
| 75 | + ...structValue, | ||
| 76 | + }; | ||
| 77 | + }; | ||
| 78 | + | ||
| 79 | + const setFieldsValue = (value: Recordable) => { | ||
| 80 | + formActionType.setFieldsValue(value); | ||
| 81 | + }; | ||
| 82 | + | ||
| 83 | + const validate = async () => { | ||
| 84 | + await formActionType.validate(); | ||
| 85 | + for (const key of Object.keys(thingsModelFormListElMap)) | ||
| 86 | + await thingsModelFormListElMap[key]?.el?.validate?.(); | ||
| 87 | + }; | ||
| 88 | + | ||
| 89 | + watch( | ||
| 90 | + () => props.value, | ||
| 91 | + async (value) => { | ||
| 92 | + await nextTick(); | ||
| 93 | + formActionType.resetFields(); | ||
| 94 | + formActionType.setFieldsValue(value || {}); | ||
| 95 | + }, | ||
| 96 | + { immediate: true } | ||
| 97 | + ); | ||
| 98 | + | ||
| 99 | + watch( | ||
| 100 | + () => [props.inputData, props.identifier], | ||
| 101 | + (value) => { | ||
| 102 | + if (value && value.length) { | ||
| 103 | + const schemas = getFormSchemas({ | ||
| 104 | + structJSON: props.inputData || [], | ||
| 105 | + required: props.required, | ||
| 106 | + transportType: props.transportType, | ||
| 107 | + }); | ||
| 108 | + formActionType.setProps({ schemas }); | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | + ); | ||
| 112 | + | ||
| 113 | + watch( | ||
| 114 | + () => props.disabled, | ||
| 115 | + (value) => { | ||
| 116 | + formActionType.setProps({ disabled: value }); | ||
| 117 | + } | ||
| 118 | + ); | ||
| 119 | + | ||
| 120 | + defineExpose<DefineComponentsBasicExpose>({ | ||
| 121 | + getFieldsValue, | ||
| 122 | + setFieldsValue, | ||
| 123 | + validate, | ||
| 124 | + }); | ||
| 125 | +</script> | ||
| 126 | + | ||
| 127 | +<template> | ||
| 128 | + <Card | ||
| 129 | + class="!border-2 !border-dashed" | ||
| 130 | + :title="title" | ||
| 131 | + :style="{ backgroundColor: disabled ? '#f0f0f0' : '', borderColor: disabled ? '#e3e3e3' : '' }" | ||
| 132 | + > | ||
| 133 | + <BasicForm class="things-model-form" @register="register" :disabled="disabled"> | ||
| 134 | + <template | ||
| 135 | + v-for="item in getStructFormItem" | ||
| 136 | + #[item.identifier!]="{ model, field }" | ||
| 137 | + :key="item.identifier" | ||
| 138 | + > | ||
| 139 | + <ThingsModelForm | ||
| 140 | + class="!ml-10" | ||
| 141 | + :ref="(el) => setFormElRef(el, item)" | ||
| 142 | + v-model:value="model[field]" | ||
| 143 | + :input-data="(item.dataType?.specs as StructJSON[]) || []" | ||
| 144 | + :title="item.functionName" | ||
| 145 | + :disabled="disabled" | ||
| 146 | + /> | ||
| 147 | + </template> | ||
| 148 | + </BasicForm> | ||
| 149 | + </Card> | ||
| 150 | +</template> | ||
| 151 | + | ||
| 152 | +<style lang="less" scoped> | ||
| 153 | + .things-model-form { | ||
| 154 | + :deep(.ant-input-number) { | ||
| 155 | + width: 100%; | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + :deep(.ant-form-item-label) { | ||
| 159 | + label { | ||
| 160 | + width: 100%; | ||
| 161 | + display: block; | ||
| 162 | + overflow: hidden; | ||
| 163 | + text-overflow: ellipsis; | ||
| 164 | + } | ||
| 165 | + } | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + :deep(.ant-form-item-control) { | ||
| 169 | + margin-left: 6px; | ||
| 170 | + } | ||
| 171 | +</style> |
| @@ -123,6 +123,7 @@ export type ComponentType = | @@ -123,6 +123,7 @@ export type ComponentType = | ||
| 123 | | 'TransferModal' | 123 | | 'TransferModal' |
| 124 | | 'TransferTableModal' | 124 | | 'TransferTableModal' |
| 125 | | 'ObjectModelValidateForm' | 125 | | 'ObjectModelValidateForm' |
| 126 | + | 'ThingsModelForm' | ||
| 126 | | 'DevicePicker' | 127 | | 'DevicePicker' |
| 127 | | 'ProductPicker' | 128 | | 'ProductPicker' |
| 128 | | 'PollCommandInput' | 129 | | 'PollCommandInput' |
| @@ -138,4 +139,8 @@ export type ComponentType = | @@ -138,4 +139,8 @@ export type ComponentType = | ||
| 138 | | 'RelationsQuery' | 139 | | 'RelationsQuery' |
| 139 | | 'CredentialsCard' | 140 | | 'CredentialsCard' |
| 140 | | 'ApiComplete' | 141 | | 'ApiComplete' |
| 141 | - | 'DeviceProfileForm'; | 142 | + | 'DeviceProfileForm' |
| 143 | + | 'ConditionFilter' | ||
| 144 | + | 'TimeRangePicker' | ||
| 145 | + | 'TriggerDurationInput' | ||
| 146 | + | 'AlarmProfileSelect'; |
| @@ -11,3 +11,19 @@ export enum AlarmStatusMean { | @@ -11,3 +11,19 @@ export enum AlarmStatusMean { | ||
| 11 | CLEARED_ACK = '清除已确认', | 11 | CLEARED_ACK = '清除已确认', |
| 12 | ACTIVE_ACK = '激活已确认', | 12 | ACTIVE_ACK = '激活已确认', |
| 13 | } | 13 | } |
| 14 | + | ||
| 15 | +export enum AlarmLevelEnum { | ||
| 16 | + CRITICAL = 'CRITICAL', | ||
| 17 | + MAJOR = 'MAJOR', | ||
| 18 | + MINOR = 'MINOR', | ||
| 19 | + WARNING = 'WARNING', | ||
| 20 | + INDETERMINATE = 'INDETERMINATE', | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | +export enum AlarmLevelNameEnum { | ||
| 24 | + CRITICAL = '紧急', | ||
| 25 | + MAJOR = '重要', | ||
| 26 | + MINOR = '次要', | ||
| 27 | + WARNING = '警告', | ||
| 28 | + INDETERMINATE = '不确定', | ||
| 29 | +} |
src/enums/linkedgeEnum.ts
0 → 100644
| 1 | +/** | ||
| 2 | + * 运算符枚举值 | ||
| 3 | + */ | ||
| 4 | + | ||
| 5 | +// 数字运算符或者时间运算符 | ||
| 6 | +export enum NumberOperationEnum { | ||
| 7 | + EQUAL = 'EQUAL', | ||
| 8 | + NOT_EQUAL = 'NOT_EQUAL', | ||
| 9 | + LESS = 'LESS', | ||
| 10 | + LESS_OR_EQUAL = 'LESS_OR_EQUAL', | ||
| 11 | + GREATER = 'GREATER', | ||
| 12 | + GREATER_OR_EQUAL = 'GREATER_OR_EQUAL', | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +export enum NumberOperationNameEnum { | ||
| 16 | + EQUAL = '等于', | ||
| 17 | + NOT_EQUAL = '不等于', | ||
| 18 | + LESS = '小于', | ||
| 19 | + LESS_OR_EQUAL = '小于等于', | ||
| 20 | + GREATER = '大于', | ||
| 21 | + GREATER_OR_EQUAL = '大于等于', | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +export enum StringOperationEnum { | ||
| 25 | + EQUAL = 'EQUAL', | ||
| 26 | + NOT_EQUAL = 'NOT_EQUAL', | ||
| 27 | + STARTS_WITH = 'STARTS_WITH', | ||
| 28 | + ENDS_WITH = 'ENDS_WITH', | ||
| 29 | + CONTAINS = 'CONTAINS', | ||
| 30 | + NOT_CONTAINS = 'NOT_CONTAINS', | ||
| 31 | +} | ||
| 32 | + | ||
| 33 | +export enum StringOperationNameEnum { | ||
| 34 | + EQUAL = '等于', | ||
| 35 | + NOT_EQUAL = '不等于', | ||
| 36 | + STARTS_WITH = '开始于', | ||
| 37 | + ENDS_WITH = '结束于', | ||
| 38 | + CONTAINS = '包含', | ||
| 39 | + NOT_CONTAINS = '不包含', | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +export enum BooleanOperationEnum { | ||
| 43 | + EQUAL = 'EQUAL', | ||
| 44 | + NOT_EQUAL = 'NOT_EQUAL', | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +export enum BooleanOperationNameEnum { | ||
| 48 | + EQUAL = '等于', | ||
| 49 | + NOT_EQUAL = '不等于', | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +export enum BooleanOperationValueEnum { | ||
| 53 | + TRUE = 'true', | ||
| 54 | + FALSE = 'false', | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +export enum BooleanOperationValueNameEnum { | ||
| 58 | + TRUE = '真', | ||
| 59 | + FALSE = '假', | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +export enum FlipFlopTypeEnum { | ||
| 63 | + SIMPLE = 'SIMPLE', | ||
| 64 | + DURATION = 'DURATION', | ||
| 65 | + REPEATING = 'REPEATING', | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +export enum ScheduleTypeEnum { | ||
| 69 | + ANY_TIME = 'ANY_TIME', | ||
| 70 | + SPECIFIC_TIME = 'SPECIFIC_TIME', | ||
| 71 | + CUSTOM = 'CUSTOM', | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +export enum ScheduleTypeNameEnum { | ||
| 75 | + ANY_TIME = '始终启用', | ||
| 76 | + SPECIFIC_TIME = '定时启用', | ||
| 77 | + CUSTOM = '自定义启用', | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +export enum FlipFlopTypeNameEnum { | ||
| 81 | + SIMPLE = '简单', | ||
| 82 | + DURATION = '持续时长', | ||
| 83 | + REPEATING = '重复次数', | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +export enum TriggerTypeEnum { | ||
| 87 | + DEVICE_TRIGGER = 'DEVICE_TRIGGER', | ||
| 88 | + SCHEDULE_TRIGGER = 'SCHEDULE_TRIGGER', | ||
| 89 | + SCENE_TRIGGER = 'SCENE_TRIGGER', | ||
| 90 | + HAND_ACT = 'HAND_ACT', | ||
| 91 | +} | ||
| 92 | + | ||
| 93 | +export enum TriggerTypeNameEnum { | ||
| 94 | + DEVICE_TRIGGER = '设备触发', | ||
| 95 | + SCHEDULE_TRIGGER = '定时触发', | ||
| 96 | + SCENE_TRIGGER = '场景触发', | ||
| 97 | + HAND_ACT = '手动触发', | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +export enum DeviceTriggerTypeEum { | ||
| 101 | + TIME_SERIES = 'TIME_SERIES', | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +export enum DeviceTriggerTypeNameEum { | ||
| 105 | + TIME_SERIES = '属性触发', | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +export enum TriggerEntityTypeEnum { | ||
| 109 | + ALL = 'ALL', | ||
| 110 | + PART = 'PART', | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +export enum TriggerEntityTypeNameEnum { | ||
| 114 | + ALL = '全部', | ||
| 115 | + PART = '部分', | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +export enum TriggerValueTypeEnum { | ||
| 119 | + NUMERIC = 'NUMERIC', | ||
| 120 | + BOOLEAN = 'BOOLEAN', | ||
| 121 | + STRING = 'STRING', | ||
| 122 | + DATE_TIME = 'DATE_TIME', | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +export enum TriggerValueTypeNameEnum { | ||
| 126 | + NUMERIC = '数字', | ||
| 127 | + BOOLEAN = '布尔值', | ||
| 128 | + STRING = '字符串', | ||
| 129 | + DATE_TIME = '时间', | ||
| 130 | +} | ||
| 131 | + | ||
| 132 | +export enum TriggerUnitEnum { | ||
| 133 | + SECONDS = 'SECONDS', | ||
| 134 | + MINUTES = 'MINUTES', | ||
| 135 | + HOURS = 'HOURS', | ||
| 136 | + DAYS = 'DAYS', | ||
| 137 | +} | ||
| 138 | + | ||
| 139 | +export enum TriggerUnitNameEnum { | ||
| 140 | + SECONDS = '秒', | ||
| 141 | + MINUTES = '分', | ||
| 142 | + HOURS = '时', | ||
| 143 | + DAYS = '天', | ||
| 144 | +} | ||
| 145 | + | ||
| 146 | +export enum ExecutionActionEnum { | ||
| 147 | + DEVICE_OUT = 'DEVICE_OUT', | ||
| 148 | + MSG_NOTIFY = 'MSG_NOTIFY', | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +export enum ExecutionActionNameEnum { | ||
| 152 | + DEVICE_OUT = '设备输出', | ||
| 153 | + MSG_NOTIFY = '告警输出', | ||
| 154 | +} | ||
| 155 | + | ||
| 156 | +export enum CommandTypeEnum { | ||
| 157 | + CUSTOM = 0, | ||
| 158 | + SERVICE = 1, | ||
| 159 | + ATTRIBUTE = 2, | ||
| 160 | + API = 'api', | ||
| 161 | +} | ||
| 162 | + | ||
| 163 | +export enum CommandTypeNameEnum { | ||
| 164 | + CUSTOM = '自定义', | ||
| 165 | + SERVICE = '服务', | ||
| 166 | + ATTRIBUTE = '属性', | ||
| 167 | +} |
src/enums/objectModelEnum.ts
0 → 100644
src/enums/operationEnum.ts
deleted
100644 → 0
| 1 | -/** | ||
| 2 | - * 运算符枚举值 | ||
| 3 | - */ | ||
| 4 | - | ||
| 5 | -// 数字运算符或者时间运算符 | ||
| 6 | -export enum Number_Operation { | ||
| 7 | - EQUAL = 'EQUAL', | ||
| 8 | - NOT_EQUAL = 'NOT_EQUAL', | ||
| 9 | - LESS = 'LESS', | ||
| 10 | - LESS_OR_EQUAL = 'LESS_OR_EQUAL', | ||
| 11 | - GREATER = 'GREATER', | ||
| 12 | - GREATER_OR_EQUAL = 'GREATER_OR_EQUAL', | ||
| 13 | -} | ||
| 14 | - | ||
| 15 | -export enum String_Operation { | ||
| 16 | - EQUAL = 'EQUAL', | ||
| 17 | - NOT_EQUAL = 'NOT_EQUAL', | ||
| 18 | - BEGAN_IN = 'STARTS_WITH', | ||
| 19 | - END_IN = 'ENDS_WITH', | ||
| 20 | - INCLUDE = 'CONTAINS', | ||
| 21 | - NOT_INCLUDE = 'NOT_CONTAINS', | ||
| 22 | -} | ||
| 23 | - | ||
| 24 | -export enum Boolean_Operation { | ||
| 25 | - EQUAL = 'EQUAL', | ||
| 26 | - NOT_EQUAL = 'NOT_EQUAL', | ||
| 27 | -} |
| @@ -7,7 +7,7 @@ export enum DataActionModeEnum { | @@ -7,7 +7,7 @@ export enum DataActionModeEnum { | ||
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | export enum DataActionModeNameEnum { | 9 | export enum DataActionModeNameEnum { |
| 10 | - CREATE = '创建', | 10 | + CREATE = '新增', |
| 11 | READ = '查看', | 11 | READ = '查看', |
| 12 | UPDATE = '编辑', | 12 | UPDATE = '编辑', |
| 13 | DELETE = '删除', | 13 | DELETE = '删除', |
| @@ -40,6 +40,11 @@ export enum ServiceCallTypeEnum { | @@ -40,6 +40,11 @@ export enum ServiceCallTypeEnum { | ||
| 40 | SYNC = 'SYNC', | 40 | SYNC = 'SYNC', |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | +export enum ServiceCallTypeNameEnum { | ||
| 44 | + ASYNC = '异步', | ||
| 45 | + SYNC = '同步', | ||
| 46 | +} | ||
| 47 | + | ||
| 43 | export enum CommandDeliveryWayEnum { | 48 | export enum CommandDeliveryWayEnum { |
| 44 | ONE_WAY = 'oneway', | 49 | ONE_WAY = 'oneway', |
| 45 | TWO_WAY = 'twoway', | 50 | TWO_WAY = 'twoway', |
| @@ -16,15 +16,17 @@ | @@ -16,15 +16,17 @@ | ||
| 16 | value?: string | string[]; | 16 | value?: string | string[]; |
| 17 | apiTreeSelectProps?: Recordable; | 17 | apiTreeSelectProps?: Recordable; |
| 18 | showCreate?: boolean; | 18 | showCreate?: boolean; |
| 19 | + disabled?: boolean; | ||
| 19 | }>(), | 20 | }>(), |
| 20 | { | 21 | { |
| 21 | showCreate: true, | 22 | showCreate: true, |
| 23 | + disabled: false, | ||
| 22 | } | 24 | } |
| 23 | ); | 25 | ); |
| 24 | 26 | ||
| 25 | const needReload = ref(true); | 27 | const needReload = ref(true); |
| 26 | 28 | ||
| 27 | - const emit = defineEmits(['change']); | 29 | + const emit = defineEmits(['change', 'optionsChange']); |
| 28 | 30 | ||
| 29 | const handleOpenCreate = () => { | 31 | const handleOpenCreate = () => { |
| 30 | openDrawer(true, { isUpdate: false }); | 32 | openDrawer(true, { isUpdate: false }); |
| @@ -35,13 +37,14 @@ | @@ -35,13 +37,14 @@ | ||
| 35 | const orgList = ref<Recordable[]>([]); | 37 | const orgList = ref<Recordable[]>([]); |
| 36 | 38 | ||
| 37 | const getBindProps = computed<Recordable>(() => { | 39 | const getBindProps = computed<Recordable>(() => { |
| 38 | - const { value, apiTreeSelectProps = {} } = props; | 40 | + const { value, apiTreeSelectProps = {}, disabled } = props; |
| 39 | const { params = {} } = apiTreeSelectProps; | 41 | const { params = {} } = apiTreeSelectProps; |
| 40 | return { | 42 | return { |
| 41 | replaceFields: { children: 'children', key: 'id', title: 'name', value: 'id' }, | 43 | replaceFields: { children: 'children', key: 'id', title: 'name', value: 'id' }, |
| 42 | getPopupContainer: () => document.body, | 44 | getPopupContainer: () => document.body, |
| 43 | placeholder: '请选择所属组织', | 45 | placeholder: '请选择所属组织', |
| 44 | maxLength: 250, | 46 | maxLength: 250, |
| 47 | + disabled, | ||
| 45 | ...apiTreeSelectProps, | 48 | ...apiTreeSelectProps, |
| 46 | value, | 49 | value, |
| 47 | dropdownStyle: { maxHeight: '300px' }, | 50 | dropdownStyle: { maxHeight: '300px' }, |
| @@ -63,6 +66,7 @@ | @@ -63,6 +66,7 @@ | ||
| 63 | onChange: (...args: any[]) => { | 66 | onChange: (...args: any[]) => { |
| 64 | emit('change', ...args); | 67 | emit('change', ...args); |
| 65 | }, | 68 | }, |
| 69 | + onOptionsChange: (...args: any[]) => emit('optionsChange', ...args), | ||
| 66 | }; | 70 | }; |
| 67 | }); | 71 | }); |
| 68 | 72 | ||
| @@ -80,7 +84,9 @@ | @@ -80,7 +84,9 @@ | ||
| 80 | <template> | 84 | <template> |
| 81 | <section class="flex"> | 85 | <section class="flex"> |
| 82 | <ApiTreeSelect v-bind="getBindProps" /> | 86 | <ApiTreeSelect v-bind="getBindProps" /> |
| 83 | - <Button v-if="getShowCreate" type="link" @click="handleOpenCreate">新增组织</Button> | 87 | + <Button v-if="getShowCreate" type="link" @click="handleOpenCreate" :disabled="disabled" |
| 88 | + >新增组织</Button | ||
| 89 | + > | ||
| 84 | <OrganizationDrawer v-if="getShowCreate" @register="registerDrawer" @success="handleReload" /> | 90 | <OrganizationDrawer v-if="getShowCreate" @register="registerDrawer" @success="handleReload" /> |
| 85 | </section> | 91 | </section> |
| 86 | </template> | 92 | </template> |
| @@ -15,13 +15,13 @@ | @@ -15,13 +15,13 @@ | ||
| 15 | import { useHistoryData } from '../../hook/useHistoryData'; | 15 | import { useHistoryData } from '../../hook/useHistoryData'; |
| 16 | import { formatToDateTime } from '/@/utils/dateUtil'; | 16 | import { formatToDateTime } from '/@/utils/dateUtil'; |
| 17 | import { useTable, BasicTable, BasicColumn } from '/@/components/Table'; | 17 | import { useTable, BasicTable, BasicColumn } from '/@/components/Table'; |
| 18 | - import { DataTypeEnum } from '/@/components/Form/src/externalCompns/components/StructForm/config'; | ||
| 19 | import { | 18 | import { |
| 20 | ModeSwitchButton, | 19 | ModeSwitchButton, |
| 21 | TABLE_CHART_MODE_LIST, | 20 | TABLE_CHART_MODE_LIST, |
| 22 | EnumTableChartMode, | 21 | EnumTableChartMode, |
| 23 | } from '/@/components/Widget'; | 22 | } from '/@/components/Widget'; |
| 24 | import { SchemaFiled } from '/@/views/visual/palette/components/HistoryTrendModal/config'; | 23 | import { SchemaFiled } from '/@/views/visual/palette/components/HistoryTrendModal/config'; |
| 24 | + import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 25 | 25 | ||
| 26 | interface DeviceDetail { | 26 | interface DeviceDetail { |
| 27 | tbDeviceId: string; | 27 | tbDeviceId: string; |
| @@ -188,7 +188,7 @@ | @@ -188,7 +188,7 @@ | ||
| 188 | method.setFieldsValue({ keys: props.attr }); | 188 | method.setFieldsValue({ keys: props.attr }); |
| 189 | const attrInfo = unref(deviceAttrs).find((item) => item.identifier === props.attr); | 189 | const attrInfo = unref(deviceAttrs).find((item) => item.identifier === props.attr); |
| 190 | if ( | 190 | if ( |
| 191 | - [DataTypeEnum.IS_STRING, DataTypeEnum.IS_STRUCT].includes( | 191 | + [DataTypeEnum.STRING, DataTypeEnum.STRUCT].includes( |
| 192 | attrInfo?.detail.dataType.type as unknown as DataTypeEnum | 192 | attrInfo?.detail.dataType.type as unknown as DataTypeEnum |
| 193 | ) | 193 | ) |
| 194 | ) { | 194 | ) { |
| @@ -16,7 +16,6 @@ | @@ -16,7 +16,6 @@ | ||
| 16 | import { DeviceModelOfMatterAttrs, DeviceRecord } from '/@/api/device/model/deviceModel'; | 16 | import { DeviceModelOfMatterAttrs, DeviceRecord } from '/@/api/device/model/deviceModel'; |
| 17 | import { Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | 17 | import { Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
| 18 | import { isArray, isNull, isObject } from '/@/utils/is'; | 18 | import { isArray, isNull, isObject } from '/@/utils/is'; |
| 19 | - import { DataTypeEnum } from '/@/components/Form/src/externalCompns/components/StructForm/config'; | ||
| 20 | import { useGlobSetting } from '/@/hooks/setting'; | 19 | import { useGlobSetting } from '/@/hooks/setting'; |
| 21 | import { ModeSwitchButton, EnumTableCardMode } from '/@/components/Widget'; | 20 | import { ModeSwitchButton, EnumTableCardMode } from '/@/components/Widget'; |
| 22 | import { toRaw } from 'vue'; | 21 | import { toRaw } from 'vue'; |
| @@ -25,6 +24,7 @@ | @@ -25,6 +24,7 @@ | ||
| 25 | import { ModalParamsType } from '/#/utils'; | 24 | import { ModalParamsType } from '/#/utils'; |
| 26 | import { AreaChartOutlined } from '@ant-design/icons-vue'; | 25 | import { AreaChartOutlined } from '@ant-design/icons-vue'; |
| 27 | import { SvgIcon } from '/@/components/Icon'; | 26 | import { SvgIcon } from '/@/components/Icon'; |
| 27 | + import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 28 | 28 | ||
| 29 | interface ReceiveMessage { | 29 | interface ReceiveMessage { |
| 30 | data: { | 30 | data: { |
| @@ -220,7 +220,7 @@ | @@ -220,7 +220,7 @@ | ||
| 220 | }; | 220 | }; |
| 221 | 221 | ||
| 222 | const isStructAndTextType = (type: DataTypeEnum) => { | 222 | const isStructAndTextType = (type: DataTypeEnum) => { |
| 223 | - return [DataTypeEnum.IS_STRUCT, DataTypeEnum.IS_STRING].includes(type); | 223 | + return [DataTypeEnum.STRUCT, DataTypeEnum.STRING].includes(type); |
| 224 | }; | 224 | }; |
| 225 | 225 | ||
| 226 | const setDataSource = () => { | 226 | const setDataSource = () => { |
| @@ -311,7 +311,7 @@ | @@ -311,7 +311,7 @@ | ||
| 311 | }); | 311 | }); |
| 312 | 312 | ||
| 313 | const formatValue = (item: DataSource) => { | 313 | const formatValue = (item: DataSource) => { |
| 314 | - return item.type === DataTypeEnum.IS_BOOL | 314 | + return item.type === DataTypeEnum.BOOL |
| 315 | ? !isNull(item.value) | 315 | ? !isNull(item.value) |
| 316 | ? !!Number(item.value) | 316 | ? !!Number(item.value) |
| 317 | ? item.boolOpen | 317 | ? item.boolOpen |
| @@ -6,7 +6,6 @@ | @@ -6,7 +6,6 @@ | ||
| 6 | import { StructJSON } from '/@/api/device/model/modelOfMatterModel'; | 6 | import { StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
| 7 | import { BasicForm, useForm } from '/@/components/Form'; | 7 | import { BasicForm, useForm } from '/@/components/Form'; |
| 8 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 8 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
| 9 | - import { DataTypeEnum } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | ||
| 10 | import { sendCommandOneway } from '/@/api/dataBoard'; | 9 | import { sendCommandOneway } from '/@/api/dataBoard'; |
| 11 | import { useMessage } from '/@/hooks/web/useMessage'; | 10 | import { useMessage } from '/@/hooks/web/useMessage'; |
| 12 | import { unref } from 'vue'; | 11 | import { unref } from 'vue'; |
| @@ -14,6 +13,7 @@ | @@ -14,6 +13,7 @@ | ||
| 14 | import { TaskTypeEnum } from '/@/views/task/center/config'; | 13 | import { TaskTypeEnum } from '/@/views/task/center/config'; |
| 15 | import { SingleToHex, formSchemasConfig } from './config'; | 14 | import { SingleToHex, formSchemasConfig } from './config'; |
| 16 | import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; | 15 | import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; |
| 16 | + import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 17 | 17 | ||
| 18 | defineEmits(['register']); | 18 | defineEmits(['register']); |
| 19 | const props = defineProps<{ deviceId: string; deviceName: string }>(); | 19 | const props = defineProps<{ deviceId: string; deviceName: string }>(); |
| @@ -51,7 +51,7 @@ | @@ -51,7 +51,7 @@ | ||
| 51 | 51 | ||
| 52 | let schemas = [{ dataType: dataType, identifier, functionName: name } as StructJSON]; | 52 | let schemas = [{ dataType: dataType, identifier, functionName: name } as StructJSON]; |
| 53 | 53 | ||
| 54 | - if (type === DataTypeEnum.IS_STRUCT) { | 54 | + if (type === DataTypeEnum.STRUCT) { |
| 55 | schemas = dataType?.specs as StructJSON[]; | 55 | schemas = dataType?.specs as StructJSON[]; |
| 56 | } | 56 | } |
| 57 | 57 |
| 1 | import { DataType, Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | 1 | import { DataType, Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
| 2 | import { JSONEditor } from '/@/components/CodeEditor'; | 2 | import { JSONEditor } from '/@/components/CodeEditor'; |
| 3 | import { FormSchema, useComponentRegister } from '/@/components/Form'; | 3 | import { FormSchema, useComponentRegister } from '/@/components/Form'; |
| 4 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 4 | import { useJsonParse } from '/@/hooks/business/useJsonParse'; | 5 | import { useJsonParse } from '/@/hooks/business/useJsonParse'; |
| 5 | -import { DataTypeEnum } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | ||
| 6 | 6 | ||
| 7 | export interface BasicCreateFormParams { | 7 | export interface BasicCreateFormParams { |
| 8 | identifier: string; | 8 | identifier: string; |
| @@ -19,9 +19,9 @@ const validateDouble = ( | @@ -19,9 +19,9 @@ const validateDouble = ( | ||
| 19 | max?: number | string | 19 | max?: number | string |
| 20 | ) => { | 20 | ) => { |
| 21 | min = | 21 | min = |
| 22 | - Number(min) || type === DataTypeEnum.IS_NUMBER_INT ? Number.MIN_SAFE_INTEGER : Number.MIN_VALUE; | 22 | + Number(min) || type === DataTypeEnum.NUMBER_INT ? Number.MIN_SAFE_INTEGER : Number.MIN_VALUE; |
| 23 | max = | 23 | max = |
| 24 | - Number(max) || type === DataTypeEnum.IS_NUMBER_INT ? Number.MAX_SAFE_INTEGER : Number.MAX_VALUE; | 24 | + Number(max) || type === DataTypeEnum.NUMBER_INT ? Number.MAX_SAFE_INTEGER : Number.MAX_VALUE; |
| 25 | 25 | ||
| 26 | return { | 26 | return { |
| 27 | flag: value < min || value > max, | 27 | flag: value < min || value > max, |
| @@ -56,13 +56,11 @@ export const useGenDynamicForm = () => { | @@ -56,13 +56,11 @@ export const useGenDynamicForm = () => { | ||
| 56 | }, | 56 | }, |
| 57 | ], | 57 | ], |
| 58 | componentProps: { | 58 | componentProps: { |
| 59 | - max: | ||
| 60 | - max ?? type === DataTypeEnum.IS_NUMBER_INT ? Number.MAX_SAFE_INTEGER : Number.MAX_VALUE, | ||
| 61 | - min: | ||
| 62 | - min ?? type === DataTypeEnum.IS_NUMBER_INT ? Number.MIN_SAFE_INTEGER : Number.MIN_VALUE, | 59 | + max: max ?? type === DataTypeEnum.NUMBER_INT ? Number.MAX_SAFE_INTEGER : Number.MAX_VALUE, |
| 60 | + min: min ?? type === DataTypeEnum.NUMBER_INT ? Number.MIN_SAFE_INTEGER : Number.MIN_VALUE, | ||
| 63 | step, | 61 | step, |
| 64 | placeholder: `请输入${functionName}`, | 62 | placeholder: `请输入${functionName}`, |
| 65 | - precision: type === DataTypeEnum.IS_NUMBER_INT ? 0 : 2, | 63 | + precision: type === DataTypeEnum.NUMBER_INT ? 0 : 2, |
| 66 | }, | 64 | }, |
| 67 | } as FormSchema; | 65 | } as FormSchema; |
| 68 | }; | 66 | }; |
| @@ -141,11 +139,11 @@ export const useGenDynamicForm = () => { | @@ -141,11 +139,11 @@ export const useGenDynamicForm = () => { | ||
| 141 | }; | 139 | }; |
| 142 | 140 | ||
| 143 | const schemaMethod = { | 141 | const schemaMethod = { |
| 144 | - [DataTypeEnum.IS_BOOL]: createSelect, | ||
| 145 | - [DataTypeEnum.IS_NUMBER_DOUBLE]: createInputNumber, | ||
| 146 | - [DataTypeEnum.IS_NUMBER_INT]: createInputNumber, | ||
| 147 | - [DataTypeEnum.IS_STRING]: createInput, | ||
| 148 | - [DataTypeEnum.IS_STRUCT]: createInputJson, | 142 | + [DataTypeEnum.BOOL]: createSelect, |
| 143 | + [DataTypeEnum.NUMBER_DOUBLE]: createInputNumber, | ||
| 144 | + [DataTypeEnum.NUMBER_INT]: createInputNumber, | ||
| 145 | + [DataTypeEnum.STRING]: createInput, | ||
| 146 | + [DataTypeEnum.STRUCT]: createInputJson, | ||
| 149 | }; | 147 | }; |
| 150 | 148 | ||
| 151 | const fieldTypeMap = new Map<string, DataTypeEnum>(); | 149 | const fieldTypeMap = new Map<string, DataTypeEnum>(); |
| @@ -176,7 +174,7 @@ export const useGenDynamicForm = () => { | @@ -176,7 +174,7 @@ export const useGenDynamicForm = () => { | ||
| 176 | const dataType = fieldTypeMap.get(next)!; | 174 | const dataType = fieldTypeMap.get(next)!; |
| 177 | 175 | ||
| 178 | let itemValue = value[next]; | 176 | let itemValue = value[next]; |
| 179 | - if (dataType === DataTypeEnum.IS_STRUCT) { | 177 | + if (dataType === DataTypeEnum.STRUCT) { |
| 180 | const { value } = useJsonParse(itemValue); | 178 | const { value } = useJsonParse(itemValue); |
| 181 | itemValue = value; | 179 | itemValue = value; |
| 182 | } | 180 | } |
| 1 | import { FormSchema } from '/@/components/Table'; | 1 | import { FormSchema } from '/@/components/Table'; |
| 2 | import { findDictItemByCode } from '/@/api/system/dict'; | 2 | import { findDictItemByCode } from '/@/api/system/dict'; |
| 3 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 3 | 4 | ||
| 4 | export enum FormField { | 5 | export enum FormField { |
| 5 | FUNCTION_NAME = 'functionName', | 6 | FUNCTION_NAME = 'functionName', |
| @@ -40,30 +41,19 @@ export enum AssessMode { | @@ -40,30 +41,19 @@ export enum AssessMode { | ||
| 40 | WRITE = 'w', | 41 | WRITE = 'w', |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 43 | -/** | ||
| 44 | - * 新增参数 动态显示表单 | ||
| 45 | - */ | ||
| 46 | -export enum DataTypeEnum { | ||
| 47 | - IS_NUMBER_INT = 'INT', | ||
| 48 | - IS_NUMBER_DOUBLE = 'DOUBLE', | ||
| 49 | - IS_STRING = 'TEXT', | ||
| 50 | - IS_STRUCT = 'STRUCT', | ||
| 51 | - IS_BOOL = 'BOOL', | ||
| 52 | -} | ||
| 53 | - | ||
| 54 | const isNumber = (type: string) => { | 44 | const isNumber = (type: string) => { |
| 55 | - return type === DataTypeEnum.IS_NUMBER_INT || type === DataTypeEnum.IS_NUMBER_DOUBLE; | 45 | + return type === DataTypeEnum.NUMBER_INT || type === DataTypeEnum.NUMBER_DOUBLE; |
| 56 | }; | 46 | }; |
| 57 | 47 | ||
| 58 | const isString = (type: string) => { | 48 | const isString = (type: string) => { |
| 59 | - return type === DataTypeEnum.IS_STRING; | 49 | + return type === DataTypeEnum.STRING; |
| 60 | }; | 50 | }; |
| 61 | const isStruct = (type: string) => { | 51 | const isStruct = (type: string) => { |
| 62 | - return type === DataTypeEnum.IS_STRUCT; | 52 | + return type === DataTypeEnum.STRUCT; |
| 63 | }; | 53 | }; |
| 64 | 54 | ||
| 65 | const isBool = (type: string) => { | 55 | const isBool = (type: string) => { |
| 66 | - return type === DataTypeEnum.IS_BOOL; | 56 | + return type === DataTypeEnum.BOOL; |
| 67 | }; | 57 | }; |
| 68 | 58 | ||
| 69 | export const serviceSchemas = (tcpDeviceFlag: boolean): FormSchema[] => { | 59 | export const serviceSchemas = (tcpDeviceFlag: boolean): FormSchema[] => { |
src/views/rule/linkedge/SceneLinkAgeDrawer.vue
deleted
100644 → 0
| 1 | -<template> | ||
| 2 | - <div> | ||
| 3 | - <BasicDrawer | ||
| 4 | - v-bind="$attrs" | ||
| 5 | - @register="registerDrawer" | ||
| 6 | - @ok="handleSubmit" | ||
| 7 | - destroy-on-close | ||
| 8 | - width="50%" | ||
| 9 | - showFooter | ||
| 10 | - @close="handleClose" | ||
| 11 | - :title="title" | ||
| 12 | - > | ||
| 13 | - <div> | ||
| 14 | - <!-- 基础表单 --> | ||
| 15 | - <BasicForm @register="registerForm" /> | ||
| 16 | - <!-- 基础表单 --> | ||
| 17 | - <!-- 触发器-begin --> | ||
| 18 | - <!-- <Divider orientation="left">触发器</Divider> --> | ||
| 19 | - <Divider orientation="left"> | ||
| 20 | - <a-tooltip> | ||
| 21 | - <template #title>触发器不可为空,消息只要满足触发条件中任意一个即可触发。</template> | ||
| 22 | - <label class="validate-dot"></label> 触发器 | ||
| 23 | - <QuestionCircleOutlined :style="{ fontSize: '14px', marginLeft: '5px' }" /> | ||
| 24 | - </a-tooltip> | ||
| 25 | - </Divider> | ||
| 26 | - <div> | ||
| 27 | - <template v-for="(item, index) in triggerData" :key="item"> | ||
| 28 | - <TriggerOrCondition | ||
| 29 | - class="mt-4" | ||
| 30 | - title="触发器" | ||
| 31 | - :index="index" | ||
| 32 | - :provideOrgid="provideOrgid" | ||
| 33 | - :ref="skipUnwrap.triggerItemRefs" | ||
| 34 | - @delete="deleteTriggerOrCondition" | ||
| 35 | - /> | ||
| 36 | - </template> | ||
| 37 | - <!-- 按钮 --> | ||
| 38 | - <a-button type="primary" class="mt-4" @click="addTrigger" v-if="isView"> | ||
| 39 | - <PlusOutlined /> | ||
| 40 | - 触发器(OR)<span style="visibility: hidden">发</span> | ||
| 41 | - </a-button> | ||
| 42 | - <!-- 按钮 --> | ||
| 43 | - </div> | ||
| 44 | - <!-- 触发器-end --> | ||
| 45 | - | ||
| 46 | - <!-- 执行条件-begin --> | ||
| 47 | - <Divider orientation="left"> | ||
| 48 | - <a-tooltip> | ||
| 49 | - <template #title>执行条件可为空,消息需要满足所有执行条件才会被处理。</template> | ||
| 50 | - 执行条件 | ||
| 51 | - <QuestionCircleOutlined :style="{ fontSize: '14px', marginLeft: '5px' }" /> | ||
| 52 | - </a-tooltip> | ||
| 53 | - </Divider> | ||
| 54 | - <div> | ||
| 55 | - <template v-for="(item, index) in conditionData" :key="item"> | ||
| 56 | - <TriggerOrCondition | ||
| 57 | - class="mt-4" | ||
| 58 | - title="执行条件" | ||
| 59 | - :index="index" | ||
| 60 | - :provideOrgid="provideOrgid" | ||
| 61 | - :ref="skipUnwrap.conditionItemRefs" | ||
| 62 | - @delete="deleteTriggerOrCondition" | ||
| 63 | - /> | ||
| 64 | - </template> | ||
| 65 | - <!-- 按钮 --> | ||
| 66 | - <a-button type="primary" class="mt-4" @click="addCondition" v-if="isView"> | ||
| 67 | - <PlusOutlined /> | ||
| 68 | - 执行条件(AND) | ||
| 69 | - </a-button> | ||
| 70 | - <!-- 按钮 --> | ||
| 71 | - </div> | ||
| 72 | - <!-- 执行条件-end --> | ||
| 73 | - | ||
| 74 | - <!-- 执行动作-begin --> | ||
| 75 | - <Divider orientation="left"> | ||
| 76 | - <a-tooltip> | ||
| 77 | - <template #title | ||
| 78 | - >触发器和执行条件都满足时,场景联动会做什么,例如:设备联动、告警通知等。</template | ||
| 79 | - > | ||
| 80 | - <label class="validate-dot"></label> 执行动作 | ||
| 81 | - <QuestionCircleOutlined :style="{ fontSize: '14px', marginLeft: '5px' }" /> | ||
| 82 | - </a-tooltip> | ||
| 83 | - </Divider> | ||
| 84 | - <div> | ||
| 85 | - <template v-for="(item, index) in actionData" :key="item"> | ||
| 86 | - <Action | ||
| 87 | - class="mt-4" | ||
| 88 | - :actionIndex="index" | ||
| 89 | - :actionData="actionData" | ||
| 90 | - :triggerData="triggerData" | ||
| 91 | - :ref="skipUnwrap.actionItemRefs" | ||
| 92 | - :provideOrgid="provideOrgid" | ||
| 93 | - :deviceList="getMasterDeviceList" | ||
| 94 | - :arr="arr" | ||
| 95 | - @deleteAction="deleteAction" | ||
| 96 | - @getActionFormArr="getActionFormArr" | ||
| 97 | - @dynamicChangeAlarmConfig="handleDynamicChangeAlarmConfig" | ||
| 98 | - /> | ||
| 99 | - </template> | ||
| 100 | - <!-- 按钮 --> | ||
| 101 | - <a-button type="primary" class="mt-4" @click="addAction" v-if="isView"> | ||
| 102 | - <PlusOutlined /> | ||
| 103 | - 新增执行动作 | ||
| 104 | - </a-button> | ||
| 105 | - <!-- 按钮 --> | ||
| 106 | - </div> | ||
| 107 | - <!-- 执行动作-end --> | ||
| 108 | - </div> | ||
| 109 | - </BasicDrawer> | ||
| 110 | - </div> | ||
| 111 | -</template> | ||
| 112 | -<script lang="ts" setup> | ||
| 113 | - import { ref, watch, unref, computed, nextTick } from 'vue'; | ||
| 114 | - import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | ||
| 115 | - import { formSchema, organizationId as organizationIdRef } from './config/config.data'; | ||
| 116 | - import { BasicForm, useForm } from '/@/components/Form'; | ||
| 117 | - import { genTriggerOrConditionData, genActionData } from './config/formatData'; | ||
| 118 | - import { Divider } from 'ant-design-vue'; | ||
| 119 | - import { PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons-vue'; | ||
| 120 | - import { useMessage } from '/@/hooks/web/useMessage'; | ||
| 121 | - import { | ||
| 122 | - screenLinkPageAddApi, | ||
| 123 | - screenLinkPageByDeptIdGetDevice, | ||
| 124 | - getOrganizationAlarmConfig, | ||
| 125 | - } from '/@/api/ruleengine/ruleengineApi'; | ||
| 126 | - import TriggerOrCondition from './cpns/Trigger-Condition.vue'; | ||
| 127 | - import Action from './cpns/Action.vue'; | ||
| 128 | - import { findOperation } from './config/formatData'; | ||
| 129 | - import { formatToDateTime } from '/@/utils/dateUtil'; | ||
| 130 | - import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/components/ObjectModelValidateForm/ObjectModelValidateForm.vue'; | ||
| 131 | - import { isEmpty } from '/@/utils/is'; | ||
| 132 | - import { add } from '/@/components/Form/src/componentMap'; | ||
| 133 | - | ||
| 134 | - add('ObjectModelValidateForm', ObjectModelValidateForm); | ||
| 135 | - | ||
| 136 | - const emit = defineEmits(['register', 'success']); | ||
| 137 | - const provideOrgid = ref(''); | ||
| 138 | - | ||
| 139 | - const { createMessage } = useMessage(); | ||
| 140 | - const triggerData = ref<number[]>([]); | ||
| 141 | - const conditionData = ref<number[]>([]); | ||
| 142 | - const actionData = ref<number[]>([]); | ||
| 143 | - const skipUnwrap = { | ||
| 144 | - triggerItemRefs: ref<InstanceType<typeof TriggerOrCondition>[]>([]), | ||
| 145 | - conditionItemRefs: ref<InstanceType<typeof TriggerOrCondition>[]>([]), | ||
| 146 | - actionItemRefs: ref<InstanceType<typeof Action>[]>([]), | ||
| 147 | - }; | ||
| 148 | - const title = computed( | ||
| 149 | - () => `${isUpdate.value === 3 ? '查看' : isUpdate.value ? '编辑' : '新增'}场景联动` | ||
| 150 | - ); | ||
| 151 | - let getTriggerFormValue = ref([]); | ||
| 152 | - let getConditionFormValue = ref([]); | ||
| 153 | - let getActionFormValue = ref([]); | ||
| 154 | - const editEntryIdData = ref([]); | ||
| 155 | - const editAlarmConfigData = ref([]); | ||
| 156 | - const isUpdate = ref<boolean | number>(false); | ||
| 157 | - const id = ref(undefined); | ||
| 158 | - const tenantId = ref(undefined); | ||
| 159 | - const isView = ref(true); | ||
| 160 | - const [ | ||
| 161 | - registerForm, | ||
| 162 | - { resetFields, validate, setFieldsValue, getFieldsValue, setProps, updateSchema }, | ||
| 163 | - ] = useForm({ | ||
| 164 | - labelWidth: 120, | ||
| 165 | - schemas: formSchema, | ||
| 166 | - showActionButtonGroup: false, | ||
| 167 | - }); | ||
| 168 | - const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { | ||
| 169 | - setDrawerProps({ confirmLoading: false, loading: true }); | ||
| 170 | - isUpdate.value = data.isUpdate; | ||
| 171 | - getActionFormArr(); | ||
| 172 | - if (!unref(isUpdate)) { | ||
| 173 | - resetFields(); | ||
| 174 | - //初始化执行动作 | ||
| 175 | - actionData.value = [Date.now()]; | ||
| 176 | - } else { | ||
| 177 | - // 取值 | ||
| 178 | - const { | ||
| 179 | - id: recordId, | ||
| 180 | - tenantId: recordTenantId, | ||
| 181 | - organizationId, | ||
| 182 | - triggers, | ||
| 183 | - doConditions, | ||
| 184 | - doActions, | ||
| 185 | - } = data.record; | ||
| 186 | - organizationIdRef.value = organizationId; | ||
| 187 | - // 赋值 | ||
| 188 | - await setFieldsValue(data.record); | ||
| 189 | - id.value = recordId; | ||
| 190 | - tenantId.value = recordTenantId; | ||
| 191 | - //TODO-fengtao-把组织id传给子组件 | ||
| 192 | - provideOrgid.value = organizationId; | ||
| 193 | - //TODO-fengtao获取当前执行动作下的设备(master那个接口) | ||
| 194 | - // getMasterDeviceList.value = await byOrganizationIdGetMasterDevice(organizationId); | ||
| 195 | - //TODO-fengtao | ||
| 196 | - // 获取当前组织下的设备列表 | ||
| 197 | - const options = await screenLinkPageByDeptIdGetDevice({ | ||
| 198 | - organizationId, | ||
| 199 | - }); | ||
| 200 | - // 获取当前组织下的告警配置 | ||
| 201 | - const alarmConfig = await getOrganizationAlarmConfig({ organizationId }); | ||
| 202 | - | ||
| 203 | - // 生成回显时对应得组件数量 | ||
| 204 | - triggerData.value = [...new Array(triggers.length).keys()]; | ||
| 205 | - conditionData.value = [...new Array(doConditions.length).keys()]; | ||
| 206 | - actionData.value = [...new Array(doActions.length).keys()]; | ||
| 207 | - // 回显设备列表 | ||
| 208 | - editEntryIdData.value = options.items.map((item) => { | ||
| 209 | - return { | ||
| 210 | - value: item.tbDeviceId, | ||
| 211 | - label: item.name, | ||
| 212 | - }; | ||
| 213 | - }); | ||
| 214 | - editAlarmConfigData.value = alarmConfig.map((item) => { | ||
| 215 | - return { | ||
| 216 | - value: item.id, | ||
| 217 | - label: item.name, | ||
| 218 | - status: item.status, | ||
| 219 | - }; | ||
| 220 | - }); | ||
| 221 | - deviceList.value = editEntryIdData.value; | ||
| 222 | - nextTick(() => { | ||
| 223 | - setEditFields(skipUnwrap.triggerItemRefs, editEntryIdData); | ||
| 224 | - setEditFields(skipUnwrap.conditionItemRefs, editEntryIdData); | ||
| 225 | - setEditFields(skipUnwrap.actionItemRefs, getMasterDeviceList); | ||
| 226 | - setEditAlarmConfig(skipUnwrap.actionItemRefs, editAlarmConfigData); | ||
| 227 | - }); | ||
| 228 | - | ||
| 229 | - const map = { | ||
| 230 | - ANY_TIME: 0, | ||
| 231 | - SPECIFIC_TIME: 1, | ||
| 232 | - CUSTOM: 2, | ||
| 233 | - }; | ||
| 234 | - // 回显触发器数据---此处是个闭包! | ||
| 235 | - triggers.forEach((trigger, index) => { | ||
| 236 | - nextTick(async () => { | ||
| 237 | - const selectProductId = ref(''); | ||
| 238 | - // 回显启用规则 | ||
| 239 | - unref(skipUnwrap.triggerItemRefs)[index].currentIndex = | ||
| 240 | - map[trigger.triggerCondition.schedule.type]; | ||
| 241 | - unref(skipUnwrap.triggerItemRefs)[index].scheduleData = trigger.triggerCondition.schedule; | ||
| 242 | - unref(skipUnwrap.triggerItemRefs)[index].isUpdate = true; | ||
| 243 | - unref(skipUnwrap.triggerItemRefs)[index].alarmScheduleRef.scheduleData = | ||
| 244 | - trigger.triggerCondition.schedule; | ||
| 245 | - unref(skipUnwrap.triggerItemRefs)[index].setFieldsFormValueFun({ | ||
| 246 | - triggered: trigger?.triggerCondition?.condition?.spec?.type, | ||
| 247 | - device: trigger?.entityType, | ||
| 248 | - deviceType: trigger?.deviceType, | ||
| 249 | - triggerType: trigger?.triggerType, | ||
| 250 | - type1: trigger?.triggerCondition?.condition?.condition[0]?.key?.type, | ||
| 251 | - type2: trigger?.triggerCondition?.condition?.condition[0]?.key?.key, | ||
| 252 | - operationType: trigger?.triggerCondition?.condition?.condition[0]?.valueType, | ||
| 253 | - detail: trigger?.triggerCondition?.alarmDetails, | ||
| 254 | - entityId: trigger?.entityId, | ||
| 255 | - deviceProfileId: trigger?.deviceProfileId, | ||
| 256 | - replaceValue: trigger?.triggerCondition?.condition?.spec?.predicate?.defaultValue, | ||
| 257 | - time: trigger?.triggerCondition?.condition?.spec?.predicate?.defaultValue, | ||
| 258 | - timeUnit: trigger?.triggerCondition?.condition?.spec?.unit, | ||
| 259 | - }); | ||
| 260 | - if (trigger.deviceProfileId != undefined) { | ||
| 261 | - selectProductId.value = trigger?.deviceProfileId; | ||
| 262 | - } | ||
| 263 | - //fengtao-把设备id回传给子组件 | ||
| 264 | - unref(skipUnwrap.triggerItemRefs)[index].updateFieldAttributeFunc(selectProductId.value); | ||
| 265 | - //fengtao | ||
| 266 | - // 设置值operationType | ||
| 267 | - unref(skipUnwrap.triggerItemRefs)[index].operationType = | ||
| 268 | - trigger.triggerCondition?.condition.condition[0].valueType; | ||
| 269 | - | ||
| 270 | - const ConditionScreeningForm = await unref(skipUnwrap.triggerItemRefs)[ | ||
| 271 | - index | ||
| 272 | - ].getRefItemConditionScreeningRefs(); | ||
| 273 | - | ||
| 274 | - // 设置对应条件筛选的个数 | ||
| 275 | - unref(skipUnwrap.triggerItemRefs)[index].setConditionScreeningList([ | ||
| 276 | - ...new Array(trigger.triggerCondition.condition.condition.length).keys(), | ||
| 277 | - ]); | ||
| 278 | - // 操作符类型 NUMERIC|String|Boolean|DATE_TIME | ||
| 279 | - const valueType = trigger.triggerCondition?.condition.condition[0].valueType; | ||
| 280 | - | ||
| 281 | - // 循环设置条件筛选值。TODO:此处设置顺序有问题 | ||
| 282 | - nextTick(() => { | ||
| 283 | - const richTextList = []; | ||
| 284 | - trigger.triggerCondition.condition.condition.forEach((item, index) => { | ||
| 285 | - const formItem = { | ||
| 286 | - operation: item.predicate.operation, | ||
| 287 | - value: | ||
| 288 | - valueType === 'DATE_TIME' | ||
| 289 | - ? formatToDateTime( | ||
| 290 | - Number(item.predicate.value.defaultValue), | ||
| 291 | - 'YYYY-MM-DD HH:mm:ss' | ||
| 292 | - ) | ||
| 293 | - : String(item.predicate.value.defaultValue), | ||
| 294 | - ignoreCase: item.valueType === 'STRING' ? item.predicate.ignoreCase : undefined, | ||
| 295 | - }; | ||
| 296 | - richTextList.push({ | ||
| 297 | - // 查询中文操作符 | ||
| 298 | - operation: findOperation(valueType, item.predicate.operation).label, | ||
| 299 | - value: | ||
| 300 | - valueType === 'DATE_TIME' | ||
| 301 | - ? formatToDateTime( | ||
| 302 | - Number(item.predicate.value.defaultValue), | ||
| 303 | - 'YYYY-MM-DD HH:mm:ss' | ||
| 304 | - ) | ||
| 305 | - : String(item.predicate.value.defaultValue), | ||
| 306 | - attribute: trigger.triggerCondition?.condition.condition[0]?.key?.key, | ||
| 307 | - }); | ||
| 308 | - ConditionScreeningForm.value[index].setFieldsValue(formItem); | ||
| 309 | - }); | ||
| 310 | - unref(skipUnwrap.triggerItemRefs)[index].setRichText(richTextList); | ||
| 311 | - }); | ||
| 312 | - }); | ||
| 313 | - }); | ||
| 314 | - | ||
| 315 | - doConditions.forEach((condition, index) => { | ||
| 316 | - nextTick(async () => { | ||
| 317 | - const selectProductId = ref(''); | ||
| 318 | - // 回显启用规则 | ||
| 319 | - unref(skipUnwrap.conditionItemRefs)[index].currentIndex = | ||
| 320 | - map[condition.triggerCondition.schedule.type]; | ||
| 321 | - unref(skipUnwrap.conditionItemRefs)[index].scheduleData = | ||
| 322 | - condition.triggerCondition.schedule; | ||
| 323 | - unref(skipUnwrap.conditionItemRefs)[index].isUpdate = true; | ||
| 324 | - unref(skipUnwrap.conditionItemRefs)[index].alarmScheduleRef.scheduleData = | ||
| 325 | - condition.triggerCondition.schedule; | ||
| 326 | - unref(skipUnwrap.conditionItemRefs)[index].setFieldsFormValueFun({ | ||
| 327 | - triggered: condition?.triggerCondition?.condition?.spec?.type, | ||
| 328 | - device: condition?.entityType, | ||
| 329 | - triggerType: condition?.triggerType, | ||
| 330 | - type1: condition?.triggerCondition?.condition?.condition[0]?.key?.type, | ||
| 331 | - type2: condition?.triggerCondition?.condition?.condition[0]?.key?.key, | ||
| 332 | - operationType: condition?.triggerCondition?.condition?.condition[0]?.valueType, | ||
| 333 | - detail: condition?.triggerCondition?.alarmDetails, | ||
| 334 | - entityId: condition?.entityId, | ||
| 335 | - deviceProfileId: condition?.deviceProfileId, | ||
| 336 | - deviceType: condition?.deviceType, | ||
| 337 | - replaceValue: condition?.triggerCondition?.condition?.spec?.predicate?.defaultValue, | ||
| 338 | - time: condition?.triggerCondition?.condition?.spec?.predicate?.defaultValue, | ||
| 339 | - timeUnit: condition?.triggerCondition?.condition?.spec?.unit, | ||
| 340 | - }); | ||
| 341 | - if (condition?.deviceProfileId != undefined) { | ||
| 342 | - selectProductId.value = condition?.deviceProfileId; | ||
| 343 | - } | ||
| 344 | - //fengtao-把设备id回传给子组件 | ||
| 345 | - unref(skipUnwrap.conditionItemRefs)[index].updateFieldAttributeFunc( | ||
| 346 | - selectProductId.value | ||
| 347 | - ); | ||
| 348 | - //fengtao | ||
| 349 | - // 设置值operationType | ||
| 350 | - unref(skipUnwrap.conditionItemRefs)[index].operationType = | ||
| 351 | - condition.triggerCondition?.condition.condition[0].valueType; | ||
| 352 | - | ||
| 353 | - const ConditionScreeningForm = await unref(skipUnwrap.conditionItemRefs)[ | ||
| 354 | - index | ||
| 355 | - ].getRefItemConditionScreeningRefs(); | ||
| 356 | - | ||
| 357 | - // 设置对应条件筛选的个数 | ||
| 358 | - unref(skipUnwrap.conditionItemRefs)[index].setConditionScreeningList([ | ||
| 359 | - ...new Array(condition.triggerCondition.condition.condition.length).keys(), | ||
| 360 | - ]); | ||
| 361 | - // 操作符类型 NUMERIC|String|Boolean|DATorganizeImportsE_TIME | ||
| 362 | - const valueType = condition.triggerCondition?.condition.condition[0].valueType; | ||
| 363 | - | ||
| 364 | - // 循环设置条件筛选值。TODO:此处设置顺序有问题 | ||
| 365 | - nextTick(() => { | ||
| 366 | - const richTextList = []; | ||
| 367 | - condition.triggerCondition.condition.condition.forEach((item, index) => { | ||
| 368 | - const formItem = { | ||
| 369 | - operation: item.predicate.operation, | ||
| 370 | - value: | ||
| 371 | - valueType === 'DATE_TIME' | ||
| 372 | - ? formatToDateTime( | ||
| 373 | - Number(item.predicate.value.defaultValue), | ||
| 374 | - 'YYYY-MM-DD HH:mm:ss' | ||
| 375 | - ) | ||
| 376 | - : String(item.predicate.value.defaultValue), | ||
| 377 | - ignoreCase: item.valueType === 'STRING' ? item.predicate.ignoreCase : undefined, | ||
| 378 | - }; | ||
| 379 | - richTextList.push({ | ||
| 380 | - // 查询中文操作符 | ||
| 381 | - operation: findOperation(valueType, item.predicate.operation).label, | ||
| 382 | - value: | ||
| 383 | - valueType === 'DATE_TIME' | ||
| 384 | - ? formatToDateTime( | ||
| 385 | - Number(item.predicate.value.defaultValue), | ||
| 386 | - 'YYYY-MM-DD HH:mm:ss' | ||
| 387 | - ) | ||
| 388 | - : String(item.predicate.value.defaultValue), | ||
| 389 | - attribute: condition.triggerCondition?.condition.condition[0]?.key?.key, | ||
| 390 | - }); | ||
| 391 | - ConditionScreeningForm.value[index].setFieldsValue(formItem); | ||
| 392 | - }); | ||
| 393 | - unref(skipUnwrap.conditionItemRefs)[index].setRichText(richTextList); | ||
| 394 | - }); | ||
| 395 | - }); | ||
| 396 | - }); | ||
| 397 | - doActions.forEach((action, index) => { | ||
| 398 | - nextTick(() => { | ||
| 399 | - const selectProductId = ref(''); | ||
| 400 | - // 设置执行动作外层值 | ||
| 401 | - unref(skipUnwrap.actionItemRefs)[index].setFieldsFormValueFun({ | ||
| 402 | - ...action, | ||
| 403 | - outTarget: action.outTarget, | ||
| 404 | - device: action.entityType, | ||
| 405 | - deviceId: action.deviceId, | ||
| 406 | - alarm_config: action.alarmProfileId, | ||
| 407 | - alarm_level: action.doContext.alarmLevel, | ||
| 408 | - }); | ||
| 409 | - // 如果是设备输出设置脚本值 | ||
| 410 | - if (action.outTarget === 'DEVICE_OUT') { | ||
| 411 | - if (action.commandType.toString() === '0') { | ||
| 412 | - unref(skipUnwrap.actionItemRefs)[index].setJsonValue(action.doContext.params); | ||
| 413 | - } | ||
| 414 | - } | ||
| 415 | - // 清除告警有值?{数组} | ||
| 416 | - if (action?.doContext?.clearRule?.length) { | ||
| 417 | - unref(skipUnwrap.actionItemRefs)[index].checked = true; | ||
| 418 | - // 生成对应清除告警的数组长度 | ||
| 419 | - unref(skipUnwrap.actionItemRefs)[index].clearRuleList = [ | ||
| 420 | - ...new Array(action?.doContext?.clearRule?.length).keys(), | ||
| 421 | - ]; | ||
| 422 | - // 推迟执行时机-DOM渲染完毕在执行 | ||
| 423 | - nextTick(async () => { | ||
| 424 | - unref(skipUnwrap.actionItemRefs)[index].refItem.clearRuleRefs.value.map( | ||
| 425 | - (item, index) => { | ||
| 426 | - // 回显启用规则 | ||
| 427 | - item.currentIndex = | ||
| 428 | - map[action.doContext.clearRule[index].triggerCondition.schedule.type]; | ||
| 429 | - item.scheduleData = action.doContext.clearRule[index].triggerCondition.schedule; | ||
| 430 | - item.isUpdate = true; | ||
| 431 | - item.alarmScheduleRef.scheduleData = | ||
| 432 | - action.doContext.clearRule[index].triggerCondition.schedule; | ||
| 433 | - item.setFieldsFormValueFun({ | ||
| 434 | - triggered: | ||
| 435 | - action.doContext.clearRule[index].triggerCondition.condition.spec.type, | ||
| 436 | - device: action.doContext.clearRule[index].entityType, | ||
| 437 | - deviceType: action.doContext.clearRule[index].deviceType, | ||
| 438 | - triggerType: action.doContext.clearRule[index].triggerType, | ||
| 439 | - type1: | ||
| 440 | - action.doContext.clearRule[index].triggerCondition.condition.condition[0].key | ||
| 441 | - .type, | ||
| 442 | - type2: | ||
| 443 | - action.doContext.clearRule[index].triggerCondition.condition.condition[0].key | ||
| 444 | - .key, | ||
| 445 | - operationType: | ||
| 446 | - action.doContext.clearRule[index].triggerCondition.condition.condition[0] | ||
| 447 | - .valueType, | ||
| 448 | - detail: action.doContext.clearRule[index].triggerCondition.alarmDetails, | ||
| 449 | - entityId: action.doContext.clearRule[index].entityId, | ||
| 450 | - deviceProfileId: action.doContext.clearRule[index]?.deviceProfileId, | ||
| 451 | - replaceValue: | ||
| 452 | - action.doContext.clearRule[index].triggerCondition.condition.spec.predicate | ||
| 453 | - .defaultValue, | ||
| 454 | - time: action.doContext.clearRule[index].triggerCondition.condition.spec | ||
| 455 | - .predicate.defaultValue, | ||
| 456 | - timeUnit: | ||
| 457 | - action.doContext.clearRule[index].triggerCondition.condition.spec.unit, | ||
| 458 | - }); | ||
| 459 | - if (action.doContext.clearRule[index]?.deviceProfileId != undefined) { | ||
| 460 | - selectProductId.value = action.doContext.clearRule[index]?.deviceProfileId; | ||
| 461 | - } | ||
| 462 | - //fengtao-把设备id回传给子组件 | ||
| 463 | - item.updateFieldAttributeFunc(selectProductId.value); | ||
| 464 | - item.updateFieldDeviceId(deviceList.value, provideOrgid.value, isUpdate.value); | ||
| 465 | - //fengtao | ||
| 466 | - // 单独设置operationType值 操作符类型 NUMERIC|String|Boolean|DATE_TIME | ||
| 467 | - item.operationType = | ||
| 468 | - action.doContext.clearRule[ | ||
| 469 | - index | ||
| 470 | - ].triggerCondition.condition.condition[0].valueType; | ||
| 471 | - } | ||
| 472 | - ); | ||
| 473 | - | ||
| 474 | - const ConditionScreeningForm = await unref(skipUnwrap.actionItemRefs)[ | ||
| 475 | - index | ||
| 476 | - ].getRefItemConditionScreeningRefs(); | ||
| 477 | - | ||
| 478 | - // 循环设置条件筛选值。TODO:此处设置顺序有问题 | ||
| 479 | - action.doContext.clearRule.map((rule, ruleIndex) => { | ||
| 480 | - // 生成对应条件筛选的数组个数 | ||
| 481 | - unref(skipUnwrap.actionItemRefs)[index].setConditionScreeningList([ | ||
| 482 | - ...new Array( | ||
| 483 | - action.doContext.clearRule[ | ||
| 484 | - ruleIndex | ||
| 485 | - ].triggerCondition.condition.condition.length | ||
| 486 | - ).keys(), | ||
| 487 | - ]); | ||
| 488 | - nextTick(() => { | ||
| 489 | - const richTextList = []; | ||
| 490 | - rule.triggerCondition.condition.condition.forEach((item, conditionIndex) => { | ||
| 491 | - //TODO-fengtao之前是Number( item.predicate.value.defaultValue)-发现回显是Invalide Time | ||
| 492 | - const formItem = { | ||
| 493 | - operation: item.predicate.operation, | ||
| 494 | - value: | ||
| 495 | - item.valueType === 'DATE_TIME' | ||
| 496 | - ? formatToDateTime( | ||
| 497 | - Number(item.predicate.value.defaultValue), | ||
| 498 | - 'YYYY-MM-DD HH:mm:ss' | ||
| 499 | - ) | ||
| 500 | - : String(item.predicate.value.defaultValue), | ||
| 501 | - ignoreCase: | ||
| 502 | - item.valueType === 'STRING' ? item.predicate.ignoreCase : undefined, | ||
| 503 | - }; | ||
| 504 | - //TODO-fengtao之前是Number( item.predicate.value.defaultValue)-发现回显是Invalide Time | ||
| 505 | - richTextList.push({ | ||
| 506 | - // 查询中文操作符 | ||
| 507 | - operation: findOperation(item.valueType, item.predicate.operation).label, | ||
| 508 | - value: | ||
| 509 | - item.valueType === 'DATE_TIME' | ||
| 510 | - ? formatToDateTime( | ||
| 511 | - item.predicate.value.defaultValue, | ||
| 512 | - 'YYYY-MM-DD HH:mm:ss' | ||
| 513 | - ) | ||
| 514 | - : String(item.predicate.value.defaultValue), | ||
| 515 | - attribute: item?.key?.key, | ||
| 516 | - }); | ||
| 517 | - //TODO-fengtao之前是Number( item.predicate.value.defaultValue)-发现回显是Invalide Time | ||
| 518 | - ConditionScreeningForm[ruleIndex].value[conditionIndex].setFieldsValue( | ||
| 519 | - formItem | ||
| 520 | - ); | ||
| 521 | - }); | ||
| 522 | - unref(skipUnwrap.actionItemRefs)[index].setRichText(richTextList, ruleIndex); | ||
| 523 | - }); | ||
| 524 | - }); | ||
| 525 | - }); | ||
| 526 | - } | ||
| 527 | - nextTick(() => { | ||
| 528 | - setEditFields(skipUnwrap.actionItemRefs, editEntryIdData); | ||
| 529 | - }); | ||
| 530 | - }); | ||
| 531 | - }); | ||
| 532 | - } | ||
| 533 | - if (unref(isUpdate) === 3) isView.value = false; | ||
| 534 | - setDrawerProps({ | ||
| 535 | - showFooter: unref(isView), | ||
| 536 | - loading: false, | ||
| 537 | - }); | ||
| 538 | - | ||
| 539 | - if (isUpdate.value == 3) { | ||
| 540 | - setProps({ disabled: true }); | ||
| 541 | - updateSchema({ | ||
| 542 | - field: 'organizationId', | ||
| 543 | - componentProps: { apiTreeSelectProps: { disabled: true } }, | ||
| 544 | - }); | ||
| 545 | - await nextTick(); | ||
| 546 | - unref(skipUnwrap.triggerItemRefs)?.forEach((item) => { | ||
| 547 | - item.setDisabledProps({ disabled: true }); | ||
| 548 | - }); | ||
| 549 | - | ||
| 550 | - unref(skipUnwrap.conditionItemRefs)?.forEach((item) => { | ||
| 551 | - item.setDisabledProps({ disabled: true }); | ||
| 552 | - }); | ||
| 553 | - | ||
| 554 | - unref(skipUnwrap.actionItemRefs)?.forEach((item) => { | ||
| 555 | - item.setDisabledProps({ disabled: true }); | ||
| 556 | - }); | ||
| 557 | - } else { | ||
| 558 | - updateSchema({ | ||
| 559 | - field: 'organizationId', | ||
| 560 | - componentProps: { apiTreeSelectProps: { disabled: false } }, | ||
| 561 | - }); | ||
| 562 | - unref(skipUnwrap.triggerItemRefs)?.forEach((item) => { | ||
| 563 | - item.setCancelDisabled(); | ||
| 564 | - }); | ||
| 565 | - unref(skipUnwrap.conditionItemRefs)?.forEach((item) => { | ||
| 566 | - item.setCancelDisabled(); | ||
| 567 | - }); | ||
| 568 | - } | ||
| 569 | - }); | ||
| 570 | - | ||
| 571 | - // 设置设备的options | ||
| 572 | - const setEditFields = (linkAge, deviceList) => { | ||
| 573 | - unref(linkAge).map((item) => { | ||
| 574 | - // TODO-fengtao | ||
| 575 | - item.updateFieldDeviceId(deviceList, orgId, isUpdate); | ||
| 576 | - // TODO-fengtao | ||
| 577 | - }); | ||
| 578 | - }; | ||
| 579 | - // 设置告警配置options | ||
| 580 | - const setEditAlarmConfig = (linkAge, alarmConfigList) => { | ||
| 581 | - unref(linkAge).map((item) => { | ||
| 582 | - item.updateEditFieldAlarmConfig(alarmConfigList); | ||
| 583 | - }); | ||
| 584 | - }; | ||
| 585 | - // 监听组织变化更新设备列表 | ||
| 586 | - const deviceList = ref([]); | ||
| 587 | - const getMasterDeviceList = ref([]); | ||
| 588 | - const orgId = ref(''); | ||
| 589 | - const alarmConfigList = ref([]); | ||
| 590 | - //FT add 2022-10-27 | ||
| 591 | - const addOrgId = ref(''); | ||
| 592 | - //FT add 2022-10-27 | ||
| 593 | - watch(organizationIdRef, async (newValue: string) => { | ||
| 594 | - if (!newValue) return; | ||
| 595 | - //FT add 2022-10-27 | ||
| 596 | - addOrgId.value = newValue; | ||
| 597 | - //FT add 2022-10-27 | ||
| 598 | - const { items = [] } = await screenLinkPageByDeptIdGetDevice({ organizationId: newValue }); | ||
| 599 | - //TODO fengtao | ||
| 600 | - // getMasterDeviceList.value = await byOrganizationIdGetMasterDevice(newValue); | ||
| 601 | - //TODO fengtao | ||
| 602 | - deviceList.value = (items || []).map((item) => ({ | ||
| 603 | - ...item, | ||
| 604 | - label: item.name, | ||
| 605 | - value: item.tbDeviceId, | ||
| 606 | - })); | ||
| 607 | - //TODO fengtao | ||
| 608 | - orgId.value = newValue; | ||
| 609 | - //TODO fengtao | ||
| 610 | - setFields(skipUnwrap.triggerItemRefs, true); | ||
| 611 | - setFields(skipUnwrap.conditionItemRefs, true); | ||
| 612 | - setFields(skipUnwrap.actionItemRefs, true); | ||
| 613 | - const data = await getOrganizationAlarmConfig({ organizationId: newValue }); | ||
| 614 | - alarmConfigList.value = data.map((item) => ({ | ||
| 615 | - label: item.name, | ||
| 616 | - value: item.id, | ||
| 617 | - status: item.status, | ||
| 618 | - })); | ||
| 619 | - setEditAlarmConfig(skipUnwrap.actionItemRefs, alarmConfigList); | ||
| 620 | - // setFields(skipUnwrap.actionItemRefs, true); | ||
| 621 | - // console.log(unref(organizationIdRef)); | ||
| 622 | - // setAlarmConfig(skipUnwrap.actionItemRefs, true); | ||
| 623 | - }); | ||
| 624 | - //FT add 2022-10-27 | ||
| 625 | - const handleDynamicChangeAlarmConfig = async () => { | ||
| 626 | - const data = await getOrganizationAlarmConfig({ | ||
| 627 | - organizationId: isUpdate.value ? provideOrgid.value : addOrgId.value, | ||
| 628 | - }); | ||
| 629 | - const res = data.map((item) => ({ label: item.name, value: item.id, status: item.status })); | ||
| 630 | - isUpdate.value ? (editAlarmConfigData.value = res) : (alarmConfigList.value = res); | ||
| 631 | - unref(skipUnwrap.actionItemRefs)?.map((item: any) => { | ||
| 632 | - if (isUpdate.value) { | ||
| 633 | - item.updateEditFieldAlarmConfig(editAlarmConfigData); | ||
| 634 | - } else { | ||
| 635 | - item.updateFieldAlarmConfig(alarmConfigList); | ||
| 636 | - } | ||
| 637 | - }); | ||
| 638 | - }; | ||
| 639 | - //FT add 2022-10-27 | ||
| 640 | - // 根据上面组织变化动态改变触发器,执行条件,执行动作的设备值 | ||
| 641 | - function setFields(linkAge, isOrganizationChange = false) { | ||
| 642 | - unref(linkAge).map((item) => { | ||
| 643 | - isOrganizationChange && item.resetFieldsValueFunc(); | ||
| 644 | - //TODO fengtao | ||
| 645 | - item.updateFieldDeviceId(deviceList, orgId, isUpdate); | ||
| 646 | - if (isUpdate.value) { | ||
| 647 | - item.updateEditFieldAlarmConfig(editAlarmConfigData); | ||
| 648 | - } else { | ||
| 649 | - item.updateFieldAlarmConfig(alarmConfigList); | ||
| 650 | - } | ||
| 651 | - //TODO fengtao | ||
| 652 | - }); | ||
| 653 | - } | ||
| 654 | - // function setAlarmConfig(linkAge, isOrganizationChange = false) { | ||
| 655 | - // unref(linkAge).map((item) => { | ||
| 656 | - // isOrganizationChange && item.resetFieldsValueFunc(); | ||
| 657 | - // item.updateFieldAlarmConfig(alarmConfigList); | ||
| 658 | - // }); | ||
| 659 | - // } | ||
| 660 | - | ||
| 661 | - const isEmptyThrowError = (obj) => { | ||
| 662 | - if (isEmpty(obj)) { | ||
| 663 | - createMessage.error('请选择组织'); | ||
| 664 | - throw Error('请选择组织'); | ||
| 665 | - } | ||
| 666 | - if (!Reflect.get(obj, 'organizationId')) { | ||
| 667 | - createMessage.error('请选择组织'); | ||
| 668 | - throw Error('请选择组织'); | ||
| 669 | - } | ||
| 670 | - }; | ||
| 671 | - | ||
| 672 | - // 添加触发器 | ||
| 673 | - const addTrigger = () => { | ||
| 674 | - unref(triggerData).push(Date.now()); | ||
| 675 | - nextTick(() => { | ||
| 676 | - setFields(skipUnwrap.triggerItemRefs); | ||
| 677 | - }); | ||
| 678 | - isEmptyThrowError(getFieldsValue()); | ||
| 679 | - }; | ||
| 680 | - // 添加执行条件 | ||
| 681 | - const addCondition = () => { | ||
| 682 | - unref(conditionData).push(Date.now()); | ||
| 683 | - nextTick(() => { | ||
| 684 | - setFields(skipUnwrap.conditionItemRefs); | ||
| 685 | - }); | ||
| 686 | - isEmptyThrowError(getFieldsValue()); | ||
| 687 | - }; | ||
| 688 | - // 添加执行动作 | ||
| 689 | - const addAction = () => { | ||
| 690 | - unref(actionData).push(Date.now()); | ||
| 691 | - nextTick(() => { | ||
| 692 | - setFields(skipUnwrap.actionItemRefs); | ||
| 693 | - }); | ||
| 694 | - isEmptyThrowError(getFieldsValue()); | ||
| 695 | - }; | ||
| 696 | - | ||
| 697 | - /** | ||
| 698 | - * 获取触发器、执行条件、执行动作表单值--多个 | ||
| 699 | - */ | ||
| 700 | - const getFormValueFunc = () => { | ||
| 701 | - getTriggerFormValue.value = unref(skipUnwrap.triggerItemRefs)?.map((item) => | ||
| 702 | - genTriggerOrConditionData(item.getFieldsValueFunc()) | ||
| 703 | - ); | ||
| 704 | - getConditionFormValue.value = unref(skipUnwrap.conditionItemRefs)?.map((item) => | ||
| 705 | - genTriggerOrConditionData(item.getFieldsValueFunc()) | ||
| 706 | - ); | ||
| 707 | - getActionFormValue.value = unref(skipUnwrap.actionItemRefs)?.map((item) => | ||
| 708 | - genActionData(item.getFieldsValueFunc()) | ||
| 709 | - ); | ||
| 710 | - }; | ||
| 711 | - const handleSubmit = async () => { | ||
| 712 | - let basicFormValue = await validate(); | ||
| 713 | - if (!basicFormValue) return; | ||
| 714 | - for (const item of unref(skipUnwrap.actionItemRefs)) { | ||
| 715 | - const valid = await item.validateForm(); | ||
| 716 | - if (!valid) return; | ||
| 717 | - } | ||
| 718 | - try { | ||
| 719 | - setDrawerProps({ confirmLoading: true }); | ||
| 720 | - getFormValueFunc(); | ||
| 721 | - //新增的代码2022-11-22 | ||
| 722 | - if (unref(getTriggerFormValue).length === 0 && unref(getConditionFormValue).length === 0) { | ||
| 723 | - createMessage.error('请添加触发器或者执行条件'); | ||
| 724 | - throw '请添加触发器或者执行条件'; | ||
| 725 | - } | ||
| 726 | - | ||
| 727 | - // return; | ||
| 728 | - //新增的代码2022-11-22 | ||
| 729 | - const postAddOrEditData = { | ||
| 730 | - ...basicFormValue, | ||
| 731 | - triggers: !unref(getTriggerFormValue).length ? null : unref(getTriggerFormValue), | ||
| 732 | - doConditions: !unref(getConditionFormValue).length ? null : unref(getConditionFormValue), | ||
| 733 | - doActions: unref(getActionFormValue).flat(), | ||
| 734 | - id: unref(id), | ||
| 735 | - tenantId: unref(tenantId), | ||
| 736 | - }; | ||
| 737 | - //FT change | ||
| 738 | - let mustTriggerCondition = false; | ||
| 739 | - let mustCondition = false; | ||
| 740 | - if (postAddOrEditData?.triggers !== null && postAddOrEditData?.triggers.length > 0) { | ||
| 741 | - postAddOrEditData?.triggers.some((s) => { | ||
| 742 | - if (s.triggerCondition?.condition?.condition == undefined) { | ||
| 743 | - mustTriggerCondition = true; | ||
| 744 | - } | ||
| 745 | - }); | ||
| 746 | - } else { | ||
| 747 | - mustTriggerCondition = false; | ||
| 748 | - } | ||
| 749 | - if (postAddOrEditData?.doConditions !== null && postAddOrEditData?.doConditions.length > 0) { | ||
| 750 | - postAddOrEditData?.doConditions.some((s) => { | ||
| 751 | - if (s.triggerCondition?.condition?.condition == undefined) { | ||
| 752 | - mustCondition = true; | ||
| 753 | - } | ||
| 754 | - }); | ||
| 755 | - } else { | ||
| 756 | - mustCondition = false; | ||
| 757 | - } | ||
| 758 | - if (mustTriggerCondition) return; | ||
| 759 | - if (mustCondition) return; | ||
| 760 | - //FT change | ||
| 761 | - await screenLinkPageAddApi(postAddOrEditData, unref(isUpdate)); | ||
| 762 | - createMessage.success(`${unref(isUpdate) ? '编辑' : '新增'}成功`); | ||
| 763 | - closeDrawer(); | ||
| 764 | - handleClose(); | ||
| 765 | - emit('success'); | ||
| 766 | - } finally { | ||
| 767 | - setDrawerProps({ confirmLoading: false }); | ||
| 768 | - } | ||
| 769 | - }; | ||
| 770 | - // 删除 | ||
| 771 | - const deleteTriggerOrCondition = ({ index, title }) => { | ||
| 772 | - if (title === '触发器') { | ||
| 773 | - unref(triggerData).splice(index, 1); | ||
| 774 | - } else if (title === '执行条件') { | ||
| 775 | - unref(conditionData).splice(index, 1); | ||
| 776 | - } | ||
| 777 | - }; | ||
| 778 | - const deleteAction = (actionIndex) => { | ||
| 779 | - unref(actionData).splice(actionIndex, 1); | ||
| 780 | - unref(arr).splice(actionIndex, 1); | ||
| 781 | - }; | ||
| 782 | - const arr = ref([]); | ||
| 783 | - const getActionFormArr = () => { | ||
| 784 | - arr.value = unref(skipUnwrap.actionItemRefs).map((item) => item.getFieldsValue()); | ||
| 785 | - }; | ||
| 786 | - const handleClose = () => { | ||
| 787 | - id.value = undefined; | ||
| 788 | - tenantId.value = undefined; | ||
| 789 | - organizationIdRef.value = undefined; | ||
| 790 | - isView.value = true; | ||
| 791 | - getTriggerFormValue.value = []; | ||
| 792 | - getConditionFormValue.value = []; | ||
| 793 | - getActionFormValue.value = []; | ||
| 794 | - triggerData.value = []; | ||
| 795 | - conditionData.value = []; | ||
| 796 | - actionData.value = []; | ||
| 797 | - unref(skipUnwrap.triggerItemRefs).map((item) => { | ||
| 798 | - item.resetFieldsValueFunc(); | ||
| 799 | - }); | ||
| 800 | - unref(skipUnwrap.conditionItemRefs).map((item) => { | ||
| 801 | - item.resetFieldsValueFunc(); | ||
| 802 | - }); | ||
| 803 | - unref(skipUnwrap.actionItemRefs).map((item) => { | ||
| 804 | - item.resetFieldsValueFunc(); | ||
| 805 | - }); | ||
| 806 | - window.localStorage.removeItem('isViewDisabledBtn'); | ||
| 807 | - // window.localStorage.setItem('isViewDisabledBtn', 'no') | ||
| 808 | - }; | ||
| 809 | -</script> | ||
| 810 | - | ||
| 811 | -<style lang="less" scoped> | ||
| 812 | - //TODO-fengtao | ||
| 813 | - ///移除选择框默认样式(24px)否则超出默认宽度会造成页面样式错乱 | ||
| 814 | - :deep(.ant-select-selector) { | ||
| 815 | - padding-right: 0 !important; | ||
| 816 | - } | ||
| 817 | - | ||
| 818 | - :deep(.ant-select-selection-overflow) { | ||
| 819 | - max-width: 10vw !important; | ||
| 820 | - } | ||
| 821 | - | ||
| 822 | - //TODO-fengtao | ||
| 823 | - | ||
| 824 | - label.validate-dot::before { | ||
| 825 | - display: inline-block; | ||
| 826 | - color: #ff4d4f; | ||
| 827 | - font-size: 14px; | ||
| 828 | - font-family: SimSun, sans-serif; | ||
| 829 | - line-height: 1; | ||
| 830 | - content: '*'; | ||
| 831 | - } | ||
| 832 | -</style> |
| 1 | +import { OperationType } from './type'; | ||
| 2 | +import { FormSchema } from '/@/components/Form'; | ||
| 3 | +import { | ||
| 4 | + BooleanOperationEnum, | ||
| 5 | + BooleanOperationNameEnum, | ||
| 6 | + BooleanOperationValueEnum, | ||
| 7 | + BooleanOperationValueNameEnum, | ||
| 8 | + NumberOperationEnum, | ||
| 9 | + NumberOperationNameEnum, | ||
| 10 | + StringOperationEnum, | ||
| 11 | + StringOperationNameEnum, | ||
| 12 | + TriggerValueTypeEnum, | ||
| 13 | +} from '/@/enums/linkedgeEnum'; | ||
| 14 | + | ||
| 15 | +export enum FormFieldsEnum { | ||
| 16 | + CONDITION_OPERATION = 'operation', | ||
| 17 | + CONDITION_VALUE = 'defaultValue', | ||
| 18 | + CONDITION_VALUE_IGNORE_CASE = 'ignoreCase', | ||
| 19 | +} | ||
| 20 | + | ||
| 21 | +export enum FormFieldsNameEnum { | ||
| 22 | + CONDITION_OPERATION = '执行操作', | ||
| 23 | + CONDITION_VALUE = '操作值', | ||
| 24 | + CONDITION_VALUE_IGNORE_CASE = '忽略大小写', | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +interface GetFormSchemasParamsType { | ||
| 28 | + triggerType: TriggerValueTypeEnum; | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +export interface ConditionFormRecordType { | ||
| 32 | + [FormFieldsEnum.CONDITION_OPERATION]: OperationType; | ||
| 33 | + [FormFieldsEnum.CONDITION_VALUE]: any; | ||
| 34 | + [FormFieldsEnum.CONDITION_VALUE_IGNORE_CASE]?: boolean; | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +export const getOperationMap = (type: TriggerValueTypeEnum) => { | ||
| 38 | + const keyMap = { | ||
| 39 | + [TriggerValueTypeEnum.NUMERIC]: { value: NumberOperationEnum, label: NumberOperationNameEnum }, | ||
| 40 | + [TriggerValueTypeEnum.BOOLEAN]: { | ||
| 41 | + value: BooleanOperationEnum, | ||
| 42 | + label: BooleanOperationNameEnum, | ||
| 43 | + }, | ||
| 44 | + [TriggerValueTypeEnum.STRING]: { value: StringOperationEnum, label: StringOperationNameEnum }, | ||
| 45 | + [TriggerValueTypeEnum.DATE_TIME]: { | ||
| 46 | + value: NumberOperationEnum, | ||
| 47 | + label: NumberOperationNameEnum, | ||
| 48 | + }, | ||
| 49 | + }; | ||
| 50 | + | ||
| 51 | + return keyMap[type]; | ||
| 52 | +}; | ||
| 53 | + | ||
| 54 | +const getOperation = (type: TriggerValueTypeEnum) => { | ||
| 55 | + const res = getOperationMap(type); | ||
| 56 | + | ||
| 57 | + const { label, value } = res; | ||
| 58 | + return Object.keys(value).map((value) => ({ label: label[value], value })); | ||
| 59 | +}; | ||
| 60 | + | ||
| 61 | +const getOperationValueFormSchemas = (triggerType: TriggerValueTypeEnum): FormSchema[] => { | ||
| 62 | + const getNumberSchemas = (): FormSchema[] => { | ||
| 63 | + return [ | ||
| 64 | + { | ||
| 65 | + field: FormFieldsEnum.CONDITION_VALUE, | ||
| 66 | + label: FormFieldsNameEnum.CONDITION_VALUE, | ||
| 67 | + component: 'InputNumber', | ||
| 68 | + required: true, | ||
| 69 | + componentProps: () => { | ||
| 70 | + return { | ||
| 71 | + placeholder: `请输入${FormFieldsNameEnum.CONDITION_VALUE}`, | ||
| 72 | + }; | ||
| 73 | + }, | ||
| 74 | + }, | ||
| 75 | + ]; | ||
| 76 | + }; | ||
| 77 | + | ||
| 78 | + const getBoolSchemas = (): FormSchema[] => { | ||
| 79 | + return [ | ||
| 80 | + { | ||
| 81 | + field: FormFieldsEnum.CONDITION_VALUE, | ||
| 82 | + label: FormFieldsNameEnum.CONDITION_VALUE, | ||
| 83 | + component: 'Select', | ||
| 84 | + required: true, | ||
| 85 | + componentProps: () => { | ||
| 86 | + return { | ||
| 87 | + options: [ | ||
| 88 | + { label: BooleanOperationValueNameEnum.TRUE, value: BooleanOperationValueEnum.TRUE }, | ||
| 89 | + { | ||
| 90 | + label: BooleanOperationValueNameEnum.FALSE, | ||
| 91 | + value: BooleanOperationValueEnum.FALSE, | ||
| 92 | + }, | ||
| 93 | + ], | ||
| 94 | + placeholder: `请输入${FormFieldsNameEnum.CONDITION_VALUE}`, | ||
| 95 | + }; | ||
| 96 | + }, | ||
| 97 | + }, | ||
| 98 | + ]; | ||
| 99 | + }; | ||
| 100 | + | ||
| 101 | + const getStringSchemas = (): FormSchema[] => { | ||
| 102 | + return [ | ||
| 103 | + { | ||
| 104 | + field: FormFieldsEnum.CONDITION_VALUE, | ||
| 105 | + label: FormFieldsNameEnum.CONDITION_VALUE, | ||
| 106 | + component: 'Input', | ||
| 107 | + required: true, | ||
| 108 | + componentProps: () => { | ||
| 109 | + return { | ||
| 110 | + placeholder: `请输入${FormFieldsNameEnum.CONDITION_VALUE}`, | ||
| 111 | + }; | ||
| 112 | + }, | ||
| 113 | + }, | ||
| 114 | + { | ||
| 115 | + field: FormFieldsEnum.CONDITION_VALUE_IGNORE_CASE, | ||
| 116 | + label: ' ', | ||
| 117 | + component: 'Checkbox', | ||
| 118 | + renderComponentContent: () => ({ | ||
| 119 | + default: () => FormFieldsNameEnum.CONDITION_VALUE_IGNORE_CASE, | ||
| 120 | + }), | ||
| 121 | + }, | ||
| 122 | + ]; | ||
| 123 | + }; | ||
| 124 | + | ||
| 125 | + const getDateSchemas = (): FormSchema[] => { | ||
| 126 | + return [ | ||
| 127 | + { | ||
| 128 | + field: FormFieldsEnum.CONDITION_VALUE, | ||
| 129 | + label: FormFieldsNameEnum.CONDITION_VALUE, | ||
| 130 | + component: 'DatePicker', | ||
| 131 | + required: true, | ||
| 132 | + componentProps: () => { | ||
| 133 | + return { | ||
| 134 | + showTime: true, | ||
| 135 | + placeholder: `请输入${FormFieldsNameEnum.CONDITION_VALUE}`, | ||
| 136 | + }; | ||
| 137 | + }, | ||
| 138 | + }, | ||
| 139 | + ]; | ||
| 140 | + }; | ||
| 141 | + | ||
| 142 | + const schemasMap = { | ||
| 143 | + [TriggerValueTypeEnum.BOOLEAN]: getBoolSchemas, | ||
| 144 | + [TriggerValueTypeEnum.DATE_TIME]: getDateSchemas, | ||
| 145 | + [TriggerValueTypeEnum.NUMERIC]: getNumberSchemas, | ||
| 146 | + [TriggerValueTypeEnum.STRING]: getStringSchemas, | ||
| 147 | + }; | ||
| 148 | + | ||
| 149 | + return schemasMap[triggerType]?.() || []; | ||
| 150 | +}; | ||
| 151 | + | ||
| 152 | +export const getFormSchemas = ({ triggerType }: GetFormSchemasParamsType): FormSchema[] => { | ||
| 153 | + return [ | ||
| 154 | + { | ||
| 155 | + field: FormFieldsEnum.CONDITION_OPERATION, | ||
| 156 | + label: FormFieldsNameEnum.CONDITION_OPERATION, | ||
| 157 | + component: 'Select', | ||
| 158 | + required: true, | ||
| 159 | + componentProps: () => { | ||
| 160 | + return { | ||
| 161 | + options: getOperation(triggerType), | ||
| 162 | + placeholder: `请选择${FormFieldsNameEnum.CONDITION_OPERATION}`, | ||
| 163 | + }; | ||
| 164 | + }, | ||
| 165 | + }, | ||
| 166 | + ...getOperationValueFormSchemas(triggerType), | ||
| 167 | + ]; | ||
| 168 | +}; |
| 1 | +import { ConditionListItemType } from './type'; | ||
| 2 | +import { buildUUID } from '/@/utils/uuid'; | ||
| 3 | + | ||
| 4 | +export { default as ConditionFilter } from './index.vue'; | ||
| 5 | + | ||
| 6 | +export function getNewConditionFilterItem(value?: Recordable): ConditionListItemType { | ||
| 7 | + return { | ||
| 8 | + key: buildUUID(), | ||
| 9 | + value, | ||
| 10 | + }; | ||
| 11 | +} |
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { ComponentPublicInstance, computed, ref, unref, watch } from 'vue'; | ||
| 3 | + import { Card, Tag, Button } from 'ant-design-vue'; | ||
| 4 | + import { Icon } from '/@/components/Icon'; | ||
| 5 | + import { getFormSchemas, FormFieldsEnum } from './config'; | ||
| 6 | + import { CollapseContainer } from '/@/components/Container'; | ||
| 7 | + import { BasicForm, FormActionType } from '/@/components/Form'; | ||
| 8 | + import { TriggerValueTypeEnum } from '/@/enums/linkedgeEnum'; | ||
| 9 | + import { ConditionFilterProps, ConditionListItemType } from './type'; | ||
| 10 | + import { ConditionMessageItemType, useConditionFilterMessage } from './useConditionFilterMessage'; | ||
| 11 | + import { useConditionData } from './useConditionData'; | ||
| 12 | + import { getNewConditionFilterItem } from '.'; | ||
| 13 | + import { useSceneLinkageDrawerContext } from '../SceneLinkageDrawer/sceneLinkageDrawerContext'; | ||
| 14 | + | ||
| 15 | + const { disabledDrawer } = useSceneLinkageDrawerContext(); | ||
| 16 | + | ||
| 17 | + const props = withDefaults(defineProps<ConditionFilterProps>(), { | ||
| 18 | + triggerType: TriggerValueTypeEnum.BOOLEAN, | ||
| 19 | + }); | ||
| 20 | + | ||
| 21 | + const getSchemas = computed(() => { | ||
| 22 | + const { triggerType } = props; | ||
| 23 | + return getFormSchemas({ triggerType }); | ||
| 24 | + }); | ||
| 25 | + | ||
| 26 | + const conditionListElRef = ref<ConditionListItemType[]>([getNewConditionFilterItem()]); | ||
| 27 | + | ||
| 28 | + const getConditionFormValues = (): Record<FormFieldsEnum, string>[] => { | ||
| 29 | + return unref(conditionListElRef).map( | ||
| 30 | + (conditionForm) => conditionForm.ref?.getFieldsValue() as Record<FormFieldsEnum, string> | ||
| 31 | + ); | ||
| 32 | + }; | ||
| 33 | + | ||
| 34 | + const conditionMessageList = ref<ConditionMessageItemType[]>([]); | ||
| 35 | + | ||
| 36 | + const handleConditionFormValueChange = () => { | ||
| 37 | + const condition = getConditionFormValues(); | ||
| 38 | + const { triggerType } = props; | ||
| 39 | + const message = useConditionFilterMessage({ triggerType, condition }); | ||
| 40 | + conditionMessageList.value = message; | ||
| 41 | + }; | ||
| 42 | + | ||
| 43 | + const setConditionRef = ( | ||
| 44 | + conditionItem: ConditionListItemType, | ||
| 45 | + el: Element | ComponentPublicInstance | null | ||
| 46 | + ) => { | ||
| 47 | + conditionItem.ref = el as unknown as FormActionType; | ||
| 48 | + }; | ||
| 49 | + | ||
| 50 | + const handleDelete = (conditionItem: ConditionListItemType) => { | ||
| 51 | + const { key } = conditionItem; | ||
| 52 | + | ||
| 53 | + const index = unref(conditionListElRef).findIndex((item) => item.key === key); | ||
| 54 | + | ||
| 55 | + ~index && unref(conditionListElRef).splice(index, 1); | ||
| 56 | + }; | ||
| 57 | + | ||
| 58 | + const handleAdd = () => { | ||
| 59 | + conditionListElRef.value.push(getNewConditionFilterItem()); | ||
| 60 | + }; | ||
| 61 | + | ||
| 62 | + watch( | ||
| 63 | + () => props.triggerType, | ||
| 64 | + () => { | ||
| 65 | + conditionListElRef.value = [getNewConditionFilterItem()]; | ||
| 66 | + conditionMessageList.value = []; | ||
| 67 | + } | ||
| 68 | + ); | ||
| 69 | + | ||
| 70 | + const { getFieldsValue, setFieldsValue, validate } = useConditionData( | ||
| 71 | + props, | ||
| 72 | + conditionListElRef, | ||
| 73 | + handleConditionFormValueChange | ||
| 74 | + ); | ||
| 75 | + | ||
| 76 | + const handelValidate = async () => { | ||
| 77 | + await validate?.(); | ||
| 78 | + }; | ||
| 79 | + | ||
| 80 | + defineExpose({ getFieldsValue, setFieldsValue, validate }); | ||
| 81 | +</script> | ||
| 82 | + | ||
| 83 | +<template> | ||
| 84 | + <Card class="condition-filter-card !border-dashed !border-2 !border-gray-200 !rounded-lg"> | ||
| 85 | + <CollapseContainer class="rounded-lg" :is-close="!disabledDrawer"> | ||
| 86 | + <template #title> | ||
| 87 | + <section class="flex !p-2"> | ||
| 88 | + <div class="w-20 flex-grow-0 flex-shrink-0"> 条件筛选 </div> | ||
| 89 | + <div class="flex flex-wrap"> | ||
| 90 | + <template v-for="(item, index) in conditionMessageList" :key="index"> | ||
| 91 | + <Tag class="!rounded-md !m-0 !text-sky-700"> {{ objectModel?.name }} </Tag> | ||
| 92 | + <span class="mx-2">{{ item.operation }}</span> | ||
| 93 | + <Tag class="!rounded-md !m-0 !text-orange-300"> | ||
| 94 | + {{ item.defaultValue }} | ||
| 95 | + </Tag> | ||
| 96 | + <span class="mx-2" v-if="conditionMessageList.length - 1 !== index">和</span> | ||
| 97 | + </template> | ||
| 98 | + </div> | ||
| 99 | + </section> | ||
| 100 | + </template> | ||
| 101 | + <!-- --> | ||
| 102 | + <main | ||
| 103 | + class="flex gap-4 items-center mb-2" | ||
| 104 | + v-for="(conditionItem, index) in conditionListElRef" | ||
| 105 | + :key="conditionItem.key" | ||
| 106 | + > | ||
| 107 | + <section class="border-2 border-dashed border-gray-200 rounded-lg px-4 py-2 flex-1"> | ||
| 108 | + <!-- --> | ||
| 109 | + <BasicForm | ||
| 110 | + :ref="(el) => setConditionRef(conditionItem, el)" | ||
| 111 | + :show-action-button-group="false" | ||
| 112 | + layout="horizontal" | ||
| 113 | + :disabled="disabledDrawer" | ||
| 114 | + :label-width="80" | ||
| 115 | + :schemas="getSchemas" | ||
| 116 | + :base-col-props="{ span: 24 / getSchemas.length, xl: 8, lg: 12, sm: 24 }" | ||
| 117 | + @field-value-change="handleConditionFormValueChange" | ||
| 118 | + /> | ||
| 119 | + </section> | ||
| 120 | + <span | ||
| 121 | + class="w-5" | ||
| 122 | + :style="{ visibility: conditionListElRef.length - 1 !== index ? 'visible' : 'hidden' }" | ||
| 123 | + > | ||
| 124 | + 和 | ||
| 125 | + </span> | ||
| 126 | + <Icon | ||
| 127 | + v-if="!disabledDrawer" | ||
| 128 | + icon="fluent:delete-off-20-regular" | ||
| 129 | + size="24" | ||
| 130 | + class="cursor-pointer" | ||
| 131 | + @click="handleDelete(conditionItem)" | ||
| 132 | + /> | ||
| 133 | + </main> | ||
| 134 | + <section class="flex mt-4 items-center justify-between"> | ||
| 135 | + <Button v-if="!disabledDrawer" type="primary" @click="handleAdd"> | ||
| 136 | + <Icon icon="ant-design:plus-outlined" /> | ||
| 137 | + 新增条件筛选 | ||
| 138 | + </Button> | ||
| 139 | + <Button v-if="!disabledDrawer" type="primary" @click="handelValidate">添加</Button> | ||
| 140 | + </section> | ||
| 141 | + </CollapseContainer> | ||
| 142 | + </Card> | ||
| 143 | +</template> | ||
| 144 | + | ||
| 145 | +<style lang="less" scoped> | ||
| 146 | + .condition-filter-card { | ||
| 147 | + :deep(.ant-card-body) { | ||
| 148 | + @apply p-3; | ||
| 149 | + | ||
| 150 | + .vben-collapse-container__header { | ||
| 151 | + height: fit-content; | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + .ant-calendar-picker { | ||
| 155 | + min-width: auto !important; | ||
| 156 | + width: 100%; | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + .ant-input-number { | ||
| 160 | + min-width: auto !important; | ||
| 161 | + } | ||
| 162 | + } | ||
| 163 | + } | ||
| 164 | +</style> | ||
| 165 | +./type |
| 1 | +import { ScheduleType } from '../EnablingRule/type'; | ||
| 2 | +import { DeviceModelOfMatterAttrs } from '/@/api/device/model/deviceModel'; | ||
| 3 | +import { FormActionType } from '/@/components/Form'; | ||
| 4 | +import { | ||
| 5 | + BooleanOperationEnum, | ||
| 6 | + DeviceTriggerTypeEum, | ||
| 7 | + FlipFlopTypeEnum, | ||
| 8 | + NumberOperationEnum, | ||
| 9 | + StringOperationNameEnum, | ||
| 10 | + TriggerTypeEnum, | ||
| 11 | + TriggerValueTypeEnum, | ||
| 12 | +} from '/@/enums/linkedgeEnum'; | ||
| 13 | + | ||
| 14 | +export interface ConditionListItemType { | ||
| 15 | + key: string; | ||
| 16 | + value?: Recordable; | ||
| 17 | + ref?: FormActionType; | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +export interface ConditionFilterProps { | ||
| 21 | + triggerType?: TriggerValueTypeEnum; | ||
| 22 | + objectModel?: DeviceModelOfMatterAttrs; | ||
| 23 | + conditionType?: DeviceTriggerTypeEum; | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +export interface TriggerCondition { | ||
| 27 | + condition: ConditionType; | ||
| 28 | + alarmDetails?: Nullable<any>; | ||
| 29 | + dashboardId?: Nullable<any>; | ||
| 30 | + schedule: ScheduleType; | ||
| 31 | + triggerType?: TriggerTypeEnum; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +export interface ConditionType { | ||
| 35 | + condition: ConditionItemType[]; | ||
| 36 | + spec: { type: FlipFlopTypeEnum; unit?: string; predicate?: { defaultValue: any } }; | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +export type OperationType = NumberOperationEnum | StringOperationNameEnum | BooleanOperationEnum; | ||
| 40 | + | ||
| 41 | +export interface ConditionItemType { | ||
| 42 | + key: { type: DeviceTriggerTypeEum; key: string }; | ||
| 43 | + predicate: { | ||
| 44 | + type: TriggerValueTypeEnum; | ||
| 45 | + operation: OperationType; | ||
| 46 | + ignoreCase?: boolean; | ||
| 47 | + value: { | ||
| 48 | + defaultValue: number | string | boolean; | ||
| 49 | + userValue?: Nullable<number | string | boolean>; | ||
| 50 | + dynamicValue?: Nullable<number | string | boolean>; | ||
| 51 | + }; | ||
| 52 | + }; | ||
| 53 | + valueType: TriggerValueTypeEnum; | ||
| 54 | + value?: Nullable<any>; | ||
| 55 | +} |
| 1 | +import { Ref, nextTick, unref } from 'vue'; | ||
| 2 | +import { ConditionFilterProps, ConditionItemType, ConditionListItemType } from './type'; | ||
| 3 | +import { DefineComponentsBasicExpose } from '/#/utils'; | ||
| 4 | +import { DeviceTriggerTypeEum, TriggerValueTypeEnum } from '/@/enums/linkedgeEnum'; | ||
| 5 | +import { ConditionFormRecordType, FormFieldsEnum } from './config'; | ||
| 6 | +import { getNewConditionFilterItem } from '.'; | ||
| 7 | +import { dateUtil } from '/@/utils/dateUtil'; | ||
| 8 | + | ||
| 9 | +function getPredicateType(triggerType: TriggerValueTypeEnum) { | ||
| 10 | + const map = { | ||
| 11 | + [TriggerValueTypeEnum.BOOLEAN]: TriggerValueTypeEnum.BOOLEAN, | ||
| 12 | + [TriggerValueTypeEnum.STRING]: TriggerValueTypeEnum.STRING, | ||
| 13 | + [TriggerValueTypeEnum.NUMERIC]: TriggerValueTypeEnum.NUMERIC, | ||
| 14 | + [TriggerValueTypeEnum.DATE_TIME]: TriggerValueTypeEnum.NUMERIC, | ||
| 15 | + }; | ||
| 16 | + | ||
| 17 | + return map[triggerType]; | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +export function useConditionData( | ||
| 21 | + props: ConditionFilterProps, | ||
| 22 | + conditionItemRef: Ref<ConditionListItemType[]>, | ||
| 23 | + handleConditionFormValueChange: Fn | ||
| 24 | +): DefineComponentsBasicExpose<ConditionItemType[]> { | ||
| 25 | + const createConditionItem = ({ | ||
| 26 | + operation, | ||
| 27 | + defaultValue, | ||
| 28 | + ignoreCase, | ||
| 29 | + }: ConditionFormRecordType): ConditionItemType => { | ||
| 30 | + const { triggerType, objectModel } = props; | ||
| 31 | + const { identifier } = objectModel || {}; | ||
| 32 | + return { | ||
| 33 | + key: { key: identifier!, type: DeviceTriggerTypeEum.TIME_SERIES }, | ||
| 34 | + predicate: { | ||
| 35 | + ...(ignoreCase ? { ignoreCase } : {}), | ||
| 36 | + operation, | ||
| 37 | + type: getPredicateType(triggerType!), | ||
| 38 | + value: { | ||
| 39 | + defaultValue: | ||
| 40 | + triggerType === TriggerValueTypeEnum.DATE_TIME | ||
| 41 | + ? Number(dateUtil(defaultValue).format('x')) | ||
| 42 | + : defaultValue, | ||
| 43 | + }, | ||
| 44 | + }, | ||
| 45 | + valueType: triggerType!, | ||
| 46 | + }; | ||
| 47 | + }; | ||
| 48 | + | ||
| 49 | + const getFieldsValue = (): ConditionItemType[] => { | ||
| 50 | + return unref(conditionItemRef).map((conditionItem) => { | ||
| 51 | + const value = conditionItem.ref?.getFieldsValue() as ConditionFormRecordType; | ||
| 52 | + return createConditionItem(value); | ||
| 53 | + }); | ||
| 54 | + }; | ||
| 55 | + | ||
| 56 | + const setFieldsValue = (condition: ConditionItemType[]) => { | ||
| 57 | + conditionItemRef.value = Array.from({ length: condition.length }, () => | ||
| 58 | + getNewConditionFilterItem() | ||
| 59 | + ); | ||
| 60 | + | ||
| 61 | + nextTick(() => { | ||
| 62 | + unref(conditionItemRef).forEach((conditionItem, index) => { | ||
| 63 | + const result = condition[index] || {}; | ||
| 64 | + | ||
| 65 | + const { operation, value, ignoreCase, type } = result.predicate || {}; | ||
| 66 | + | ||
| 67 | + conditionItem.ref?.setFieldsValue({ | ||
| 68 | + [FormFieldsEnum.CONDITION_OPERATION]: operation, | ||
| 69 | + [FormFieldsEnum.CONDITION_VALUE]: | ||
| 70 | + type === TriggerValueTypeEnum.BOOLEAN | ||
| 71 | + ? value.defaultValue.toString() | ||
| 72 | + : value.defaultValue, | ||
| 73 | + [FormFieldsEnum.CONDITION_VALUE_IGNORE_CASE]: ignoreCase, | ||
| 74 | + }); | ||
| 75 | + }); | ||
| 76 | + handleConditionFormValueChange(); | ||
| 77 | + }); | ||
| 78 | + }; | ||
| 79 | + | ||
| 80 | + const validate = async () => { | ||
| 81 | + for (const conditionItem of unref(conditionItemRef)) { | ||
| 82 | + await conditionItem.ref?.validate(); | ||
| 83 | + } | ||
| 84 | + }; | ||
| 85 | + return { | ||
| 86 | + getFieldsValue, | ||
| 87 | + setFieldsValue, | ||
| 88 | + validate, | ||
| 89 | + }; | ||
| 90 | +} |
| 1 | +import { FormFieldsEnum, getOperationMap } from './config'; | ||
| 2 | +import { | ||
| 3 | + BooleanOperationValueEnum, | ||
| 4 | + BooleanOperationValueNameEnum, | ||
| 5 | + TriggerValueTypeEnum, | ||
| 6 | +} from '/@/enums/linkedgeEnum'; | ||
| 7 | + | ||
| 8 | +export type ConditionMessageItemType = Record< | ||
| 9 | + Exclude<FormFieldsEnum, FormFieldsEnum.CONDITION_VALUE_IGNORE_CASE>, | ||
| 10 | + string | ||
| 11 | +>; | ||
| 12 | + | ||
| 13 | +interface UseConditionFilterMessageParamsType { | ||
| 14 | + triggerType: TriggerValueTypeEnum; | ||
| 15 | + condition: ConditionMessageItemType[]; | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +export function useConditionFilterMessage({ | ||
| 19 | + triggerType, | ||
| 20 | + condition, | ||
| 21 | +}: UseConditionFilterMessageParamsType) { | ||
| 22 | + const { label } = getOperationMap(triggerType); | ||
| 23 | + const list: ConditionMessageItemType[] = []; | ||
| 24 | + for (const item of condition) { | ||
| 25 | + let { defaultValue, operation } = item; | ||
| 26 | + if (!defaultValue || !operation) continue; | ||
| 27 | + operation = label[operation]; | ||
| 28 | + if (triggerType === TriggerValueTypeEnum.BOOLEAN) | ||
| 29 | + defaultValue = | ||
| 30 | + defaultValue === BooleanOperationValueEnum.TRUE | ||
| 31 | + ? BooleanOperationValueNameEnum.TRUE | ||
| 32 | + : BooleanOperationValueNameEnum.FALSE; | ||
| 33 | + list.push({ operation, defaultValue }); | ||
| 34 | + } | ||
| 35 | + return list; | ||
| 36 | +} |
| 1 | +import TimeRangePicker from './TimeRangePicker.vue'; | ||
| 2 | +import { WeekName } from './config'; | ||
| 3 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | ||
| 4 | + | ||
| 5 | +enum FormFieldsEnum { | ||
| 6 | + DAY_OF_WEEK = 'dayOfWeek', | ||
| 7 | + ENABLED = 'enabled', | ||
| 8 | + ENDS_ON = 'endsOn', | ||
| 9 | + STARTS_ON = 'startsOn', | ||
| 10 | + TIME_RANGE = 'timeRange', | ||
| 11 | +} | ||
| 12 | + | ||
| 13 | +export interface RuleFormRecordItem { | ||
| 14 | + [FormFieldsEnum.DAY_OF_WEEK]: number; | ||
| 15 | + [FormFieldsEnum.ENABLED]: boolean; | ||
| 16 | + [FormFieldsEnum.TIME_RANGE]: { | ||
| 17 | + [FormFieldsEnum.STARTS_ON]: number; | ||
| 18 | + [FormFieldsEnum.ENDS_ON]: number; | ||
| 19 | + }; | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +useComponentRegister('TimeRangePicker', TimeRangePicker); | ||
| 23 | + | ||
| 24 | +export const getFormSchemas = (index: number): FormSchema[] => { | ||
| 25 | + return [ | ||
| 26 | + { | ||
| 27 | + field: FormFieldsEnum.DAY_OF_WEEK, | ||
| 28 | + label: '', | ||
| 29 | + component: 'InputNumber', | ||
| 30 | + defaultValue: index + 1, | ||
| 31 | + ifShow: false, | ||
| 32 | + }, | ||
| 33 | + { | ||
| 34 | + field: FormFieldsEnum.ENABLED, | ||
| 35 | + label: '', | ||
| 36 | + component: 'Checkbox', | ||
| 37 | + defaultValue: false, | ||
| 38 | + renderComponentContent: () => ({ | ||
| 39 | + default: () => `星期${WeekName[index]}`, | ||
| 40 | + }), | ||
| 41 | + colProps: { span: 5 }, | ||
| 42 | + }, | ||
| 43 | + { | ||
| 44 | + field: FormFieldsEnum.TIME_RANGE, | ||
| 45 | + label: '', | ||
| 46 | + changeEvent: 'update:value', | ||
| 47 | + valueField: 'value', | ||
| 48 | + component: 'TimeRangePicker', | ||
| 49 | + dynamicDisabled: ({ model }) => !model[FormFieldsEnum.ENABLED], | ||
| 50 | + colProps: { span: 16 }, | ||
| 51 | + defaultValue: { startsOn: 0, endsOn: 0 }, | ||
| 52 | + dynamicRules: ({ model }) => { | ||
| 53 | + return [ | ||
| 54 | + { | ||
| 55 | + required: model[FormFieldsEnum.ENABLED], | ||
| 56 | + validator(_rule, value: Record<'startsOn' | 'endsOn', number>, _callback) { | ||
| 57 | + if (!model[FormFieldsEnum.ENABLED]) return Promise.resolve(); | ||
| 58 | + if (!value?.endsOn) return Promise.reject('请选择结束时间'); | ||
| 59 | + if (!value?.startsOn) return Promise.reject('请选择开始时间'); | ||
| 60 | + return Promise.resolve(); | ||
| 61 | + }, | ||
| 62 | + }, | ||
| 63 | + ]; | ||
| 64 | + }, | ||
| 65 | + }, | ||
| 66 | + ]; | ||
| 67 | +}; |
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { CustomRuleItemType } from './type'; | ||
| 3 | + import { ComponentPublicInstance, nextTick, ref, unref, watch } from 'vue'; | ||
| 4 | + import { BasicForm, FormActionType } from '/@/components/Form'; | ||
| 5 | + import { getFormSchemas, RuleFormRecordItem } from './CustomRule.config'; | ||
| 6 | + import { buildUUID } from '/@/utils/uuid'; | ||
| 7 | + import { DefineComponentsBasicExpose } from '/#/utils'; | ||
| 8 | + | ||
| 9 | + interface CustomRuleItemRefType { | ||
| 10 | + key: string; | ||
| 11 | + ref?: FormActionType; | ||
| 12 | + value?: CustomRuleItemType; | ||
| 13 | + } | ||
| 14 | + | ||
| 15 | + const props = withDefaults( | ||
| 16 | + defineProps<{ | ||
| 17 | + value?: CustomRuleItemType[]; | ||
| 18 | + }>(), | ||
| 19 | + { | ||
| 20 | + value: () => [], | ||
| 21 | + } | ||
| 22 | + ); | ||
| 23 | + | ||
| 24 | + const customRuleListRef = ref<CustomRuleItemRefType[]>( | ||
| 25 | + Array.from({ length: 7 }, () => ({ key: buildUUID() })) | ||
| 26 | + ); | ||
| 27 | + | ||
| 28 | + const setRuleItemRef = ( | ||
| 29 | + el: Nullable<Element | ComponentPublicInstance>, | ||
| 30 | + ruleItem: CustomRuleItemRefType | ||
| 31 | + ) => { | ||
| 32 | + ruleItem.ref = el as unknown as FormActionType; | ||
| 33 | + }; | ||
| 34 | + | ||
| 35 | + const validate = async () => { | ||
| 36 | + for (const item of unref(customRuleListRef)) { | ||
| 37 | + await item.ref?.validate?.(); | ||
| 38 | + } | ||
| 39 | + }; | ||
| 40 | + | ||
| 41 | + const getFieldsValue = (): CustomRuleItemType[] => { | ||
| 42 | + return unref(customRuleListRef).map((item) => { | ||
| 43 | + const { dayOfWeek, enabled, timeRange } = item.ref?.getFieldsValue() as RuleFormRecordItem; | ||
| 44 | + return { | ||
| 45 | + dayOfWeek, | ||
| 46 | + enabled, | ||
| 47 | + ...timeRange, | ||
| 48 | + }; | ||
| 49 | + }); | ||
| 50 | + }; | ||
| 51 | + | ||
| 52 | + const setFieldsValue = async (ruleList: CustomRuleItemType[]) => { | ||
| 53 | + if (!ruleList.length) return; | ||
| 54 | + await nextTick(); | ||
| 55 | + | ||
| 56 | + ruleList.forEach((value, index) => { | ||
| 57 | + const refEl = unref(customRuleListRef)[index]; | ||
| 58 | + refEl.ref?.setFieldsValue({ | ||
| 59 | + ...value, | ||
| 60 | + timeRange: { | ||
| 61 | + startsOn: value.startsOn, | ||
| 62 | + endsOn: value.endsOn, | ||
| 63 | + }, | ||
| 64 | + } as RuleFormRecordItem); | ||
| 65 | + }); | ||
| 66 | + }; | ||
| 67 | + | ||
| 68 | + watch( | ||
| 69 | + () => props.value, | ||
| 70 | + () => { | ||
| 71 | + setFieldsValue(props.value); | ||
| 72 | + }, | ||
| 73 | + { immediate: true } | ||
| 74 | + ); | ||
| 75 | + | ||
| 76 | + defineExpose<DefineComponentsBasicExpose<CustomRuleItemType[]>>({ | ||
| 77 | + getFieldsValue, | ||
| 78 | + setFieldsValue, | ||
| 79 | + validate, | ||
| 80 | + }); | ||
| 81 | +</script> | ||
| 82 | + | ||
| 83 | +<template> | ||
| 84 | + <section> | ||
| 85 | + <template v-for="(item, index) in customRuleListRef" :key="index"> | ||
| 86 | + <BasicForm | ||
| 87 | + :ref="(el) => setRuleItemRef(el, item)" | ||
| 88 | + :show-action-button-group="false" | ||
| 89 | + :schemas="getFormSchemas(index)" | ||
| 90 | + class="h-14" | ||
| 91 | + /> | ||
| 92 | + </template> | ||
| 93 | + </section> | ||
| 94 | +</template> |
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { TimePicker } from 'ant-design-vue'; | ||
| 3 | + import { Moment } from 'moment'; | ||
| 4 | + import { computed, unref } from 'vue'; | ||
| 5 | + import { dateUtil } from '/@/utils/dateUtil'; | ||
| 6 | + | ||
| 7 | + interface TimeRangePickerProps { | ||
| 8 | + timestampToNumber?: boolean; | ||
| 9 | + value?: Record<string, number>; | ||
| 10 | + startValue?: number; | ||
| 11 | + endValue?: number; | ||
| 12 | + startField?: string; | ||
| 13 | + endField?: string; | ||
| 14 | + disabled?: boolean; | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + enum TimePickerTypeEnum { | ||
| 18 | + START = 'START', | ||
| 19 | + END = 'END', | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + const emit = defineEmits(['update:value', 'update:startValue', 'update:endValue', 'change']); | ||
| 23 | + | ||
| 24 | + const props = withDefaults(defineProps<TimeRangePickerProps>(), { | ||
| 25 | + value: () => ({}), | ||
| 26 | + startField: 'startsOn', | ||
| 27 | + endField: 'endsOn', | ||
| 28 | + }); | ||
| 29 | + | ||
| 30 | + const getTimeMoment = (value: number) => { | ||
| 31 | + value = value / 1000; | ||
| 32 | + const hour = Math.floor(value / 60 / 60); | ||
| 33 | + const minute = Math.floor((value - hour * 60 * 60) / 60); | ||
| 34 | + const second = value - hour * 60 * 60 - minute * 60; | ||
| 35 | + | ||
| 36 | + return dateUtil({ hour, minute, second }); | ||
| 37 | + }; | ||
| 38 | + | ||
| 39 | + const getRangeValue = computed(() => { | ||
| 40 | + const { value, startValue, endValue, startField, endField } = props; | ||
| 41 | + | ||
| 42 | + let startTs = startValue || value[startField]; | ||
| 43 | + | ||
| 44 | + let endTs = endValue || value[endField]; | ||
| 45 | + | ||
| 46 | + return { | ||
| 47 | + startTs: startTs ? getTimeMoment(startTs) : null, | ||
| 48 | + endTs: endTs ? getTimeMoment(endTs) : null, | ||
| 49 | + }; | ||
| 50 | + }); | ||
| 51 | + | ||
| 52 | + const getTimestamp = (moment: Moment | null) => { | ||
| 53 | + if (!moment) return null; | ||
| 54 | + const { hours, minutes, seconds } = moment.toObject(); | ||
| 55 | + return (hours * 60 * 60 + minutes * 60 + seconds) * 1000; | ||
| 56 | + }; | ||
| 57 | + | ||
| 58 | + const handleTimeChange = (time: Moment, type: TimePickerTypeEnum) => { | ||
| 59 | + const { value, startField, endField } = props; | ||
| 60 | + const { startTs, endTs } = unref(getRangeValue); | ||
| 61 | + | ||
| 62 | + const rangeValue = { | ||
| 63 | + [startField]: getTimestamp(startTs), | ||
| 64 | + [endField]: getTimestamp(endTs), | ||
| 65 | + }; | ||
| 66 | + | ||
| 67 | + Reflect.set( | ||
| 68 | + rangeValue, | ||
| 69 | + type === TimePickerTypeEnum.START ? startField : endField, | ||
| 70 | + getTimestamp(time) | ||
| 71 | + ); | ||
| 72 | + | ||
| 73 | + if ( | ||
| 74 | + rangeValue[startField] && | ||
| 75 | + rangeValue[endField] && | ||
| 76 | + rangeValue[startField]! > rangeValue[endField]! | ||
| 77 | + ) { | ||
| 78 | + Reflect.set(rangeValue, type === TimePickerTypeEnum.START ? startField : endField, null); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + emit('update:startValue', rangeValue[startField]); | ||
| 82 | + emit('update:endValue', rangeValue[endField]); | ||
| 83 | + emit('update:value', rangeValue); | ||
| 84 | + emit('change', value); | ||
| 85 | + }; | ||
| 86 | + | ||
| 87 | + const handleBasicDisabledHours = (type: TimePickerTypeEnum) => { | ||
| 88 | + return () => { | ||
| 89 | + const { startTs, endTs } = unref(getRangeValue); | ||
| 90 | + | ||
| 91 | + if (type === TimePickerTypeEnum.START && !endTs) return []; | ||
| 92 | + if (type === TimePickerTypeEnum.END && !startTs) return []; | ||
| 93 | + | ||
| 94 | + const selectedHour = type === TimePickerTypeEnum.END ? startTs!.hour() : endTs!.hour(); | ||
| 95 | + | ||
| 96 | + return type === TimePickerTypeEnum.START | ||
| 97 | + ? Array.from({ length: 24 - selectedHour }, (_, index) => selectedHour + index + 1) | ||
| 98 | + : Array.from({ length: selectedHour }, (_, index) => index); | ||
| 99 | + }; | ||
| 100 | + }; | ||
| 101 | + | ||
| 102 | + const handleBasicDisabledMinutes = (type: TimePickerTypeEnum) => { | ||
| 103 | + return (currentSelectedHour: number) => { | ||
| 104 | + const { startTs, endTs } = unref(getRangeValue); | ||
| 105 | + | ||
| 106 | + if (type === TimePickerTypeEnum.START && !endTs) return []; | ||
| 107 | + if (type === TimePickerTypeEnum.END && !startTs) return []; | ||
| 108 | + | ||
| 109 | + const selectedTime = type === TimePickerTypeEnum.END ? startTs : endTs; | ||
| 110 | + const selectedHour = selectedTime!.hour(); | ||
| 111 | + const selectedMinute = selectedTime!.minute(); | ||
| 112 | + | ||
| 113 | + if (type == TimePickerTypeEnum.START) { | ||
| 114 | + return selectedHour > currentSelectedHour | ||
| 115 | + ? [] | ||
| 116 | + : Array.from({ length: 60 - selectedMinute }, (_, index) => selectedMinute + index + 1); | ||
| 117 | + } else { | ||
| 118 | + return selectedHour < currentSelectedHour | ||
| 119 | + ? [] | ||
| 120 | + : Array.from({ length: selectedMinute }, (_, index) => index); | ||
| 121 | + } | ||
| 122 | + }; | ||
| 123 | + }; | ||
| 124 | + | ||
| 125 | + const handleBasicDisabledSeconds = (type: TimePickerTypeEnum) => { | ||
| 126 | + return (currentSelectedHour: number, currentSelectedMinute: number) => { | ||
| 127 | + const { startTs, endTs } = unref(getRangeValue); | ||
| 128 | + | ||
| 129 | + if (type === TimePickerTypeEnum.START && !endTs) return []; | ||
| 130 | + if (type === TimePickerTypeEnum.END && !startTs) return []; | ||
| 131 | + | ||
| 132 | + const selectedTime = type === TimePickerTypeEnum.END ? startTs : endTs; | ||
| 133 | + const selectedHour = selectedTime!.hour(); | ||
| 134 | + const selectedMinute = selectedTime!.minute(); | ||
| 135 | + const selectedSeconds = selectedTime!.seconds(); | ||
| 136 | + | ||
| 137 | + if (type === TimePickerTypeEnum.START) { | ||
| 138 | + return selectedHour >= currentSelectedHour && selectedMinute > currentSelectedMinute | ||
| 139 | + ? [] | ||
| 140 | + : Array.from({ length: 60 - selectedSeconds }, (_, index) => selectedSeconds + index + 1); | ||
| 141 | + } else { | ||
| 142 | + return selectedHour <= currentSelectedHour && selectedMinute < currentSelectedMinute | ||
| 143 | + ? [] | ||
| 144 | + : Array.from({ length: selectedSeconds }, (_, index) => index); | ||
| 145 | + } | ||
| 146 | + }; | ||
| 147 | + }; | ||
| 148 | +</script> | ||
| 149 | + | ||
| 150 | +<template> | ||
| 151 | + <main class="time-range-picker flex items-center"> | ||
| 152 | + <TimePicker | ||
| 153 | + :value="getRangeValue.startTs" | ||
| 154 | + format="HH:mm" | ||
| 155 | + :disabled="disabled" | ||
| 156 | + @change="(time) => handleTimeChange(time, TimePickerTypeEnum.START)" | ||
| 157 | + :disabled-hours="handleBasicDisabledHours(TimePickerTypeEnum.START)" | ||
| 158 | + :disabled-minutes="handleBasicDisabledMinutes(TimePickerTypeEnum.START)" | ||
| 159 | + :disabled-seconds="handleBasicDisabledSeconds(TimePickerTypeEnum.START)" | ||
| 160 | + /> | ||
| 161 | + <slot v-if="$slots?.separator" name="separator"></slot> | ||
| 162 | + <span v-else class="mx-4">~</span> | ||
| 163 | + <TimePicker | ||
| 164 | + :value="getRangeValue.endTs" | ||
| 165 | + format="HH:mm" | ||
| 166 | + :disabled="disabled" | ||
| 167 | + @change="(time) => handleTimeChange(time, TimePickerTypeEnum.END)" | ||
| 168 | + :disabled-hours="handleBasicDisabledHours(TimePickerTypeEnum.END)" | ||
| 169 | + :disabled-minutes="handleBasicDisabledMinutes(TimePickerTypeEnum.END)" | ||
| 170 | + :disabled-seconds="handleBasicDisabledSeconds(TimePickerTypeEnum.END)" | ||
| 171 | + /> | ||
| 172 | + </main> | ||
| 173 | +</template> | ||
| 174 | + | ||
| 175 | +<style scoped lang="less"> | ||
| 176 | + .time-range-picker { | ||
| 177 | + :deep(.ant-time-picker) { | ||
| 178 | + width: auto; | ||
| 179 | + } | ||
| 180 | + } | ||
| 181 | +</style> |
| 1 | +import TimeRangePicker from './TimeRangePicker.vue'; | ||
| 2 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | ||
| 3 | +import { ScheduleTypeEnum, ScheduleTypeNameEnum } from '/@/enums/linkedgeEnum'; | ||
| 4 | + | ||
| 5 | +export enum FormFieldsEnum { | ||
| 6 | + SCHEDULE_TYPE = 'type', | ||
| 7 | + TIMEZONE = 'timezone', | ||
| 8 | + STARTS_ON = 'startsOn', | ||
| 9 | + ENDS_ON = 'endsOn', | ||
| 10 | + DAYS_OF_WEEK = 'daysOfWeek', | ||
| 11 | + SCHEDULE_ITEMS = 'items', | ||
| 12 | + TIME_RANGE = 'timeRange', | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +export enum FormFieldsNameEnum { | ||
| 16 | + SCHEDULE_TYPE = '启用类型', | ||
| 17 | + TIMEZONE = '时区', | ||
| 18 | + DAYS_OF_WEEK = '启用日', | ||
| 19 | + TIME_RANGE = '启用时间', | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +export interface EnableRuleFormType { | ||
| 23 | + [FormFieldsEnum.DAYS_OF_WEEK]: number[]; | ||
| 24 | + [FormFieldsEnum.SCHEDULE_TYPE]: ScheduleTypeEnum; | ||
| 25 | + [FormFieldsEnum.TIMEZONE]: string; | ||
| 26 | + [FormFieldsEnum.TIME_RANGE]: { | ||
| 27 | + [FormFieldsEnum.STARTS_ON]: number; | ||
| 28 | + [FormFieldsEnum.ENDS_ON]: number; | ||
| 29 | + }; | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +useComponentRegister('TimeRangePicker', TimeRangePicker); | ||
| 33 | + | ||
| 34 | +export const WeekName = ['一', '二', '三', '四', '五', '六', '日']; | ||
| 35 | + | ||
| 36 | +enum TimezoneEnum { | ||
| 37 | + SHANG_HAI = 'Asia/Shanghai', | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +export const getFormSchemas = (): FormSchema[] => { | ||
| 41 | + return [ | ||
| 42 | + { | ||
| 43 | + field: FormFieldsEnum.SCHEDULE_TYPE, | ||
| 44 | + label: FormFieldsNameEnum.SCHEDULE_TYPE, | ||
| 45 | + component: 'Select', | ||
| 46 | + required: true, | ||
| 47 | + defaultValue: ScheduleTypeEnum.ANY_TIME, | ||
| 48 | + componentProps: () => { | ||
| 49 | + return { | ||
| 50 | + options: Object.keys(ScheduleTypeEnum).map((value) => ({ | ||
| 51 | + label: ScheduleTypeNameEnum[value], | ||
| 52 | + value, | ||
| 53 | + })), | ||
| 54 | + allowClear: false, | ||
| 55 | + }; | ||
| 56 | + }, | ||
| 57 | + }, | ||
| 58 | + { | ||
| 59 | + field: FormFieldsEnum.TIMEZONE, | ||
| 60 | + label: FormFieldsNameEnum.TIMEZONE, | ||
| 61 | + component: 'Select', | ||
| 62 | + required: true, | ||
| 63 | + defaultValue: TimezoneEnum.SHANG_HAI, | ||
| 64 | + ifShow: ({ model }) => model[FormFieldsEnum.SCHEDULE_TYPE] !== ScheduleTypeEnum.ANY_TIME, | ||
| 65 | + componentProps: () => { | ||
| 66 | + return { | ||
| 67 | + options: [{ label: TimezoneEnum.SHANG_HAI, value: TimezoneEnum.SHANG_HAI }], | ||
| 68 | + allowClear: false, | ||
| 69 | + }; | ||
| 70 | + }, | ||
| 71 | + }, | ||
| 72 | + { | ||
| 73 | + field: FormFieldsEnum.SCHEDULE_ITEMS, | ||
| 74 | + label: '规则', | ||
| 75 | + component: 'Input', | ||
| 76 | + ifShow: ({ model }) => model[FormFieldsEnum.SCHEDULE_TYPE] === ScheduleTypeEnum.CUSTOM, | ||
| 77 | + slot: 'custom', | ||
| 78 | + }, | ||
| 79 | + { | ||
| 80 | + field: FormFieldsEnum.DAYS_OF_WEEK, | ||
| 81 | + label: FormFieldsNameEnum.DAYS_OF_WEEK, | ||
| 82 | + component: 'CheckboxGroup', | ||
| 83 | + ifShow: ({ model }) => model[FormFieldsEnum.SCHEDULE_TYPE] === ScheduleTypeEnum.SPECIFIC_TIME, | ||
| 84 | + rules: [{ required: true, type: 'array' }], | ||
| 85 | + componentProps: () => { | ||
| 86 | + return { | ||
| 87 | + options: Array.from({ length: 7 }, (_, index) => ({ | ||
| 88 | + label: `星期${WeekName[index]}`, | ||
| 89 | + value: index + 1, | ||
| 90 | + })), | ||
| 91 | + }; | ||
| 92 | + }, | ||
| 93 | + }, | ||
| 94 | + { | ||
| 95 | + field: FormFieldsEnum.TIME_RANGE, | ||
| 96 | + label: FormFieldsNameEnum.TIME_RANGE, | ||
| 97 | + component: 'TimeRangePicker', | ||
| 98 | + changeEvent: 'update:value', | ||
| 99 | + valueField: 'value', | ||
| 100 | + ifShow: ({ model }) => model[FormFieldsEnum.SCHEDULE_TYPE] === ScheduleTypeEnum.SPECIFIC_TIME, | ||
| 101 | + rules: [ | ||
| 102 | + { | ||
| 103 | + required: true, | ||
| 104 | + validator(_rule, value: Record<'startsOn' | 'endsOn', number>, _callback) { | ||
| 105 | + if (!value?.endsOn) return Promise.reject('请选择结束时间'); | ||
| 106 | + if (!value?.startsOn) return Promise.reject('请选择开始时间'); | ||
| 107 | + return Promise.resolve(); | ||
| 108 | + }, | ||
| 109 | + }, | ||
| 110 | + ], | ||
| 111 | + }, | ||
| 112 | + ]; | ||
| 113 | +}; |
| 1 | +export { default as EnablingRule } from './index.vue'; |
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 3 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
| 4 | + import { EnableRuleFormType, getFormSchemas } from './config'; | ||
| 5 | + import { nextTick, ref, unref } from 'vue'; | ||
| 6 | + import CustomRule from './CustomRule.vue'; | ||
| 7 | + import { ScheduleTypeEnum } from '/@/enums/linkedgeEnum'; | ||
| 8 | + import { EnableRuleFormModalParamsType, ScheduleType } from './type'; | ||
| 9 | + import { useSceneLinkageDrawerContext } from '../SceneLinkageDrawer/sceneLinkageDrawerContext'; | ||
| 10 | + | ||
| 11 | + const { disabledDrawer } = useSceneLinkageDrawerContext(); | ||
| 12 | + | ||
| 13 | + const emit = defineEmits(['register', 'settingComplete']); | ||
| 14 | + | ||
| 15 | + const scheduleItemKey = ref<string>(); | ||
| 16 | + const [registerModal, { closeModal }] = useModalInner( | ||
| 17 | + ({ record }: EnableRuleFormModalParamsType) => { | ||
| 18 | + resetFields(); | ||
| 19 | + const { type, schedule, key } = record; | ||
| 20 | + scheduleItemKey.value = key; | ||
| 21 | + handleSetFieldsValue({ ...schedule, type }); | ||
| 22 | + clearValidate(); | ||
| 23 | + } | ||
| 24 | + ); | ||
| 25 | + | ||
| 26 | + const [register, { getFieldsValue, validate, setFieldsValue, resetFields, clearValidate }] = | ||
| 27 | + useForm({ | ||
| 28 | + schemas: getFormSchemas(), | ||
| 29 | + showActionButtonGroup: false, | ||
| 30 | + layout: 'vertical', | ||
| 31 | + }); | ||
| 32 | + | ||
| 33 | + const customRuleElRef = ref<Nullable<InstanceType<typeof CustomRule>>>(); | ||
| 34 | + | ||
| 35 | + const handleGetFieldsValue = async (): Promise<ScheduleType> => { | ||
| 36 | + await unref(customRuleElRef)?.validate?.(); | ||
| 37 | + await validate(); | ||
| 38 | + const { type, timeRange, timezone, daysOfWeek } = getFieldsValue() as EnableRuleFormType; | ||
| 39 | + const customValue = unref(customRuleElRef)?.getFieldsValue(); | ||
| 40 | + | ||
| 41 | + if (type === ScheduleTypeEnum.ANY_TIME) return { type }; | ||
| 42 | + | ||
| 43 | + if (type === ScheduleTypeEnum.SPECIFIC_TIME) | ||
| 44 | + return { | ||
| 45 | + type, | ||
| 46 | + timezone, | ||
| 47 | + daysOfWeek, | ||
| 48 | + ...timeRange, | ||
| 49 | + }; | ||
| 50 | + | ||
| 51 | + return { | ||
| 52 | + type, | ||
| 53 | + timezone, | ||
| 54 | + items: customValue, | ||
| 55 | + }; | ||
| 56 | + }; | ||
| 57 | + | ||
| 58 | + const handleSetFieldsValue = async (schedule: ScheduleType) => { | ||
| 59 | + const { type, startsOn, endsOn, timezone, daysOfWeek } = schedule; | ||
| 60 | + | ||
| 61 | + if (type === ScheduleTypeEnum.ANY_TIME) return setFieldsValue({ type }); | ||
| 62 | + | ||
| 63 | + if (type === ScheduleTypeEnum.SPECIFIC_TIME) | ||
| 64 | + return setFieldsValue({ type, timezone, daysOfWeek, timeRange: { startsOn, endsOn } }); | ||
| 65 | + | ||
| 66 | + setFieldsValue(schedule); | ||
| 67 | + await nextTick(); | ||
| 68 | + unref(customRuleElRef)?.setFieldsValue(schedule.items || []); | ||
| 69 | + }; | ||
| 70 | + | ||
| 71 | + const handleOk = async () => { | ||
| 72 | + const result = await handleGetFieldsValue(); | ||
| 73 | + emit('settingComplete', result, unref(scheduleItemKey)); | ||
| 74 | + closeModal(); | ||
| 75 | + }; | ||
| 76 | +</script> | ||
| 77 | + | ||
| 78 | +<template> | ||
| 79 | + <BasicModal @register="registerModal" title="启用规则" :width="600" @ok="handleOk"> | ||
| 80 | + <BasicForm @register="register" :disabled="disabledDrawer"> | ||
| 81 | + <template #custom="{ model, field }"> | ||
| 82 | + <CustomRule ref="customRuleElRef" v-model:value="model[field]" /> | ||
| 83 | + </template> | ||
| 84 | + </BasicForm> | ||
| 85 | + </BasicModal> | ||
| 86 | +</template> |
| 1 | +import { ScheduleTypeEnum } from '/@/enums/linkedgeEnum'; | ||
| 2 | + | ||
| 3 | +export interface CustomRuleItemType { | ||
| 4 | + dayOfWeek: number; | ||
| 5 | + enabled: boolean; | ||
| 6 | + endsOn: number; | ||
| 7 | + startsOn: number; | ||
| 8 | +} | ||
| 9 | + | ||
| 10 | +export interface ScheduleType { | ||
| 11 | + type: ScheduleTypeEnum; | ||
| 12 | + timezone?: string; | ||
| 13 | + items?: CustomRuleItemType[]; | ||
| 14 | + daysOfWeek?: number[]; | ||
| 15 | + endsOn?: number; | ||
| 16 | + startsOn?: number; | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +interface EnableRuleFormModalParams { | ||
| 20 | + type: ScheduleTypeEnum; | ||
| 21 | + schedule: ScheduleType; | ||
| 22 | + key: string; | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +export type EnableRuleFormModalParamsType = ModalParamsType<EnableRuleFormModalParams>; |
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { ApiSelect } from '/@/components/Form'; | ||
| 3 | + import { Divider } from 'ant-design-vue'; | ||
| 4 | + import { Icon } from '/@/components/Icon'; | ||
| 5 | + import { VNode } from 'vue'; | ||
| 6 | + import AlarmConfigDrawer from '/@/views/alarm/config/ContactDrawer.vue'; | ||
| 7 | + import { useDrawer } from '/@/components/Drawer'; | ||
| 8 | + | ||
| 9 | + const [registerAlarmContactDrawer, { openDrawer }] = useDrawer(); | ||
| 10 | + | ||
| 11 | + const Options = (props: { menuNode: VNode }) => { | ||
| 12 | + return props.menuNode; | ||
| 13 | + }; | ||
| 14 | + | ||
| 15 | + const handleOpenAlarmConfig = () => { | ||
| 16 | + openDrawer(); | ||
| 17 | + }; | ||
| 18 | + | ||
| 19 | + const handleSuccess = () => {}; | ||
| 20 | +</script> | ||
| 21 | + | ||
| 22 | +<template> | ||
| 23 | + <section> | ||
| 24 | + <ApiSelect v-bind="$attrs"> | ||
| 25 | + <template #dropdownRender="{ menuNode }"> | ||
| 26 | + <Options :menuNode="menuNode" /> | ||
| 27 | + <Divider class="!my-2" /> | ||
| 28 | + <div class="cursor-pointer text-gray-500" @click="handleOpenAlarmConfig"> | ||
| 29 | + <Icon icon="ant-design:plus-outlined" class="mx-2" /> | ||
| 30 | + <span>新增告警配置</span> | ||
| 31 | + </div> | ||
| 32 | + </template> | ||
| 33 | + </ApiSelect> | ||
| 34 | + <AlarmConfigDrawer | ||
| 35 | + @register="registerAlarmContactDrawer" | ||
| 36 | + default-enable | ||
| 37 | + @success="handleSuccess" | ||
| 38 | + /> | ||
| 39 | + </section> | ||
| 40 | +</template> |
| 1 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | ||
| 2 | +import { | ||
| 3 | + CommandTypeEnum, | ||
| 4 | + CommandTypeNameEnum, | ||
| 5 | + ExecutionActionEnum, | ||
| 6 | + ExecutionActionNameEnum, | ||
| 7 | + TriggerEntityTypeEnum, | ||
| 8 | + TriggerEntityTypeNameEnum, | ||
| 9 | +} from '/@/enums/linkedgeEnum'; | ||
| 10 | +import AlarmProfileSelect from './AlarmProfileSelect.vue'; | ||
| 11 | +import { | ||
| 12 | + byOrganizationIdGetMasterDevice, | ||
| 13 | + getOrganizationAlarmConfig, | ||
| 14 | +} from '/@/api/ruleengine/ruleengineApi'; | ||
| 15 | +import { useSceneLinkageDrawerContext } from '../SceneLinkageDrawer/sceneLinkageDrawerContext'; | ||
| 16 | +import { Ref, h, toRaw, unref } from 'vue'; | ||
| 17 | +import { AlarmLevelEnum, AlarmLevelNameEnum } from '/@/enums/alarmEnum'; | ||
| 18 | +import Icon from '/@/components/Icon'; | ||
| 19 | +import { Tooltip } from 'ant-design-vue'; | ||
| 20 | +import { findDictItemByCode } from '/@/api/system/dict'; | ||
| 21 | +import { DictEnum } from '/@/enums/dictEnum'; | ||
| 22 | +import { getDeviceProfile } from '/@/api/alarm/position'; | ||
| 23 | +import { createPickerSearch } from '/@/utils/pickerSearch'; | ||
| 24 | +import { ServiceCallTypeEnum, ServiceCallTypeNameEnum } from '/@/enums/toolEnum'; | ||
| 25 | +import { DeviceTypeEnum } from '../../../dataFlow/cpns/config'; | ||
| 26 | +import { getModelServices } from '/@/api/device/modelOfMatter'; | ||
| 27 | +import { ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | ||
| 28 | +import { DeviceProfileModel } from '/@/api/device/model/deviceModel'; | ||
| 29 | +import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; | ||
| 30 | +import { JSONEditor } from '/@/components/CodeEditor'; | ||
| 31 | +import { useJsonParse } from '/@/hooks/business/useJsonParse'; | ||
| 32 | +import { validateTCPCustomCommand } from '/@/components/Form/src/externalCompns/components/ThingsModelForm'; | ||
| 33 | + | ||
| 34 | +export enum FormFieldsEnum { | ||
| 35 | + OUT_TARGET = 'outTarget', | ||
| 36 | + ALARM_PROFILED = 'alarmProfileId', | ||
| 37 | + ALARM_LEVEL = 'alarmLevel', | ||
| 38 | + DEVICE_TYPE = 'deviceType', | ||
| 39 | + DEVICE_PROFILE_ID = 'deviceProfileId', | ||
| 40 | + ENTITY_TYPE = 'entityType', | ||
| 41 | + ENTITY_ID = 'entityId', | ||
| 42 | + COMMAND_TYPE = 'commandType', | ||
| 43 | + CALL_TYPE = 'callType', | ||
| 44 | + CALL_SERVICE_IDENTIFIER = 'callServiceIdentifier', | ||
| 45 | + | ||
| 46 | + TCP_CUSTOM_COMMAND = 'tcpCustomCommand', | ||
| 47 | + CUSTOM_COMMAND = 'customCommand', | ||
| 48 | + CALL_SERVICE = 'callService', | ||
| 49 | + SERVICE_COMMAND = 'serviceCommand', | ||
| 50 | + SERVICE_ID = 'serviceId', | ||
| 51 | + TRANSPORT_TYPE = 'transportType', | ||
| 52 | + ENABLE_CLEAR_RULE = 'enableClearRule', | ||
| 53 | + CLEAR_RULE = 'clearRule', | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +export enum FormFieldsNameEnum { | ||
| 57 | + OUT_TARGET = '执行动作', | ||
| 58 | + ALARM_PROFILED = '告警配置', | ||
| 59 | + ALARM_LEVEL = '告警等级', | ||
| 60 | + DEVICE_TYPE = '设备类型', | ||
| 61 | + DEVICE_PROFILE_ID = '产品', | ||
| 62 | + ENTITY_TYPE = '触发设备类型', | ||
| 63 | + ENTITY_ID = '设备', | ||
| 64 | + COMMAND_TYPE = '类型', | ||
| 65 | + CALL_TYPE = '命令下发类型', | ||
| 66 | + CALL_SERVICE_IDENTIFIER = '服务', | ||
| 67 | + | ||
| 68 | + ENABLE_CLEAR_RULE = '清除告警', | ||
| 69 | + TCP_CUSTOM_COMMAND = '自定义命令', | ||
| 70 | + CUSTOM_COMMAND = '自定义命令', | ||
| 71 | +} | ||
| 72 | + | ||
| 73 | +useComponentRegister('AlarmProfileSelect', AlarmProfileSelect); | ||
| 74 | +useComponentRegister('JSONEditor', JSONEditor); | ||
| 75 | + | ||
| 76 | +export const getFormSchemas = (hasAlarmNotify: Ref<boolean>): FormSchema[] => { | ||
| 77 | + const { organizationId } = useSceneLinkageDrawerContext(); | ||
| 78 | + return [ | ||
| 79 | + { | ||
| 80 | + field: FormFieldsEnum.OUT_TARGET, | ||
| 81 | + label: '', | ||
| 82 | + component: 'Select', | ||
| 83 | + rules: [{ required: true, message: `请选择${FormFieldsNameEnum.OUT_TARGET}` }], | ||
| 84 | + defaultValue: ExecutionActionEnum.DEVICE_OUT, | ||
| 85 | + componentProps: () => { | ||
| 86 | + return { | ||
| 87 | + options: [ | ||
| 88 | + { label: ExecutionActionNameEnum.DEVICE_OUT, value: ExecutionActionEnum.DEVICE_OUT }, | ||
| 89 | + { | ||
| 90 | + label: ExecutionActionNameEnum.MSG_NOTIFY, | ||
| 91 | + value: ExecutionActionEnum.MSG_NOTIFY, | ||
| 92 | + disabled: unref(hasAlarmNotify), | ||
| 93 | + }, | ||
| 94 | + ], | ||
| 95 | + labelField: 'name', | ||
| 96 | + valueField: 'id', | ||
| 97 | + placeholder: `请选择${FormFieldsNameEnum.OUT_TARGET}`, | ||
| 98 | + onChange(value: ExecutionActionEnum) { | ||
| 99 | + hasAlarmNotify.value = value === ExecutionActionEnum.MSG_NOTIFY; | ||
| 100 | + }, | ||
| 101 | + }; | ||
| 102 | + }, | ||
| 103 | + }, | ||
| 104 | + { | ||
| 105 | + field: FormFieldsEnum.ALARM_PROFILED, | ||
| 106 | + label: '', | ||
| 107 | + component: 'AlarmProfileSelect', | ||
| 108 | + rules: [{ required: true, message: `请选择${FormFieldsEnum.ALARM_PROFILED}` }], | ||
| 109 | + ifShow: ({ model }) => model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.MSG_NOTIFY, | ||
| 110 | + componentProps: () => { | ||
| 111 | + return { | ||
| 112 | + api: async () => { | ||
| 113 | + if (!unref(organizationId)) return []; | ||
| 114 | + return await getOrganizationAlarmConfig({ organizationId: unref(organizationId) }); | ||
| 115 | + }, | ||
| 116 | + labelField: 'name', | ||
| 117 | + valueField: 'id', | ||
| 118 | + placeholder: `请选择${FormFieldsNameEnum.ALARM_PROFILED}`, | ||
| 119 | + }; | ||
| 120 | + }, | ||
| 121 | + }, | ||
| 122 | + { | ||
| 123 | + field: FormFieldsEnum.ALARM_LEVEL, | ||
| 124 | + label: '', | ||
| 125 | + component: 'Select', | ||
| 126 | + ifShow: ({ model }) => model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.MSG_NOTIFY, | ||
| 127 | + rules: [{ required: true, message: `请选择${FormFieldsEnum.ALARM_LEVEL}` }], | ||
| 128 | + componentProps: () => { | ||
| 129 | + return { | ||
| 130 | + options: Object.keys(AlarmLevelEnum).map((value) => ({ | ||
| 131 | + label: AlarmLevelNameEnum[value], | ||
| 132 | + value, | ||
| 133 | + })), | ||
| 134 | + placeholder: `请选择${FormFieldsNameEnum.ALARM_LEVEL}`, | ||
| 135 | + }; | ||
| 136 | + }, | ||
| 137 | + }, | ||
| 138 | + { | ||
| 139 | + field: FormFieldsEnum.ENABLE_CLEAR_RULE, | ||
| 140 | + label: '', | ||
| 141 | + component: 'Checkbox', | ||
| 142 | + ifShow: ({ model }) => model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.MSG_NOTIFY, | ||
| 143 | + renderComponentContent: () => ({ | ||
| 144 | + default: () => [ | ||
| 145 | + h('span', FormFieldsNameEnum.ENABLE_CLEAR_RULE), | ||
| 146 | + h(Tooltip, { title: '清除告警与触发器一一对应' }, () => | ||
| 147 | + h(Icon, { | ||
| 148 | + icon: 'ant-design:question-circle-outlined', | ||
| 149 | + class: ' cursor-pointer ml-1', | ||
| 150 | + }) | ||
| 151 | + ), | ||
| 152 | + ], | ||
| 153 | + }), | ||
| 154 | + }, | ||
| 155 | + { | ||
| 156 | + field: FormFieldsEnum.CLEAR_RULE, | ||
| 157 | + label: '', | ||
| 158 | + component: 'Input', | ||
| 159 | + colProps: { span: 24, xxl: 24, xl: 24, lg: 24, md: 24, sm: 24, xs: 24 }, | ||
| 160 | + slot: 'alarmClearRule', | ||
| 161 | + ifShow: ({ model }) => | ||
| 162 | + model[FormFieldsEnum.ENABLE_CLEAR_RULE] && | ||
| 163 | + model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.MSG_NOTIFY, | ||
| 164 | + }, | ||
| 165 | + { | ||
| 166 | + field: FormFieldsEnum.DEVICE_TYPE, | ||
| 167 | + label: '', | ||
| 168 | + component: 'ApiSelect', | ||
| 169 | + rules: [{ required: true, message: `请选择${FormFieldsNameEnum.DEVICE_TYPE}` }], | ||
| 170 | + ifShow: ({ model }) => model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.DEVICE_OUT, | ||
| 171 | + defaultValue: DeviceTypeEnum.SENSOR, | ||
| 172 | + componentProps: ({ formActionType }) => { | ||
| 173 | + return { | ||
| 174 | + api: findDictItemByCode, | ||
| 175 | + params: { | ||
| 176 | + dictCode: DictEnum.DEVICE_TYPE, | ||
| 177 | + }, | ||
| 178 | + labelField: 'itemText', | ||
| 179 | + valueField: 'itemValue', | ||
| 180 | + placeholder: `请选择${FormFieldsNameEnum.DEVICE_TYPE}`, | ||
| 181 | + onChange() { | ||
| 182 | + const { setFieldsValue } = formActionType; | ||
| 183 | + setFieldsValue({ | ||
| 184 | + [FormFieldsEnum.DEVICE_PROFILE_ID]: null, | ||
| 185 | + [FormFieldsEnum.ENTITY_ID]: [], | ||
| 186 | + [FormFieldsEnum.CALL_SERVICE_IDENTIFIER]: null, | ||
| 187 | + [FormFieldsEnum.SERVICE_COMMAND]: null, | ||
| 188 | + [FormFieldsEnum.CALL_SERVICE]: null, | ||
| 189 | + [FormFieldsEnum.TRANSPORT_TYPE]: null, | ||
| 190 | + }); | ||
| 191 | + }, | ||
| 192 | + }; | ||
| 193 | + }, | ||
| 194 | + }, | ||
| 195 | + { | ||
| 196 | + field: FormFieldsEnum.TRANSPORT_TYPE, | ||
| 197 | + label: '传输协议', | ||
| 198 | + component: 'Input', | ||
| 199 | + ifShow: false, | ||
| 200 | + }, | ||
| 201 | + { | ||
| 202 | + field: FormFieldsEnum.DEVICE_PROFILE_ID, | ||
| 203 | + label: '', | ||
| 204 | + component: 'ApiSelect', | ||
| 205 | + rules: [{ required: true, message: `请选择${FormFieldsNameEnum.DEVICE_PROFILE_ID}` }], | ||
| 206 | + ifShow: ({ model }) => model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.DEVICE_OUT, | ||
| 207 | + componentProps: ({ formModel, formActionType }) => { | ||
| 208 | + const deviceType = formModel[FormFieldsEnum.DEVICE_TYPE]; | ||
| 209 | + const { setFieldsValue } = formActionType; | ||
| 210 | + return { | ||
| 211 | + api: async () => { | ||
| 212 | + return await getDeviceProfile(deviceType); | ||
| 213 | + }, | ||
| 214 | + labelField: 'name', | ||
| 215 | + valueField: 'id', | ||
| 216 | + placeholder: `请选择${FormFieldsNameEnum.DEVICE_PROFILE_ID}`, | ||
| 217 | + ...createPickerSearch(), | ||
| 218 | + onChange(_value: string, option: DeviceProfileModel) { | ||
| 219 | + setFieldsValue({ | ||
| 220 | + [FormFieldsEnum.ENTITY_ID]: [], | ||
| 221 | + [FormFieldsEnum.TRANSPORT_TYPE]: option?.transportType, | ||
| 222 | + }); | ||
| 223 | + }, | ||
| 224 | + onOptionsChange(options: (DeviceProfileModel & Record<'label' | 'value', string>)[]) { | ||
| 225 | + const deviceProfileId = formModel[FormFieldsEnum.DEVICE_PROFILE_ID]; | ||
| 226 | + const res = options.find((item) => item.value === deviceProfileId); | ||
| 227 | + res && | ||
| 228 | + setFieldsValue({ | ||
| 229 | + [FormFieldsEnum.TRANSPORT_TYPE]: res.transportType, | ||
| 230 | + }); | ||
| 231 | + }, | ||
| 232 | + }; | ||
| 233 | + }, | ||
| 234 | + }, | ||
| 235 | + { | ||
| 236 | + field: FormFieldsEnum.ENTITY_TYPE, | ||
| 237 | + label: '', | ||
| 238 | + component: 'Select', | ||
| 239 | + rules: [{ required: true, message: `请选择${FormFieldsNameEnum.ENTITY_TYPE}` }], | ||
| 240 | + ifShow: ({ model }) => model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.DEVICE_OUT, | ||
| 241 | + componentProps: () => { | ||
| 242 | + return { | ||
| 243 | + options: Object.keys(TriggerEntityTypeEnum).map((value) => ({ | ||
| 244 | + label: TriggerEntityTypeNameEnum[value], | ||
| 245 | + value, | ||
| 246 | + })), | ||
| 247 | + placeholder: `请选择${FormFieldsNameEnum.ENTITY_TYPE}`, | ||
| 248 | + }; | ||
| 249 | + }, | ||
| 250 | + }, | ||
| 251 | + { | ||
| 252 | + field: FormFieldsEnum.ENTITY_ID, | ||
| 253 | + label: '', | ||
| 254 | + component: 'ApiSelect', | ||
| 255 | + rules: [{ required: true, type: 'array', message: `请选择${FormFieldsNameEnum.ENTITY_ID}` }], | ||
| 256 | + ifShow: ({ model }) => | ||
| 257 | + model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.DEVICE_OUT && | ||
| 258 | + model[FormFieldsEnum.ENTITY_TYPE] === TriggerEntityTypeEnum.PART, | ||
| 259 | + componentProps: ({ formModel }) => { | ||
| 260 | + return { | ||
| 261 | + api: async (params: Record<'organizationId' | 'deviceProfileId', string>) => { | ||
| 262 | + if (params.deviceProfileId && params.organizationId) { | ||
| 263 | + const result = await byOrganizationIdGetMasterDevice(params); | ||
| 264 | + if (result) { | ||
| 265 | + return result.map((item) => ({ | ||
| 266 | + ...item, | ||
| 267 | + label: item.alias || item.name, | ||
| 268 | + value: item.tbDeviceId, | ||
| 269 | + })); | ||
| 270 | + } | ||
| 271 | + } | ||
| 272 | + return []; | ||
| 273 | + }, | ||
| 274 | + mode: 'multiple', | ||
| 275 | + maxTagCount: 3, | ||
| 276 | + params: { | ||
| 277 | + organizationId: unref(organizationId), | ||
| 278 | + deviceProfileId: formModel[FormFieldsEnum.DEVICE_PROFILE_ID], | ||
| 279 | + }, | ||
| 280 | + placeholder: `请选择${FormFieldsNameEnum.ENTITY_ID}`, | ||
| 281 | + ...createPickerSearch(), | ||
| 282 | + }; | ||
| 283 | + }, | ||
| 284 | + }, | ||
| 285 | + { | ||
| 286 | + field: FormFieldsEnum.COMMAND_TYPE, | ||
| 287 | + label: '', | ||
| 288 | + component: 'Select', | ||
| 289 | + rules: [ | ||
| 290 | + { required: true, message: `请选择${FormFieldsNameEnum.COMMAND_TYPE}`, type: 'number' }, | ||
| 291 | + ], | ||
| 292 | + defaultValue: CommandTypeEnum.CUSTOM, | ||
| 293 | + ifShow: ({ model }) => model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.DEVICE_OUT, | ||
| 294 | + componentProps: ({ formActionType }) => { | ||
| 295 | + return { | ||
| 296 | + options: [ | ||
| 297 | + { label: CommandTypeNameEnum.CUSTOM, value: CommandTypeEnum.CUSTOM }, | ||
| 298 | + { label: CommandTypeNameEnum.SERVICE, value: CommandTypeEnum.SERVICE }, | ||
| 299 | + ], | ||
| 300 | + placeholder: `请选择${FormFieldsNameEnum.COMMAND_TYPE}`, | ||
| 301 | + onChange() { | ||
| 302 | + const { setFieldsValue } = formActionType; | ||
| 303 | + setFieldsValue({ | ||
| 304 | + [FormFieldsEnum.CALL_SERVICE]: null, | ||
| 305 | + [FormFieldsEnum.CALL_SERVICE_IDENTIFIER]: null, | ||
| 306 | + [FormFieldsEnum.SERVICE_COMMAND]: null, | ||
| 307 | + }); | ||
| 308 | + }, | ||
| 309 | + }; | ||
| 310 | + }, | ||
| 311 | + }, | ||
| 312 | + { | ||
| 313 | + field: FormFieldsEnum.CALL_TYPE, | ||
| 314 | + label: '', | ||
| 315 | + component: 'Select', | ||
| 316 | + defaultValue: ServiceCallTypeEnum.ASYNC, | ||
| 317 | + rules: [{ required: true, message: `请选择${FormFieldsNameEnum.CALL_TYPE}` }], | ||
| 318 | + ifShow: ({ model }) => | ||
| 319 | + model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.DEVICE_OUT && | ||
| 320 | + model[FormFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.CUSTOM, | ||
| 321 | + componentProps: () => { | ||
| 322 | + return { | ||
| 323 | + options: [ | ||
| 324 | + { label: ServiceCallTypeNameEnum.ASYNC, value: ServiceCallTypeEnum.ASYNC }, | ||
| 325 | + { label: ServiceCallTypeNameEnum.SYNC, value: ServiceCallTypeEnum.SYNC }, | ||
| 326 | + ], | ||
| 327 | + placeholder: `请选择${FormFieldsNameEnum.CALL_TYPE}`, | ||
| 328 | + }; | ||
| 329 | + }, | ||
| 330 | + }, | ||
| 331 | + { | ||
| 332 | + field: FormFieldsEnum.SERVICE_ID, | ||
| 333 | + label: '', | ||
| 334 | + component: 'ApiSelect', | ||
| 335 | + rules: [{ required: true, message: `请选择${FormFieldsNameEnum.CALL_SERVICE_IDENTIFIER}` }], | ||
| 336 | + ifShow: ({ model }) => | ||
| 337 | + model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.DEVICE_OUT && | ||
| 338 | + model[FormFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.SERVICE, | ||
| 339 | + componentProps: ({ formModel, formActionType }) => { | ||
| 340 | + return { | ||
| 341 | + api: async () => { | ||
| 342 | + const deviceProfileId = formModel[FormFieldsEnum.DEVICE_PROFILE_ID]; | ||
| 343 | + if (!deviceProfileId) return []; | ||
| 344 | + return await getModelServices({ deviceProfileId }); | ||
| 345 | + }, | ||
| 346 | + labelField: 'functionName', | ||
| 347 | + valueField: 'id', | ||
| 348 | + placeholder: `请选择${FormFieldsNameEnum.CALL_SERVICE_IDENTIFIER}`, | ||
| 349 | + onChange( | ||
| 350 | + value: string, | ||
| 351 | + option: ModelOfMatterParams & Record<'label' | 'value' | 'id', string> | ||
| 352 | + ) { | ||
| 353 | + const { setFieldsValue } = formActionType; | ||
| 354 | + setFieldsValue({ | ||
| 355 | + [FormFieldsEnum.CALL_TYPE]: value ? option.callType : null, | ||
| 356 | + [FormFieldsEnum.CALL_SERVICE_IDENTIFIER]: value ? option.identifier : null, | ||
| 357 | + [FormFieldsEnum.CALL_SERVICE]: value | ||
| 358 | + ? { ...toRaw(option), id: option?.value, functionName: option?.label } | ||
| 359 | + : null, | ||
| 360 | + [FormFieldsEnum.SERVICE_COMMAND]: {}, | ||
| 361 | + }); | ||
| 362 | + }, | ||
| 363 | + onOptionsChange(options: (StructJSON & Record<'label' | 'value' | 'id', string>)[]) { | ||
| 364 | + const { setFieldsValue } = formActionType; | ||
| 365 | + const serviceId = formModel[FormFieldsEnum.SERVICE_ID]; | ||
| 366 | + const res = options.find((item) => item.value === serviceId); | ||
| 367 | + res && | ||
| 368 | + setFieldsValue({ | ||
| 369 | + [FormFieldsEnum.CALL_SERVICE_IDENTIFIER]: res.identifier, | ||
| 370 | + [FormFieldsEnum.CALL_SERVICE]: { | ||
| 371 | + ...toRaw(res), | ||
| 372 | + id: res?.value, | ||
| 373 | + functionName: res?.label, | ||
| 374 | + }, | ||
| 375 | + }); | ||
| 376 | + }, | ||
| 377 | + }; | ||
| 378 | + }, | ||
| 379 | + }, | ||
| 380 | + { | ||
| 381 | + field: FormFieldsEnum.CALL_SERVICE_IDENTIFIER, | ||
| 382 | + label: '服务标识符', | ||
| 383 | + component: 'Input', | ||
| 384 | + ifShow: false, | ||
| 385 | + }, | ||
| 386 | + { | ||
| 387 | + field: FormFieldsEnum.CALL_SERVICE, | ||
| 388 | + label: '服务详情', | ||
| 389 | + component: 'Input', | ||
| 390 | + ifShow: false, | ||
| 391 | + }, | ||
| 392 | + { | ||
| 393 | + field: FormFieldsEnum.SERVICE_COMMAND, | ||
| 394 | + label: '', | ||
| 395 | + component: 'Input', | ||
| 396 | + colProps: { span: 24, xxl: 24, xl: 24, lg: 24, md: 24, sm: 24, xs: 24 }, | ||
| 397 | + ifShow: ({ model }) => | ||
| 398 | + model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.DEVICE_OUT && | ||
| 399 | + model[FormFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.SERVICE && | ||
| 400 | + model[FormFieldsEnum.CALL_SERVICE], | ||
| 401 | + colSlot: 'serviceCommand', | ||
| 402 | + }, | ||
| 403 | + { | ||
| 404 | + field: FormFieldsEnum.CUSTOM_COMMAND, | ||
| 405 | + label: '', | ||
| 406 | + component: 'JSONEditor', | ||
| 407 | + valueField: 'value', | ||
| 408 | + changeEvent: 'update:value', | ||
| 409 | + colProps: { span: 24, xxl: 24, xl: 24, lg: 24, md: 24, sm: 24, xs: 24 }, | ||
| 410 | + rules: [ | ||
| 411 | + { | ||
| 412 | + required: true, | ||
| 413 | + validator(_rule, value: string) { | ||
| 414 | + const { flag } = useJsonParse(value); | ||
| 415 | + return flag ? Promise.resolve() : Promise.reject('请检查自定义命令'); | ||
| 416 | + }, | ||
| 417 | + }, | ||
| 418 | + ], | ||
| 419 | + ifShow: ({ model }) => | ||
| 420 | + model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.DEVICE_OUT && | ||
| 421 | + model[FormFieldsEnum.TRANSPORT_TYPE] !== TransportTypeEnum.TCP && | ||
| 422 | + model[FormFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.CUSTOM, | ||
| 423 | + componentProps: () => { | ||
| 424 | + return { | ||
| 425 | + title: FormFieldsNameEnum.CUSTOM_COMMAND, | ||
| 426 | + }; | ||
| 427 | + }, | ||
| 428 | + }, | ||
| 429 | + { | ||
| 430 | + field: FormFieldsEnum.TCP_CUSTOM_COMMAND, | ||
| 431 | + label: FormFieldsNameEnum.TCP_CUSTOM_COMMAND, | ||
| 432 | + component: 'Input', | ||
| 433 | + colProps: { span: 24, xxl: 24, xl: 24, lg: 24, md: 24, sm: 24, xs: 24 }, | ||
| 434 | + rules: [ | ||
| 435 | + { required: true, message: `请输入${FormFieldsNameEnum.TCP_CUSTOM_COMMAND}` }, | ||
| 436 | + { validator: validateTCPCustomCommand }, | ||
| 437 | + ], | ||
| 438 | + ifShow: ({ model }) => | ||
| 439 | + model[FormFieldsEnum.OUT_TARGET] === ExecutionActionEnum.DEVICE_OUT && | ||
| 440 | + model[FormFieldsEnum.TRANSPORT_TYPE] === TransportTypeEnum.TCP && | ||
| 441 | + model[FormFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.CUSTOM, | ||
| 442 | + componentProps: () => { | ||
| 443 | + return { | ||
| 444 | + placeholder: `请输入${FormFieldsNameEnum.TCP_CUSTOM_COMMAND}`, | ||
| 445 | + }; | ||
| 446 | + }, | ||
| 447 | + // labelWidth: 120, | ||
| 448 | + }, | ||
| 449 | + ]; | ||
| 450 | +}; |
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { CollapseContainer } from '/@/components/Container'; | ||
| 3 | + import { Icon } from '/@/components/Icon'; | ||
| 4 | + import { Tooltip, Button } from 'ant-design-vue'; | ||
| 5 | + import { BasicForm, FormActionType, ThingsModelForm } from '/@/components/Form'; | ||
| 6 | + import { getFormSchemas, FormFieldsEnum } from './config'; | ||
| 7 | + import { FlipFlop } from '../FlipFlop'; | ||
| 8 | + import { ComponentPublicInstance, ref, unref } from 'vue'; | ||
| 9 | + import { ExecutionActionListRefItemType } from './type'; | ||
| 10 | + import { useExecutionActionData } from './useExecutionActionData'; | ||
| 11 | + import { createNewExecutionActionItem } from '.'; | ||
| 12 | + import { useSceneLinkageDrawerContext } from '../SceneLinkageDrawer/sceneLinkageDrawerContext'; | ||
| 13 | + | ||
| 14 | + const { disabledDrawer } = useSceneLinkageDrawerContext(); | ||
| 15 | + | ||
| 16 | + const hasAlarmNotify = ref(false); | ||
| 17 | + | ||
| 18 | + const formSchemas = getFormSchemas(hasAlarmNotify); | ||
| 19 | + | ||
| 20 | + const executionActionListRef = ref<ExecutionActionListRefItemType[]>([ | ||
| 21 | + createNewExecutionActionItem(), | ||
| 22 | + ]); | ||
| 23 | + | ||
| 24 | + const handleAdd = () => { | ||
| 25 | + executionActionListRef.value.push(createNewExecutionActionItem()); | ||
| 26 | + }; | ||
| 27 | + | ||
| 28 | + const handleDelete = (executionActionItem: ExecutionActionListRefItemType) => { | ||
| 29 | + const index = unref(executionActionListRef).findIndex( | ||
| 30 | + (item) => item.key === executionActionItem.key | ||
| 31 | + ); | ||
| 32 | + ~index && unref(executionActionListRef).splice(index, 1); | ||
| 33 | + }; | ||
| 34 | + | ||
| 35 | + const setExecutionActionRef = ( | ||
| 36 | + el: Nullable<Element | ComponentPublicInstance>, | ||
| 37 | + executionActionItem: ExecutionActionListRefItemType | ||
| 38 | + ) => { | ||
| 39 | + executionActionItem.ref = el as unknown as FormActionType; | ||
| 40 | + }; | ||
| 41 | + | ||
| 42 | + const setAlarmClearRuleRef = ( | ||
| 43 | + el: Nullable<Element | ComponentPublicInstance>, | ||
| 44 | + executionActionItem: ExecutionActionListRefItemType | ||
| 45 | + ) => { | ||
| 46 | + executionActionItem.alarmClearRuleElRef = el as unknown as InstanceType<typeof FlipFlop>; | ||
| 47 | + }; | ||
| 48 | + | ||
| 49 | + const handleClearRuleDelete = (_executionActionItem: ExecutionActionListRefItemType) => { | ||
| 50 | + // | ||
| 51 | + }; | ||
| 52 | + | ||
| 53 | + const setThingsModelFormRef = ( | ||
| 54 | + el: Nullable<Element | ComponentPublicInstance>, | ||
| 55 | + executionActionItem: ExecutionActionListRefItemType | ||
| 56 | + ) => { | ||
| 57 | + executionActionItem.thingsModelFormRefl = el as unknown as InstanceType<typeof ThingsModelForm>; | ||
| 58 | + }; | ||
| 59 | + | ||
| 60 | + const { getFieldsValue, setFieldsValue, validate, resetFieldsValue } = useExecutionActionData( | ||
| 61 | + executionActionListRef, | ||
| 62 | + hasAlarmNotify | ||
| 63 | + ); | ||
| 64 | + | ||
| 65 | + defineExpose({ | ||
| 66 | + getFieldsValue, | ||
| 67 | + setFieldsValue, | ||
| 68 | + validate, | ||
| 69 | + resetFieldsValue, | ||
| 70 | + }); | ||
| 71 | +</script> | ||
| 72 | + | ||
| 73 | +<template> | ||
| 74 | + <section> | ||
| 75 | + <CollapseContainer | ||
| 76 | + class="mb-4" | ||
| 77 | + v-for="(executionActionItem, index) in executionActionListRef" | ||
| 78 | + :title="`执行动作${index + 1}`" | ||
| 79 | + :key="executionActionItem.key" | ||
| 80 | + > | ||
| 81 | + <template #action> | ||
| 82 | + <Tooltip title="删除"> | ||
| 83 | + <Icon | ||
| 84 | + v-if="!disabledDrawer" | ||
| 85 | + class="ml-2 cursor-pointer" | ||
| 86 | + icon="fluent:delete-off-20-regular" | ||
| 87 | + size="20" | ||
| 88 | + @click="handleDelete(executionActionItem)" | ||
| 89 | + /> | ||
| 90 | + </Tooltip> | ||
| 91 | + </template> | ||
| 92 | + <BasicForm | ||
| 93 | + :ref="(el) => setExecutionActionRef(el, executionActionItem)" | ||
| 94 | + :disabled="disabledDrawer" | ||
| 95 | + :show-action-button-group="false" | ||
| 96 | + :baseColProps="{ span: 6, xxl: 6, xl: 8, lg: 12, sm: 24 }" | ||
| 97 | + :schemas="formSchemas" | ||
| 98 | + > | ||
| 99 | + <template #alarmClearRule> | ||
| 100 | + <FlipFlop | ||
| 101 | + :ref="(el) => setAlarmClearRuleRef(el, executionActionItem)" | ||
| 102 | + :panel-title="(index) => `清除告警${index}`" | ||
| 103 | + :disabled="disabledDrawer" | ||
| 104 | + addButtonName="新增清除告警" | ||
| 105 | + @delete="handleClearRuleDelete(executionActionItem)" | ||
| 106 | + /> | ||
| 107 | + </template> | ||
| 108 | + | ||
| 109 | + <template #serviceCommand="{ field, model }"> | ||
| 110 | + <ThingsModelForm | ||
| 111 | + :ref="(el) => setThingsModelFormRef(el, executionActionItem)" | ||
| 112 | + :value="model[field]" | ||
| 113 | + :identifier="model[FormFieldsEnum.CALL_SERVICE_IDENTIFIER]" | ||
| 114 | + :input-data="model[FormFieldsEnum.CALL_SERVICE]?.functionJson?.inputData" | ||
| 115 | + :title="model[FormFieldsEnum.CALL_SERVICE]?.functionName" | ||
| 116 | + :disabled="disabledDrawer" | ||
| 117 | + :transport-type="model[FormFieldsEnum.TRANSPORT_TYPE]" | ||
| 118 | + /> | ||
| 119 | + </template> | ||
| 120 | + </BasicForm> | ||
| 121 | + </CollapseContainer> | ||
| 122 | + <Button v-if="!disabledDrawer" class="w-full" type="primary" @click="handleAdd"> | ||
| 123 | + <Icon icon="ant-design:plus-outlined" /> | ||
| 124 | + 执行动作 | ||
| 125 | + </Button> | ||
| 126 | + </section> | ||
| 127 | +</template> |
| 1 | +export { default as ExecutionAction } from './index.vue'; | ||
| 2 | +import { FlipFlop } from '../FlipFlop'; | ||
| 3 | +import { FormFieldsEnum } from './config'; | ||
| 4 | +import { FlipFlopConditionType } from '../FlipFlop/types'; | ||
| 5 | +import { DeviceModelOfMatterAttrs, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | ||
| 6 | +import { FormActionType, ThingsModelForm } from '/@/components/Form'; | ||
| 7 | +import { AlarmLevelEnum } from '/@/enums/alarmEnum'; | ||
| 8 | +import { CommandTypeEnum, ExecutionActionEnum, TriggerEntityTypeEnum } from '/@/enums/linkedgeEnum'; | ||
| 9 | +import { ServiceCallTypeEnum } from '/@/enums/toolEnum'; | ||
| 10 | +import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; | ||
| 11 | + | ||
| 12 | +export interface ExecutionActionListRefItemType { | ||
| 13 | + key: string; | ||
| 14 | + alarmClearRuleElRef?: InstanceType<typeof FlipFlop>; | ||
| 15 | + ref?: FormActionType; | ||
| 16 | + thingsModelFormRefl?: InstanceType<typeof ThingsModelForm>; | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +export interface ExecutionActionDataItemType { | ||
| 20 | + callType: ServiceCallTypeEnum; | ||
| 21 | + commandType: CommandTypeEnum; | ||
| 22 | + deviceProfileId: string; | ||
| 23 | + deviceType: DeviceTypeEnum; | ||
| 24 | + entityType: TriggerEntityTypeEnum; | ||
| 25 | + outTarget: ExecutionActionEnum; | ||
| 26 | + deviceId?: string[]; | ||
| 27 | + thingsModelId?: string; | ||
| 28 | + doContext: DoContextType | DoContextAlarmType; | ||
| 29 | + alarmProfileId: string; | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +export interface DoContextType { | ||
| 33 | + method?: string; | ||
| 34 | + additionalInfo?: { cmdType: string | number }; | ||
| 35 | + params?: string | Recordable; | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +export interface DoContextAlarmType { | ||
| 39 | + alarmLevel: AlarmLevelEnum; | ||
| 40 | + clearRule: FlipFlopConditionType[]; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +export interface ExecutionActionFormItemRecordType { | ||
| 44 | + [FormFieldsEnum.ALARM_LEVEL]?: AlarmLevelEnum; | ||
| 45 | + [FormFieldsEnum.ALARM_PROFILED]?: string; | ||
| 46 | + [FormFieldsEnum.CALL_TYPE]?: ServiceCallTypeEnum; | ||
| 47 | + [FormFieldsEnum.COMMAND_TYPE]?: CommandTypeEnum; | ||
| 48 | + [FormFieldsEnum.DEVICE_TYPE]?: DeviceTypeEnum; | ||
| 49 | + [FormFieldsEnum.DEVICE_PROFILE_ID]?: string; | ||
| 50 | + [FormFieldsEnum.OUT_TARGET]?: ExecutionActionEnum; | ||
| 51 | + [FormFieldsEnum.TCP_CUSTOM_COMMAND]?: string; | ||
| 52 | + [FormFieldsEnum.CUSTOM_COMMAND]?: string; | ||
| 53 | + [FormFieldsEnum.TRANSPORT_TYPE]?: TransportTypeEnum; | ||
| 54 | + [FormFieldsEnum.ENTITY_TYPE]?: TriggerEntityTypeEnum; | ||
| 55 | + [FormFieldsEnum.ENTITY_ID]?: string[]; | ||
| 56 | + [FormFieldsEnum.CALL_SERVICE_IDENTIFIER]?: string; | ||
| 57 | + [FormFieldsEnum.CALL_SERVICE]?: DeviceModelOfMatterAttrs; | ||
| 58 | + [FormFieldsEnum.SERVICE_ID]?: string; | ||
| 59 | +} |
| 1 | +import { Ref, unref, nextTick, toRaw } from 'vue'; | ||
| 2 | +import { DefineComponentsBasicExpose } from '/#/utils'; | ||
| 3 | +import { | ||
| 4 | + DoContextAlarmType, | ||
| 5 | + DoContextType, | ||
| 6 | + ExecutionActionDataItemType, | ||
| 7 | + ExecutionActionFormItemRecordType, | ||
| 8 | + ExecutionActionListRefItemType, | ||
| 9 | +} from './type'; | ||
| 10 | +import { CommandTypeEnum, ExecutionActionEnum } from '/@/enums/linkedgeEnum'; | ||
| 11 | +import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; | ||
| 12 | +import { useJsonParse } from '/@/hooks/business/useJsonParse'; | ||
| 13 | +import { createNewExecutionActionItem } from '.'; | ||
| 14 | +import { FormFieldsEnum } from './config'; | ||
| 15 | +import { isObject, isString } from '/@/utils/is'; | ||
| 16 | + | ||
| 17 | +export function useExecutionActionData( | ||
| 18 | + executionActionListRef: Ref<ExecutionActionListRefItemType[]>, | ||
| 19 | + hasAlarmNotify: Ref<boolean> | ||
| 20 | +): DefineComponentsBasicExpose<ExecutionActionDataItemType[]> { | ||
| 21 | + const getExecutionActionItemData = (executionActionItem: ExecutionActionListRefItemType) => { | ||
| 22 | + const { ref, alarmClearRuleElRef, thingsModelFormRefl } = executionActionItem; | ||
| 23 | + const { | ||
| 24 | + callType, | ||
| 25 | + commandType, | ||
| 26 | + deviceType, | ||
| 27 | + deviceProfileId, | ||
| 28 | + entityType, | ||
| 29 | + entityId, | ||
| 30 | + outTarget, | ||
| 31 | + transportType, | ||
| 32 | + alarmLevel, | ||
| 33 | + callServiceIdentifier, | ||
| 34 | + serviceId, | ||
| 35 | + tcpCustomCommand, | ||
| 36 | + customCommand, | ||
| 37 | + alarmProfileId, | ||
| 38 | + } = (ref?.getFieldsValue?.() || {}) as Required<ExecutionActionFormItemRecordType>; | ||
| 39 | + | ||
| 40 | + const thingsModelFormRecord = thingsModelFormRefl?.getFieldsValue?.(); | ||
| 41 | + | ||
| 42 | + const clearRule = alarmClearRuleElRef?.getFieldsValue(); | ||
| 43 | + | ||
| 44 | + const record: ExecutionActionDataItemType = { | ||
| 45 | + callType, | ||
| 46 | + commandType, | ||
| 47 | + alarmProfileId, | ||
| 48 | + deviceType, | ||
| 49 | + deviceProfileId, | ||
| 50 | + entityType, | ||
| 51 | + deviceId: entityId, | ||
| 52 | + outTarget, | ||
| 53 | + thingsModelId: serviceId, | ||
| 54 | + doContext: {}, | ||
| 55 | + }; | ||
| 56 | + | ||
| 57 | + if (outTarget === ExecutionActionEnum.DEVICE_OUT) { | ||
| 58 | + record.doContext = { | ||
| 59 | + method: 'methodThingskit', | ||
| 60 | + additionalInfo: { cmdType: commandType }, | ||
| 61 | + params: | ||
| 62 | + commandType === CommandTypeEnum.CUSTOM | ||
| 63 | + ? transportType === TransportTypeEnum.TCP | ||
| 64 | + ? tcpCustomCommand | ||
| 65 | + : useJsonParse(customCommand).value | ||
| 66 | + : { | ||
| 67 | + [callServiceIdentifier]: thingsModelFormRecord, | ||
| 68 | + }, | ||
| 69 | + }; | ||
| 70 | + } else { | ||
| 71 | + record.doContext = { | ||
| 72 | + alarmLevel, | ||
| 73 | + clearRule: clearRule || [], | ||
| 74 | + }; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + return record; | ||
| 78 | + }; | ||
| 79 | + | ||
| 80 | + const getFieldsValue = () => { | ||
| 81 | + const dataList: ExecutionActionDataItemType[] = []; | ||
| 82 | + for (const executionActionItem of unref(executionActionListRef)) { | ||
| 83 | + dataList.push(getExecutionActionItemData(executionActionItem)); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + return dataList; | ||
| 87 | + }; | ||
| 88 | + | ||
| 89 | + const setFieldsValue = (executionActionData: ExecutionActionDataItemType[]) => { | ||
| 90 | + executionActionListRef.value = Array.from({ length: executionActionData.length }, () => | ||
| 91 | + createNewExecutionActionItem() | ||
| 92 | + ); | ||
| 93 | + | ||
| 94 | + nextTick(() => { | ||
| 95 | + unref(executionActionListRef).forEach((executionActionItem, index) => { | ||
| 96 | + const result = executionActionData[index]; | ||
| 97 | + | ||
| 98 | + const { doContext, outTarget, commandType } = result; | ||
| 99 | + | ||
| 100 | + const { thingsModelId, deviceId } = result; | ||
| 101 | + | ||
| 102 | + const record = { | ||
| 103 | + ...result, | ||
| 104 | + [FormFieldsEnum.SERVICE_ID]: thingsModelId, | ||
| 105 | + [FormFieldsEnum.ENTITY_ID]: deviceId, | ||
| 106 | + }; | ||
| 107 | + | ||
| 108 | + if (outTarget === ExecutionActionEnum.MSG_NOTIFY) { | ||
| 109 | + const { alarmLevel, clearRule } = doContext as DoContextAlarmType; | ||
| 110 | + Object.assign(record, { | ||
| 111 | + [FormFieldsEnum.ALARM_LEVEL]: alarmLevel, | ||
| 112 | + [FormFieldsEnum.ENABLE_CLEAR_RULE]: !!(clearRule && clearRule.length), | ||
| 113 | + }); | ||
| 114 | + hasAlarmNotify.value = true; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + if (outTarget == ExecutionActionEnum.DEVICE_OUT && (doContext as DoContextType)?.params) { | ||
| 118 | + const { params } = doContext as DoContextType; | ||
| 119 | + Object.assign(record, { | ||
| 120 | + [isString(params) ? FormFieldsEnum.TCP_CUSTOM_COMMAND : FormFieldsEnum.CUSTOM_COMMAND]: | ||
| 121 | + params, | ||
| 122 | + }); | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + if ( | ||
| 126 | + outTarget === ExecutionActionEnum.DEVICE_OUT && | ||
| 127 | + commandType === CommandTypeEnum.SERVICE | ||
| 128 | + ) { | ||
| 129 | + const { params } = doContext as DoContextType; | ||
| 130 | + if (isObject(params)) { | ||
| 131 | + const [identifier] = Object.keys(params); | ||
| 132 | + const result = params[identifier]; | ||
| 133 | + Object.assign(record, { [FormFieldsEnum.SERVICE_COMMAND]: toRaw(result || {}) }); | ||
| 134 | + executionActionItem.thingsModelFormRefl?.setFieldsValue(result || {}); | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + executionActionItem.ref?.setFieldsValue(record); | ||
| 139 | + | ||
| 140 | + if ( | ||
| 141 | + outTarget === ExecutionActionEnum.MSG_NOTIFY && | ||
| 142 | + (doContext as DoContextAlarmType).clearRule && | ||
| 143 | + (doContext as DoContextAlarmType).clearRule.length | ||
| 144 | + ) { | ||
| 145 | + nextTick(() => { | ||
| 146 | + executionActionItem.alarmClearRuleElRef?.setFieldsValue( | ||
| 147 | + (result.doContext as DoContextAlarmType).clearRule | ||
| 148 | + ); | ||
| 149 | + }); | ||
| 150 | + } | ||
| 151 | + }); | ||
| 152 | + }); | ||
| 153 | + }; | ||
| 154 | + | ||
| 155 | + const validate = async () => { | ||
| 156 | + for (const executionActionItem of unref(executionActionListRef)) { | ||
| 157 | + const { ref, alarmClearRuleElRef, thingsModelFormRefl } = executionActionItem; | ||
| 158 | + await ref?.validate?.(); | ||
| 159 | + await alarmClearRuleElRef?.validate?.(); | ||
| 160 | + await thingsModelFormRefl?.validate?.(); | ||
| 161 | + } | ||
| 162 | + }; | ||
| 163 | + | ||
| 164 | + const resetFieldsValue = () => { | ||
| 165 | + executionActionListRef.value = [createNewExecutionActionItem()]; | ||
| 166 | + hasAlarmNotify.value = false; | ||
| 167 | + }; | ||
| 168 | + | ||
| 169 | + return { | ||
| 170 | + getFieldsValue, | ||
| 171 | + setFieldsValue, | ||
| 172 | + validate, | ||
| 173 | + resetFieldsValue, | ||
| 174 | + }; | ||
| 175 | +} |
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { InputGroup, InputNumber, Select } from 'ant-design-vue'; | ||
| 3 | + import { TriggerUnitEnum } from '/@/enums/linkedgeEnum'; | ||
| 4 | + | ||
| 5 | + withDefaults( | ||
| 6 | + defineProps<{ | ||
| 7 | + value?: number; | ||
| 8 | + unit?: TriggerUnitEnum; | ||
| 9 | + unitOptions: Record<'label' | 'value', any>[]; | ||
| 10 | + disabled?: boolean; | ||
| 11 | + }>(), | ||
| 12 | + { | ||
| 13 | + value: undefined, | ||
| 14 | + unit: TriggerUnitEnum.SECONDS, | ||
| 15 | + unitOptions: () => [], | ||
| 16 | + } | ||
| 17 | + ); | ||
| 18 | + const emit = defineEmits(['unitChange', 'update:unit', 'update:value']); | ||
| 19 | + | ||
| 20 | + const handleUnitChange = (value: TriggerUnitEnum) => { | ||
| 21 | + emit('update:unit', value); | ||
| 22 | + emit('unitChange', value); | ||
| 23 | + }; | ||
| 24 | +</script> | ||
| 25 | + | ||
| 26 | +<template> | ||
| 27 | + <InputGroup class="!flex" compact> | ||
| 28 | + <InputNumber | ||
| 29 | + :disabled="disabled" | ||
| 30 | + :value="value" | ||
| 31 | + :min="0" | ||
| 32 | + @change="$emit('update:value', $event)" | ||
| 33 | + v-bind="$attrs" | ||
| 34 | + /> | ||
| 35 | + <Select | ||
| 36 | + :disabled="disabled" | ||
| 37 | + :value="unit" | ||
| 38 | + :options="unitOptions" | ||
| 39 | + :allow-clear="false" | ||
| 40 | + @change="handleUnitChange" | ||
| 41 | + /> | ||
| 42 | + </InputGroup> | ||
| 43 | +</template> |
| 1 | +import { unref } from 'vue'; | ||
| 2 | +import { useSceneLinkageDrawerContext } from '../SceneLinkageDrawer/sceneLinkageDrawerContext'; | ||
| 3 | +import { getDeviceProfile } from '/@/api/alarm/position'; | ||
| 4 | +import { byOrganizationIdGetMasterDevice } from '/@/api/ruleengine/ruleengineApi'; | ||
| 5 | +import { findDictItemByCode } from '/@/api/system/dict'; | ||
| 6 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | ||
| 7 | +import { DictEnum } from '/@/enums/dictEnum'; | ||
| 8 | +import { createPickerSearch } from '/@/utils/pickerSearch'; | ||
| 9 | +import { DeviceTypeEnum } from '../../../dataFlow/cpns/config'; | ||
| 10 | +import { getDeviceAttributes } from '/@/api/dataBoard'; | ||
| 11 | +import { DeviceAttributeParams } from '/@/api/dataBoard/model'; | ||
| 12 | +import { | ||
| 13 | + TriggerValueTypeEnum, | ||
| 14 | + TriggerValueTypeNameEnum, | ||
| 15 | + TriggerEntityTypeEnum, | ||
| 16 | + TriggerEntityTypeNameEnum, | ||
| 17 | + TriggerTypeEnum, | ||
| 18 | + TriggerTypeNameEnum, | ||
| 19 | + DeviceTriggerTypeEum, | ||
| 20 | + DeviceTriggerTypeNameEum, | ||
| 21 | + FlipFlopTypeEnum, | ||
| 22 | + FlipFlopTypeNameEnum, | ||
| 23 | + TriggerUnitEnum, | ||
| 24 | + TriggerUnitNameEnum, | ||
| 25 | +} from '/@/enums/linkedgeEnum'; | ||
| 26 | +import { DeviceModelOfMatterAttrs } from '/@/api/device/model/deviceModel'; | ||
| 27 | +import TriggerDurationInput from './TriggerDurationInput.vue'; | ||
| 28 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
| 29 | + | ||
| 30 | +export enum FormFieldEnum { | ||
| 31 | + FLIP_FLOP_TYPE = 'flipFlopType', | ||
| 32 | + DEVICE_TYPE = 'deviceType', | ||
| 33 | + DEVICE_PROFILE_ID = 'deviceProfileId', | ||
| 34 | + ENTITY_TYPE = 'entityType', | ||
| 35 | + ENTITY_ID = 'entityId', | ||
| 36 | + TRIGGER_TYPE = 'triggerType', | ||
| 37 | + CONDITION_TYPE = 'conditionType', | ||
| 38 | + CONDITION_KEY = 'conditionKey', | ||
| 39 | + CONDITION_VALUE_TYPE = 'conditionValueType', | ||
| 40 | + TRIGGER_DURATION_UNIT = 'triggerDurationUnit', | ||
| 41 | + TRIGGER_DURATION_VALUE = 'triggerDurationValue', | ||
| 42 | + TRIGGER_REPEAT_COUNT = 'triggerRepeatCount', | ||
| 43 | + | ||
| 44 | + CONDITION_KEY_DETAIL = 'conditionKeyDetail', | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +export enum FormFieldNameEnum { | ||
| 48 | + FLIP_FLOP_TYPE = '触发类型', | ||
| 49 | + DEVICE_TYPE = '设备类型', | ||
| 50 | + DEVICE_PROFILE_ID = '产品', | ||
| 51 | + ENTITY_TYPE = '触发设备类型', | ||
| 52 | + ENTITY_ID = '设备', | ||
| 53 | + TRIGGER_TYPE = '触发方式', | ||
| 54 | + CONDITION_TYPE = '触发条件', | ||
| 55 | + CONDITION_KEY = '属性', | ||
| 56 | + CONDITION_VALUE_TYPE = '比较类型', | ||
| 57 | + TRIGGER_DURATION_VALUE = '持续时长', | ||
| 58 | + TRIGGER_REPEAT_COUNT = '重复次数', | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +useComponentRegister('TriggerDurationInput', TriggerDurationInput); | ||
| 62 | + | ||
| 63 | +function getTriggerValueTypeByThingsModelType(type: DataTypeEnum) { | ||
| 64 | + const map = { | ||
| 65 | + [DataTypeEnum.BOOL]: TriggerValueTypeEnum.BOOLEAN, | ||
| 66 | + [DataTypeEnum.NUMBER_DOUBLE]: TriggerValueTypeEnum.NUMERIC, | ||
| 67 | + [DataTypeEnum.NUMBER_INT]: TriggerValueTypeEnum.NUMERIC, | ||
| 68 | + [DataTypeEnum.STRING]: TriggerValueTypeEnum.STRING, | ||
| 69 | + [DataTypeEnum.STRUCT]: TriggerValueTypeEnum.STRING, | ||
| 70 | + }; | ||
| 71 | + | ||
| 72 | + return map[type]; | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +export const getFormSchemas = (): FormSchema[] => { | ||
| 76 | + const { organizationId } = useSceneLinkageDrawerContext(); | ||
| 77 | + | ||
| 78 | + return [ | ||
| 79 | + { | ||
| 80 | + field: FormFieldEnum.FLIP_FLOP_TYPE, | ||
| 81 | + label: '', | ||
| 82 | + component: 'Select', | ||
| 83 | + rules: [{ required: true, message: `请选择${FormFieldNameEnum.FLIP_FLOP_TYPE}` }], | ||
| 84 | + defaultValue: FlipFlopTypeEnum.SIMPLE, | ||
| 85 | + componentProps: () => { | ||
| 86 | + return { | ||
| 87 | + options: Object.keys(FlipFlopTypeEnum).map((value) => ({ | ||
| 88 | + label: FlipFlopTypeNameEnum[value], | ||
| 89 | + value, | ||
| 90 | + })), | ||
| 91 | + placeholder: `请选择${FormFieldNameEnum.FLIP_FLOP_TYPE}`, | ||
| 92 | + }; | ||
| 93 | + }, | ||
| 94 | + }, | ||
| 95 | + { | ||
| 96 | + field: FormFieldEnum.DEVICE_TYPE, | ||
| 97 | + label: '', | ||
| 98 | + component: 'ApiSelect', | ||
| 99 | + defaultValue: DeviceTypeEnum.SENSOR, | ||
| 100 | + rules: [{ required: true, message: `请选择${FormFieldNameEnum.DEVICE_TYPE}` }], | ||
| 101 | + componentProps: ({ formActionType }) => { | ||
| 102 | + const { setFieldsValue } = formActionType; | ||
| 103 | + return { | ||
| 104 | + api: findDictItemByCode, | ||
| 105 | + params: { | ||
| 106 | + dictCode: DictEnum.DEVICE_TYPE, | ||
| 107 | + }, | ||
| 108 | + labelField: 'itemText', | ||
| 109 | + valueField: 'itemValue', | ||
| 110 | + placeholder: `请选择${FormFieldNameEnum.DEVICE_TYPE}`, | ||
| 111 | + onChange() { | ||
| 112 | + setFieldsValue({ | ||
| 113 | + [FormFieldEnum.DEVICE_PROFILE_ID]: null, | ||
| 114 | + [FormFieldEnum.ENTITY_ID]: [], | ||
| 115 | + [FormFieldEnum.CONDITION_KEY]: null, | ||
| 116 | + }); | ||
| 117 | + }, | ||
| 118 | + }; | ||
| 119 | + }, | ||
| 120 | + }, | ||
| 121 | + { | ||
| 122 | + field: FormFieldEnum.DEVICE_PROFILE_ID, | ||
| 123 | + label: '', | ||
| 124 | + component: 'ApiSelect', | ||
| 125 | + rules: [{ required: true, message: `请选择${FormFieldNameEnum.DEVICE_PROFILE_ID}` }], | ||
| 126 | + componentProps: ({ formModel, formActionType }) => { | ||
| 127 | + const deviceType = formModel[FormFieldEnum.DEVICE_TYPE]; | ||
| 128 | + const { setFieldsValue } = formActionType; | ||
| 129 | + return { | ||
| 130 | + api: async () => { | ||
| 131 | + return await getDeviceProfile(deviceType); | ||
| 132 | + }, | ||
| 133 | + labelField: 'name', | ||
| 134 | + valueField: 'id', | ||
| 135 | + placeholder: `请选择${FormFieldNameEnum.DEVICE_PROFILE_ID}`, | ||
| 136 | + ...createPickerSearch(), | ||
| 137 | + onChange() { | ||
| 138 | + setFieldsValue({ | ||
| 139 | + [FormFieldEnum.ENTITY_ID]: [], | ||
| 140 | + [FormFieldEnum.CONDITION_KEY]: null, | ||
| 141 | + }); | ||
| 142 | + }, | ||
| 143 | + }; | ||
| 144 | + }, | ||
| 145 | + }, | ||
| 146 | + { | ||
| 147 | + field: FormFieldEnum.ENTITY_TYPE, | ||
| 148 | + label: '', | ||
| 149 | + component: 'Select', | ||
| 150 | + rules: [{ required: true, message: `请选择${FormFieldNameEnum.ENTITY_TYPE}` }], | ||
| 151 | + componentProps: () => { | ||
| 152 | + return { | ||
| 153 | + options: Object.keys(TriggerEntityTypeEnum).map((value) => ({ | ||
| 154 | + label: TriggerEntityTypeNameEnum[value], | ||
| 155 | + value, | ||
| 156 | + })), | ||
| 157 | + placeholder: `请选择${FormFieldNameEnum.ENTITY_TYPE}`, | ||
| 158 | + }; | ||
| 159 | + }, | ||
| 160 | + }, | ||
| 161 | + { | ||
| 162 | + field: FormFieldEnum.TRIGGER_DURATION_UNIT, | ||
| 163 | + label: '', | ||
| 164 | + component: 'Input', | ||
| 165 | + ifShow: false, | ||
| 166 | + defaultValue: TriggerUnitEnum.SECONDS, | ||
| 167 | + }, | ||
| 168 | + { | ||
| 169 | + field: FormFieldEnum.TRIGGER_DURATION_VALUE, | ||
| 170 | + label: '', | ||
| 171 | + component: 'TriggerDurationInput', | ||
| 172 | + rules: [ | ||
| 173 | + { | ||
| 174 | + required: true, | ||
| 175 | + message: `请输入${FormFieldNameEnum.TRIGGER_DURATION_VALUE}`, | ||
| 176 | + type: 'number', | ||
| 177 | + }, | ||
| 178 | + ], | ||
| 179 | + changeEvent: 'update:value', | ||
| 180 | + ifShow: ({ model }) => model[FormFieldEnum.FLIP_FLOP_TYPE] === FlipFlopTypeEnum.DURATION, | ||
| 181 | + componentProps: ({ formActionType, formModel }) => { | ||
| 182 | + const { setFieldsValue } = formActionType; | ||
| 183 | + return { | ||
| 184 | + placeholder: `请输入${FormFieldNameEnum.TRIGGER_DURATION_VALUE}`, | ||
| 185 | + unit: formModel[FormFieldEnum.TRIGGER_DURATION_UNIT], | ||
| 186 | + unitOptions: Object.values(TriggerUnitEnum).map((value) => ({ | ||
| 187 | + label: TriggerUnitNameEnum[value], | ||
| 188 | + value, | ||
| 189 | + })), | ||
| 190 | + onUnitChange(value: TriggerUnitEnum) { | ||
| 191 | + setFieldsValue({ [FormFieldEnum.TRIGGER_DURATION_UNIT]: value }); | ||
| 192 | + }, | ||
| 193 | + }; | ||
| 194 | + }, | ||
| 195 | + }, | ||
| 196 | + { | ||
| 197 | + field: FormFieldEnum.TRIGGER_REPEAT_COUNT, | ||
| 198 | + label: '', | ||
| 199 | + component: 'InputNumber', | ||
| 200 | + rules: [{ required: true, message: `请输入${FormFieldNameEnum.TRIGGER_REPEAT_COUNT}` }], | ||
| 201 | + ifShow: ({ model }) => model[FormFieldEnum.FLIP_FLOP_TYPE] === FlipFlopTypeEnum.REPEATING, | ||
| 202 | + componentProps: { | ||
| 203 | + placeholder: `请输入${FormFieldNameEnum.TRIGGER_REPEAT_COUNT}`, | ||
| 204 | + min: 0, | ||
| 205 | + }, | ||
| 206 | + }, | ||
| 207 | + { | ||
| 208 | + field: FormFieldEnum.ENTITY_ID, | ||
| 209 | + label: '', | ||
| 210 | + component: 'ApiSelect', | ||
| 211 | + rules: [{ required: true, type: 'array', message: `请选择${FormFieldNameEnum.ENTITY_ID}` }], | ||
| 212 | + ifShow: ({ model }) => model[FormFieldEnum.ENTITY_TYPE] === TriggerEntityTypeEnum.PART, | ||
| 213 | + componentProps: ({ formModel }) => { | ||
| 214 | + return { | ||
| 215 | + api: async (params: Record<'organizationId' | 'deviceProfileId', string>) => { | ||
| 216 | + if (params.deviceProfileId && params.organizationId) { | ||
| 217 | + const result = await byOrganizationIdGetMasterDevice(params); | ||
| 218 | + if (result) { | ||
| 219 | + return result.map((item) => ({ | ||
| 220 | + ...item, | ||
| 221 | + label: item.alias || item.name, | ||
| 222 | + value: item.tbDeviceId, | ||
| 223 | + })); | ||
| 224 | + } | ||
| 225 | + } | ||
| 226 | + return []; | ||
| 227 | + }, | ||
| 228 | + mode: 'multiple', | ||
| 229 | + maxTagCount: 3, | ||
| 230 | + params: { | ||
| 231 | + organizationId: unref(organizationId), | ||
| 232 | + deviceProfileId: formModel[FormFieldEnum.DEVICE_PROFILE_ID], | ||
| 233 | + }, | ||
| 234 | + placeholder: `请选择${FormFieldNameEnum.ENTITY_ID}`, | ||
| 235 | + ...createPickerSearch(), | ||
| 236 | + }; | ||
| 237 | + }, | ||
| 238 | + }, | ||
| 239 | + { | ||
| 240 | + field: FormFieldEnum.TRIGGER_TYPE, | ||
| 241 | + label: '', | ||
| 242 | + component: 'Select', | ||
| 243 | + rules: [{ required: true, message: `请选择${FormFieldNameEnum.TRIGGER_TYPE}` }], | ||
| 244 | + defaultValue: TriggerTypeEnum.DEVICE_TRIGGER, | ||
| 245 | + componentProps: () => { | ||
| 246 | + return { | ||
| 247 | + options: [ | ||
| 248 | + { label: TriggerTypeNameEnum.DEVICE_TRIGGER, value: TriggerTypeEnum.DEVICE_TRIGGER }, | ||
| 249 | + ], | ||
| 250 | + }; | ||
| 251 | + }, | ||
| 252 | + }, | ||
| 253 | + { | ||
| 254 | + field: FormFieldEnum.CONDITION_TYPE, | ||
| 255 | + label: '', | ||
| 256 | + component: 'Select', | ||
| 257 | + rules: [{ required: true, message: `请选择${FormFieldNameEnum.CONDITION_TYPE}` }], | ||
| 258 | + defaultValue: DeviceTriggerTypeEum.TIME_SERIES, | ||
| 259 | + componentProps: () => { | ||
| 260 | + return { | ||
| 261 | + options: [ | ||
| 262 | + { | ||
| 263 | + label: DeviceTriggerTypeNameEum.TIME_SERIES, | ||
| 264 | + value: DeviceTriggerTypeEum.TIME_SERIES, | ||
| 265 | + }, | ||
| 266 | + ], | ||
| 267 | + }; | ||
| 268 | + }, | ||
| 269 | + }, | ||
| 270 | + { | ||
| 271 | + field: FormFieldEnum.CONDITION_KEY_DETAIL, | ||
| 272 | + label: '', | ||
| 273 | + component: 'Input', | ||
| 274 | + ifShow: false, | ||
| 275 | + }, | ||
| 276 | + { | ||
| 277 | + field: FormFieldEnum.CONDITION_KEY, | ||
| 278 | + label: '', | ||
| 279 | + component: 'ApiSelect', | ||
| 280 | + rules: [{ required: true, message: `请选择${FormFieldNameEnum.CONDITION_KEY}` }], | ||
| 281 | + componentProps: ({ formModel, formActionType }) => { | ||
| 282 | + const { setFieldsValue } = formActionType; | ||
| 283 | + return { | ||
| 284 | + api: async (params: DeviceAttributeParams) => { | ||
| 285 | + if (params.deviceProfileId) { | ||
| 286 | + return await getDeviceAttributes(params); | ||
| 287 | + } | ||
| 288 | + return []; | ||
| 289 | + }, | ||
| 290 | + labelField: 'name', | ||
| 291 | + valueField: 'identifier', | ||
| 292 | + params: { | ||
| 293 | + deviceProfileId: formModel[FormFieldEnum.DEVICE_PROFILE_ID], | ||
| 294 | + }, | ||
| 295 | + placeholder: `请选择${FormFieldNameEnum.CONDITION_KEY}`, | ||
| 296 | + onChange( | ||
| 297 | + value: string, | ||
| 298 | + option: DeviceModelOfMatterAttrs & Record<'label' | 'value', string> | ||
| 299 | + ) { | ||
| 300 | + setFieldsValue({ | ||
| 301 | + [FormFieldEnum.CONDITION_KEY_DETAIL]: value | ||
| 302 | + ? { ...option, identifier: option?.value, name: option?.label } | ||
| 303 | + : {}, | ||
| 304 | + [FormFieldEnum.CONDITION_VALUE_TYPE]: | ||
| 305 | + value && option?.detail?.dataType?.type | ||
| 306 | + ? getTriggerValueTypeByThingsModelType(option.detail.dataType?.type) | ||
| 307 | + : null, | ||
| 308 | + }); | ||
| 309 | + }, | ||
| 310 | + onOptionsChange( | ||
| 311 | + options: (DeviceModelOfMatterAttrs & Record<'label' | 'value', string>)[] | ||
| 312 | + ) { | ||
| 313 | + const conditionKey = formModel[FormFieldEnum.CONDITION_KEY]; | ||
| 314 | + const res = options.find((item) => item.value === conditionKey); | ||
| 315 | + res && | ||
| 316 | + setFieldsValue({ | ||
| 317 | + [FormFieldEnum.CONDITION_KEY_DETAIL]: { | ||
| 318 | + ...res, | ||
| 319 | + identifier: res?.value, | ||
| 320 | + name: res?.label, | ||
| 321 | + }, | ||
| 322 | + }); | ||
| 323 | + }, | ||
| 324 | + }; | ||
| 325 | + }, | ||
| 326 | + }, | ||
| 327 | + { | ||
| 328 | + field: FormFieldEnum.CONDITION_VALUE_TYPE, | ||
| 329 | + label: '', | ||
| 330 | + component: 'Select', | ||
| 331 | + rules: [{ required: true, message: `请选择${FormFieldNameEnum.CONDITION_VALUE_TYPE}` }], | ||
| 332 | + componentProps: () => { | ||
| 333 | + return { | ||
| 334 | + options: Object.keys(TriggerValueTypeEnum).map((value) => ({ | ||
| 335 | + label: TriggerValueTypeNameEnum[value], | ||
| 336 | + value, | ||
| 337 | + })), | ||
| 338 | + placeholder: `请选择${FormFieldNameEnum.CONDITION_VALUE_TYPE}`, | ||
| 339 | + }; | ||
| 340 | + }, | ||
| 341 | + }, | ||
| 342 | + { | ||
| 343 | + field: 'conditionFilter', | ||
| 344 | + label: '', | ||
| 345 | + component: 'Input', | ||
| 346 | + colProps: { span: 24, xxl: 24, xl: 24, lg: 24, md: 24, sm: 24, xs: 24 }, | ||
| 347 | + ifShow: ({ model }) => | ||
| 348 | + model[FormFieldEnum.CONDITION_KEY] && model[FormFieldEnum.CONDITION_VALUE_TYPE], | ||
| 349 | + colSlot: 'conditionFilter', | ||
| 350 | + }, | ||
| 351 | + ]; | ||
| 352 | +}; |
| 1 | +import { FlipFlopItemType } from './types'; | ||
| 2 | +import { ScheduleTypeEnum } from '/@/enums/linkedgeEnum'; | ||
| 3 | +import { buildUUID } from '/@/utils/uuid'; | ||
| 4 | + | ||
| 5 | +export { default as FlipFlop } from './index.vue'; | ||
| 6 | + | ||
| 7 | +export function createNewFlipFlopItem(): FlipFlopItemType { | ||
| 8 | + return { key: buildUUID(), schedule: { type: ScheduleTypeEnum.ANY_TIME } }; | ||
| 9 | +} |
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { ComponentPublicInstance, ref, unref, watch } from 'vue'; | ||
| 3 | + import { Tooltip, Button } from 'ant-design-vue'; | ||
| 4 | + import { CollapseContainer } from '/@/components/Container'; | ||
| 5 | + import { Icon } from '/@/components/Icon'; | ||
| 6 | + import { FlipFlopItemType, ScheduleOptionItemType } from './types'; | ||
| 7 | + import { BasicForm, FormActionType } from '/@/components/Form'; | ||
| 8 | + import { getFormSchemas, FormFieldEnum } from './config'; | ||
| 9 | + import { useSceneLinkageDrawerContext } from '../SceneLinkageDrawer/sceneLinkageDrawerContext'; | ||
| 10 | + import { ScheduleTypeEnum, ScheduleTypeNameEnum } from '/@/enums/linkedgeEnum'; | ||
| 11 | + import { ConditionFilter } from '../ConditionFilter'; | ||
| 12 | + import { EnablingRule } from '../EnablingRule'; | ||
| 13 | + import { useModal } from '/@/components/Modal'; | ||
| 14 | + import { DataActionModeEnum } from '/@/enums/toolEnum'; | ||
| 15 | + import { EnableRuleFormModalParamsType, ScheduleType } from '../EnablingRule/type'; | ||
| 16 | + import { useFlipFlopData } from './useFlipFlopData'; | ||
| 17 | + import { createNewFlipFlopItem } from '.'; | ||
| 18 | + | ||
| 19 | + const { disabledDrawer } = useSceneLinkageDrawerContext(); | ||
| 20 | + | ||
| 21 | + const emit = defineEmits(['delete']); | ||
| 22 | + | ||
| 23 | + const props = withDefaults( | ||
| 24 | + defineProps<{ | ||
| 25 | + addButtonName?: string; | ||
| 26 | + defaultNull?: boolean; | ||
| 27 | + panelTitle?: (index: number) => string; | ||
| 28 | + showAddButton?: boolean; | ||
| 29 | + disabled?: boolean; | ||
| 30 | + }>(), | ||
| 31 | + { | ||
| 32 | + addButtonName: '触发器 (OR)', | ||
| 33 | + defaultNull: false, | ||
| 34 | + panelTitle: (index: number) => `触发器${index}`, | ||
| 35 | + showAddButton: true, | ||
| 36 | + disabled: false, | ||
| 37 | + } | ||
| 38 | + ); | ||
| 39 | + | ||
| 40 | + const formSchemas = getFormSchemas(); | ||
| 41 | + | ||
| 42 | + const [registerModal, { openModal }] = useModal(); | ||
| 43 | + | ||
| 44 | + const handleOpenModal = (type: ScheduleTypeEnum, flipFlopItem: FlipFlopItemType) => { | ||
| 45 | + if (unref(disabledDrawer) && type !== flipFlopItem.schedule.type) return; | ||
| 46 | + | ||
| 47 | + if (type === ScheduleTypeEnum.ANY_TIME) { | ||
| 48 | + flipFlopItem.schedule = { type }; | ||
| 49 | + return; | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + openModal(true, { | ||
| 53 | + mode: DataActionModeEnum.CREATE, | ||
| 54 | + record: { | ||
| 55 | + type, | ||
| 56 | + schedule: flipFlopItem.schedule, | ||
| 57 | + key: flipFlopItem.key, | ||
| 58 | + }, | ||
| 59 | + } as EnableRuleFormModalParamsType); | ||
| 60 | + }; | ||
| 61 | + | ||
| 62 | + const handleRuleSetting = (params: ScheduleType, key: string) => { | ||
| 63 | + const index = unref(flipFlopListElRef).findIndex((flipFlopItem) => flipFlopItem.key === key); | ||
| 64 | + | ||
| 65 | + ~index && (unref(flipFlopListElRef)[index].schedule = params); | ||
| 66 | + }; | ||
| 67 | + | ||
| 68 | + const scheduleOptions: ScheduleOptionItemType[] = Object.keys(ScheduleTypeEnum).map((value) => ({ | ||
| 69 | + label: ScheduleTypeNameEnum[value], | ||
| 70 | + value: value as ScheduleTypeEnum, | ||
| 71 | + })); | ||
| 72 | + | ||
| 73 | + const { organizationId } = useSceneLinkageDrawerContext(); | ||
| 74 | + | ||
| 75 | + const flipFlopListElRef = ref<FlipFlopItemType[]>( | ||
| 76 | + props.defaultNull ? [] : [createNewFlipFlopItem()] | ||
| 77 | + ); | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * @description on organization change | ||
| 81 | + */ | ||
| 82 | + watch(organizationId, () => { | ||
| 83 | + unref(flipFlopListElRef).forEach((flipFlopItem) => | ||
| 84 | + flipFlopItem.ref?.setFieldsValue({ [FormFieldEnum.ENTITY_ID]: [] }) | ||
| 85 | + ); | ||
| 86 | + }); | ||
| 87 | + | ||
| 88 | + const setFlopFlipFormRef = ( | ||
| 89 | + flipFlopItem: FlipFlopItemType, | ||
| 90 | + el: Nullable<Element | ComponentPublicInstance> | ||
| 91 | + ) => { | ||
| 92 | + flipFlopItem.ref = el as unknown as FormActionType; | ||
| 93 | + }; | ||
| 94 | + | ||
| 95 | + const setFlopFlipConditionRef = ( | ||
| 96 | + flipFlopItem: FlipFlopItemType, | ||
| 97 | + el: Nullable<Element | ComponentPublicInstance> | ||
| 98 | + ) => { | ||
| 99 | + flipFlopItem.conditionRef = el as unknown as InstanceType<typeof ConditionFilter>; | ||
| 100 | + }; | ||
| 101 | + | ||
| 102 | + const handleDelete = (flipFlopItem: FlipFlopItemType) => { | ||
| 103 | + const index = unref(flipFlopListElRef).findIndex((item) => item.key === flipFlopItem.key); | ||
| 104 | + ~index && unref(flipFlopListElRef).splice(index, 1); | ||
| 105 | + emit('delete'); | ||
| 106 | + }; | ||
| 107 | + | ||
| 108 | + const handleAdd = () => { | ||
| 109 | + flipFlopListElRef.value.push(createNewFlipFlopItem()); | ||
| 110 | + }; | ||
| 111 | + | ||
| 112 | + const { getFieldsValue, setFieldsValue, validate, resetFieldsValue } = | ||
| 113 | + useFlipFlopData(flipFlopListElRef); | ||
| 114 | + | ||
| 115 | + defineExpose({ getFieldsValue, setFieldsValue, validate, resetFieldsValue }); | ||
| 116 | +</script> | ||
| 117 | + | ||
| 118 | +<template> | ||
| 119 | + <section> | ||
| 120 | + <CollapseContainer | ||
| 121 | + v-for="(flipFlopItem, index) in flipFlopListElRef" | ||
| 122 | + :key="flipFlopItem.key" | ||
| 123 | + :title="panelTitle(index + 1)" | ||
| 124 | + class="mb-4" | ||
| 125 | + > | ||
| 126 | + <template #action> | ||
| 127 | + <header class="flex items-center justify-between"> | ||
| 128 | + <div class="flex items-center"> | ||
| 129 | + <div class="flex"> | ||
| 130 | + <span class="mr-2">启用规则:</span> | ||
| 131 | + <div | ||
| 132 | + class="px-1 cursor-pointer" | ||
| 133 | + v-for="schedule in scheduleOptions" | ||
| 134 | + :key="schedule.value" | ||
| 135 | + type="text" | ||
| 136 | + :class="flipFlopItem.schedule.type === schedule.value ? 'text-blue-400' : ''" | ||
| 137 | + @click="handleOpenModal(schedule.value, flipFlopItem)" | ||
| 138 | + > | ||
| 139 | + {{ schedule.label }} | ||
| 140 | + </div> | ||
| 141 | + </div> | ||
| 142 | + <Tooltip title="删除"> | ||
| 143 | + <Icon | ||
| 144 | + v-if="!disabledDrawer" | ||
| 145 | + class="ml-2 cursor-pointer" | ||
| 146 | + icon="fluent:delete-off-20-regular" | ||
| 147 | + size="20" | ||
| 148 | + @click="handleDelete(flipFlopItem)" | ||
| 149 | + /> | ||
| 150 | + </Tooltip> | ||
| 151 | + </div> | ||
| 152 | + </header> | ||
| 153 | + </template> | ||
| 154 | + <BasicForm | ||
| 155 | + :ref="(el) => setFlopFlipFormRef(flipFlopItem, el)" | ||
| 156 | + :key="flipFlopItem.key" | ||
| 157 | + class="trigger-form" | ||
| 158 | + layout="horizontal" | ||
| 159 | + :disabled="disabledDrawer" | ||
| 160 | + :schemas="formSchemas" | ||
| 161 | + :showActionButtonGroup="false" | ||
| 162 | + :baseColProps="{ span: 6, xxl: 6, xl: 8, lg: 12, sm: 24 }" | ||
| 163 | + > | ||
| 164 | + <template #conditionFilter="{ model }"> | ||
| 165 | + <ConditionFilter | ||
| 166 | + :ref="(el) => setFlopFlipConditionRef(flipFlopItem, el)" | ||
| 167 | + :triggerType="model[FormFieldEnum.CONDITION_VALUE_TYPE]" | ||
| 168 | + :object-model="model[FormFieldEnum.CONDITION_KEY_DETAIL]" | ||
| 169 | + :condition-type="model[FormFieldEnum.CONDITION_TYPE]" | ||
| 170 | + /> | ||
| 171 | + </template> | ||
| 172 | + </BasicForm> | ||
| 173 | + </CollapseContainer> | ||
| 174 | + <Button | ||
| 175 | + v-if="showAddButton && !disabledDrawer" | ||
| 176 | + type="primary" | ||
| 177 | + class="w-full" | ||
| 178 | + @click="handleAdd" | ||
| 179 | + > | ||
| 180 | + <Icon icon="ant-design:plus-outlined" /> | ||
| 181 | + {{ addButtonName }} | ||
| 182 | + </Button> | ||
| 183 | + | ||
| 184 | + <EnablingRule @register="registerModal" @setting-complete="handleRuleSetting" /> | ||
| 185 | + </section> | ||
| 186 | +</template> | ||
| 187 | + | ||
| 188 | +<style lang="less" scoped> | ||
| 189 | + .trigger-form { | ||
| 190 | + :deep(.ant-form-item-control-input-content) { | ||
| 191 | + width: 100%; | ||
| 192 | + | ||
| 193 | + > div > div { | ||
| 194 | + width: 100%; | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + .ant-input-number { | ||
| 198 | + width: 100% !important; | ||
| 199 | + } | ||
| 200 | + // .ant-col { | ||
| 201 | + // .ant-row{ | ||
| 202 | + // .ant-col { | ||
| 203 | + // . | ||
| 204 | + // } | ||
| 205 | + // } | ||
| 206 | + // } | ||
| 207 | + } | ||
| 208 | + } | ||
| 209 | +</style> |
| 1 | +import { ConditionFilter } from '../ConditionFilter'; | ||
| 2 | +import { TriggerCondition } from '../ConditionFilter/type'; | ||
| 3 | +import { ScheduleType } from '../EnablingRule/type'; | ||
| 4 | +import { FormFieldEnum } from './config'; | ||
| 5 | +import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | ||
| 6 | +import { FormActionType } from '/@/components/Form'; | ||
| 7 | +import { | ||
| 8 | + DeviceTriggerTypeEum, | ||
| 9 | + FlipFlopTypeEnum, | ||
| 10 | + ScheduleTypeEnum, | ||
| 11 | + TriggerEntityTypeEnum, | ||
| 12 | + TriggerTypeEnum, | ||
| 13 | + TriggerUnitEnum, | ||
| 14 | + TriggerValueTypeNameEnum, | ||
| 15 | +} from '/@/enums/linkedgeEnum'; | ||
| 16 | + | ||
| 17 | +export interface ScheduleOptionItemType { | ||
| 18 | + label: string; | ||
| 19 | + value: ScheduleTypeEnum; | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +export interface FlipFlopItemType { | ||
| 23 | + key: string; | ||
| 24 | + ref?: FormActionType; | ||
| 25 | + schedule: ScheduleType; | ||
| 26 | + conditionRef?: InstanceType<typeof ConditionFilter>; | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +export interface FlipFlopConditionType { | ||
| 30 | + deviceProfileId: string; | ||
| 31 | + deviceType: DeviceTypeEnum; | ||
| 32 | + entityId: string[]; | ||
| 33 | + entityType: TriggerEntityTypeEnum; | ||
| 34 | + triggerCondition: TriggerCondition; | ||
| 35 | + triggerType: TriggerTypeEnum; | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +export interface FlipFlopFormRecordType { | ||
| 39 | + [FormFieldEnum.FLIP_FLOP_TYPE]: FlipFlopTypeEnum; | ||
| 40 | + [FormFieldEnum.DEVICE_TYPE]: DeviceTypeEnum; | ||
| 41 | + [FormFieldEnum.DEVICE_PROFILE_ID]: string; | ||
| 42 | + [FormFieldEnum.ENTITY_TYPE]: TriggerEntityTypeEnum; | ||
| 43 | + [FormFieldEnum.ENTITY_ID]: string[]; | ||
| 44 | + [FormFieldEnum.TRIGGER_TYPE]: TriggerTypeEnum; | ||
| 45 | + [FormFieldEnum.CONDITION_TYPE]: DeviceTriggerTypeEum; | ||
| 46 | + [FormFieldEnum.CONDITION_KEY]: string; | ||
| 47 | + [FormFieldEnum.CONDITION_VALUE_TYPE]: TriggerValueTypeNameEnum; | ||
| 48 | + [FormFieldEnum.TRIGGER_DURATION_VALUE]: number; | ||
| 49 | + [FormFieldEnum.TRIGGER_REPEAT_COUNT]: number; | ||
| 50 | + [FormFieldEnum.TRIGGER_DURATION_UNIT]: TriggerUnitEnum; | ||
| 51 | +} |