Commit 23e69ffb1e134c6ef5cb781e41c877de943b2551

Authored by xp.Huang
2 parents 84b86771 76f82075

Merge branch 'f-dev' into 'main'

fix:修改数据流转 clientId限制8位

See merge request huang/yun-teng-iot-front!259
... ... @@ -85,6 +85,7 @@
85 85 proxy.$refs.mqttRef?.setStepFieldsValueFunc(v?.profileData?.transportConfiguration);
86 86 proxy.$refs.coapRef?.setStepFieldsValueFunc(v?.profileData?.transportConfiguration);
87 87 proxy.$refs.lwm2mRef?.setStepFieldsValueFunc(v?.profileData?.transportConfiguration);
  88 + // proxy.$refs.snmpRef?.setStepFieldsValueFunc(v?.profileData?.transportConfiguration);
88 89 }, 100);
89 90 };
90 91
... ... @@ -128,10 +129,12 @@
128 129 const getMqttVal = await proxy.$refs.mqttRef?.getDataFunc();
129 130 const getCoapVal = await proxy.$refs.coapRef?.getDataFunc();
130 131 const getLwm2mVal = await proxy.$refs.lwm2mRef?.getDataFunc();
  132 + // const getSnmpVal = await proxy.$refs.snmpRef?.getSnmpForm();
