Commit f65c43197421df9a1880d8925905d215515b2bf1

Authored by fengtao
1 parent b5a37c58

fix:修改设备配置相关

... ... @@ -60,7 +60,7 @@
60 60 });
61 61 const emit = defineEmits(['expand']);
62 62
63   - const show = ref(true);
  63 + const show = ref(false);
64 64
65 65 const { prefixCls } = useDesign('collapse-container');
66 66
... ...
... ... @@ -214,45 +214,49 @@
214 214 if (isUpdate.value == 1) {
215 215 delete postDeviceConfogData.id;
216 216 }
217   - //1 TODO 待解决OID对象唯一标识不能重复问题验证
218   - let isMappings = false;
219   - // let isQuerying = false;
  217 + let isMappingsKey = ref(false);
  218 + let isMappingValue = ref(false);
  219 + let isQueryings = ref(false);
  220 + let isOIDRepet = ref(false);
220 221 postDeviceConfogData?.profileData?.transportConfiguration?.communicationConfigs?.forEach(
221   - (f) => {
222   - // if (f.spec == 'TELEMETRY_QUERYING' && f.queryingFrequencyMs == null) {
223   - // isQuerying = true;
224   - // } else {
225   - // isQuerying = false;
226   - // }
227   - // if (f.spec == 'CLIENT_ATTRIBUTES_QUERYING' && f.queryingFrequencyMs == null) {
228   - // isQuerying = true;
229   - // } else {
230   - // isQuerying = false;
231   - // }
  222 + (f: any) => {
  223 + if (f.spec == 'TELEMETRY_QUERYING' || f.spec == 'CLIENT_ATTRIBUTES_QUERYING') {
  224 + if (f.queryingFrequencyMs == null) {
  225 + isQueryings.value = true;
  226 + return createMessage.error('请填写查询频率');
  227 + } else {
  228 + isQueryings.value = false;
  229 + }
  230 + }
232 231 if (f.mappings.length == 0) {
233   - isMappings = true;
  232 + isMappingsKey.value = true;
  233 + isMappingValue.value = true;
234 234 } else {
235 235 f.mappings.forEach((f1) => {
236 236 const findNoneKey = Object.keys(f1).includes('');
237 237 if (findNoneKey) {
238   - isMappings = findNoneKey;
239   - } else {
240   - isMappings = false;
  238 + isMappingsKey.value = true;
241 239 }
242 240 });
243 241 f.mappings.forEach((f2) => {
244 242 const findNoneVal = Object.values(f2).includes('');
245 243 if (findNoneVal) {
246   - isMappings = findNoneVal;
247   - } else {
248   - isMappings = false;
  244 + isMappingValue.value = true;
  245 + }
  246 + });
  247 + //新增OID不能重复=====同一层级的OID不能重复
  248 + f.mappings.forEach((item, _) => {
  249 + if (f.mappings.some((citem) => citem !== item && citem.oid === item.oid)) {
  250 + isOIDRepet.value = true;
249 251 }
250 252 });
251 253 }
252 254 }
253 255 );
254   - // if (isQuerying) return createMessage.error('请填写Querying frequency,ms');
255   - if (isMappings) return createMessage.error('请填写Date key和OID');
  256 + if (isQueryings.value) return createMessage.error('请填写查询频率');
  257 + if (isMappingsKey.value) return createMessage.error('请填写Date key和OID');
  258 + if (isMappingValue.value) return createMessage.error('请填写Date key和OID');
  259 + if (isOIDRepet.value) return createMessage.error('OID不能重复');
256 260 deviceConfigAddOrEdit(isEdit.value ? noEditObj : postDeviceConfogData)
257 261 .then((res) => {
258 262 if (!res) return;
... ...
... ... @@ -32,7 +32,7 @@ export const CoapSchemas: FormSchema[] = [
32 32 {
33 33 field: 'coapDeviceType',
34 34 component: 'Select',
35   - label: 'CoAP 设备类型',
  35 + label: 'CoAP设备类型',
36 36 defaultValue: 'DEFAULT',
37 37 componentProps: {
38 38 options: [
... ... @@ -45,7 +45,7 @@ export const CoapSchemas: FormSchema[] = [
45 45 {
46 46 field: 'transportPayloadType',
47 47 component: 'Select',
48   - label: 'CoAP 设备消息 Payload',
  48 + label: 'CoAP设备消息Payload',
49 49 defaultValue: 'JSON',
50 50 componentProps: {
51 51 options: [
... ... @@ -59,7 +59,7 @@ export const CoapSchemas: FormSchema[] = [
59 59 {
60 60 field: 'powerMode',
61 61 component: 'Select',
62   - label: 'Power Saving Mode',
  62 + label: '节能模式',
63 63 defaultValue: 'DRX',
64 64 componentProps: {
65 65 options: [
... ... @@ -76,11 +76,11 @@ export const CoapSchemas: FormSchema[] = [
76 76 {
77 77 field: 'psmActivityTimer',
78 78 component: 'InputNumber',
79   - label: 'PSM Activity Timer',
  79 + label: 'PSM活动计时器',
80 80 required: true,
81   - defaultValue: '10',
  81 + defaultValue: 10,
82 82 componentProps: {
83   - placeholder: '请输入PSM Activity Timer',
  83 + placeholder: '请输入PSM活动计时器',
84 84 },
85 85 colProps: { span: 11 },
86 86 ifShow: ({ values }) => isPsm(values.powerMode),
... ... @@ -104,11 +104,11 @@ export const CoapSchemas: FormSchema[] = [
104 104 {
105 105 field: 'edrxCycle',
106 106 component: 'InputNumber',
107   - label: 'eDRX cycle',
  107 + label: 'eDRX循环',
108 108 required: true,
109   - defaultValue: '81',
  109 + defaultValue: 81,
110 110 componentProps: {
111   - placeholder: '请输入PSM Activity Timer',
  111 + placeholder: '请输入eDRX循环',
112 112 },
113 113 colProps: { span: 11 },
114 114 ifShow: ({ values }) => isDrx(values.powerMode),
... ... @@ -132,11 +132,11 @@ export const CoapSchemas: FormSchema[] = [
132 132 {
133 133 field: 'pagingTransmissionWindow',
134 134 component: 'InputNumber',
135   - label: 'Paging Transmission Window',
  135 + label: '寻呼传输窗口',
136 136 required: true,
137   - defaultValue: '10',
  137 + defaultValue: 10,
138 138 componentProps: {
139   - placeholder: '请输入Paging Transmission Window',
  139 + placeholder: '请输入寻呼传输窗口',
140 140 },
141 141 colProps: { span: 11 },
142 142 ifShow: ({ values }) => isDrx(values.powerMode),
... ...
  1 +<template>
  2 + <div>
  3 + <BasicModal
  4 + v-bind="$attrs"
  5 + width="30rem"
  6 + :height="heightNum"
  7 + @register="register"
  8 + title="Add new server config"
  9 + @cancel="handleCancel"
  10 + :showOkBtn="true"
  11 + @ok="handleSubmit"
  12 + v-model:visible="visible"
  13 + >
  14 + <div style="display: flex; align-items: center; justify-content: center">
  15 + <h2>Server type:</h2>
  16 + <Select
  17 + v-model:value="selectValue"
  18 + style="width: 340px"
  19 + :options="selectOptions"
  20 + @change="emitChange"
  21 + />
  22 + </div>
  23 + </BasicModal>
  24 + </div>
  25 +</template>
  26 +<script setup lang="ts">
  27 + import { ref } from 'vue';
  28 + import { BasicModal, useModalInner } from '/@/components/Modal';
  29 + import { Select } from 'ant-design-vue';
  30 + import { SelectTypes } from 'ant-design-vue/es/select';
  31 +
  32 + const emit = defineEmits(['register', 'emitSelect']);
  33 + const [register] = useModalInner((data) => {
  34 + console.log(data);
  35 + });
  36 + const heightNum = ref(80);
  37 + const visible = ref(false);
  38 + const selectValue = ref('LwM2M');
  39 + const selectOptions = ref<SelectTypes['options']>([
  40 + {
  41 + label: 'LwM2M Server',
  42 + value: 'LwM2M',
  43 + },
  44 + {
  45 + label: 'Bootstrap Server',
  46 + value: 'Bootstrap',
  47 + },
  48 + ]);
  49 + const emitChange = (e) => {
  50 + selectValue.value = e;
  51 + };
  52 + const handleSubmit = () => {
  53 + emit('emitSelect', selectValue.value);
  54 + handleCancel();
  55 + };
  56 +
  57 + const handleCancel = () => {
  58 + visible.value = false;
  59 + };
  60 +</script>
  61 +<style lang="less" scoped></style>
... ...
... ... @@ -236,7 +236,6 @@ export const deviceSchemas: FormSchema[] = [
236 236 colProps: { span: 22 },
237 237 component: 'InputTextArea',
238 238 componentProps: {
239   - disabled: true,
240 239 autoSize: {
241 240 maxRows: 50,
242 241 },
... ... @@ -250,45 +249,31 @@ export const deviceSchemas: FormSchema[] = [
250 249 "keyName": {},
251 250 "attributeLwm2m": {}
252 251 },
253   - "bootstrap": {
254   - "servers": {
255   - "binding": "UQ",
256   - "shortId": 123,
257   - "lifetime": 300,
258   - "notifIfDisabled": true,
259   - "defaultMinPeriod": 1
260   - },
261   - "bootstrapServer": {
262   - "bootstrapServerIs": true,
263   - "host": "0.0.0.0",
264   - "port": 5687,
265   - "securityHost": "0.0.0.0",
266   - "securityPort": 5688,
267   - "serverId": 111,
268   - "clientHoldOffTime": 1,
269   - "serverPublicKey": "",
270   - "bootstrapServerAccountTimeout": 0
271   - },
272   - "lwm2mServer": {
  252 + "bootstrap": [
  253 + {
  254 + "shortServerId": 123,
273 255 "bootstrapServerIs": false,
274 256 "host": "0.0.0.0",
275 257 "port": 5685,
276   - "securityHost": "0.0.0.0",
277   - "securityPort": 5686,
278   - "serverId": 123,
279 258 "clientHoldOffTime": 1,
280 259 "serverPublicKey": "",
281   - "bootstrapServerAccountTimeout": 0
  260 + "serverCertificate": "",
  261 + "bootstrapServerAccountTimeout": 0,
  262 + "lifetime": 300,
  263 + "defaultMinPeriod": 1,
  264 + "notifIfDisabled": true,
  265 + "binding": "U",
  266 + "securityMode": "NO_SEC"
282 267 }
283   - },
  268 + ],
284 269 "clientLwM2mSettings": {
285 270 "clientOnlyObserveAfterConnect": 1,
286 271 "fwUpdateStrategy": 1,
287   - "swUpdateStrategy": 2,
288   - "swUpdateResource": "coap://localhost:5685",
  272 + "swUpdateStrategy": 1,
289 273 "powerMode": "DRX",
290 274 "compositeOperationsSupport": false
291 275 },
  276 + "bootstrapServerUpdateEnable": false,
292 277 "type": "LWM2M"
293 278 }
294 279 `,
... ...
... ... @@ -11,29 +11,44 @@
11 11 </TabPane>
12 12 <TabPane forceRender key="2" tab="Bootstrap">
13 13 <div>
14   - <Checkbox v-model:checked="bootstrapServerUpdateEnable">包括引导服务器更新</Checkbox>
15   - <Card
  14 + <Checkbox
  15 + @change="handleCheckChange($event)"
  16 + v-model:checked="bootstrapServerUpdateEnable"
  17 + >包括引导服务器更新</Checkbox
  18 + >
  19 + <CollapseContainer
16 20 v-for="(item, index) in dynamicBOOTSTRAP.bootstrap"
17 21 :key="item"
18   - title="LwM2M Server"
19   - style="width: 99%; margin-top: 2vh"
  22 + :title="collapseTitle(item)"
  23 + class="mt-4"
20 24 >
21   - <template #extra>
22   - <Button size="small" type="dashed" @click="handleRemove(index)">
23   - <template #icon>
24   - <MinusCircleOutlined />
25   - </template>
  25 + <template #action>
  26 + <Button
  27 + style="margin-right: 1vw"
  28 + size="small"
  29 + type="text"
  30 + @click="handleRemove(index)"
  31 + >
  32 + <template #icon> <DeleteOutlined /> </template>
26 33 </Button>
27 34 </template>
28   - <!-- BootStrapForm表单项 -->
29   - <BootStrapForm :ref="dynamicBindRef.BootStrapFormItemRef" :index="index" :item="item" />
30   - </Card>
  35 + <div style="border: 1px solid #d9d9d9; width: 100%">
  36 + <div style="margin: 10px 15px">
  37 + <BootStrapForm
  38 + :ref="dynamicBindRef.BootStrapFormItemRef"
  39 + :index="index"
  40 + :item="item"
  41 + />
  42 + </div>
  43 + </div>
  44 + </CollapseContainer>
31 45 <div style="margin-top: 2vh">
32   - <Button size="middle" type="dashed" @click="handleAdd">
  46 + <Button size="middle" type="text" @click="handleAdd">
33 47 <template #icon>
34 48 <PlusCircleOutlined />
35 49 </template>
36   - Add LwM2M Server
  50 + <span v-if="selectCheckStatus">Add server config</span>
  51 + <span v-else>Add LwM2M Server</span>
37 52 </Button>
38 53 </div>
39 54 </div>
... ... @@ -61,6 +76,7 @@
61 76 <BasicForm :showResetButton="false" :showSubmitButton="false" @register="registerDevice" />
62 77 </TabPane>
63 78 </Tabs>
  79 + <ServerConfigModal @register="registerModal" @emitSelect="acceptEmitFunc" />
64 80 </div>
65 81 </template>
66 82
... ... @@ -70,8 +86,11 @@
70 86 import { BasicForm, useForm } from '/@/components/Form';
71 87 import { modelSchemas, settingsSchemas, deviceSchemas } from './index';
72 88 import BootStrapForm from './cpns/BootStrapForm.vue';
73   - import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons-vue';
  89 + import { DeleteOutlined, PlusCircleOutlined } from '@ant-design/icons-vue';
74 90 import { Button, Checkbox } from 'ant-design-vue';
  91 + import { CollapseContainer } from '/@/components/Container';
  92 + import { useModal } from '/@/components/Modal';
  93 + import ServerConfigModal from './cpns/ServerConfigModal.vue';
75 94
76 95 export default defineComponent({
77 96 name: 'index',
... ... @@ -80,16 +99,21 @@
80 99 TabPane: Tabs.TabPane,
81 100 BasicForm,
82 101 BootStrapForm,
83   - MinusCircleOutlined,
  102 + DeleteOutlined,
84 103 Card,
85 104 PlusCircleOutlined,
86 105 Button,
87 106 Checkbox,
  107 + CollapseContainer,
  108 + ServerConfigModal,
88 109 },
89 110 setup() {
  111 + const collapseTitle = (item) => {
  112 + return `LwM2M Server Short server ID: ${item.shortServerId} Security config mode: ${item.securityMode}`;
  113 + };
90 114 const bootstrapServerUpdateEnable = ref(false);
91 115 const dynamicBOOTSTRAP: any = reactive({
92   - bootstrap: [{}],
  116 + bootstrap: [{ securityMode: 'NO_SEC', shortServerId: 1234 }],
93 117 });
94 118 const dynamicBindRef: any = {
95 119 BootStrapFormItemRef: ref([]),
... ... @@ -140,9 +164,20 @@
140 164 span: 14,
141 165 },
142 166 });
  167 + const [registerModal, { openModal }] = useModal();
143 168
144 169 const handleAdd = () => {
145   - dynamicBOOTSTRAP.bootstrap.push({});
  170 + //TODO 如果是server config 则只弹窗一次
  171 + if (selectCheckStatus.value) {
  172 + openModal(true, {
  173 + isUpdate: true,
  174 + });
  175 + } else {
  176 + dynamicBOOTSTRAP.bootstrap.push({
  177 + securityMode: 'NO_SEC',
  178 + shortServerId: 1234,
  179 + });
  180 + }
146 181 };
147 182 const handleRemove = (index) => {
148 183 dynamicBOOTSTRAP.bootstrap.splice(index, 1);
... ... @@ -240,7 +275,32 @@
240 275 resetDeviceValue();
241 276 });
242 277 };
243   -
  278 + const selectCheckStatus = ref(false);
  279 + const handleCheckChange = (e) => {
  280 + selectCheckStatus.value = e.target.checked;
  281 + if (!selectCheckStatus.value) {
  282 + const findIndex = dynamicBOOTSTRAP.bootstrap.findIndex((o) => o.type == 'Bootstrap');
  283 + if (findIndex !== -1) {
  284 + dynamicBOOTSTRAP.bootstrap.splice(findIndex, 1);
  285 + }
  286 + }
  287 + };
  288 + const acceptEmitFunc = (e) => {
  289 + switch (e) {
  290 + case 'LwM2M':
  291 + dynamicBOOTSTRAP.bootstrap.push({
  292 + securityMode: 'NO_SEC',
  293 + shortServerId: 1234,
  294 + });
  295 + break;
  296 + case 'Bootstrap':
  297 + dynamicBOOTSTRAP.bootstrap.push({
  298 + securityMode: 'NO_SEC',
  299 + shortServerId: 1234,
  300 + });
  301 + break;
  302 + }
  303 + };
244 304 return {
245 305 currentKey,
246 306 currentSize,
... ... @@ -256,6 +316,11 @@
256 316 handleAdd,
257 317 handleRemove,
258 318 bootstrapServerUpdateEnable,
  319 + collapseTitle,
  320 + handleCheckChange,
  321 + registerModal,
  322 + acceptEmitFunc,
  323 + selectCheckStatus,
259 324 };
260 325 },
261 326 });
... ...
... ... @@ -20,7 +20,7 @@ export const MqttSchemas: FormSchema[] = [
20 20 {
21 21 field: 'deviceTelemetryTopic',
22 22 component: 'Input',
23   - label: '遥测数据 topic 筛选器',
  23 + label: '遥测数据主题筛选器',
24 24 required: true,
25 25 defaultValue: 'v1/devices/me/telemetry',
26 26 componentProps: {
... ... @@ -32,7 +32,7 @@ export const MqttSchemas: FormSchema[] = [
32 32 field: 'deviceAttributesTopic',
33 33 component: 'Input',
34 34 required: true,
35   - label: 'Attributes topic filter',
  35 + label: '属性主题过滤器',
36 36 defaultValue: 'v1/devices/me/attributes',
37 37 componentProps: {
38 38 placeholder: '请输入Attributes topic 筛选器',
... ... @@ -64,7 +64,14 @@ export const MqttSchemas: FormSchema[] = [
64 64 colProps: { span: 23 },
65 65 defaultValue: false,
66 66 component: 'Checkbox',
67   - renderComponentContent: `启用后,平台将默认使用Protobuf有效载荷格式。如果解析失败,平台将尝试使用JSON有效负载格式。用于固件更新期间的向后兼容性。例如,固件的初始版本使用Json,而新版本使用Protobuf。在设备组的固件更新过程中,需要同时支持Protobuf和JSON。兼容性模式会导致性能轻微下降,因此建议在所有设备更新后禁用此模式。`,
  67 + ifShow: ({ values }) => isProtobuf(values.transportPayloadType),
  68 + renderComponentContent: '启用与其他有效负载格式的兼容性',
  69 + },
  70 + {
  71 + field: 'desc1',
  72 + component: 'InputTextArea',
  73 + label: '',
  74 + slot: 'desc1',
68 75 ifShow: ({ values }) => isProtobuf(values.transportPayloadType),
69 76 },
70 77 {
... ... @@ -73,7 +80,16 @@ export const MqttSchemas: FormSchema[] = [
73 80 colProps: { span: 23 },
74 81 defaultValue: false,
75 82 component: 'Checkbox',
76   - renderComponentContent: `启用后,平台将使用Json有效负载格式通过以下主题推送属性和RPC:v1/devices/me/attributes/response/$request_id, v1/devices/me/attributes, v1/devices/me/rpc/request/$request_id,v1/devices/me/rpc/response/$request_id.此设置不会影响使用新(v2)主题发送的属性和rpc订阅:v2/a/res/$request_id, v2/a, v2/r/req/$request_id, v2/r/res/$request_id. Where $request_id是一个整数请求标识符。`,
  83 + renderComponentContent: '默认下行主题使用Json格式',
  84 + ifShow: ({ values }) =>
  85 + isProtobuf(values.transportPayloadType) &&
  86 + !!values.useJsonPayloadFormatForDefaultDownlinkTopics,
  87 + },
  88 + {
  89 + field: 'desc2',
  90 + component: 'InputTextArea',
  91 + label: '',
  92 + slot: 'desc2',
77 93 ifShow: ({ values }) =>
78 94 isProtobuf(values.transportPayloadType) &&
79 95 !!values.useJsonPayloadFormatForDefaultDownlinkTopics,
... ...
... ... @@ -19,6 +19,28 @@
19 19 </p>
20 20 </div>
21 21 </template>
  22 + <template #desc1>
  23 + <div style="width: 47rem; margin-left: 2rem">
  24 + <p>
  25 + 启用时,默认情况下,平台将使用Protobuf有效载荷格式。如果解析失败,平台将尝试使用JSON负载格式。
  26 + 有助于固件更新期间的向后兼容性。例如,固件的初始版本使用Json,而新版本使用Protobuf。
  27 + 在设备组的固件更新过程中,需要同时支持Protobuf和JSON。兼容性模式会导致性能略有下降,
  28 + 因此建议在更新所有设备后禁用此模式。
  29 + </p>
  30 + </div>
  31 + </template>
  32 + <template #desc2>
  33 + <div style="width: 47rem; margin-left: 2rem">
  34 + <p>
  35 + 启用后,平台将使用Json负载格式通过以下主题推送属性
  36 + 和RPC:v1/devices/me/attributes/response/$request\u id、v1/devices/me/attributes、
  37 + v1/devices/me/RPC/request/$request\u id、v1/devices/me/RPC/response/$request\u id。
  38 + 此设置不会影响使用新(v2)主题发送的属性和rpc订阅:
  39 + v2/a/res/$request\u id、v2/a、v2/r/req/$request\u id、v2/r/res/$request\u id。
  40 + 其中,$request\u id是整数请求标识符。
  41 + </p>
  42 + </div>
  43 + </template>
22 44 </BasicForm>
23 45 </div>
24 46 </div>
... ...
... ... @@ -2,7 +2,7 @@
2 2 <div
3 3 v-for="(param, index) in dynamicInput.params"
4 4 :key="index"
5   - style="display: flex; margin-top: 0.2vh"
  5 + style="display: flex; margin-top: 0.25vh"
6 6 >
7 7 <Select
8 8 v-model:value="param.dataType"
... ... @@ -17,7 +17,7 @@
17 17 @change="emitChange"
18 18 />
19 19 <a-input
20   - placeholder="请输入OID"
  20 + placeholder="请输入OID(不能重复)"
21 21 v-model:value="param.oid"
22 22 style="width: 38%; margin: 0 0 5px 8px"
23 23 @change="emitChange"
... ... @@ -30,7 +30,7 @@
30 30 />
31 31 </div>
32 32 <div>
33   - <a-button type="dashed" style="width: 38%" @click="add">
  33 + <a-button type="text" style="width: 28%; margin-top: 0.25vh" @click="add">
34 34 <PlusCircleOutlined />
35 35 Add mapping
36 36 </a-button>
... ...
... ... @@ -16,10 +16,12 @@
16 16 >
17 17 <InputNumber
18 18 v-if="item.spec == 'TELEMETRY_QUERYING' || item.spec == 'CLIENT_ATTRIBUTES_QUERYING'"
19   - v-model:value="item.queryingFrequencyMs"
20   - :min="5000"
21   - :max="1000000000"
  19 + v-model:value="queryingFrequencyMs"
  20 + :min="0"
  21 + :max="99999999999999999999"
  22 + style="margin-top: 0.25vh"
22 23 />
  24 + <div style="margin-top: 0.65vh"></div>
23 25 <MappingsForm
24 26 :value="item.mappings"
25 27 @change="handleMappingsChange"
... ... @@ -33,7 +35,7 @@
33 35 style="text-align: center; line-height: 20vh"
34 36 :style="{ lineHeight: dynamicHeight + 'vh' }"
35 37 >
36   - <Button size="small" type="dashed" @click="handleRemove(item, index)">
  38 + <Button size="small" type="default" @click="handleRemove(item, index)">
37 39 <template #icon>
38 40 <MinusCircleOutlined />
39 41 </template>
... ... @@ -47,6 +49,7 @@
47 49 import { Button, InputNumber } from 'ant-design-vue';
48 50 import { MinusCircleOutlined } from '@ant-design/icons-vue';
49 51 import MappingsForm from './MappingsForm.vue';
  52 + import { useMessage } from '/@/hooks/web/useMessage';
50 53
51 54 const props = defineProps({
52 55 item: {
... ... @@ -59,7 +62,8 @@
59 62 });
60 63 const emit = defineEmits(['removeItem']);
61 64 const dynamicHeight = ref(25);
62   -
  65 + const queryingFrequencyMs = ref(5000);
  66 + const { createMessage } = useMessage();
63 67 const handleMappingsChange = (e) => {
64 68 // eslint-disable-next-line vue/no-mutating-props
65 69 props.item.mappings = e;
... ... @@ -70,9 +74,18 @@
70 74 //设置回显的高度
71 75 const setFieldsValueFunc = () => {
72 76 dynamicHeight.value = props.item.mappings.length * 3 + props.item.mappings.length + 15;
  77 + queryingFrequencyMs.value = props.item.queryingFrequencyMs;
73 78 };
74 79 //获取表单的值
75 80 const getSnmpFormFunc = () => {
  81 + if (
  82 + props.item.spec == 'TELEMETRY_QUERYING' ||
  83 + props.item.spec == 'CLIENT_ATTRIBUTES_QUERYING'
  84 + ) {
  85 + if (queryingFrequencyMs.value == null) {
  86 + return createMessage.error('请填写查询频率');
  87 + }
  88 + }
76 89 let obj: any = {};
77 90 obj = {
78 91 ...{ spec: props.item.spec },
... ... @@ -80,7 +93,7 @@
80 93 ...{
81 94 queryingFrequencyMs:
82 95 props.item.spec == 'TELEMETRY_QUERYING' || props.item.spec == 'CLIENT_ATTRIBUTES_QUERYING'
83   - ? props.item.queryingFrequencyMs
  96 + ? queryingFrequencyMs.value
84 97 : null,
85 98 },
86 99 };
... ...
... ... @@ -27,22 +27,14 @@
27 27 :options="selectOptions"
28 28 @change="handleChange(item.spec)"
29 29 allowClear
30   - >
31   - <SelectOption
32   - v-for="it in selectOptions"
33   - :value="it.value"
34   - :key="it.value"
35   - :label="it.label"
36   - :disabled="it.disabled"
37   - />
38   - </Select>
  30 + />
39 31 </SnmpForm>
40 32 </template>
41 33 <div
42 34 v-if="dynamicSNMP.communicationConfigs.length < 4"
43 35 style="margin-left: 0vw; margin-top: 2vh"
44 36 >
45   - <Button size="middle" type="dashed" @click="handleAdd">
  37 + <Button size="middle" type="text" @click="handleAdd">
46 38 <template #icon>
47 39 <PlusCircleOutlined />
48 40 </template>
... ... @@ -60,7 +52,7 @@
60 52 import { BasicForm, useForm } from '/@/components/Form';
61 53 import { snmpSchemas } from './config';
62 54 import { PlusCircleOutlined } from '@ant-design/icons-vue';
63   - import { Button, Select, SelectOption } from 'ant-design-vue';
  55 + import { Button, Select } from 'ant-design-vue';
64 56 import SnmpForm from './cpns/SnmpForm.vue';
65 57
66 58 interface mappingsI {
... ... @@ -77,26 +69,22 @@
77 69 {
78 70 label: 'Telemetry',
79 71 value: 'TELEMETRY_QUERYING',
80   - disabled: false,
81 72 },
82 73 {
83 74 label: 'Client attributes',
84 75 value: 'CLIENT_ATTRIBUTES_QUERYING',
85   - disabled: false,
86 76 },
87 77 {
88 78 label: 'Shared attributes',
89 79 value: 'SHARED_ATTRIBUTES_SETTING',
90   - disabled: false,
91 80 },
92 81 {
93 82 label: 'RPC request',
94 83 value: 'TO_DEVICE_RPC_REQUEST',
95   - disabled: false,
96 84 },
97 85 ]);
98 86 const selectValue = ref('');
99   - //解决新增选择框互斥问题和编辑回显互斥问题
  87 + //Select互斥
100 88 const handleChange = (value: string) => {
101 89 selectValue.value = value;
102 90 selectOptions.value.forEach((ele: any) => {
... ... @@ -154,12 +142,15 @@
154 142 });
155 143 };
156 144 const handleRemoveItem = (item, index) => {
157   - console.log(item.spec);
158   - //2 TODO待解决删除时清空互斥问题
  145 + selectOptions.value.forEach((ele: any) => {
  146 + if (ele.value == item.spec) {
  147 + ele.disabled = false;
  148 + }
  149 + });
159 150 dynamicSNMP.communicationConfigs.splice(index, 1);
160 151 };
  152 +
161 153 //回显表单值
162   - //TODO 采用这种方式动态绑定ref 都会造成回显数据顺序是随机的但不影响回显数据的正确性
163 154 const setStepFieldsValueFunc = (v) => {
164 155 setFieldsValue({
165 156 timeoutMs: v.timeoutMs,
... ... @@ -168,14 +159,13 @@
168 159 dynamicSNMP.communicationConfigs = v.communicationConfigs;
169 160 dynamicSNMP.communicationConfigs.forEach((snmp, index: number) => {
170 161 nextTick(() => {
171   - //编辑回显互斥赋值
172 162 handleChange(snmp.spec);
173 163 unref(dynamicBindRef.SnmpFormItemRef)[index]?.setFieldsValueFunc();
174 164 });
175 165 });
176 166 };
177 167
178   - //获取最终的
  168 + //获取表单
179 169 const getSnmpForm = async () => {
180 170 let value = await validate();
181 171 if (!value) return;
... ...