Commit 3e8d5f2470edd1435fdb24853600d5a969c3fdd6

Authored by ww
1 parent ba226a67

fix: 命令下发新增服务下发功能

... ... @@ -13,6 +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 17 enum DeviceManagerApi {
17 18 /**
18 19 * 设备URL
... ... @@ -260,11 +261,14 @@ export const generateSNCode = () => {
260 261 };
261 262
262 263 //命令下发
263   -export const commandIssuanceApi = (type, tbDeviceId, data) => {
264   - const T = type === 'OneWay' ? 'oneway' : 'twoway';
  264 +export const commandIssuanceApi = (
  265 + type: CommandDeliveryWayEnum,
  266 + tbDeviceId: string,
  267 + data: Recordable
  268 +) => {
265 269 return defHttp.post(
266 270 {
267   - url: DeviceManagerApi.COMMAND_ISSUANCE + '/' + T + '/' + tbDeviceId,
  271 + url: `${DeviceManagerApi.COMMAND_ISSUANCE}/${type}/${tbDeviceId}`,
268 272 data,
269 273 },
270 274 {
... ...
1 1 <script lang="ts" setup>
2 2 import { Card } from 'ant-design-vue';
3   - import { nextTick, onBeforeUpdate, onUpdated } from 'vue';
  3 + import { computed, nextTick, onMounted, onUpdated, unref, watch } from 'vue';
4 4 import { DataTypeEnum } from '../StructForm/config';
5 5 import { BasicCreateFormParams } from './type';
6 6 import { DynamicProps } from '/#/utils';
... ... @@ -22,6 +22,11 @@
22 22
23 23 const emit = defineEmits(['update:value']);
24 24
  25 + const getCurrentKeys = computed(() => {
  26 + const { inputData } = props;
  27 + return (inputData || []).map((item) => item.identifier);
  28 + });
  29 +
25 30 const [register, { setProps, getFieldsValue, setFieldsValue }] = useForm({
26 31 schemas: [],
27 32 showActionButtonGroup: false,
... ... @@ -32,8 +37,16 @@
32 37 });
33 38
34 39 const syncValue = (key: string, value: any) => {
35   - const record = getFieldsValue();
36   - emit('update:value', { ...record, [key]: value });
  40 + let record = getFieldsValue();
  41 + record = { ...record, [key]: value };
  42 + const setValues = {};
  43 + Object.keys(record).forEach((key) => {
  44 + const hasKey = unref(getCurrentKeys).includes(key);
  45 + if (hasKey) {
  46 + setValues[key] = record[key];
  47 + }
  48 + });
  49 + emit('update:value', setValues);
37 50 };
38 51
39 52 const createInputNumber = ({
... ... @@ -52,6 +65,8 @@
52 65 type: 'number',
53 66 trigger: 'change',
54 67 validator: (_rule, value) => {
  68 + const reg = /^[0-9]*$/;
  69 + if (!reg.test(value)) return Promise.reject(`${functionName}不是一个有效的数字`);
55 70 if (value < min || value > max) {
56 71 return Promise.reject(`${functionName}取值范围在${min}~${max}之间`);
57 72 }
... ... @@ -167,19 +182,37 @@
167 182 return schemas;
168 183 };
169 184
170   - onBeforeUpdate(() => {
171   - if (props.inputData && props.inputData.length) {
172   - const schemas = transformToFormSchema(props.inputData);
  185 + const generateSchemas = (value: StructJSON[]) => {
  186 + if (value && value.length) {
  187 + const schemas = transformToFormSchema(value);
173 188 setProps({ schemas });
174 189 }
  190 + };
  191 +
  192 + onMounted(() => {
  193 + generateSchemas(props.inputData);
175 194 });
176 195
177 196 onUpdated(async () => {
178 197 if (props.inputData && props.inputData.length) {
179 198 await nextTick();
180   - setFieldsValue(props.value);
  199 + setFieldsValue(props.value || {});
181 200 }
182 201 });
  202 +
  203 + watch(
  204 + () => props.inputData,
  205 + (value) => {
  206 + generateSchemas(value);
  207 + }
  208 + );
  209 +
  210 + watch(
  211 + () => props.formProps,
  212 + (value) => {
  213 + setProps(value);
  214 + }
  215 + );
183 216 </script>
184 217
185 218 <template>
... ...
... ... @@ -34,3 +34,13 @@ export enum ReadAndWriteEnum {
34 34 READ = 'r',
35 35 READ_AND_WRITE = 'rw',
36 36 }
  37 +
  38 +export enum ServiceCallTypeEnum {
  39 + ASYNC = 'ASYNC',
  40 + SYNC = 'SYNC',
  41 +}
  42 +
  43 +export enum CommandDeliveryWayEnum {
  44 + ONE_WAY = 'oneway',
  45 + TWO_WAY = 'twoway',
  46 +}
... ...
1   -import { FormSchema, useComponentRegister } from '/@/components/Form';
  1 +import { FormProps, FormSchema, useComponentRegister } from '/@/components/Form';
2 2 import { findDictItemByCode } from '/@/api/system/dict';
3 3 import { deviceProfile, getGatewayDevice } from '/@/api/device/deviceManager';
4 4 import { TransportTypeEnum } from '../../profiles/components/TransportDescript/const';
5 5 import { JSONEditorValidator } from '/@/components/CodeEditor/src/JSONEditor';
6 6 import { JSONEditor } from '/@/components/CodeEditor';
7 7 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
  8 +import { getModelServices } from '/@/api/device/modelOfMatter';
  9 +import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
  10 +import { toRaw, unref } from 'vue';
  11 +import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/components/ObjectModelValidateForm/ObjectModelValidateForm.vue';
  12 +import { CommandDeliveryWayEnum, ServiceCallTypeEnum } from '/@/enums/toolEnum';
8 13 useComponentRegister('JSONEditor', JSONEditor);
  14 +useComponentRegister('ObjectModelValidateForm', ObjectModelValidateForm);
9 15
10 16 export enum TypeEnum {
11 17 IS_GATEWAY = 'GATEWAY',
... ... @@ -711,37 +717,87 @@ export const TokenSchemas: FormSchema[] = [
711 717 },
712 718 ];
713 719
714   -export const CommandSchemas = (transportType: TransportTypeEnum): FormSchema[] => {
  720 +export enum ValueType {
  721 + JSON = 'json',
  722 + STRING = 'string',
  723 +}
  724 +
  725 +export enum CommandFieldsEnum {
  726 + COMMAND_TYPE = 'commandType',
  727 + VALUE_TYPE = 'valueType',
  728 + COMMAND_TEXT = 'commandText',
  729 + COMAND_VALUE = 'commandValue',
  730 + SERVICE = 'service',
  731 + SERVICE_TYPE = 'service_type',
  732 + TCP_SERVICE = 'tcpService',
  733 + MODEL_INPUT = 'modelInput',
  734 + CUSTOM_TYPE = 'customType',
  735 +}
  736 +
  737 +export enum CommandType {
  738 + CUSTOM = 'custom',
  739 + SERVICE = 'service',
  740 +}
  741 +
  742 +export const CommandSchemas = (
  743 + transportType: TransportTypeEnum,
  744 + deviceProfileId: string
  745 +): FormSchema[] => {
715 746 return [
716 747 {
717   - field: 'commandType',
  748 + field: CommandFieldsEnum.COMMAND_TYPE,
718 749 component: 'RadioGroup',
719 750 label: '下发类型',
720   - defaultValue: 'OneWay',
  751 + defaultValue: CommandType.CUSTOM,
  752 + componentProps: ({ formActionType }) => {
  753 + const { setFieldsValue } = formActionType;
  754 + return {
  755 + options: [
  756 + { label: '自定义', value: CommandType.CUSTOM },
  757 + { label: '服务', value: CommandType.SERVICE },
  758 + ],
  759 + onChange() {
  760 + setFieldsValue({
  761 + [CommandFieldsEnum.SERVICE]: null,
  762 + [CommandFieldsEnum.MODEL_INPUT]: null,
  763 + [CommandFieldsEnum.COMAND_VALUE]: null,
  764 + [CommandFieldsEnum.COMMAND_TEXT]: null,
  765 + });
  766 + },
  767 + };
  768 + },
  769 + },
  770 + {
  771 + field: CommandFieldsEnum.CUSTOM_TYPE,
  772 + component: 'RadioGroup',
  773 + label: '单向/双向',
  774 + defaultValue: CommandDeliveryWayEnum.ONE_WAY,
  775 + ifShow: ({ model }) => model[CommandFieldsEnum.COMMAND_TYPE] === CommandType.CUSTOM,
721 776 componentProps: {
722 777 options: [
723 778 {
724 779 label: '单向',
725   - value: 'OneWay',
  780 + value: CommandDeliveryWayEnum.ONE_WAY,
726 781 },
727 782 {
728 783 label: '双向',
729   - value: 'TwoWay',
  784 + value: CommandDeliveryWayEnum.TWO_WAY,
730 785 },
731 786 ],
732 787 },
733 788 },
734 789 {
735   - field: 'valueType',
  790 + field: CommandFieldsEnum.VALUE_TYPE,
736 791 label: '命令类型',
737 792 component: 'RadioGroup',
738   - defaultValue: transportType === TransportTypeEnum.TCP ? 'string' : 'json',
  793 + ifShow: ({ model }) => model[CommandFieldsEnum.COMMAND_TYPE] === CommandType.CUSTOM,
  794 + defaultValue: transportType === TransportTypeEnum.TCP ? ValueType.STRING : ValueType.JSON,
739 795 componentProps: () => {
740 796 const options: Record<'label' | 'value', string>[] = [];
741 797 if (transportType === TransportTypeEnum.TCP) {
742   - options.push({ label: '字符串', value: 'string' });
  798 + options.push({ label: '字符串', value: ValueType.STRING });
743 799 } else {
744   - options.push({ label: 'JSON', value: 'json' });
  800 + options.push({ label: 'JSON', value: ValueType.JSON });
745 801 }
746 802 return {
747 803 options,
... ... @@ -749,18 +805,18 @@ export const CommandSchemas = (transportType: TransportTypeEnum): FormSchema[] =
749 805 },
750 806 },
751 807 {
752   - field: 'commandText',
753   - label: '请输入命令内容',
754   - ifShow: ({ model }) => {
755   - return model['valueType'] === 'string';
756   - },
  808 + field: CommandFieldsEnum.COMMAND_TEXT,
  809 + label: '命令',
  810 + ifShow: ({ model }) =>
  811 + model[CommandFieldsEnum.VALUE_TYPE] === ValueType.STRING &&
  812 + model[CommandFieldsEnum.COMMAND_TYPE] === CommandType.CUSTOM,
757 813 component: 'InputTextArea',
758 814 componentProps: {
759 815 autoSize: {
760   - minRows: 6,
  816 + minRows: 3,
761 817 },
  818 + placeholder: '请输入命令内容',
762 819 },
763   - colProps: { span: 20 },
764 820 dynamicRules: () => {
765 821 return [
766 822 {
... ... @@ -778,19 +834,97 @@ export const CommandSchemas = (transportType: TransportTypeEnum): FormSchema[] =
778 834 },
779 835 },
780 836 {
781   - field: 'commandValue',
782   - label: '请输入命令内容',
  837 + field: CommandFieldsEnum.COMAND_VALUE,
  838 + label: '命令',
783 839 component: 'JSONEditor',
784 840 colProps: { span: 20 },
785 841 changeEvent: 'update:value',
786 842 valueField: 'value',
787 843 rules: [...JSONEditorValidator()],
788   - ifShow: ({ model }) => {
789   - return model['valueType'] === 'json';
790   - },
  844 + ifShow: ({ model }) =>
  845 + model[CommandFieldsEnum.VALUE_TYPE] === ValueType.JSON &&
  846 + model[CommandFieldsEnum.COMMAND_TYPE] === CommandType.CUSTOM,
  847 +
791 848 componentProps: {
792 849 height: 250,
793 850 },
794 851 },
  852 + {
  853 + field: CommandFieldsEnum.SERVICE,
  854 + label: '服务',
  855 + component: 'ApiSelect',
  856 + ifShow: ({ model }) => model[CommandFieldsEnum.COMMAND_TYPE] !== CommandType.CUSTOM,
  857 + rules: [{ required: true, message: '请选择服务' }],
  858 + componentProps: ({ formActionType }) => {
  859 + const { setFieldsValue, updateSchema } = formActionType;
  860 + return {
  861 + api: async () => {
  862 + try {
  863 + const result = await getModelServices({ deviceProfileId });
  864 + return result || [];
  865 + } catch (error) {
  866 + console.error(error);
  867 + return [];
  868 + }
  869 + },
  870 + valueField: 'id',
  871 + labelField: 'functionName',
  872 + getPopupContainer: () => document.body,
  873 + onChange(value: string, options: ModelOfMatterParams) {
  874 + if (!value) return;
  875 +
  876 + const setValues = {
  877 + [CommandFieldsEnum.CUSTOM_TYPE]:
  878 + options.callType === ServiceCallTypeEnum.ASYNC
  879 + ? CommandDeliveryWayEnum.TWO_WAY
  880 + : CommandDeliveryWayEnum.ONE_WAY,
  881 + [CommandFieldsEnum.MODEL_INPUT]: null,
  882 + };
  883 +
  884 + if (transportType !== TransportTypeEnum.TCP) {
  885 + updateSchema({
  886 + field: CommandFieldsEnum.MODEL_INPUT,
  887 + componentProps: {
  888 + inputData: toRaw(unref(options.functionJson.inputData)),
  889 + },
  890 + });
  891 + } else {
  892 + Object.assign(setValues, {
  893 + [CommandFieldsEnum.TCP_SERVICE]:
  894 + options.functionJson?.inputData?.[0]?.serviceCommand,
  895 + });
  896 + }
  897 +
  898 + setFieldsValue(setValues);
  899 + },
  900 + };
  901 + },
  902 + },
  903 + {
  904 + field: CommandFieldsEnum.TCP_SERVICE,
  905 + component: 'Input',
  906 + label: '命令',
  907 + dynamicDisabled: true,
  908 + ifShow: ({ model }) =>
  909 + model[CommandFieldsEnum.SERVICE] &&
  910 + transportType === TransportTypeEnum.TCP &&
  911 + model[CommandFieldsEnum.COMMAND_TYPE] !== CommandType.CUSTOM,
  912 + },
  913 + {
  914 + field: CommandFieldsEnum.MODEL_INPUT,
  915 + component: 'ObjectModelValidateForm',
  916 + label: '输入参数',
  917 + changeEvent: 'update:value',
  918 + valueField: 'value',
  919 + ifShow: ({ model }) =>
  920 + model[CommandFieldsEnum.SERVICE] &&
  921 + transportType !== TransportTypeEnum.TCP &&
  922 + model[CommandFieldsEnum.COMMAND_TYPE] !== CommandType.CUSTOM,
  923 + componentProps: {
  924 + formProps: {
  925 + wrapperCol: { span: 24 },
  926 + } as FormProps,
  927 + },
  928 + },
795 929 ];
796 930 };
... ...
... ... @@ -12,7 +12,7 @@
12 12 <script lang="ts">
13 13 import { defineComponent, ref } from 'vue';
14 14 import { BasicForm, useForm } from '/@/components/Form';
15   - import { CommandSchemas } from '../../config/data';
  15 + import { CommandFieldsEnum, CommandSchemas, CommandType, ValueType } from '../../config/data';
16 16 import { commandIssuanceApi } from '/@/api/device/deviceManager';
17 17 import { useMessage } from '/@/hooks/web/useMessage';
18 18 import { Button } from '/@/components/Button';
... ... @@ -20,6 +20,7 @@
20 20 import { DeviceRecord } from '/@/api/device/model/deviceModel';
21 21 import { TransportTypeEnum } from '../../../profiles/components/TransportDescript/const';
22 22 import { parseStringToJSON } from '/@/components/CodeEditor/src/JSONEditor';
  23 + import { CommandDeliveryWayEnum } from '/@/enums/toolEnum';
23 24
24 25 export default defineComponent({
25 26 components: { BasicForm, Button, Space },
... ... @@ -37,8 +38,10 @@
37 38 const [registerForm, { getFieldsValue, validate, resetFields }] = useForm({
38 39 labelWidth: 120,
39 40 schemas: CommandSchemas(
40   - props.deviceDetail.deviceProfile.transportType as TransportTypeEnum
  41 + props.deviceDetail.deviceProfile.transportType as TransportTypeEnum,
  42 + props.deviceDetail.deviceProfileId
41 43 ),
  44 + baseColProps: { span: 20 },
42 45 labelAlign: 'right',
43 46 showSubmitButton: false,
44 47 showResetButton: false,
... ... @@ -59,14 +62,27 @@
59 62 let command = {
60 63 persistent: true,
61 64 method: 'methodThingskit',
62   - params: field.commandText,
  65 + params: field[CommandFieldsEnum.COMMAND_TEXT],
63 66 };
64   - if (field.valueType === 'json') {
65   - const { json } = parseStringToJSON(field.commandValue);
66   - command.params = json;
  67 +
  68 + if (field[CommandFieldsEnum.COMMAND_TYPE] === CommandType.CUSTOM) {
  69 + if (field[CommandFieldsEnum.VALUE_TYPE] === ValueType.JSON) {
  70 + const { json } = parseStringToJSON(field.commandValue);
  71 + command.params = json;
  72 + }
  73 + } else {
  74 + const { transportType } = props.deviceDetail.deviceProfile;
  75 + command.params =
  76 + transportType === TransportTypeEnum.TCP
  77 + ? field[CommandFieldsEnum.TCP_SERVICE]
  78 + : field[CommandFieldsEnum.MODEL_INPUT];
67 79 }
68 80
69   - commandIssuanceApi(field.commandType, props.deviceDetail.tbDeviceId, command)
  81 + commandIssuanceApi(
  82 + field[CommandFieldsEnum.CUSTOM_TYPE] as CommandDeliveryWayEnum,
  83 + props.deviceDetail.tbDeviceId,
  84 + command
  85 + )
70 86 .then((res) => {
71 87 if (!res) return;
72 88 createMessage.success('命令下发成功');
... ... @@ -100,9 +116,15 @@
100 116 },
101 117 });
102 118 </script>
103   -<style scoped>
  119 +<style scoped lang="less">
104 120 .jsoneditor-transform {
105 121 background-position: -144px -96px;
106 122 display: none !important;
107 123 }
  124 +
  125 + .tabs-detail:deep(.object-model-validate-form) {
  126 + > .ant-row {
  127 + @apply w-full;
  128 + }
  129 + }
108 130 </style>
... ...