131 133 step2Data.transportConfiguration = {
132 134 ...getMqttVal,
133 135 ...getCoapVal,
134 136 ...getLwm2mVal,
  137 + // ...getSnmpVal,
135 138 ...val,
136 139 };
137 140 return step2Data;
... ...
src/views/device/profiles/step/cpns/snmp/config.ts renamed from src/views/device/profiles/step/cpns/snmp/index.ts
1   -<template>
2   - <div style="display: flex; flex-direction: row; width: 30vw">
3   - <div style="width: 9vw">
4   - <BasicForm
5   - :showResetButton="false"
6   - :showSubmitButton="false"
7   - @register="registerRightSelect"
8   - />
9   - </div>
10   - <div style="width: 20vw">
11   - <BasicForm :showResetButton="false" :showSubmitButton="false" @register="registerRightInput"
12   - /></div>
13   - <div style="width: 1vw; margin-left: -0.8vw">
14   - <span @click="handleDelScopeAndKeyAndVal" style="color: red; cursor: pointer">X</span>
15   - </div>
16   - </div>
17   -</template>
18   -<script lang="ts">
19   - import { defineComponent } from 'vue';
20   - import { BasicForm, useForm } from '/@/components/Form';
21   - import { snmpRightSelectSchemas, snmpRightInputSchemas } from '../index';
22   -
23   - export default defineComponent({
24   - components: {
25   - BasicForm,
26   - },
27   -
28   - emits: ['next', 'prev', 'register', 'clear'],
29   - setup(_, { emit }) {
30   - const [registerRightSelect] = useForm({
31   - labelWidth: 80,
32   - schemas: snmpRightSelectSchemas,
33   - actionColOptions: {
34   - span: 14,
35   - },
36   - });
37   - const [registerRightInput] = useForm({
38   - labelWidth: 80,
39   - schemas: snmpRightInputSchemas,
40   - actionColOptions: {
41   - span: 14,
42   - },
43   - });
44   - const handleDelScopeAndKeyAndVal = () => {
45   - emit('clear');
46   - };
47   - return {
48   - registerRightSelect,
49   - registerRightInput,
50   - handleDelScopeAndKeyAndVal,
51   - };
52   - },
53   - });
54   -</script>
55   -<style lang="less" scoped></style>
  1 +<template>
  2 + <div v-for="(param, index) in dynamicInput.params" :key="index" style="display: flex">
  3 + <Select
  4 + v-model:value="param.dataType"
  5 + style="width: 140px"
  6 + :options="selectOptions"
  7 + @focus="focus"
  8 + @change="handleChange"
  9 + />
  10 + <a-input
  11 + placeholder="请输入Data key"
  12 + v-model:value="param.key"
  13 + style="width: 38%; margin-bottom: 5px"
  14 + @change="emitChange"
  15 + />
  16 + <a-input
  17 + placeholder="请输入OID"
  18 + v-model:value="param.oid"
  19 + style="width: 38%; margin: 0 0 5px 60px"
  20 + @change="emitChange"
  21 + />
  22 + <MinusCircleOutlined
  23 + v-if="dynamicInput.params.length > min"
  24 + class="dynamic-delete-button"
  25 + @click="remove(param)"
  26 + style="width: 50px"
  27 + />
  28 + </div>
  29 + <div>
  30 + <a-button type="dashed" style="width: 38%" @click="add">
  31 + <PlusCircleOutlined />
  32 + Add mapping
  33 + </a-button>
  34 + </div>
  35 +</template>
  36 +<script lang="ts">
  37 + import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons-vue';
  38 + import { defineComponent, reactive, UnwrapRef, watchEffect, ref } from 'vue';
  39 + import { propTypes } from '/@/utils/propTypes';
  40 + import { SelectTypes } from 'ant-design-vue/es/select';
  41 + import { Select } from 'ant-design-vue';
  42 +
  43 + interface Params {
  44 + dataType: string;
  45 + key: string;
  46 + oid: string;
  47 + }
  48 +
  49 + export default defineComponent({
  50 + name: 'JAddInput',
  51 + components: {
  52 + MinusCircleOutlined,
  53 + PlusCircleOutlined,
  54 + Select,
  55 + },
  56 + //--------------不继承Antd Design Vue Input的所有属性 否则控制台报大片警告--------------
  57 + inheritAttrs: false,
  58 + props: {
  59 + value: propTypes.array.def([]),
  60 + //自定义删除按钮多少才会显示
  61 + min: propTypes.integer.def(0),
  62 + },
  63 + emits: ['change', 'update:value'],
  64 + setup(props, { emit }) {
  65 + const selectOptions = ref<SelectTypes['options']>([
  66 + {
  67 + label: '字符串',
  68 + value: 'STRING',
  69 + },
  70 + {
  71 + label: '数字',
  72 + value: 'LONG',
  73 + },
  74 + {
  75 + label: '布尔值',
  76 + value: 'BOOLEAN',
  77 + },
  78 + {
  79 + label: '双精度小数',
  80 + value: 'DOUBLE',
  81 + },
  82 + {
  83 + label: 'JSON',
  84 + value: 'JSON',
  85 + },
  86 + ]);
  87 + const focus = () => {
  88 + console.log('focus');
  89 + };
  90 +
  91 + const handleChange = (value: string) => {
  92 + console.log(`selected ${value}`);
  93 + };
  94 +
  95 + //input动态数据
  96 + const dynamicInput: UnwrapRef<{ params: Params[] }> = reactive({ params: [] });
  97 + //删除Input
  98 + const remove = (item: Params) => {
  99 + let index = dynamicInput.params.indexOf(item);
  100 + if (index !== -1) {
  101 + dynamicInput.params.splice(index, 1);
  102 + }
  103 + emitChange();
  104 + };
  105 +
  106 + //新增Input
  107 + const add = () => {
  108 + dynamicInput.params.push({
  109 + dataType: '',
  110 + key: '',
  111 + oid: '',
  112 + });
  113 + emitChange();
  114 + };
  115 +
  116 + //监听传入数据value
  117 + watchEffect(() => {
  118 + initVal();
  119 + });
  120 +
  121 + /**
  122 + * 初始化数值
  123 + */
  124 + function initVal() {
  125 + dynamicInput.params = [];
  126 + if (props.value) {
  127 + let jsonObj = props.value;
  128 + jsonObj.forEach((item: Params) => {
  129 + dynamicInput.params.push({
  130 + dataType: item.dataType,
  131 + key: item.key,
  132 + oid: item.oid,
  133 + });
  134 + });
  135 + }
  136 + }
  137 + /**
  138 + * 数值改变
  139 + */
  140 + function emitChange() {
  141 + let obj: any = [];
  142 + if (dynamicInput.params.length > 0) {
  143 + dynamicInput.params.forEach((item: Params) => {
  144 + obj.push({
  145 + dataType: item.dataType,
  146 + key: item.key,
  147 + oid: item.oid,
  148 + });
  149 + });
  150 + }
  151 + emit('change', obj);
  152 + emit('update:value', obj);
  153 + }
  154 +
  155 + return {
  156 + dynamicInput,
  157 + emitChange,
  158 + remove,
  159 + add,
  160 + selectOptions,
  161 + focus,
  162 + handleChange,
  163 + };
  164 + },
  165 + });
  166 +</script>
  167 +<style scoped>
  168 + .dynamic-delete-button {
  169 + cursor: pointer;
  170 + position: relative;
  171 + top: 4px;
  172 + font-size: 24px;
  173 + color: #999;
  174 + transition: all 0.3s;
  175 + }
  176 +
  177 + .dynamic-delete-button:hover {
  178 + color: #777;
  179 + }
  180 +
  181 + .dynamic-delete-button[disabled] {
  182 + cursor: not-allowed;
  183 + opacity: 0.5;
  184 + }
  185 +</style>
