Commit 1b2f1b0047ffb71c27ae947b0fb5a953bba8dc0b

Authored by xp.Huang
2 parents 74283102 dde63339

Merge branch 'perf/device-create-add-code-type-field' into 'main_dev'

fix: 修复设备创建新增codeType字段

See merge request yunteng/thingskit-front!757
... ... @@ -10,6 +10,9 @@ import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
10 10 import { toRaw, unref } from 'vue';
11 11 import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/components/ObjectModelValidateForm/ObjectModelValidateForm.vue';
12 12 import { CommandDeliveryWayEnum, ServiceCallTypeEnum } from '/@/enums/toolEnum';
  13 +import { TaskTypeEnum } from '/@/views/task/center/config';
  14 +import { AddressTypeEnum } from '/@/views/task/center/components/PollCommandInput';
  15 +
13 16 useComponentRegister('JSONEditor', JSONEditor);
14 17 useComponentRegister('ObjectModelValidateForm', ObjectModelValidateForm);
15 18
... ... @@ -17,6 +20,7 @@ export enum TypeEnum {
17 20 IS_GATEWAY = 'GATEWAY',
18 21 SENSOR = 'SENSOR',
19 22 }
  23 +
20 24 export const isGateWay = (type: string) => {
21 25 return type === TypeEnum.IS_GATEWAY;
22 26 };
... ... @@ -112,8 +116,60 @@ export const step1Schemas: FormSchema[] = [
112 116 },
113 117 },
114 118 {
  119 + field: 'codeType',
  120 + label: '标识符类型',
  121 + component: 'Select',
  122 + dynamicRules({ values }) {
  123 + return [
  124 + {
  125 + required:
  126 + (values?.transportType === TransportTypeEnum.TCP &&
  127 + values?.deviceType === DeviceTypeEnum.SENSOR) ||
  128 + values?.deviceType === DeviceTypeEnum.GATEWAY,
  129 + message: '请输入设备标识符',
  130 + },
  131 + ];
  132 + },
  133 + ifShow: ({ values }) =>
  134 + values?.transportType === TransportTypeEnum.TCP &&
  135 + (values.deviceType === DeviceTypeEnum.SENSOR || values.deviceType === DeviceTypeEnum.GATEWAY),
  136 + componentProps: ({}) => {
  137 + return {
  138 + options: [
  139 + { label: '自定义', value: TaskTypeEnum.CUSTOM },
  140 + { label: 'ModBus', value: TaskTypeEnum.MODBUS },
  141 + ],
  142 + };
  143 + },
  144 + },
  145 + {
  146 + field: 'addressCode',
  147 + label: '地址码',
  148 + dynamicRules({ values }) {
  149 + return [
  150 + {
  151 + required:
  152 + values?.transportType === TransportTypeEnum.TCP &&
  153 + values?.deviceType === DeviceTypeEnum.SENSOR,
  154 + message: '请输入设备地址码',
  155 + },
  156 + ];
  157 + },
  158 + component: 'RegisterAddressInput',
  159 + changeEvent: 'update:value',
  160 + valueField: 'value',
  161 + componentProps: {
  162 + type: AddressTypeEnum.HEX,
  163 + maxValue: Number(247).toString(16),
  164 + minValue: 0,
  165 + },
  166 + ifShow: ({ values }) => {
  167 + return values?.codeType === TaskTypeEnum.MODBUS;
  168 + },
  169 + },
  170 + {
115 171 field: 'code',
116   - label: '设备标识/地址码',
  172 + label: '设备标识',
117 173 dynamicRules({ values }) {
118 174 return [
119 175 {
... ... @@ -125,15 +181,17 @@ export const step1Schemas: FormSchema[] = [
125 181 ];
126 182 },
127 183 component: 'Input',
128   - componentProps: {
129   - maxLength: 255,
130   - placeholder: '请输入设备标识或设备地址码',
  184 + componentProps: () => {
  185 + return {
  186 + maxLength: 255,
  187 + placeholder: '请输入设备标识或设备地址码',
  188 + };
  189 + },
  190 + ifShow: ({ values }) => {
  191 + return values?.codeType === TaskTypeEnum.CUSTOM;
131 192 },
132   - helpMessage: ['标准Modbus地址码值为16进制1-247值', '其他协议自定义'],
133   - ifShow: ({ values }) =>
134   - values?.transportType === TransportTypeEnum.TCP &&
135   - (values.deviceType === DeviceTypeEnum.SENSOR || values.deviceType === DeviceTypeEnum.GATEWAY),
136 193 },
  194 +
137 195 {
138 196 field: 'brand',
139 197 component: 'ApiRadioGroup',
... ...
... ... @@ -127,6 +127,7 @@
127 127 import { copyTransFun } from '/@/utils/fnUtils';
128 128 import { useDrawer } from '/@/components/Drawer';
129 129 import DeptDrawer from '/@/views/system/organization/OrganizationDrawer.vue';
  130 + import { TaskTypeEnum } from '/@/views/task/center/config';
130 131
131 132 export default defineComponent({
132 133 components: {
... ... @@ -385,11 +386,21 @@
385 386 positionState.latitude = deviceInfo.latitude;
386 387 positionState.address = deviceInfo.address;
387 388 devicePic.value = deviceInfo.avatar;
388   - setFieldsValue(data);
  389 + setFieldsValue({
  390 + ...data,
  391 + code: data?.code,
  392 + deviceCode: data?.code,
  393 + });
389 394 }
390 395 // 父组件调用获取字段值的方法
391 396 function parentGetFieldsValue() {
392   - return getFieldsValue();
  397 + const value = getFieldsValue();
  398 + return {
  399 + ...value,
  400 + ...(value?.code || value?.deviceCode
  401 + ? { code: value?.codeType === TaskTypeEnum.CUSTOM ? value?.code : value?.deviceCode }
  402 + : {}),
  403 + };
393 404 }
394 405
395 406 // 父组件调用表单验证
... ...
... ... @@ -183,8 +183,8 @@ export const formSchemas: FormSchema[] = [
183 183 value: TaskTypeEnum.CUSTOM,
184 184 },
185 185 {
186   - label: TaskTypeNameEnum.MODBUS_RTU,
187   - value: TaskTypeEnum.MODBUS_RTU,
  186 + label: TaskTypeNameEnum.MODBUS,
  187 + value: TaskTypeEnum.MODBUS,
188 188 disabled: transportType ? transportType && transportType !== PushWayEnum.TCP : true,
189 189 },
190 190 ],
... ... @@ -240,7 +240,7 @@ export const formSchemas: FormSchema[] = [
240 240 label: 'ModbusRTU轮询',
241 241 rules: [{ required: true, message: '请输入Modbus RTU 轮询指令' }],
242 242 ifShow: ({ model }) =>
243   - model[FormFieldsEnum.EXECUTE_CONTENT_TYPE] === TaskTypeEnum.MODBUS_RTU &&
  243 + model[FormFieldsEnum.EXECUTE_CONTENT_TYPE] === TaskTypeEnum.MODBUS &&
244 244 model[FormFieldsEnum.PUSH_WAY] === PushWayEnum.TCP,
245 245 valueField: 'value',
246 246 changeEvent: 'update:value',
... ...
1 1 <script lang="ts" setup>
2   - import { InputGroup, InputNumber, Select, Input } from 'ant-design-vue';
3   - import { unref, watch } from 'vue';
4   - import { computed } from 'vue';
5   - import { ref } from 'vue';
  2 + import { Select, InputGroup, Input } from 'ant-design-vue';
  3 + import { ref, unref, computed } from 'vue';
  4 + import { isNullOrUnDef } from '/@/utils/is';
6 5
7 6 enum AddressTypeEnum {
8 7 DEC = 'DEC',
9 8 HEX = 'HEX',
10 9 }
11   -
12 10 const emit = defineEmits(['update:value']);
13 11
14   - const DEC_MAX_VALUE = parseInt('0xffff', 16);
15   -
16 12 const props = withDefaults(
17 13 defineProps<{
18 14 value?: number | string;
19   - inputProps?: Recordable;
20 15 disabled?: boolean;
  16 + maxValue?: number | string;
  17 + minValue?: number | string;
  18 + type?: AddressTypeEnum;
  19 + toUpperCase?: boolean;
21 20 }>(),
22 21 {
23   - value: 0,
24 22 inputProps: () => ({}),
  23 + type: AddressTypeEnum.DEC,
  24 + maxValue: parseInt('FFFF', 16),
  25 + minValue: 0,
  26 + toUpperCase: true,
25 27 }
26 28 );
27 29
  30 + const maxHexPadLength = computed(() => {
  31 + const { maxValue, type } = props;
  32 + if (type === AddressTypeEnum.DEC) {
  33 + return Number(maxValue).toString(16).length;
  34 + } else {
  35 + return maxValue.toString().length;
  36 + }
  37 + });
  38 +
  39 + const inputType = ref(props.type);
  40 +
  41 + const getInputValue = computed(() => {
  42 + const { type, value, toUpperCase } = props;
  43 +
  44 + if (isNullOrUnDef(value)) return value;
  45 +
  46 + if (type === AddressTypeEnum.DEC) {
  47 + if (unref(inputType) === AddressTypeEnum.DEC) {
  48 + return Number(value);
  49 + } else {
  50 + const _value = Number(value).toString(16);
  51 + return toUpperCase ? _value.toUpperCase() : _value;
  52 + }
  53 + } else {
  54 + if (unref(inputType) === AddressTypeEnum.DEC) {
  55 + return parseInt(value, 16);
  56 + } else {
  57 + return toUpperCase ? value.toString().toUpperCase() : value;
  58 + }
  59 + }
  60 + });
  61 +
  62 + const getValueOpposite = computed(() => {
  63 + if (isNullOrUnDef(unref(getInputValue))) {
  64 + if (unref(inputType) === AddressTypeEnum.DEC) {
  65 + return `0x${decToHex(props.minValue).padStart(unref(maxHexPadLength), '0').toUpperCase()}`;
  66 + } else {
  67 + return hexToDec(props.minValue);
  68 + }
  69 + }
  70 +
  71 + if (unref(inputType) === AddressTypeEnum.DEC)
  72 + return `0x${decToHex(unref(getInputValue)!)
  73 + .toString()
  74 + .padStart(unref(maxHexPadLength), '0')
  75 + .toUpperCase()}`;
  76 + else return hexToDec(unref(getInputValue)!);
  77 + });
  78 +
28 79 const addressTypeOptions = [
29 80 { label: AddressTypeEnum.DEC, value: AddressTypeEnum.DEC },
30 81 { label: AddressTypeEnum.HEX, value: AddressTypeEnum.HEX },
31 82 ];
32 83
33   - const type = ref(AddressTypeEnum.DEC);
  84 + const getValueByInputType = (value: string | number) => {
  85 + let { type, toUpperCase, maxValue, minValue } = props;
34 86
35   - const inputValue = ref<number | string>(props.value);
  87 + if (type === AddressTypeEnum.DEC) {
  88 + if (unref(inputType) === AddressTypeEnum.HEX) {
  89 + value = hexToDec(value);
  90 + }
  91 + value = Number(value);
  92 + maxValue = Number(maxValue);
  93 + minValue = Number(minValue);
  94 + value = value > maxValue ? maxValue : value;
  95 + value = value < minValue ? minValue : value;
  96 + } else {
  97 + if (unref(inputType) === AddressTypeEnum.DEC) {
  98 + value = decToHex(value);
  99 + }
36 100
37   - const getHexValue = computed(() => {
38   - return parseInt(unref(inputValue) || 0, 16);
39   - });
  101 + const _maxValue = parseInt(maxValue, 16);
  102 + const _minValue = parseInt(minValue, 16);
40 103
41   - const getDecValue = computed(() => {
42   - let formatValue = Number(unref(inputValue) || 0).toString(16);
43   - formatValue = `0x${formatValue.padStart(4, '0')}`;
44   - return (inputValue.value as number) > DEC_MAX_VALUE ? '0x0000' : formatValue;
45   - });
  104 + value = parseInt(value, 16) > _maxValue ? maxValue : value;
  105 + value = parseInt(value, 16) < _minValue ? minValue : value;
46 106
47   - const toDEC = (value: number | string) => {
48   - return unref(type) === AddressTypeEnum.DEC
49   - ? isNaN(value as number)
50   - ? 0
51   - : Number(value)
52   - : parseInt(value, 16);
53   - };
  107 + value = toUpperCase ? value.toString().toUpperCase() : value;
  108 + }
54 109
55   - const handleEmit = () => {
56   - const syncValue = toDEC(unref(inputValue));
57   - emit('update:value', syncValue);
  110 + return value;
58 111 };
59 112
60   - const handleChange = (value: AddressTypeEnum) => {
61   - const syncValue = value === AddressTypeEnum.DEC ? unref(getHexValue) : unref(getDecValue);
62   - inputValue.value = syncValue;
63   - emit('update:value', toDEC(syncValue));
  113 + const validate = (value: string | number) => {
  114 + if (unref(inputType) === AddressTypeEnum.DEC) {
  115 + return /^[1-9]\d*$/.test(value.toString());
  116 + } else {
  117 + return /(0x)?[0-9a-fA-F]+/.test(value.toString());
  118 + }
64 119 };
65 120
66   - const stop = watch(
67   - () => props.value,
68   - (value) => {
69   - inputValue.value = value;
70   - stop();
  121 + const handleSyncValue = (event: ChangeEvent) => {
  122 + const value = (event.target as HTMLInputElement).value;
  123 + if (isNullOrUnDef(value) || value === '') {
  124 + emit('update:value', null);
  125 + return;
71 126 }
72   - );
  127 + if (!validate(value)) return;
  128 + const syncValue = getValueByInputType(value);
  129 + emit('update:value', syncValue);
  130 + };
  131 +
  132 + function decToHex(value: number | string) {
  133 + return Number(value).toString(16);
  134 + }
  135 +
  136 + function hexToDec(value: number | string) {
  137 + return parseInt(value, 16);
  138 + }
73 139 </script>
74 140
75 141 <template>
76 142 <InputGroup compact class="!flex">
77 143 <Select
78   - v-model:value="type"
  144 + v-model:value="inputType"
79 145 :options="addressTypeOptions"
80   - @change="handleChange"
81 146 :disabled="disabled"
82 147 class="bg-gray-200 max-w-20"
83 148 />
84   - <InputNumber
85   - v-if="type === AddressTypeEnum.DEC"
86   - v-model:value="inputValue"
87   - :step="1"
88   - class="flex-1"
  149 +
  150 + <Input
  151 + :value="getInputValue"
  152 + @change="handleSyncValue"
89 153 :disabled="disabled"
90   - v-bind="inputProps"
91   - @change="handleEmit"
  154 + :placeholder="`请输入${inputType === AddressTypeEnum.DEC ? '十进制' : '十六进制'}设备地址码`"
92 155 />
93   - <Input v-if="type === AddressTypeEnum.HEX" v-model:value="inputValue" @change="handleEmit" />
94 156 <div class="text-center h-8 leading-8 px-2 bg-gray-200 cursor-pointer rounded-1 w-20">
95   - <div v-if="type === AddressTypeEnum.DEC">{{ getDecValue }}</div>
96   - <div v-if="type === AddressTypeEnum.HEX">{{ getHexValue }}</div>
  157 + <div>{{ getValueOpposite }}</div>
97 158 </div>
98 159 </InputGroup>
99 160 </template>
... ...
1 1 import { findDictItemByCode } from '/@/api/system/dict';
2 2 import { FormSchema, useComponentRegister } from '/@/components/Form';
3 3 import { DictEnum } from '/@/enums/dictEnum';
4   -import RegisterAddressInput from './RegisterAddressInput.vue';
5 4 import { createPickerSearch } from '/@/utils/pickerSearch';
6 5 import { ControlGroup } from '../ControlGroup';
7 6
  7 +useComponentRegister('ControlGroup', ControlGroup);
  8 +
8 9 export enum FormFieldsEnum {
9 10 // 设备地址码
10 11 DEVICE_CODE = 'deviceCode',
... ... @@ -28,9 +29,6 @@ export enum FormFieldsEnum {
28 29 REGISTER_VALUES = 'registerValues',
29 30 }
30 31
31   -useComponentRegister('RegisterAddressInput', RegisterAddressInput);
32   -useComponentRegister('ControlGroup', ControlGroup);
33   -
34 32 export enum FunctionCodeEnum {
35 33 // 读取线圈状态01
36 34 READ_COIL_STATE_01 = '01',
... ...
... ... @@ -3,3 +3,8 @@ export enum ModeEnum {
3 3 JSON = 'application/json',
4 4 NORMAL = 'normal',
5 5 }
  6 +
  7 +export enum AddressTypeEnum {
  8 + DEC = 'DEC',
  9 + HEX = 'HEX',
  10 +}
... ...
... ... @@ -27,11 +27,11 @@ export enum TaskTargetNameEnum {
27 27
28 28 export enum TaskTypeEnum {
29 29 CUSTOM = 'CUSTOM',
30   - MODBUS_RTU = 'MODBUS_RTU',
  30 + MODBUS = 'MODBUS',
31 31 }
32 32
33 33 export enum TaskTypeNameEnum {
34   - MODBUS_RTU = 'MODBUS_RTU轮询',
  34 + MODBUS = 'MODBUS_RTU轮询',
35 35 CUSTOM = '自定义数据下发',
36 36 }
37 37
... ...