Showing
22 changed files
with
399 additions
and
402 deletions
1 | 1 | import { DeviceProfileModel } from '../../device/model/deviceModel'; |
2 | -import { HistoryData } from './model'; | |
2 | +import { DeviceAttributeItemType, HistoryData } from './model'; | |
3 | 3 | import { defHttp } from '/@/utils/http/axios'; |
4 | 4 | import { isString } from '/@/utils/is'; |
5 | 5 | import { OrderByEnum } from '/@/views/device/localtion/cpns/TimePeriodForm/config'; |
... | ... | @@ -38,7 +38,7 @@ export const getDeviceDataKeys = (id: string) => { |
38 | 38 | }; |
39 | 39 | // 获取设备状态,在线 or 离线时间 |
40 | 40 | export const getDeviceActiveTime = (entityId: string) => { |
41 | - return defHttp.get( | |
41 | + return defHttp.get<DeviceAttributeItemType[]>( | |
42 | 42 | { |
43 | 43 | url: `/plugins/telemetry/DEVICE/${entityId}/values/attributes?keys=active`, |
44 | 44 | }, | ... | ... |
... | ... | @@ -13,7 +13,7 @@ import { ChildDeviceParams } from './model/deviceModel'; |
13 | 13 | import { PaginationResult } from '/#/axios'; |
14 | 14 | import { AlarmLogItem } from './model/deviceConfigModel'; |
15 | 15 | import { omit } from 'lodash-es'; |
16 | -import { CommandDeliveryWayEnum } from '/@/enums/toolEnum'; | |
16 | +import { CommandDeliveryWayEnum } from '/@/enums/deviceEnum'; | |
17 | 17 | enum DeviceManagerApi { |
18 | 18 | /** |
19 | 19 | * 设备URL | ... | ... |
1 | 1 | import { BasicPageParams } from '/@/api/model/baseModel'; |
2 | +import { CommandTypeEnum, RPCCommandMethodEnum } from '/@/enums/deviceEnum'; | |
2 | 3 | |
3 | 4 | export type TDeviceConfigPageQueryParam = BasicPageParams & TDeviceConfigParams; |
4 | 5 | |
... | ... | @@ -184,3 +185,10 @@ export interface Configuration { |
184 | 185 | export interface TransportConfiguration { |
185 | 186 | type: string; |
186 | 187 | } |
188 | + | |
189 | +export interface RpcCommandType { | |
190 | + additionalInfo: { cmdType: CommandTypeEnum }; | |
191 | + method: RPCCommandMethodEnum; | |
192 | + params: Recordable | string | number; | |
193 | + persistent: boolean; | |
194 | +} | ... | ... |
... | ... | @@ -2,7 +2,7 @@ import { withInstall } from '/@/utils'; |
2 | 2 | // @ts-ignore |
3 | 3 | import codeEditor from './src/CodeEditor.vue'; |
4 | 4 | import jsonPreview from './src/json-preview/JsonPreview.vue'; |
5 | -export { JSONEditor } from './src/JSONEditor'; | |
5 | +export { JSONEditor, JSONEditorValidator, parseStringToJSON } from './src/JSONEditor'; | |
6 | 6 | |
7 | 7 | export const CodeEditor = withInstall(codeEditor); |
8 | 8 | export const JsonPreview = withInstall(jsonPreview); | ... | ... |
1 | -import { FormSchema } from '../../../types/form'; | |
1 | +import { FormSchema } from '/@/components/Form'; | |
2 | 2 | import { Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
3 | 3 | import { TransportTypeEnum } from '/@/enums/deviceEnum'; |
4 | 4 | import { DataTypeEnum } from '/@/enums/objectModelEnum'; |
5 | +import { validateTCPCustomCommand } from '.'; | |
5 | 6 | |
6 | 7 | export const getFormSchemas = ({ |
7 | 8 | structJSON: structJson, |
... | ... | @@ -143,6 +144,7 @@ export const getFormSchemas = ({ |
143 | 144 | component: 'Input', |
144 | 145 | required, |
145 | 146 | defaultValue: serviceCommand, |
147 | + rules: [{ validator: validateTCPCustomCommand }], | |
146 | 148 | componentProps: { |
147 | 149 | placeholder: `请输入服务命令`, |
148 | 150 | }, | ... | ... |
... | ... | @@ -6,3 +6,45 @@ export enum TransportTypeEnum { |
6 | 6 | SNMP = 'SNMP', |
7 | 7 | TCP = 'TCP', |
8 | 8 | } |
9 | + | |
10 | +export enum ReadAndWriteEnum { | |
11 | + READ = 'r', | |
12 | + READ_AND_WRITE = 'rw', | |
13 | +} | |
14 | + | |
15 | +export enum ServiceCallTypeEnum { | |
16 | + ASYNC = 'ASYNC', | |
17 | + SYNC = 'SYNC', | |
18 | +} | |
19 | + | |
20 | +export enum ServiceCallTypeNameEnum { | |
21 | + ASYNC = '异步', | |
22 | + SYNC = '同步', | |
23 | +} | |
24 | + | |
25 | +export enum CommandDeliveryWayEnum { | |
26 | + ONE_WAY = 'oneway', | |
27 | + TWO_WAY = 'twoway', | |
28 | +} | |
29 | + | |
30 | +export enum CommandDeliveryWayNameEnum { | |
31 | + ONE_WAY = '单向', | |
32 | + TWO_WAY = '双向', | |
33 | +} | |
34 | + | |
35 | +export enum CommandTypeEnum { | |
36 | + CUSTOM = 0, | |
37 | + SERVICE = 1, | |
38 | + ATTRIBUTE = 2, | |
39 | + API = 'api', | |
40 | +} | |
41 | + | |
42 | +export enum CommandTypeNameEnum { | |
43 | + CUSTOM = '自定义', | |
44 | + SERVICE = '服务', | |
45 | + ATTRIBUTE = '属性', | |
46 | +} | |
47 | + | |
48 | +export enum RPCCommandMethodEnum { | |
49 | + THINGSKIT = 'methodThingskit', | |
50 | +} | ... | ... |
... | ... | @@ -154,16 +154,3 @@ export enum ExecutionActionNameEnum { |
154 | 154 | DEVICE_OUT = '设备输出', |
155 | 155 | MSG_NOTIFY = '告警输出', |
156 | 156 | } |
157 | - | |
158 | -export enum CommandTypeEnum { | |
159 | - CUSTOM = 0, | |
160 | - SERVICE = 1, | |
161 | - ATTRIBUTE = 2, | |
162 | - API = 'api', | |
163 | -} | |
164 | - | |
165 | -export enum CommandTypeNameEnum { | |
166 | - CUSTOM = '自定义', | |
167 | - SERVICE = '服务', | |
168 | - ATTRIBUTE = '属性', | |
169 | -} | ... | ... |
... | ... | @@ -29,23 +29,3 @@ export enum BooleanStringEnum { |
29 | 29 | TRUE = 'true', |
30 | 30 | FALSE = 'false', |
31 | 31 | } |
32 | - | |
33 | -export enum ReadAndWriteEnum { | |
34 | - READ = 'r', | |
35 | - READ_AND_WRITE = 'rw', | |
36 | -} | |
37 | - | |
38 | -export enum ServiceCallTypeEnum { | |
39 | - ASYNC = 'ASYNC', | |
40 | - SYNC = 'SYNC', | |
41 | -} | |
42 | - | |
43 | -export enum ServiceCallTypeNameEnum { | |
44 | - ASYNC = '异步', | |
45 | - SYNC = '同步', | |
46 | -} | |
47 | - | |
48 | -export enum CommandDeliveryWayEnum { | |
49 | - ONE_WAY = 'oneway', | |
50 | - TWO_WAY = 'twoway', | |
51 | -} | ... | ... |
1 | -import { FormProps, FormSchema, useComponentRegister } from '/@/components/Form'; | |
1 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | |
2 | 2 | import { findDictItemByCode } from '/@/api/system/dict'; |
3 | 3 | import { getGatewayDevice, queryDeviceProfileBy } from '/@/api/device/deviceManager'; |
4 | -import { JSONEditorValidator } from '/@/components/CodeEditor/src/JSONEditor'; | |
5 | 4 | import { JSONEditor } from '/@/components/CodeEditor'; |
6 | 5 | import { DeviceRecord, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
7 | -import { getModelServices } from '/@/api/device/modelOfMatter'; | |
8 | -import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; | |
9 | -import { h, toRaw, unref } from 'vue'; | |
10 | -import { CommandDeliveryWayEnum, ServiceCallTypeEnum } from '/@/enums/toolEnum'; | |
6 | +import { h } from 'vue'; | |
11 | 7 | import { TaskTypeEnum } from '/@/views/task/center/config'; |
12 | 8 | import { AddressTypeEnum } from '/@/views/task/center/components/PollCommandInput'; |
13 | 9 | import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; |
... | ... | @@ -908,214 +904,3 @@ export const TokenSchemas: FormSchema[] = [ |
908 | 904 | }, |
909 | 905 | }, |
910 | 906 | ]; |
911 | - | |
912 | -export enum ValueType { | |
913 | - JSON = 'json', | |
914 | - STRING = 'string', | |
915 | -} | |
916 | - | |
917 | -export enum CommandFieldsEnum { | |
918 | - COMMAND_TYPE = 'commandType', | |
919 | - VALUE_TYPE = 'valueType', | |
920 | - COMMAND_TEXT = 'commandText', | |
921 | - COMAND_VALUE = 'commandValue', | |
922 | - SERVICE = 'service', | |
923 | - SERVICE_TYPE = 'service_type', | |
924 | - TCP_SERVICE = 'tcpService', | |
925 | - MODEL_INPUT = 'modelInput', | |
926 | - CUSTOM_TYPE = 'customType', | |
927 | -} | |
928 | - | |
929 | -export enum CommandType { | |
930 | - CUSTOM = 'custom', | |
931 | - SERVICE = 'service', | |
932 | -} | |
933 | - | |
934 | -export const CommandSchemas = ( | |
935 | - transportType: TransportTypeEnum, | |
936 | - deviceProfileId: string | |
937 | -): FormSchema[] => { | |
938 | - return [ | |
939 | - { | |
940 | - field: CommandFieldsEnum.COMMAND_TYPE, | |
941 | - component: 'RadioGroup', | |
942 | - label: '下发类型', | |
943 | - defaultValue: CommandType.CUSTOM, | |
944 | - componentProps: ({ formActionType }) => { | |
945 | - const { setFieldsValue } = formActionType; | |
946 | - return { | |
947 | - options: [ | |
948 | - { label: '自定义', value: CommandType.CUSTOM }, | |
949 | - { label: '服务', value: CommandType.SERVICE }, | |
950 | - ], | |
951 | - onChange() { | |
952 | - setFieldsValue({ | |
953 | - [CommandFieldsEnum.SERVICE]: null, | |
954 | - [CommandFieldsEnum.MODEL_INPUT]: null, | |
955 | - [CommandFieldsEnum.COMAND_VALUE]: null, | |
956 | - [CommandFieldsEnum.COMMAND_TEXT]: null, | |
957 | - }); | |
958 | - }, | |
959 | - }; | |
960 | - }, | |
961 | - }, | |
962 | - { | |
963 | - field: CommandFieldsEnum.CUSTOM_TYPE, | |
964 | - component: 'RadioGroup', | |
965 | - label: '单向/双向', | |
966 | - defaultValue: CommandDeliveryWayEnum.ONE_WAY, | |
967 | - ifShow: ({ model }) => model[CommandFieldsEnum.COMMAND_TYPE] === CommandType.CUSTOM, | |
968 | - componentProps: { | |
969 | - options: [ | |
970 | - { | |
971 | - label: '单向', | |
972 | - value: CommandDeliveryWayEnum.ONE_WAY, | |
973 | - }, | |
974 | - { | |
975 | - label: '双向', | |
976 | - value: CommandDeliveryWayEnum.TWO_WAY, | |
977 | - }, | |
978 | - ], | |
979 | - }, | |
980 | - }, | |
981 | - { | |
982 | - field: CommandFieldsEnum.VALUE_TYPE, | |
983 | - label: '命令类型', | |
984 | - component: 'RadioGroup', | |
985 | - ifShow: ({ model }) => model[CommandFieldsEnum.COMMAND_TYPE] === CommandType.CUSTOM, | |
986 | - defaultValue: transportType === TransportTypeEnum.TCP ? ValueType.STRING : ValueType.JSON, | |
987 | - componentProps: () => { | |
988 | - const options: Record<'label' | 'value', string>[] = []; | |
989 | - if (transportType === TransportTypeEnum.TCP) { | |
990 | - options.push({ label: '字符串', value: ValueType.STRING }); | |
991 | - } else { | |
992 | - options.push({ label: 'JSON', value: ValueType.JSON }); | |
993 | - } | |
994 | - return { | |
995 | - options, | |
996 | - }; | |
997 | - }, | |
998 | - }, | |
999 | - { | |
1000 | - field: CommandFieldsEnum.COMMAND_TEXT, | |
1001 | - label: '命令', | |
1002 | - ifShow: ({ model }) => | |
1003 | - model[CommandFieldsEnum.VALUE_TYPE] === ValueType.STRING && | |
1004 | - model[CommandFieldsEnum.COMMAND_TYPE] === CommandType.CUSTOM, | |
1005 | - component: 'InputTextArea', | |
1006 | - componentProps: { | |
1007 | - autoSize: { | |
1008 | - minRows: 3, | |
1009 | - }, | |
1010 | - placeholder: '请输入命令内容', | |
1011 | - }, | |
1012 | - dynamicRules: () => { | |
1013 | - return [ | |
1014 | - { | |
1015 | - required: false, | |
1016 | - validator: (_, value) => { | |
1017 | - const zg = /^[0-9a-zA-Z]*$/; | |
1018 | - if (!zg.test(value)) { | |
1019 | - return Promise.reject('输入的内容只能是字母和数字的组合'); | |
1020 | - } else { | |
1021 | - return Promise.resolve(); | |
1022 | - } | |
1023 | - }, | |
1024 | - }, | |
1025 | - ]; | |
1026 | - }, | |
1027 | - }, | |
1028 | - { | |
1029 | - field: CommandFieldsEnum.COMAND_VALUE, | |
1030 | - label: '命令', | |
1031 | - component: 'JSONEditor', | |
1032 | - colProps: { span: 20 }, | |
1033 | - changeEvent: 'update:value', | |
1034 | - valueField: 'value', | |
1035 | - rules: [...JSONEditorValidator()], | |
1036 | - ifShow: ({ model }) => | |
1037 | - model[CommandFieldsEnum.VALUE_TYPE] === ValueType.JSON && | |
1038 | - model[CommandFieldsEnum.COMMAND_TYPE] === CommandType.CUSTOM, | |
1039 | - | |
1040 | - componentProps: { | |
1041 | - height: 250, | |
1042 | - }, | |
1043 | - }, | |
1044 | - { | |
1045 | - field: CommandFieldsEnum.SERVICE, | |
1046 | - label: '服务', | |
1047 | - component: 'ApiSelect', | |
1048 | - ifShow: ({ model }) => model[CommandFieldsEnum.COMMAND_TYPE] !== CommandType.CUSTOM, | |
1049 | - rules: [{ required: true, message: '请选择服务' }], | |
1050 | - componentProps: ({ formActionType }) => { | |
1051 | - const { setFieldsValue, updateSchema } = formActionType; | |
1052 | - return { | |
1053 | - api: async () => { | |
1054 | - try { | |
1055 | - const result = await getModelServices({ deviceProfileId }); | |
1056 | - return result || []; | |
1057 | - } catch (error) { | |
1058 | - return []; | |
1059 | - } | |
1060 | - }, | |
1061 | - valueField: 'identifier', | |
1062 | - labelField: 'functionName', | |
1063 | - getPopupContainer: () => document.body, | |
1064 | - onChange(value: string, options: ModelOfMatterParams) { | |
1065 | - if (!value) return; | |
1066 | - | |
1067 | - const setValues = { | |
1068 | - [CommandFieldsEnum.CUSTOM_TYPE]: | |
1069 | - options.callType === ServiceCallTypeEnum.ASYNC | |
1070 | - ? CommandDeliveryWayEnum.ONE_WAY | |
1071 | - : CommandDeliveryWayEnum.TWO_WAY, | |
1072 | - [CommandFieldsEnum.MODEL_INPUT]: null, | |
1073 | - }; | |
1074 | - | |
1075 | - if (transportType !== TransportTypeEnum.TCP) { | |
1076 | - updateSchema({ | |
1077 | - field: CommandFieldsEnum.MODEL_INPUT, | |
1078 | - componentProps: { | |
1079 | - inputData: toRaw(unref(options.functionJson.inputData)), | |
1080 | - }, | |
1081 | - }); | |
1082 | - } else { | |
1083 | - Object.assign(setValues, { | |
1084 | - [CommandFieldsEnum.TCP_SERVICE]: | |
1085 | - options.functionJson?.inputData?.[0]?.serviceCommand, | |
1086 | - }); | |
1087 | - } | |
1088 | - | |
1089 | - setFieldsValue(setValues); | |
1090 | - }, | |
1091 | - }; | |
1092 | - }, | |
1093 | - }, | |
1094 | - { | |
1095 | - field: CommandFieldsEnum.TCP_SERVICE, | |
1096 | - component: 'Input', | |
1097 | - label: '命令', | |
1098 | - dynamicDisabled: true, | |
1099 | - ifShow: ({ model }) => | |
1100 | - model[CommandFieldsEnum.SERVICE] && | |
1101 | - transportType === TransportTypeEnum.TCP && | |
1102 | - model[CommandFieldsEnum.COMMAND_TYPE] !== CommandType.CUSTOM, | |
1103 | - }, | |
1104 | - { | |
1105 | - field: CommandFieldsEnum.MODEL_INPUT, | |
1106 | - component: 'ThingsModelForm', | |
1107 | - label: '输入参数', | |
1108 | - changeEvent: 'update:value', | |
1109 | - valueField: 'value', | |
1110 | - ifShow: ({ model }) => | |
1111 | - model[CommandFieldsEnum.SERVICE] && | |
1112 | - transportType !== TransportTypeEnum.TCP && | |
1113 | - model[CommandFieldsEnum.COMMAND_TYPE] !== CommandType.CUSTOM, | |
1114 | - componentProps: { | |
1115 | - formProps: { | |
1116 | - wrapperCol: { span: 24 }, | |
1117 | - } as FormProps, | |
1118 | - }, | |
1119 | - }, | |
1120 | - ]; | |
1121 | -}; | ... | ... |
1 | +import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; | |
2 | +import { getModelServices } from '/@/api/device/modelOfMatter'; | |
3 | +import { FormProps, FormSchema, useComponentRegister } from '/@/components/Form'; | |
4 | +import { validateTCPCustomCommand } from '/@/components/Form/src/components/ThingsModelForm'; | |
5 | +import { JSONEditor, JSONEditorValidator } from '/@/components/CodeEditor'; | |
6 | +import { | |
7 | + TransportTypeEnum, | |
8 | + CommandTypeNameEnum, | |
9 | + CommandTypeEnum, | |
10 | + ServiceCallTypeEnum, | |
11 | + CommandDeliveryWayEnum, | |
12 | + CommandDeliveryWayNameEnum, | |
13 | +} from '/@/enums/deviceEnum'; | |
14 | + | |
15 | +export interface CommandDeliveryFormFieldType { | |
16 | + [CommandFieldsEnum.COMMAND_TYPE]: CommandTypeEnum; | |
17 | + [CommandFieldsEnum.TCP_COMMAND_VALUE]?: string; | |
18 | + [CommandFieldsEnum.COMAND_VALUE]?: string; | |
19 | + [CommandFieldsEnum.SERVICE]?: string; | |
20 | + [CommandFieldsEnum.MODEL_INPUT]?: ModelOfMatterParams; | |
21 | + [CommandFieldsEnum.CALL_TYPE]: CommandDeliveryWayEnum; | |
22 | +} | |
23 | + | |
24 | +export enum CommandFieldsEnum { | |
25 | + COMMAND_TYPE = 'commandType', | |
26 | + TCP_COMMAND_VALUE = 'tcpCommandValue', | |
27 | + COMAND_VALUE = 'commandValue', | |
28 | + SERVICE = 'service', | |
29 | + MODEL_INPUT = 'modelInput', | |
30 | + CALL_TYPE = 'callType', | |
31 | + | |
32 | + SERVICE_COMMAND = 'serviceCommand', | |
33 | + | |
34 | + SERVICE_OBJECT_MODEL = 'serviceObjectModel', | |
35 | +} | |
36 | + | |
37 | +useComponentRegister('JSONEditor', JSONEditor); | |
38 | + | |
39 | +export const CommandSchemas = ( | |
40 | + transportType: TransportTypeEnum, | |
41 | + deviceProfileId: string | |
42 | +): FormSchema[] => { | |
43 | + return [ | |
44 | + { | |
45 | + field: CommandFieldsEnum.COMMAND_TYPE, | |
46 | + component: 'RadioGroup', | |
47 | + label: '下发类型', | |
48 | + defaultValue: CommandTypeEnum.CUSTOM, | |
49 | + required: true, | |
50 | + componentProps: ({ formActionType }) => { | |
51 | + const { setFieldsValue } = formActionType; | |
52 | + return { | |
53 | + options: [ | |
54 | + { label: CommandTypeNameEnum.CUSTOM, value: CommandTypeEnum.CUSTOM }, | |
55 | + { label: CommandTypeNameEnum.SERVICE, value: CommandTypeEnum.SERVICE }, | |
56 | + ], | |
57 | + onChange() { | |
58 | + setFieldsValue({ | |
59 | + [CommandFieldsEnum.SERVICE]: null, | |
60 | + [CommandFieldsEnum.MODEL_INPUT]: null, | |
61 | + [CommandFieldsEnum.COMAND_VALUE]: null, | |
62 | + [CommandFieldsEnum.TCP_COMMAND_VALUE]: null, | |
63 | + }); | |
64 | + }, | |
65 | + }; | |
66 | + }, | |
67 | + }, | |
68 | + { | |
69 | + field: CommandFieldsEnum.CALL_TYPE, | |
70 | + component: 'RadioGroup', | |
71 | + label: '单向/双向', | |
72 | + required: true, | |
73 | + defaultValue: CommandDeliveryWayEnum.ONE_WAY, | |
74 | + ifShow: ({ model }) => model[CommandFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.CUSTOM, | |
75 | + componentProps: { | |
76 | + options: Object.keys(CommandDeliveryWayEnum).map((key) => ({ | |
77 | + label: CommandDeliveryWayNameEnum[key], | |
78 | + value: CommandDeliveryWayEnum[key], | |
79 | + })), | |
80 | + }, | |
81 | + }, | |
82 | + { | |
83 | + field: CommandFieldsEnum.TCP_COMMAND_VALUE, | |
84 | + label: '命令', | |
85 | + required: true, | |
86 | + ifShow: ({ model }) => | |
87 | + transportType === TransportTypeEnum.TCP && | |
88 | + model[CommandFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.CUSTOM, | |
89 | + component: 'Input', | |
90 | + rules: [{ validator: validateTCPCustomCommand }], | |
91 | + componentProps: { | |
92 | + placeholder: '请输入命令', | |
93 | + }, | |
94 | + }, | |
95 | + { | |
96 | + field: CommandFieldsEnum.COMAND_VALUE, | |
97 | + label: '命令', | |
98 | + component: 'JSONEditor', | |
99 | + colProps: { span: 20 }, | |
100 | + changeEvent: 'update:value', | |
101 | + valueField: 'value', | |
102 | + required: true, | |
103 | + rules: JSONEditorValidator(), | |
104 | + ifShow: ({ model }) => | |
105 | + transportType !== TransportTypeEnum.TCP && | |
106 | + model[CommandFieldsEnum.COMMAND_TYPE] === CommandTypeEnum.CUSTOM, | |
107 | + componentProps: { | |
108 | + height: 250, | |
109 | + }, | |
110 | + }, | |
111 | + { | |
112 | + field: CommandFieldsEnum.SERVICE, | |
113 | + label: '服务', | |
114 | + component: 'ApiSelect', | |
115 | + required: true, | |
116 | + ifShow: ({ model }) => model[CommandFieldsEnum.COMMAND_TYPE] !== CommandTypeEnum.CUSTOM, | |
117 | + rules: [{ required: true, message: '请选择服务' }], | |
118 | + componentProps: ({ formActionType }) => { | |
119 | + const { setFieldsValue } = formActionType; | |
120 | + return { | |
121 | + api: getModelServices, | |
122 | + params: { | |
123 | + deviceProfileId, | |
124 | + }, | |
125 | + valueField: 'identifier', | |
126 | + labelField: 'functionName', | |
127 | + getPopupContainer: () => document.body, | |
128 | + placeholder: '请选择服务', | |
129 | + onChange( | |
130 | + value: string, | |
131 | + options: ModelOfMatterParams & Record<'label' | 'value', string> | |
132 | + ) { | |
133 | + if (!value) return; | |
134 | + setFieldsValue({ | |
135 | + [CommandFieldsEnum.CALL_TYPE]: | |
136 | + options.callType === ServiceCallTypeEnum.ASYNC | |
137 | + ? CommandDeliveryWayEnum.ONE_WAY | |
138 | + : CommandDeliveryWayEnum.TWO_WAY, | |
139 | + [CommandFieldsEnum.MODEL_INPUT]: null, | |
140 | + [CommandFieldsEnum.SERVICE_OBJECT_MODEL]: Object.assign(options, { | |
141 | + functionName: options.label, | |
142 | + identifier: options.value, | |
143 | + }), | |
144 | + }); | |
145 | + }, | |
146 | + }; | |
147 | + }, | |
148 | + }, | |
149 | + { | |
150 | + field: CommandFieldsEnum.SERVICE_OBJECT_MODEL, | |
151 | + label: '服务物模型', | |
152 | + component: 'Input', | |
153 | + ifShow: false, | |
154 | + }, | |
155 | + { | |
156 | + field: CommandFieldsEnum.MODEL_INPUT, | |
157 | + component: 'Input', | |
158 | + label: '输入参数', | |
159 | + changeEvent: 'update:value', | |
160 | + valueField: 'value', | |
161 | + ifShow: ({ model }) => | |
162 | + model[CommandFieldsEnum.SERVICE] && | |
163 | + model[CommandFieldsEnum.SERVICE_OBJECT_MODEL] && | |
164 | + model[CommandFieldsEnum.COMMAND_TYPE] !== CommandTypeEnum.CUSTOM, | |
165 | + componentProps: { | |
166 | + formProps: { | |
167 | + wrapperCol: { span: 24 }, | |
168 | + } as FormProps, | |
169 | + }, | |
170 | + slot: 'serviceCommand', | |
171 | + }, | |
172 | + ]; | |
173 | +}; | ... | ... |
1 | +export { default as CommandDeliveryModal } from './index.vue'; | ... | ... |
1 | +<template> | |
2 | + <BasicModal | |
3 | + title="命令下发" | |
4 | + :width="650" | |
5 | + @register="registerModal" | |
6 | + @ok="handleOk" | |
7 | + @cancel="handleCancel" | |
8 | + > | |
9 | + <BasicForm @register="registerForm"> | |
10 | + <template #serviceCommand="{ field, model }"> | |
11 | + <ThingsModelForm | |
12 | + :disabled="deviceDetail?.transportType === TransportTypeEnum.TCP" | |
13 | + ref="thingsModelFormRef" | |
14 | + v-model:value="model[field]" | |
15 | + :key="model[CommandFieldsEnum.SERVICE_OBJECT_MODEL]?.identifier" | |
16 | + :inputData="model[CommandFieldsEnum.SERVICE_OBJECT_MODEL]?.functionJson?.inputData" | |
17 | + :transportType="deviceDetail?.transportType" | |
18 | + /> | |
19 | + </template> | |
20 | + </BasicForm> | |
21 | + </BasicModal> | |
22 | +</template> | |
23 | +<script lang="ts" setup> | |
24 | + import { nextTick, ref, unref } from 'vue'; | |
25 | + import { BasicForm, ThingsModelForm, useForm } from '/@/components/Form'; | |
26 | + import { CommandDeliveryFormFieldType, CommandFieldsEnum, CommandSchemas } from './config'; | |
27 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
28 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
29 | + import { CommandDeliveryWayEnum } from '/@/enums/deviceEnum'; | |
30 | + import { CommandTypeEnum, RPCCommandMethodEnum, TransportTypeEnum } from '/@/enums/deviceEnum'; | |
31 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | |
32 | + import { getDeviceActiveTime } from '/@/api/alarm/position'; | |
33 | + import { RpcCommandType } from '/@/api/device/model/deviceConfigModel'; | |
34 | + import { parseStringToJSON } from '/@/components/CodeEditor'; | |
35 | + import { commandIssuanceApi } from '/@/api/device/deviceManager'; | |
36 | + | |
37 | + defineEmits(['register']); | |
38 | + | |
39 | + const thingsModelFormRef = ref<InstanceType<typeof ThingsModelForm>>(); | |
40 | + const deviceDetail = ref<DeviceRecord>(); | |
41 | + | |
42 | + const [registerModal, { setModalProps }] = useModalInner( | |
43 | + (params: ModalParamsType<DeviceRecord>) => { | |
44 | + const { record } = params; | |
45 | + deviceDetail.value = record; | |
46 | + setProps({ | |
47 | + schemas: CommandSchemas(record.transportType as TransportTypeEnum, record.deviceProfileId), | |
48 | + }); | |
49 | + } | |
50 | + ); | |
51 | + | |
52 | + const { createMessage } = useMessage(); | |
53 | + | |
54 | + const [registerForm, { setProps, getFieldsValue, validate, resetFields, clearValidate }] = | |
55 | + useForm({ | |
56 | + labelWidth: 120, | |
57 | + baseColProps: { span: 20 }, | |
58 | + labelAlign: 'right', | |
59 | + showSubmitButton: false, | |
60 | + showResetButton: false, | |
61 | + }); | |
62 | + | |
63 | + const handleCancel = async () => { | |
64 | + await resetFields(); | |
65 | + await nextTick(); | |
66 | + await clearValidate(); | |
67 | + }; | |
68 | + | |
69 | + const handleValidate = async () => { | |
70 | + await validate(); | |
71 | + await unref(thingsModelFormRef)?.validate?.(); | |
72 | + }; | |
73 | + | |
74 | + const handleValidateDeviceActive = async (): Promise<boolean> => { | |
75 | + const result = await getDeviceActiveTime(unref(deviceDetail)!.tbDeviceId); | |
76 | + const [firstItem] = result; | |
77 | + return !!firstItem.value; | |
78 | + }; | |
79 | + | |
80 | + const handleCommandParams = ( | |
81 | + values: CommandDeliveryFormFieldType, | |
82 | + serviceCommand: Recordable | |
83 | + ) => { | |
84 | + const { commandType } = values; | |
85 | + | |
86 | + const isTcpDevice = unref(deviceDetail)?.transportType === TransportTypeEnum.TCP; | |
87 | + if (commandType === CommandTypeEnum.CUSTOM) { | |
88 | + if (isTcpDevice) { | |
89 | + return values.tcpCommandValue; | |
90 | + } | |
91 | + return parseStringToJSON(values.commandValue!).json; | |
92 | + } else { | |
93 | + if (isTcpDevice) return Reflect.get(serviceCommand, CommandFieldsEnum.SERVICE_COMMAND); | |
94 | + return serviceCommand; | |
95 | + } | |
96 | + }; | |
97 | + | |
98 | + const handleOk = async () => { | |
99 | + await handleValidate(); | |
100 | + | |
101 | + try { | |
102 | + setModalProps({ loading: true, confirmLoading: true }); | |
103 | + | |
104 | + const values = getFieldsValue() as CommandDeliveryFormFieldType; | |
105 | + const { callType, commandType } = values; | |
106 | + const serviceCommand = unref(thingsModelFormRef)?.getFieldsValue() || {}; | |
107 | + | |
108 | + if (callType === CommandDeliveryWayEnum.TWO_WAY && !(await handleValidateDeviceActive())) { | |
109 | + createMessage.warn('当前设备不在线'); | |
110 | + return; | |
111 | + } | |
112 | + | |
113 | + const rpcCommands: RpcCommandType = { | |
114 | + additionalInfo: { | |
115 | + cmdType: | |
116 | + commandType === CommandTypeEnum.CUSTOM | |
117 | + ? CommandTypeEnum.CUSTOM | |
118 | + : CommandTypeEnum.SERVICE, | |
119 | + }, | |
120 | + method: RPCCommandMethodEnum.THINGSKIT, | |
121 | + persistent: true, | |
122 | + params: handleCommandParams(values, serviceCommand), | |
123 | + }; | |
124 | + | |
125 | + await commandIssuanceApi(callType, unref(deviceDetail)!.tbDeviceId, rpcCommands); | |
126 | + | |
127 | + createMessage.success('命令下发成功'); | |
128 | + } finally { | |
129 | + setModalProps({ loading: false, confirmLoading: false }); | |
130 | + } | |
131 | + }; | |
132 | +</script> | |
133 | +<style scoped lang="less"></style> | ... | ... |
src/views/device/list/cpns/tabs/CommandIssuance.vue
deleted
100644 → 0
1 | -<template> | |
2 | - <div class="tabs-detail"> | |
3 | - <div> | |
4 | - <BasicForm @register="registerForm" /> | |
5 | - <Space class="w-full justify-end py-2" justify="end"> | |
6 | - <Button :loading="loading" type="primary" @click="handleOk" class="mr-2">确定</Button> | |
7 | - <Button type="default" @click="handleCancel" class="mr-2">重置</Button> | |
8 | - </Space> | |
9 | - </div> | |
10 | - </div> | |
11 | -</template> | |
12 | -<script lang="ts" setup> | |
13 | - import { nextTick, ref } from 'vue'; | |
14 | - import { BasicForm, useForm } from '/@/components/Form'; | |
15 | - import { CommandFieldsEnum, CommandSchemas, CommandType, ValueType } from '../../config/data'; | |
16 | - import { commandIssuanceApi } from '/@/api/device/deviceManager'; | |
17 | - import { useMessage } from '/@/hooks/web/useMessage'; | |
18 | - import { Button } from '/@/components/Button'; | |
19 | - import { Space } from 'ant-design-vue'; | |
20 | - import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
21 | - import { parseStringToJSON } from '/@/components/CodeEditor/src/JSONEditor'; | |
22 | - import { CommandDeliveryWayEnum } from '/@/enums/toolEnum'; | |
23 | - import { TransportTypeEnum } from '/@/enums/deviceEnum'; | |
24 | - | |
25 | - defineEmits(['register']); | |
26 | - | |
27 | - const props = defineProps<{ | |
28 | - deviceDetail: DeviceRecord; | |
29 | - }>(); | |
30 | - | |
31 | - const { createMessage } = useMessage(); | |
32 | - const loading = ref(false); | |
33 | - | |
34 | - const [registerForm, { getFieldsValue, validate, resetFields, clearValidate }] = useForm({ | |
35 | - labelWidth: 120, | |
36 | - schemas: CommandSchemas( | |
37 | - props.deviceDetail.deviceProfile.transportType as TransportTypeEnum, | |
38 | - props.deviceDetail.deviceProfileId | |
39 | - ), | |
40 | - baseColProps: { span: 20 }, | |
41 | - labelAlign: 'right', | |
42 | - showSubmitButton: false, | |
43 | - showResetButton: false, | |
44 | - }); | |
45 | - | |
46 | - const handleCancel = async () => { | |
47 | - await resetFields(); | |
48 | - await nextTick(); | |
49 | - await clearValidate(); | |
50 | - }; | |
51 | - | |
52 | - const handleOk = async () => { | |
53 | - loading.value = true; | |
54 | - try { | |
55 | - // 验证 | |
56 | - const valid = await validate(); | |
57 | - if (!valid) return; | |
58 | - // 收集表单数据 | |
59 | - const field = getFieldsValue(); | |
60 | - let command: Recordable = { | |
61 | - persistent: true, | |
62 | - method: 'methodThingskit', | |
63 | - params: field[CommandFieldsEnum.COMMAND_TEXT], | |
64 | - }; | |
65 | - | |
66 | - if (field[CommandFieldsEnum.COMMAND_TYPE] === CommandType.CUSTOM) { | |
67 | - if (field[CommandFieldsEnum.VALUE_TYPE] === ValueType.JSON) { | |
68 | - const { json } = parseStringToJSON(field.commandValue); | |
69 | - command.params = json; | |
70 | - } | |
71 | - } else { | |
72 | - const { transportType } = props.deviceDetail.deviceProfile; | |
73 | - command.params = | |
74 | - transportType === TransportTypeEnum.TCP | |
75 | - ? field[CommandFieldsEnum.TCP_SERVICE] | |
76 | - : { | |
77 | - [field[CommandFieldsEnum.SERVICE]]: field[CommandFieldsEnum.MODEL_INPUT], | |
78 | - }; | |
79 | - command.additionalInfo = { cmdType: 1 }; | |
80 | - } | |
81 | - commandIssuanceApi( | |
82 | - field[CommandFieldsEnum.CUSTOM_TYPE] as CommandDeliveryWayEnum, | |
83 | - props.deviceDetail.tbDeviceId, | |
84 | - command | |
85 | - ) | |
86 | - .then((res) => { | |
87 | - if (!res) return; | |
88 | - createMessage.success('命令下发成功'); | |
89 | - loading.value = true; | |
90 | - // 请求 | |
91 | - handleCancel(); | |
92 | - }) | |
93 | - .catch((e) => { | |
94 | - if (e?.message) { | |
95 | - createMessage.error(e?.message); | |
96 | - } | |
97 | - handleCancel(); | |
98 | - }) | |
99 | - .finally(() => { | |
100 | - setTimeout(() => { | |
101 | - loading.value = false; | |
102 | - }, 300); | |
103 | - }); | |
104 | - } catch (e) { | |
105 | - throw e; | |
106 | - } finally { | |
107 | - loading.value = false; | |
108 | - } | |
109 | - }; | |
110 | -</script> | |
111 | -<style scoped lang="less"> | |
112 | - .jsoneditor-transform { | |
113 | - background-position: -144px -96px; | |
114 | - display: none !important; | |
115 | - } | |
116 | - | |
117 | - .tabs-detail:deep(.object-model-validate-form) { | |
118 | - > .ant-row { | |
119 | - @apply w-full; | |
120 | - } | |
121 | - } | |
122 | -</style> |
... | ... | @@ -18,7 +18,8 @@ |
18 | 18 | import { useGlobSetting } from '/@/hooks/setting'; |
19 | 19 | import { ModeSwitchButton, EnumTableCardMode } from '/@/components/Widget'; |
20 | 20 | import { toRaw } from 'vue'; |
21 | - import { DataActionModeEnum, ReadAndWriteEnum } from '/@/enums/toolEnum'; | |
21 | + import { DataActionModeEnum } from '/@/enums/toolEnum'; | |
22 | + import { ReadAndWriteEnum } from '/@/enums/deviceEnum'; | |
22 | 23 | import { ObjectModelCommandDeliveryModal } from './ObjectModelCommandDeliveryModal'; |
23 | 24 | import { ModalParamsType } from '/#/utils'; |
24 | 25 | import { AreaChartOutlined } from '@ant-design/icons-vue'; | ... | ... |
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | <template #toolbar> |
7 | 7 | <Space> |
8 | 8 | <Authority value="api:yt:device:rpc"> |
9 | - <Button type="primary" @click="openModal(true)">命令下发</Button> | |
9 | + <Button type="primary" @click="handleOpenModal">命令下发</Button> | |
10 | 10 | </Authority> |
11 | 11 | </Space> |
12 | 12 | </template> |
... | ... | @@ -24,16 +24,7 @@ |
24 | 24 | </template> |
25 | 25 | </BasicTable> |
26 | 26 | |
27 | - <BasicModal | |
28 | - @register="registerCommandIssuanceModal" | |
29 | - width="700px" | |
30 | - title="命令下发" | |
31 | - :showOkBtn="false" | |
32 | - cancelText="关闭" | |
33 | - :footer="null" | |
34 | - > | |
35 | - <CommandIssuance :deviceDetail="deviceDetail" /> | |
36 | - </BasicModal> | |
27 | + <CommandDeliveryModal @register="registerCommandDeliverModal" :deviceDetail="deviceDetail" /> | |
37 | 28 | </template> |
38 | 29 | <script lang="ts" setup> |
39 | 30 | import { h } from 'vue'; |
... | ... | @@ -43,9 +34,10 @@ |
43 | 34 | import { Button, Modal, Space } from 'ant-design-vue'; |
44 | 35 | import { JsonPreview } from '/@/components/CodeEditor'; |
45 | 36 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
46 | - import { BasicModal, useModal } from '/@/components/Modal'; | |
47 | - import CommandIssuance from '../CommandIssuance.vue'; | |
37 | + import { useModal } from '/@/components/Modal'; | |
38 | + import { CommandDeliveryModal } from '../CommandDeliveryModal'; | |
48 | 39 | import { Authority } from '/@/components/Authority'; |
40 | + import { DataActionModeEnum } from '/@/enums/toolEnum'; | |
49 | 41 | |
50 | 42 | const props = defineProps({ |
51 | 43 | fromId: { |
... | ... | @@ -58,7 +50,7 @@ |
58 | 50 | }, |
59 | 51 | }); |
60 | 52 | |
61 | - const [registerCommandIssuanceModal, { openModal }] = useModal(); | |
53 | + const [registerCommandDeliverModal, { openModal }] = useModal(); | |
62 | 54 | |
63 | 55 | const [registerTable] = useTable({ |
64 | 56 | api: deviceCommandRecordGetQuery, |
... | ... | @@ -79,6 +71,7 @@ |
79 | 71 | }, |
80 | 72 | useSearchForm: true, |
81 | 73 | }); |
74 | + | |
82 | 75 | const commonModalInfo = (title, value) => { |
83 | 76 | Modal.info({ |
84 | 77 | title, |
... | ... | @@ -86,14 +79,23 @@ |
86 | 79 | content: h(JsonPreview, { data: value }), |
87 | 80 | }); |
88 | 81 | }; |
82 | + | |
89 | 83 | const handleRecordContent = (record) => { |
90 | 84 | if (!record?.request?.body) return; |
91 | 85 | if (Object.prototype.toString.call(record?.request?.body) !== '[object Object]') return; |
92 | 86 | const jsonParams = record?.request?.body?.params; |
93 | 87 | commonModalInfo('命令下发内容', jsonParams); |
94 | 88 | }; |
89 | + | |
95 | 90 | const handleRecordResponseContent = (record) => { |
96 | 91 | const jsonParams = record?.response; |
97 | 92 | commonModalInfo('响应内容', jsonParams); |
98 | 93 | }; |
94 | + | |
95 | + function handleOpenModal() { | |
96 | + openModal(true, { | |
97 | + mode: DataActionModeEnum.READ, | |
98 | + record: props.deviceDetail, | |
99 | + } as ModalParamsType<DeviceRecord>); | |
100 | + } | |
99 | 101 | </script> | ... | ... |
1 | 1 | import { FormSchema, useComponentRegister } from '/@/components/Form'; |
2 | 2 | import { |
3 | - CommandTypeEnum, | |
4 | - CommandTypeNameEnum, | |
5 | 3 | ExecutionActionEnum, |
6 | 4 | ExecutionActionNameEnum, |
7 | 5 | TriggerEntityTypeEnum, |
8 | 6 | TriggerEntityTypeNameEnum, |
9 | 7 | } from '/@/enums/linkedgeEnum'; |
8 | +import { CommandTypeEnum, CommandTypeNameEnum } from '/@/enums/deviceEnum'; | |
10 | 9 | import AlarmProfileSelect from './AlarmProfileSelect.vue'; |
11 | 10 | import { |
12 | 11 | byOrganizationIdGetMasterDevice, |
... | ... | @@ -21,7 +20,7 @@ import { findDictItemByCode } from '/@/api/system/dict'; |
21 | 20 | import { DictEnum } from '/@/enums/dictEnum'; |
22 | 21 | import { getDeviceProfile } from '/@/api/alarm/position'; |
23 | 22 | import { createPickerSearch } from '/@/utils/pickerSearch'; |
24 | -import { ServiceCallTypeEnum, ServiceCallTypeNameEnum } from '/@/enums/toolEnum'; | |
23 | +import { ServiceCallTypeEnum, ServiceCallTypeNameEnum } from '/@/enums/deviceEnum'; | |
25 | 24 | import { DeviceTypeEnum } from '../../../dataFlow/cpns/config'; |
26 | 25 | import { getModelServices } from '/@/api/device/modelOfMatter'; |
27 | 26 | import { ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | ... | ... |
... | ... | @@ -5,8 +5,8 @@ import { FlipFlopConditionType } from '../FlipFlop/types'; |
5 | 5 | import { DeviceModelOfMatterAttrs, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
6 | 6 | import { FormActionType, ThingsModelForm } from '/@/components/Form'; |
7 | 7 | import { AlarmLevelEnum } from '/@/enums/alarmEnum'; |
8 | -import { CommandTypeEnum, ExecutionActionEnum, TriggerEntityTypeEnum } from '/@/enums/linkedgeEnum'; | |
9 | -import { ServiceCallTypeEnum } from '/@/enums/toolEnum'; | |
8 | +import { ExecutionActionEnum, TriggerEntityTypeEnum } from '/@/enums/linkedgeEnum'; | |
9 | +import { CommandTypeEnum, ServiceCallTypeEnum } from '/@/enums/deviceEnum'; | |
10 | 10 | import { TransportTypeEnum } from '/@/enums/deviceEnum'; |
11 | 11 | |
12 | 12 | export interface ExecutionActionListRefItemType { | ... | ... |
... | ... | @@ -7,7 +7,8 @@ import { |
7 | 7 | ExecutionActionFormItemRecordType, |
8 | 8 | ExecutionActionListRefItemType, |
9 | 9 | } from './type'; |
10 | -import { CommandTypeEnum, ExecutionActionEnum } from '/@/enums/linkedgeEnum'; | |
10 | +import { ExecutionActionEnum } from '/@/enums/linkedgeEnum'; | |
11 | +import { CommandTypeEnum } from '/@/enums/deviceEnum'; | |
11 | 12 | import { useJsonParse } from '/@/hooks/business/useJsonParse'; |
12 | 13 | import { createNewExecutionActionItem } from '.'; |
13 | 14 | import { FormFieldsEnum } from './config'; | ... | ... |
... | ... | @@ -3,7 +3,7 @@ import { TaskTypeEnum } from '/@/views/task/center/config'; |
3 | 3 | import { genModbusCommand } from '/@/api/task'; |
4 | 4 | import { useMessage } from '/@/hooks/web/useMessage'; |
5 | 5 | import { SingleToHex } from '/@/views/device/list/cpns/tabs/ObjectModelCommandDeliveryModal/config'; |
6 | -import { CommandTypeEnum } from '/@/enums/linkedgeEnum'; | |
6 | +import { CommandTypeEnum } from '/@/enums/deviceEnum'; | |
7 | 7 | import { TransportTypeEnum } from '/@/enums/deviceEnum'; |
8 | 8 | |
9 | 9 | const getArray = (values) => { | ... | ... |
... | ... | @@ -14,7 +14,7 @@ import { DataActionModeEnum } from '/@/enums/toolEnum'; |
14 | 14 | import { TaskTypeEnum } from '/@/views/task/center/config'; |
15 | 15 | import { createPickerSearch } from '/@/utils/pickerSearch'; |
16 | 16 | import { DataTypeEnum } from '/@/enums/objectModelEnum'; |
17 | -import { CommandTypeEnum } from '/@/enums/linkedgeEnum'; | |
17 | +import { CommandTypeEnum } from '/@/enums/deviceEnum'; | |
18 | 18 | import { TransportTypeEnum } from '/@/enums/deviceEnum'; |
19 | 19 | |
20 | 20 | useComponentRegister('OrgTreeSelect', OrgTreeSelect); | ... | ... |
... | ... | @@ -2,8 +2,7 @@ import { ref } from 'vue'; |
2 | 2 | import { DataSource } from '../../palette/types'; |
3 | 3 | import { sendCommandOneway, sendCommandTwoway } from '/@/api/dataBoard'; |
4 | 4 | import { useMessage } from '/@/hooks/web/useMessage'; |
5 | -import { ServiceCallTypeEnum } from '/@/enums/toolEnum'; | |
6 | -import { TransportTypeEnum } from '/@/enums/deviceEnum'; | |
5 | +import { TransportTypeEnum, ServiceCallTypeEnum } from '/@/enums/deviceEnum'; | |
7 | 6 | |
8 | 7 | const { createMessage } = useMessage(); |
9 | 8 | export function useSendCommand() { | ... | ... |