... ...
  1 +<template>
  2 + <div class="snmp-form">
  3 + <div class="form-item1">
  4 + <div style="margin-left: 1vw">
  5 + <h3 style="color: gray">Scope</h3>
  6 + <Select
  7 + v-model:value="selectValue"
  8 + style="width: 140px"
  9 + :options="selectOptions"
  10 + @focus="focus"
  11 + @change="handleChange"
  12 + />
  13 + </div>
  14 + </div>
  15 + <div class="form-item2">
  16 + <div style="margin-left: 1vw">
  17 + <h3 style="color: gray">Querying frequency,ms*</h3>
  18 + <InputNumber v-model:value="inputNmberValue" :min="1" :max="50000" />
  19 + <MappingsForm :value="mappings" @change="handleMappingsChange" />
  20 + </div>
  21 + </div>
  22 + <div class="form-item3">
  23 + <div style="text-align: center; line-height: 20vh">
  24 + <Button size="small" type="default" @click="handleRemove(item)">
  25 + <template #icon>
  26 + <MinusCircleOutlined />
  27 + </template>
  28 + </Button>
  29 + </div>
  30 + </div>
  31 + </div>
  32 +</template>
  33 +<script setup lang="ts">
  34 + import { ref } from 'vue';
  35 + import { SelectTypes } from 'ant-design-vue/es/select';
  36 + import { Select, Button, InputNumber } from 'ant-design-vue';
  37 + import { MinusCircleOutlined } from '@ant-design/icons-vue';
  38 + import MappingsForm from './MappingsForm.vue';
  39 + // interface Params {
  40 + // dataType: string;
  41 + // key: string;
  42 + // oid: string;
  43 + // }
  44 + defineProps({
  45 + item: {
  46 + type: Object,
  47 + default: () => {},
  48 + },
  49 + mappings: {
  50 + type: Array,
  51 + default: () => [],
  52 + },
  53 + });
  54 + const emit = defineEmits(['removeItem']);
  55 + const selectValue = ref('CLIENT_ATTRIBUTES_QUERYING');
  56 + const inputNmberValue = ref(5000);
  57 + // const isHasItem = [
  58 + // 'TELEMETRY_QUERYING',
  59 + // 'CLIENT_ATTRIBUTES_QUERYING',
  60 + // 'SHARED_ATTRIBUTES_SETTING',
  61 + // 'TO_DEVICE_RPC_REQUEST',
  62 + // ];
  63 + const selectOptions = ref<SelectTypes['options']>([
  64 + {
  65 + label: 'Telemetry',
  66 + value: 'TELEMETRY_QUERYING',
  67 + },
  68 + {
  69 + label: 'Client attributes',
  70 + value: 'CLIENT_ATTRIBUTES_QUERYING',
  71 + },
  72 + {
  73 + label: 'Shared attributes',
  74 + value: 'SHARED_ATTRIBUTES_SETTING',
  75 + },
  76 + {
  77 + label: 'RPC request',
  78 + value: 'TO_DEVICE_RPC_REQUEST',
  79 + },
  80 + ]);
  81 + const focus = () => {
  82 + console.log('focus');
  83 + };
  84 +
  85 + const handleChange = (value: string) => {
  86 + selectValue.value = value;
  87 + };
  88 + const mapping: any = ref([]);
  89 + const handleMappingsChange = (e) => {
  90 + mapping.value = e;
  91 + };
  92 +
  93 + const handleRemove = (item) => {
  94 + emit('removeItem', item);
  95 + };
  96 + //设置回显表单值
  97 + const setFieldsValueFunc = (item, inputValue) => {
  98 + selectValue.value = item;
  99 + inputNmberValue.value = inputValue;
  100 + };
  101 + //获取表单的值
  102 + const getSnmpFormFunc = () => {
  103 + let obj: any = {};
  104 + obj = {
  105 + ...{ spec: selectValue.value },
  106 + ...{ mappings: mapping.value },
  107 + ...{ queryingFrequencyMs: inputNmberValue.value },
  108 + };
  109 + return obj;
  110 + };
  111 + defineExpose({
  112 + getSnmpFormFunc,
  113 + setFieldsValueFunc,
  114 + });
  115 +</script>
  116 +<style lang="less" scoped>
  117 + .snmp-form {
  118 + display: flex;
  119 + align-items: center;
  120 + justify-content: space-between;
  121 + width: 40vw;
  122 + height: 20vh;
  123 + border: 1px solid gray;
  124 + margin-top: 2vh;
  125 +
  126 + .form-item1 {
  127 + width: 9vw;
  128 + height: 20vh;
  129 + border: 1px solid gray;
  130 + }
  131 +
  132 + .form-item2 {
  133 + width: 28vw;
  134 + height: 20vh;
  135 + border: 1px solid gray;
  136 + }
  137 +
  138 + .form-item3 {
  139 + width: 2vw;
  140 + height: 20vh;
  141 + border: 1px solid gray;
  142 + }
  143 + }
  144 +</style>
... ...
... ... @@ -12,68 +12,24 @@
12 12 <BasicForm :showResetButton="false" :showSubmitButton="false" @register="register">
13 13 <template #add>
14 14 <div>
15   - <template v-for="(item, index) in scopeData" :key="item.id1">
  15 + <template v-for="(item, index) in dynamicSNMP.communicationConfigs" :key="index">
16 16 <span style="display: none">{{ item }}</span>
17   - <div
18   - style="
19   - display: flex;
20   - width: 45vw;
21   - flex-direction: row;
22   - border: 0.5px solid gray;
23   - border-radius: 5px;
24   - margin-left: -1.5vw;
25   - "
26   - >
27   - <div
28   - style="
29   - width: 14vw;
30   - border: 0.5px solid gray;
31   - border-radius: 5px;
32   - margin-left: -2vw;
33   - "
34   - >
35   - <BasicForm
36   - :showResetButton="false"
37   - :showSubmitButton="false"
38   - @register="registerLeft"
39   - />
40   - </div>
41   - <div style="width: 29.3vw; border: 0.5px solid gray; border-radius: 5px">
42   - <BasicForm
43   - :showResetButton="false"
44   - :showSubmitButton="false"
45   - @register="registerRight"
46   - />
47   - <div>
48   - <template v-for="(item1, index1) in item.mappings" :key="item1.id2">
49   - <span style="display: none">{{ index1 }}</span>
50   - <span style="display: none">{{ item1 }}</span>
51   - <KeyAndValVue @clear="clearFun(index, index1)" />
52   - </template>
53   - <div
54   - style="
55   - margin-top: -3.8vh;
56   - margin-left: 2.3vw;
57   - position: relative;
58   - top: -1.5vh;
59   - "
60   - >
61   - <a-button size="small" type="default" @click="handleAddMapping(index)">
62   - Add mapping
63   - </a-button>
64   - </div>
65   - </div>
66   - </div>
67   - <div style="width: 1vw; margin-top: 8.5vh; margin-left: 0.5vw">
68   - <span @click="handleDelScope(index)" style="color: red; cursor: pointer">X</span>
69   - </div>
70   - </div>
71   - <div style="height: 2vh"></div>
  17 + <span style="display: none">{{ index }}</span>
  18 + <!-- snmp表单项 -->
  19 + <SnmpForm
  20 + :item="item"
  21 + :ref="dynamicBindRef.SnmpFormItemRef"
  22 + :mappings="item.mappings"
  23 + @removeItem="handleRemoveItem"
  24 + />
72 25 </template>
73   - <div style="margin-left: -1vw">
74   - <a-button size="small" type="default" @click="handleAddScope">
  26 + <div style="margin-left: 0vw; margin-top: 2vh">
  27 + <Button size="small" type="default" @click="handleAdd">
  28 + <template #icon>
  29 + <PlusCircleOutlined />
  30 + </template>
75 31 Add communication config
76   - </a-button>
  32 + </Button>
77 33 </div>
78 34 </div>
79 35 </template>
... ... @@ -81,95 +37,104 @@
81 37 </div>
82 38 </div>
83 39 </template>
84   -<script lang="ts">
85   - import { defineComponent, ref } from 'vue';
  40 +<script setup lang="ts">
  41 + import { UnwrapRef, reactive, ref, unref, nextTick } from 'vue';
86 42 import { BasicForm, useForm } from '/@/components/Form';
87   - import { snmpSchemas, snmpLeftSchemas, snmpRightSchemas } from './index';
88   - import { Alert, Divider, Descriptions } from 'ant-design-vue';
89   - import KeyAndValVue from './cpns/KeyAndVal.vue';
  43 + import { snmpSchemas } from './config';
  44 + import { PlusCircleOutlined } from '@ant-design/icons-vue';
  45 + import { Button } from 'ant-design-vue';
  46 + import SnmpForm from './cpns/SnmpForm.vue';
90 47
91   - export default defineComponent({
92   - components: {
93   - BasicForm,
94   - [Alert.name]: Alert,
95   - [Divider.name]: Divider,
96   - [Descriptions.name]: Descriptions,
97   - [Descriptions.Item.name]: Descriptions.Item,
98   - KeyAndValVue,
  48 + interface mappingsI {
  49 + dataType: string;
  50 + key: string;
  51 + oid: string;
  52 + }
  53 + interface Params {
  54 + spec: string;
  55 + queryingFrequencyMs: number;
  56 + mappings: mappingsI[];
  57 + }
  58 + const dynamicBindRef = {
  59 + SnmpFormItemRef: ref([]),
  60 + };
  61 + const dynamicSNMP: UnwrapRef<{ communicationConfigs: Params[] }> = reactive({
  62 + communicationConfigs: [
  63 + {
  64 + spec: '',
  65 + mappings: [
  66 + {
  67 + dataType: 'STRING',
  68 + key: '',
  69 + oid: '',
  70 + },
  71 + ],
  72 + queryingFrequencyMs: 0,
  73 + },
  74 + ],
  75 + });
  76 + const [register, { validate, setFieldsValue }] = useForm({
  77 + labelWidth: 150,
  78 + schemas: snmpSchemas,
  79 + actionColOptions: {
  80 + span: 14,
99 81 },
100   -
101   - emits: ['next', 'prev', 'register'],
102   - setup() {
103   - const scopeData: any = ref([
  82 + });
  83 + const handleAdd = () => {
  84 + dynamicSNMP.communicationConfigs.push({
  85 + spec: '',
  86 + mappings: [
104 87 {
105   - id1: 1,
106   - mappings: [
107   - {
108   - id2: 2,
109   - },
110   - ],
111   - },
112   - ]);
113   -
114   - const [register] = useForm({
115   - labelWidth: 150,
116   - schemas: snmpSchemas,
117   - actionColOptions: {
118   - span: 14,
119   - },
120   - });
121   - const [registerLeft] = useForm({
122   - labelWidth: 100,
123   - schemas: snmpLeftSchemas,
124   - actionColOptions: {
125   - span: 14,
  88 + dataType: '',
  89 + key: '',
  90 + oid: '',
126 91 },
  92 + ],
  93 + queryingFrequencyMs: 0,
  94 + });
  95 + };
  96 + const handleRemoveItem = (item) => {
  97 + let index = dynamicSNMP.communicationConfigs.indexOf(item);
  98 + if (index !== -1) {
  99 + dynamicSNMP.communicationConfigs.splice(index, 1);
  100 + }
  101 + };
  102 + //回显表单值
  103 + const setStepFieldsValueFunc = (v) => {
  104 + setFieldsValue({
  105 + timeoutMs: v.timeoutMs,
  106 + retries: v.retries,
  107 + });
  108 + dynamicSNMP.communicationConfigs = v.communicationConfigs;
  109 + dynamicSNMP.communicationConfigs.forEach((snmp: any, index: number) => {
  110 + nextTick(() => {
  111 + unref(dynamicBindRef.SnmpFormItemRef)[index]?.setFieldsValueFunc(
  112 + snmp?.spec,
  113 + snmp?.queryingFrequencyMs
  114 + );
127 115 });
128   - const [registerRight] = useForm({
129   - labelWidth: 150,
130   - schemas: snmpRightSchemas,
131   - actionColOptions: {
132   - span: 14,
133   - },
134   - });
135   -
136   - const handleAddMapping = (i) => {
137   - scopeData.value[i].mappings.push({
138   - id2: Date.now() + 3,
139   - });
140   - };
141   - const clearFun = (i1, i2) => {
142   - scopeData.value[i1].mappings.splice(i2, 1);
143   - };
  116 + });
  117 + };
144 118
145   - const handleDelScope = (i) => {
146   - scopeData.value.splice(i, 1);
147   - };
148   -
149   - const handleAddScope = () => {
150   - if (scopeData.value.length < 4) {
151   - scopeData.value.push({
152   - id1: Date.now() + 1,
153   - mappings: [
154   - {
155   - id2: Date.now() + 2,
156   - },
157   - ],
158   - });
159   - }
160   - };
161   -
162   - return {
163   - register,
164   - registerLeft,
165   - registerRight,
166   - handleAddMapping,
167   - scopeData,
168   - handleDelScope,
169   - handleAddScope,
170   - clearFun,
171   - };
172   - },
  119 + //获取最终的值
  120 + const getSnmpForm = async () => {
  121 + let value = await validate();
  122 + if (!value) return;
  123 + let tempObj: any = {};
  124 + let tempArray: any = [];
  125 + unref(dynamicBindRef.SnmpFormItemRef)?.map((item: any) => {
  126 + tempArray.push(item.getSnmpFormFunc());
  127 + });
  128 + tempObj = {
  129 + ...value,
  130 + ...{ communicationConfigs: tempArray },
  131 + ...{ type: 'SNMP' },
  132 + };
  133 + return tempObj;
  134 + };
  135 + defineExpose({
  136 + getSnmpForm,
  137 + setStepFieldsValueFunc,
173 138 });
174 139 </script>
175 140 <style lang="less" scoped></style>
... ...
... ... @@ -342,7 +342,7 @@ export const modeMqttForm: FormSchema[] = [
342 342 });
343 343 }
344 344 },
345   - maxLength: 255,
  345 + maxLength: 8,
346 346 placeholder: '请输入Client ID',
347 347 };
348 348 },
... ...
... ... @@ -104,6 +104,7 @@
104 104 import { Alert, Divider, Descriptions, Upload } from 'ant-design-vue';
105 105 import { uploadApi } from '/@/api/personal/index';
106 106 import { useMessage } from '/@/hooks/web/useMessage';
  107 + import { buildUUID } from '/@/utils/uuid';
107 108
108 109 export default defineComponent({
109 110 components: {
... ... @@ -343,6 +344,8 @@
343 344 credentialsV.credentials.certFileName = certFileName.value;
344 345 credentialsV.credentials.privateKeyFileName = privateKeyFileName.value;
345 346 }
  347 + //clientId 从uuid里切片8位
  348 + sonValues.configuration.clientId = buildUUID().slice(0, 8);
346 349 Object.assign(sonValues.configuration, credentialsV);
347 350 return sonValues;
348 351 };
... ...