Commit 5fdfd88b1aa1b5d867c1cea8e0b2109c475a5902

Authored by fengtao
1 parent 26f450d6

refractor:修改设备配置

@@ -62,7 +62,7 @@ export const step1Schemas: FormSchema[] = [ @@ -62,7 +62,7 @@ export const step1Schemas: FormSchema[] = [
62 componentProps: { 62 componentProps: {
63 api: findDictItemByCode, 63 api: findDictItemByCode,
64 params: { 64 params: {
65 - dictCode: 'DEVICE_BRAND_GATEWAY', 65 + dictCode: 'device_brand_gateway',
66 }, 66 },
67 labelField: 'itemText', 67 labelField: 'itemText',
68 valueField: 'itemValue', 68 valueField: 'itemValue',
@@ -8,23 +8,50 @@ @@ -8,23 +8,50 @@
8 @ok="handleSubmit" 8 @ok="handleSubmit"
9 @cancel="handleCancel" 9 @cancel="handleCancel"
10 > 10 >
11 - <Tabs  
12 - type="card"  
13 - :animated="true"  
14 - v-model:activeKey="activeKey"  
15 - :size="size"  
16 - @change="handleChange"  
17 - >  
18 - <TabPane forceRender key="1" tab="设备配置">  
19 - <DeviceConfigurationStep v-show="activeKey === '1'" ref="DevConStRef" />  
20 - </TabPane>  
21 - <TabPane forceRender key="2" tab="传输配置">  
22 - <TransportConfigurationStep v-show="activeKey === '2'" ref="TransConStRef" />  
23 - </TabPane>  
24 - <TabPane forceRender key="3" v-show="activeKey === '3'" tab="物模型管理">  
25 - <PhysicalModelManagementStep v-show="activeKey === '3'" ref="PhysicalModManRef" />  
26 - </TabPane>  
27 - </Tabs> 11 + <div v-if="!isViewDetail" class="step-form-form">
  12 + <a-steps :current="current">
  13 + <a-step v-for="item in steps" :key="item.title" :title="item.title" />
  14 + </a-steps>
  15 + </div>
  16 + <div v-if="!isViewDetail" class="mt-5">
  17 + <DeviceConfigurationStep
  18 + v-show="current === 0"
  19 + ref="DevConStRef"
  20 + @next="handleStepNext(true, null)"
  21 + />
  22 + <TransportConfigurationStep
  23 + v-show="current === 1"
  24 + ref="TransConStRef"
  25 + @prev="handleStepPrev"
  26 + />
  27 + </div>
  28 + <div v-if="isViewDetail">
  29 + <Tabs
  30 + type="card"
  31 + :animated="true"
  32 + v-model:activeKey="activeKey"
  33 + :size="size"
  34 + @change="handleChange"
  35 + >
  36 + <TabPane forceRender key="1" tab="设备配置">
  37 + <DeviceConfigurationStep
  38 + :ifShowBtn="isViewDetail ? false : true"
  39 + v-show="activeKey === '1'"
  40 + ref="DevConStRef"
  41 + />
  42 + </TabPane>
  43 + <TabPane forceRender key="2" tab="传输配置">
  44 + <TransportConfigurationStep
  45 + :ifShowBtn="isViewDetail ? false : true"
  46 + v-show="activeKey === '2'"
  47 + ref="TransConStRef"
  48 + />
  49 + </TabPane>
  50 + <TabPane forceRender key="3" v-show="activeKey === '3'" tab="物模型管理">
  51 + <PhysicalModelManagementStep v-show="activeKey === '3'" ref="PhysicalModManRef" />
  52 + </TabPane>
  53 + </Tabs>
  54 + </div>
28 </BasicModal> 55 </BasicModal>
29 </div> 56 </div>
30 </template> 57 </template>
@@ -33,6 +60,7 @@ @@ -33,6 +60,7 @@
33 import { BasicModal, useModalInner } from '/@/components/Modal'; 60 import { BasicModal, useModalInner } from '/@/components/Modal';
34 import { deviceConfigAddOrEdit, deviceConfigGetDetail } from '/@/api/device/deviceConfigApi'; 61 import { deviceConfigAddOrEdit, deviceConfigGetDetail } from '/@/api/device/deviceConfigApi';
35 import { useMessage } from '/@/hooks/web/useMessage'; 62 import { useMessage } from '/@/hooks/web/useMessage';
  63 + import { steps } from './device.profile.data';
36 import { isEmpty } from '/@/utils/is'; 64 import { isEmpty } from '/@/utils/is';
37 import { Tabs, TabPane } from 'ant-design-vue'; 65 import { Tabs, TabPane } from 'ant-design-vue';
38 import DeviceConfigurationStep from './step/DeviceConfigurationStep.vue'; 66 import DeviceConfigurationStep from './step/DeviceConfigurationStep.vue';
@@ -47,6 +75,7 @@ @@ -47,6 +75,7 @@
47 const { createMessage } = useMessage(); 75 const { createMessage } = useMessage();
48 const isViewDetail = ref(false); 76 const isViewDetail = ref(false);
49 const isUpdate = ref(false); 77 const isUpdate = ref(false);
  78 + const current = ref(0);
50 const DevConStRef = ref<InstanceType<typeof DeviceConfigurationStep>>(); 79 const DevConStRef = ref<InstanceType<typeof DeviceConfigurationStep>>();
51 const TransConStRef = ref<InstanceType<typeof TransportConfigurationStep>>(); 80 const TransConStRef = ref<InstanceType<typeof TransportConfigurationStep>>();
52 const PhysicalModManRef = ref<InstanceType<typeof PhysicalModelManagementStep>>(); 81 const PhysicalModManRef = ref<InstanceType<typeof PhysicalModelManagementStep>>();
@@ -59,6 +88,7 @@ @@ -59,6 +88,7 @@
59 const transportTypeStr = ref(''); 88 const transportTypeStr = ref('');
60 const [register, { closeModal, setModalProps }] = useModalInner(async (data) => { 89 const [register, { closeModal, setModalProps }] = useModalInner(async (data) => {
61 setModalProps({ confirmLoading: false }); 90 setModalProps({ confirmLoading: false });
  91 + current.value = 0;
62 isUpdate.value = data.isUpdate; 92 isUpdate.value = data.isUpdate;
63 isViewDetail.value = data.isView; 93 isViewDetail.value = data.isView;
64 const res = data.record !== undefined ? await deviceConfigGetDetail(data.record.id) : {}; 94 const res = data.record !== undefined ? await deviceConfigGetDetail(data.record.id) : {};
@@ -73,7 +103,7 @@ @@ -73,7 +103,7 @@
73 handleStepNext(false, res); 103 handleStepNext(false, res);
74 } 104 }
75 } else { 105 } else {
76 - setModalProps({ showOkBtn: false, showCancelBtn: false, title: '查看设备配置' }); 106 + setModalProps({ showOkBtn: false, showCancelBtn: false, title: '设备配置详情' });
77 await setDeviceConfEditFormData(res); 107 await setDeviceConfEditFormData(res);
78 await setTransConfEditFormData(res); 108 await setTransConfEditFormData(res);
79 handleStepNext(false, res); 109 handleStepNext(false, res);
@@ -86,10 +116,14 @@ @@ -86,10 +116,14 @@
86 }; 116 };
87 const handleStepNext = (e, data) => { 117 const handleStepNext = (e, data) => {
88 if (e) { 118 if (e) {
  119 + current.value++;
89 } else { 120 } else {
90 setTransConfEditFormData(data); 121 setTransConfEditFormData(data);
91 } 122 }
92 }; 123 };
  124 + const handleStepPrev = () => {
  125 + current.value--;
  126 + };
93 127
94 const setDeviceConfEditFormData = async (res) => { 128 const setDeviceConfEditFormData = async (res) => {
95 await DevConStRef.value?.setFormData(res); 129 await DevConStRef.value?.setFormData(res);
@@ -8,6 +8,17 @@ import { h } from 'vue'; @@ -8,6 +8,17 @@ import { h } from 'vue';
8 8
9 import { deviceConfigGetRuleChain } from '/@/api/device/deviceConfigApi'; 9 import { deviceConfigGetRuleChain } from '/@/api/device/deviceConfigApi';
10 10
  11 +export const steps = [
  12 + {
  13 + title: '设备配置',
  14 + content: 'First-content',
  15 + },
  16 + {
  17 + title: '传输配置',
  18 + content: 'Second-content',
  19 + },
  20 +];
  21 +
11 export const physicalColumn: BasicColumn[] = [ 22 export const physicalColumn: BasicColumn[] = [
12 { 23 {
13 title: '功能名称', 24 title: '功能名称',
@@ -61,6 +72,24 @@ export const step1Schemas: FormSchema[] = [ @@ -61,6 +72,24 @@ export const step1Schemas: FormSchema[] = [
61 slot: 'imageSelect', 72 slot: 'imageSelect',
62 }, 73 },
63 { 74 {
  75 + field: 'brand',
  76 + component: 'ApiRadioGroup',
  77 + label: '设备类型',
  78 + required: true,
  79 + colProps: {
  80 + span: 14,
  81 + },
  82 + defaultValue: 'GATEWAY',
  83 + componentProps: {
  84 + api: findDictItemByCode,
  85 + params: {
  86 + dictCode: 'device_type',
  87 + },
  88 + labelField: 'itemText',
  89 + valueField: 'itemValue',
  90 + },
  91 + },
  92 + {
64 field: 'name', 93 field: 'name',
65 label: '配置名称', 94 label: '配置名称',
66 required: true, 95 required: true,
@@ -37,9 +37,13 @@ @@ -37,9 +37,13 @@
37 import { useMessage } from '/@/hooks/web/useMessage'; 37 import { useMessage } from '/@/hooks/web/useMessage';
38 import type { FileItem } from '/@/components/Upload/src/typing'; 38 import type { FileItem } from '/@/components/Upload/src/typing';
39 39
  40 + const emits = defineEmits(['next']);
40 const loading = ref(false); 41 const loading = ref(false);
41 const { createMessage } = useMessage(); 42 const { createMessage } = useMessage();
42 const deviceConfigPic = ref(''); 43 const deviceConfigPic = ref('');
  44 + const props = defineProps({
  45 + ifShowBtn: { type: Boolean, default: true },
  46 + });
43 47
44 const [register, { validate, setFieldsValue, resetFields, updateSchema }] = useForm({ 48 const [register, { validate, setFieldsValue, resetFields, updateSchema }] = useForm({
45 labelWidth: 100, 49 labelWidth: 100,
@@ -48,8 +52,11 @@ @@ -48,8 +52,11 @@
48 span: 14, 52 span: 14,
49 }, 53 },
50 showResetButton: false, 54 showResetButton: false,
51 - submitOnReset: false,  
52 - showActionButtonGroup: false, 55 + showActionButtonGroup: props.ifShowBtn ? true : false,
  56 + submitButtonOptions: {
  57 + text: '下一步',
  58 + },
  59 + submitFunc: customSubmitFunc,
53 }); 60 });
54 const editOrAddNameStatus = (nameStatus) => 61 const editOrAddNameStatus = (nameStatus) =>
55 updateSchema({ 62 updateSchema({
@@ -83,6 +90,11 @@ @@ -83,6 +90,11 @@
83 } 90 }
84 return isJpgOrPng && isLt2M; 91 return isJpgOrPng && isLt2M;
85 }; 92 };
  93 + async function customSubmitFunc() {
  94 + const values = await validate();
  95 + if (!values) return;
  96 + emits('next', true, null);
  97 + }
86 //回显数据 98 //回显数据
87 const setFormData = (v) => { 99 const setFormData = (v) => {
88 setFieldsValue(v); 100 setFieldsValue(v);
1 <template> 1 <template>
2 - <div> 2 + <div class="p-style">
3 <BasicTable 3 <BasicTable
4 :rowSelection="{ type: 'checkbox' }" 4 :rowSelection="{ type: 'checkbox' }"
5 :clickToRowSelect="false" 5 :clickToRowSelect="false"
6 @register="registerTable" 6 @register="registerTable"
7 > 7 >
8 <template #toolbar> 8 <template #toolbar>
9 - <div style="display: flex; justify-content: space-between; width: 773px">  
10 - <div>  
11 - <Authority value="">  
12 - <div style="display: flex">  
13 - <a-button  
14 - style="margin-left: -20px"  
15 - type="primary"  
16 - @click="handleCreateOrEdit(null)"  
17 - >  
18 - 新增物模型  
19 - </a-button>  
20 - <a-button class="ml-2" type="primary" @click="handleOpenTsl"> 物模型TSL </a-button>  
21 - </div>  
22 - </Authority> 9 + <div class="p-column">
  10 + <div class="p-content">
  11 + <a-alert
  12 + style="width: 420px"
  13 + message="当前展示的是已发布到线上的功能定义,如需修改,请点击"
  14 + type="info"
  15 + show-icon
  16 + />
  17 + <span
  18 + @click="handleEditPhysicalModel"
  19 + class="ml-2"
  20 + style="color: #409eff; cursor: pointer"
  21 + type="primary"
  22 + size="small"
  23 + >“编辑物模型”</span
  24 + >
23 </div> 25 </div>
24 - <div>  
25 - <Authority value="">  
26 - <div style="display: flex">  
27 - <a-button type="primary"> 发布上线 </a-button>  
28 - <a-button class="ml-2" type="text"> 返回 </a-button>  
29 - <Popconfirm  
30 - title="您确定要批量删除数据"  
31 - ok-text="确定"  
32 - cancel-text="取消"  
33 - @confirm="handleDeleteOrBatchDelete(null)"  
34 - > 26 + <div style="height: 20px"></div>
  27 + <div class="p-bottom">
  28 + <div>
  29 + <Authority value="">
  30 + <div style="display: flex">
35 <a-button 31 <a-button
36 - style="display: none" 32 + v-if="isShowBtn"
  33 + style="margin-left: -20px"
37 type="primary" 34 type="primary"
38 - color="error"  
39 - :disabled="hasBatchDelete" 35 + @click="handleCreateOrEdit(null)"
40 > 36 >
41 - 批量删除 37 + 新增物模型
42 </a-button> 38 </a-button>
43 - </Popconfirm>  
44 - </div>  
45 - </Authority> 39 + <a-button
  40 + :style="[isShowBtn ? { left: 0 + 'px' } : { left: -29 + 'px' }]"
  41 + class="ml-2"
  42 + type="primary"
  43 + @click="handleOpenTsl"
  44 + >
  45 + 物模型TSL
  46 + </a-button>
  47 + </div>
  48 + </Authority>
  49 + </div>
  50 + <div>
  51 + <Authority value="">
  52 + <div style="display: flex">
  53 + <Popconfirm
  54 + title="是否需要发布上线?"
  55 + ok-text="确定"
  56 + cancel-text="取消"
  57 + @confirm="handleEmit"
  58 + >
  59 + <a-button v-if="isShowBtn" type="primary"> 发布上线 </a-button>
  60 + </Popconfirm>
  61 + <a-button
  62 + style="background: #d7d7d7"
  63 + v-if="isShowBtn"
  64 + class="ml-2"
  65 + type="text"
  66 + @click="handleReturn"
  67 + >
  68 + 返回
  69 + </a-button>
  70 + <Popconfirm
  71 + title="您确定要批量删除数据"
  72 + ok-text="确定"
  73 + cancel-text="取消"
  74 + @confirm="handleDeleteOrBatchDelete(null)"
  75 + >
  76 + <a-button
  77 + style="display: none"
  78 + type="primary"
  79 + color="error"
  80 + :disabled="hasBatchDelete"
  81 + >
  82 + 批量删除
  83 + </a-button>
  84 + </Popconfirm>
  85 + </div>
  86 + </Authority>
  87 + </div>
46 </div> 88 </div>
47 </div> 89 </div>
48 </template> 90 </template>
@@ -53,18 +95,21 @@ @@ -53,18 +95,21 @@
53 label: '查看', 95 label: '查看',
54 icon: 'ant-design:eye-outlined', 96 icon: 'ant-design:eye-outlined',
55 onClick: handleViewDetail.bind(null, record), 97 onClick: handleViewDetail.bind(null, record),
  98 + ifShow: isShowBtn ? false : true,
56 }, 99 },
57 { 100 {
58 label: '编辑', 101 label: '编辑',
59 icon: 'clarity:note-edit-line', 102 icon: 'clarity:note-edit-line',
60 auth: '', 103 auth: '',
61 onClick: handleCreateOrEdit.bind(null, record), 104 onClick: handleCreateOrEdit.bind(null, record),
  105 + ifShow: !isShowBtn ? false : true,
62 }, 106 },
63 { 107 {
64 label: '删除', 108 label: '删除',
65 icon: 'ant-design:delete-outlined', 109 icon: 'ant-design:delete-outlined',
66 auth: '', 110 auth: '',
67 color: 'error', 111 color: 'error',
  112 + ifShow: !isShowBtn ? false : true,
68 popConfirm: { 113 popConfirm: {
69 title: '是否确认删除', 114 title: '是否确认删除',
70 confirm: handleDeleteOrBatchDelete.bind(null, record), 115 confirm: handleDeleteOrBatchDelete.bind(null, record),
@@ -79,6 +124,7 @@ @@ -79,6 +124,7 @@
79 </div> 124 </div>
80 </template> 125 </template>
81 <script lang="ts" setup> 126 <script lang="ts" setup>
  127 + import { ref } from 'vue';
82 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 128 import { BasicTable, useTable, TableAction } from '/@/components/Table';
83 import { useModal } from '/@/components/Modal'; 129 import { useModal } from '/@/components/Modal';
84 import { physicalColumn } from '../device.profile.data'; 130 import { physicalColumn } from '../device.profile.data';
@@ -89,8 +135,11 @@ @@ -89,8 +135,11 @@
89 import PhysicalModelModal from './cpns/physical/PhysicalModelModal.vue'; 135 import PhysicalModelModal from './cpns/physical/PhysicalModelModal.vue';
90 import PhysicalModelTsl from './cpns/physical/PhysicalModelTsl.vue'; 136 import PhysicalModelTsl from './cpns/physical/PhysicalModelTsl.vue';
91 import { Popconfirm } from 'ant-design-vue'; 137 import { Popconfirm } from 'ant-design-vue';
  138 + import { useMessage } from '/@/hooks/web/useMessage';
92 139
93 defineEmits(['register']); 140 defineEmits(['register']);
  141 + const { createMessage } = useMessage();
  142 + const isShowBtn = ref(false);
94 const [registerModal, { openModal }] = useModal(); 143 const [registerModal, { openModal }] = useModal();
95 const [registerModalTsl, { openModal: openModalTsl }] = useModal(); 144 const [registerModalTsl, { openModal: openModalTsl }] = useModal();
96 145
@@ -158,10 +207,27 @@ @@ -158,10 +207,27 @@
158 isUpdate: true, 207 isUpdate: true,
159 }); 208 });
160 }; 209 };
  210 + const handleEditPhysicalModel = () => (isShowBtn.value = true);
  211 +
  212 + const handleReturn = () => (isShowBtn.value = false);
  213 + const handleEmit = () => {
  214 + createMessage.success('发布成功');
  215 + };
  216 +
161 defineExpose({}); 217 defineExpose({});
162 </script> 218 </script>
163 <style lang="less" scoped> 219 <style lang="less" scoped>
  220 + @import url('./common/PhysicalModelManagementStep.less');
  221 +
164 :deep(.ant-table-body) { 222 :deep(.ant-table-body) {
165 height: auto !important; 223 height: auto !important;
166 } 224 }
  225 +
  226 + :deep(.ant-divider) {
  227 + margin-top: 58px;
  228 + }
  229 +
  230 + :deep(.table-settings) {
  231 + margin-top: 58px;
  232 + }
167 </style> 233 </style>
@@ -13,6 +13,8 @@ @@ -13,6 +13,8 @@
13 ? { minHeight: 55 + 'vh' } 13 ? { minHeight: 55 + 'vh' }
14 : isMqttType == 'SNMP' 14 : isMqttType == 'SNMP'
15 ? { minHeight: 60 + 'vh' } 15 ? { minHeight: 60 + 'vh' }
  16 + : isMqttType == 'TCP'
  17 + ? { minHeight: 15 + 'vh' }
16 : { minHeight: 25 + 'vh' }, 18 : { minHeight: 25 + 'vh' },
17 ]" 19 ]"
18 > 20 >
@@ -29,6 +31,16 @@ @@ -29,6 +31,16 @@
29 <div style="margin-top: 5vh" v-else-if="isMqttType == 'SNMP'"> 31 <div style="margin-top: 5vh" v-else-if="isMqttType == 'SNMP'">
30 <SnmpCpns ref="snmpRef" /> 32 <SnmpCpns ref="snmpRef" />
31 </div> 33 </div>
  34 + <div style="margin-top: 5vh; margin-left: -102px" v-else-if="isMqttType == 'TCP'">
  35 + <TcpCpns ref="tcpRef" />
  36 + </div>
  37 + <div v-if="ifShowBtn" class="btn-style">
  38 + <div style="display: flex; width: 4vw; height: 4vh; margin-top: 1.65vh; margin-left: 44px">
  39 + <Button type="default" style="border-radius: 2px" class="mt-5" @click="customResetFunc"
  40 + >上一步</Button
  41 + >
  42 + </div>
  43 + </div>
32 </div> 44 </div>
33 </div> 45 </div>
34 </template> 46 </template>
@@ -36,15 +48,22 @@ @@ -36,15 +48,22 @@
36 import { reactive, ref, onUnmounted, nextTick } from 'vue'; 48 import { reactive, ref, onUnmounted, nextTick } from 'vue';
37 import { BasicForm, useForm } from '/@/components/Form'; 49 import { BasicForm, useForm } from '/@/components/Form';
38 import { step2Schemas } from '../device.profile.data'; 50 import { step2Schemas } from '../device.profile.data';
  51 + import { Button } from '/@/components/Button';
39 import MqttCpns from './cpns/mqtt/Mqtt.vue'; 52 import MqttCpns from './cpns/mqtt/Mqtt.vue';
40 import CoapCpns from './cpns/coap/Coap.vue'; 53 import CoapCpns from './cpns/coap/Coap.vue';
41 import Lwm2mCpns from './cpns/lwm2m/index.vue'; 54 import Lwm2mCpns from './cpns/lwm2m/index.vue';
42 import SnmpCpns from './cpns/snmp/index.vue'; 55 import SnmpCpns from './cpns/snmp/index.vue';
  56 + import TcpCpns from './cpns/tcp/index.vue';
43 57
  58 + const emits = defineEmits(['prev']);
  59 + const props = defineProps({
  60 + ifShowBtn: { type: Boolean, default: true },
  61 + });
44 const mqttRef = ref<InstanceType<typeof MqttCpns>>(); 62 const mqttRef = ref<InstanceType<typeof MqttCpns>>();
45 const coapRef = ref<InstanceType<typeof CoapCpns>>(); 63 const coapRef = ref<InstanceType<typeof CoapCpns>>();
46 const lwm2mRef = ref<InstanceType<typeof Lwm2mCpns>>(); 64 const lwm2mRef = ref<InstanceType<typeof Lwm2mCpns>>();
47 const snmpRef = ref<InstanceType<typeof SnmpCpns>>(); 65 const snmpRef = ref<InstanceType<typeof SnmpCpns>>();
  66 + const tcpRef = ref<InstanceType<typeof TcpCpns>>();
48 const isMqttType = ref('DEFAULT'); 67 const isMqttType = ref('DEFAULT');
49 let step2Data = reactive({ 68 let step2Data = reactive({
50 transportConfiguration: {}, 69 transportConfiguration: {},
@@ -57,7 +76,7 @@ @@ -57,7 +76,7 @@
57 }, 76 },
58 showResetButton: false, 77 showResetButton: false,
59 submitOnReset: false, 78 submitOnReset: false,
60 - showActionButtonGroup: false, 79 + showActionButtonGroup: props.ifShowBtn ? true : false,
61 }); 80 });
62 const setFormData = (v) => { 81 const setFormData = (v) => {
63 setFieldsValue({ 82 setFieldsValue({
@@ -68,6 +87,7 @@ @@ -68,6 +87,7 @@
68 coapRef.value?.setFormData(v?.profileData?.transportConfiguration); 87 coapRef.value?.setFormData(v?.profileData?.transportConfiguration);
69 lwm2mRef.value?.setFormData(v?.profileData?.transportConfiguration); 88 lwm2mRef.value?.setFormData(v?.profileData?.transportConfiguration);
70 snmpRef.value?.setFormData(v?.profileData?.transportConfiguration); 89 snmpRef.value?.setFormData(v?.profileData?.transportConfiguration);
  90 + tcpRef.value?.setFormData(v?.profileData?.transportConfiguration);
71 }; 91 };
72 92
73 const resetFormData = () => { 93 const resetFormData = () => {
@@ -78,8 +98,12 @@ @@ -78,8 +98,12 @@
78 coapRef.value?.resetFormData(); 98 coapRef.value?.resetFormData();
79 lwm2mRef.value?.resetFormData(); 99 lwm2mRef.value?.resetFormData();
80 snmpRef.value?.resetFormData(); 100 snmpRef.value?.resetFormData();
  101 + tcpRef.value?.resetFormData();
81 }); 102 });
82 }; 103 };
  104 + async function customResetFunc() {
  105 + emits('prev');
  106 + }
83 nextTick(() => { 107 nextTick(() => {
84 updateSchema({ 108 updateSchema({
85 field: 'transportType', 109 field: 'transportType',
@@ -91,6 +115,7 @@ @@ -91,6 +115,7 @@
91 { label: 'CoAP', value: 'COAP' }, 115 { label: 'CoAP', value: 'COAP' },
92 { label: 'LWM2M', value: 'LWM2M' }, 116 { label: 'LWM2M', value: 'LWM2M' },
93 { label: 'SNMP', value: 'SNMP' }, 117 { label: 'SNMP', value: 'SNMP' },
  118 + { label: 'TCP', value: 'TCP' },
94 ], 119 ],
95 onChange(e) { 120 onChange(e) {
96 isMqttType.value = e; 121 isMqttType.value = e;
@@ -109,11 +134,13 @@ @@ -109,11 +134,13 @@
109 const getCoapVal = await coapRef.value?.getFormData(); 134 const getCoapVal = await coapRef.value?.getFormData();
110 const getLwm2mVal = await lwm2mRef.value?.getFormData(); 135 const getLwm2mVal = await lwm2mRef.value?.getFormData();
111 const getSnmpVal = await snmpRef.value?.getFormData(); 136 const getSnmpVal = await snmpRef.value?.getFormData();
  137 + const getTcpVal = await tcpRef.value?.getFormData();
112 step2Data.transportConfiguration = { 138 step2Data.transportConfiguration = {
113 ...getMqttVal, 139 ...getMqttVal,
114 ...getCoapVal, 140 ...getCoapVal,
115 ...getLwm2mVal, 141 ...getLwm2mVal,
116 ...getSnmpVal, 142 ...getSnmpVal,
  143 + ...getTcpVal,
117 ...val, 144 ...val,
118 }; 145 };
119 return step2Data; 146 return step2Data;
  1 +.p-style {
  2 + .p-column {
  3 + display: flex;
  4 + flex-direction: column;
  5 +
  6 + .p-content {
  7 + display: flex;
  8 + align-items: center;
  9 + margin-left: -20px;
  10 + }
  11 +
  12 + .p-bottom {
  13 + display: flex;
  14 + justify-content: space-between;
  15 + width: 773px;
  16 + margin-top: 0;
  17 + }
  18 + }
  19 +}
@@ -8,32 +8,46 @@ @@ -8,32 +8,46 @@
8 @ok="handleSubmit" 8 @ok="handleSubmit"
9 @cancel="handleCancel" 9 @cancel="handleCancel"
10 > 10 >
11 - <Tabs v-model:activeKey="activeKey" :size="size">  
12 - <TabPane key="1" tab="属性">  
13 - <Attr v-show="activeKey === '1'" ref="AttrRef" />  
14 - </TabPane>  
15 - <TabPane disabled key="2" tab="服务">  
16 - <Service v-show="activeKey === '2'" ref="ServiceRef" />  
17 - </TabPane>  
18 - <TabPane disabled key="3" v-show="activeKey === '3'" tab="事件">  
19 - <Events v-show="activeKey === '3'" ref="EventsRef" />  
20 - </TabPane>  
21 - </Tabs> 11 + <div v-if="isViewDetail">
  12 + <Attribute v-show="activeKey === '1'" ref="AttrRef" />
  13 + </div>
  14 + <div v-if="!isViewDetail">
  15 + <div>
  16 + <Typography>
  17 + <TypographyParagraph>
  18 + <blockquote style="background: #f2f2f2">{{ blockContent }}</blockquote>
  19 + </TypographyParagraph>
  20 + </Typography>
  21 + </div>
  22 + <Tabs type="card" v-model:activeKey="activeKey" :size="size">
  23 + <TabPane key="1" tab="属性">
  24 + <Attribute v-show="activeKey === '1'" ref="AttrRef" />
  25 + </TabPane>
  26 + <TabPane disabled key="2" tab="服务">
  27 + <Service v-show="activeKey === '2'" ref="ServiceRef" />
  28 + </TabPane>
  29 + <TabPane disabled key="3" v-show="activeKey === '3'" tab="事件">
  30 + <Events v-show="activeKey === '3'" ref="EventsRef" />
  31 + </TabPane>
  32 + </Tabs>
  33 + </div>
22 </BasicModal> 34 </BasicModal>
23 </div> 35 </div>
24 </template> 36 </template>
25 <script lang="ts" setup> 37 <script lang="ts" setup>
26 import { ref, unref } from 'vue'; 38 import { ref, unref } from 'vue';
27 import { BasicModal, useModalInner } from '/@/components/Modal'; 39 import { BasicModal, useModalInner } from '/@/components/Modal';
28 - import { Tabs, TabPane } from 'ant-design-vue';  
29 - import Attr from './cpns/Attr.vue'; 40 + import { Tabs, TabPane, Typography, TypographyParagraph } from 'ant-design-vue';
  41 + import Attribute from './cpns/Attribute.vue';
30 import Service from './cpns/Service.vue'; 42 import Service from './cpns/Service.vue';
31 import Events from './cpns/Events.vue'; 43 import Events from './cpns/Events.vue';
32 44
33 defineEmits(['register']); 45 defineEmits(['register']);
  46 + const blockContent = `属性一般是设备的运行状态,如当前温度等;服务是设备可被调用的方法,支持定义参数,如执行某项任务;事件则是设备上报的
  47 +通知,如告警,需要被及时处理。`;
34 const activeKey = ref('1'); 48 const activeKey = ref('1');
35 const size = ref('small'); 49 const size = ref('small');
36 - const AttrRef = ref<InstanceType<typeof Attr>>(); 50 + const AttrRef = ref<InstanceType<typeof Attribute>>();
37 const ServiceRef = ref<InstanceType<typeof Service>>(); 51 const ServiceRef = ref<InstanceType<typeof Service>>();
38 const EventsRef = ref<InstanceType<typeof Events>>(); 52 const EventsRef = ref<InstanceType<typeof Events>>();
39 const isUpdate = ref(false); 53 const isUpdate = ref(false);
src/views/device/profiles/step/cpns/physical/cpns/Attribute.vue renamed from src/views/device/profiles/step/cpns/physical/cpns/Attr.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 - <div style="display: flex; justify-content: space-between"> 3 + <div>
  4 + <Typography>
  5 + <TypographyParagraph>
  6 + <blockquote style="background: #f2f2f2">{{ blockContent }}</blockquote>
  7 + </TypographyParagraph>
  8 + </Typography>
  9 + </div>
  10 + <div style="display: flex; justify-content: space-between; align-items: center">
4 <div>模型内容</div> 11 <div>模型内容</div>
5 <div> 12 <div>
6 <Button @click="handlePremitter"> 13 <Button @click="handlePremitter">
@@ -29,10 +36,13 @@ @@ -29,10 +36,13 @@
29 import { useMessage } from '/@/hooks/web/useMessage'; 36 import { useMessage } from '/@/hooks/web/useMessage';
30 import jsoneditor from 'jsoneditor'; 37 import jsoneditor from 'jsoneditor';
31 import 'jsoneditor/dist/jsoneditor.min.css'; 38 import 'jsoneditor/dist/jsoneditor.min.css';
32 - import { Button } from 'ant-design-vue'; 39 + import { Button, Typography, TypographyParagraph } from 'ant-design-vue';
33 import { defaultTslContent } from './config'; 40 import { defaultTslContent } from './config';
34 41
35 const { createMessage } = useMessage(); 42 const { createMessage } = useMessage();
  43 + const blockContent = `物模型是对设备在云端的功能描述,包括设备的属性、服务和事件。物联网平台通过定义一种物的描述语言来描述物模型,称之为 TSL(即 Thing
  44 +Specification Language),采用 JSON 格式,您可以根据 TSL 组装上报设备的数据。您可以导出完整物模型,用于云端应用开发;您也可以只导出
  45 +精简物模型,配合设备端 SDK 实现设备开发。`;
36 const jsonValue = ref(defaultTslContent); 46 const jsonValue = ref(defaultTslContent);
37 const jsonInstance = ref(); 47 const jsonInstance = ref();
38 const jsoneditorRef = ref(); 48 const jsoneditorRef = ref();
  1 +<template>
  2 + <div>
  3 + <BasicModal
  4 + destroyOnClose
  5 + v-bind="$attrs"
  6 + width="60rem"
  7 + @register="register"
  8 + :title="getTitle"
  9 + :minHeight="500"
  10 + @cancel="handleCancel"
  11 + @ok="handleSubmit"
  12 + >
  13 + <ConverScript :ifAdd="!isUpdate ? false : true" ref="converScriptRef" />
  14 + </BasicModal>
  15 + </div>
  16 +</template>
  17 +<script setup lang="ts">
  18 + import { ref, computed, unref } from 'vue';
  19 + import { BasicModal, useModalInner } from '/@/components/Modal';
  20 + import ConverScript from '/@/views/scriptmanage/converscript/ConverScript.vue';
  21 +
  22 + const converScriptRef = ref<InstanceType<typeof ConverScript>>();
  23 + const getTitle = computed(() => (isUpdate.value ? '测试脚本' : '新建脚本'));
  24 + const isUpdate = ref(false);
  25 + const [register, { setModalProps, closeModal }] = useModalInner(async (data) => {
  26 + setModalProps({ loading: true });
  27 + handleCancel(false);
  28 + isUpdate.value = data.isUpdate;
  29 + converScriptRef.value?.initEditor(data.record?.configuration?.jsScript);
  30 + setModalProps({ loading: false });
  31 + const title = !unref(isUpdate) ? '测试脚本' : '新建脚本';
  32 + const okText = !unref(isUpdate) ? '测试' : '确定';
  33 + setModalProps({ title, showOkBtn: true, showCancelBtn: true, okText });
  34 + // converScriptRef.value?.setFormData();
  35 + });
  36 + const handleSubmit = async () => {
  37 + const val = await converScriptRef.value?.getFormData();
  38 + console.log(val);
  39 + handleCancel(true);
  40 + };
  41 + const handleCancel = (flag) => {
  42 + if (flag) {
  43 + closeModal();
  44 + }
  45 + converScriptRef.value?.resetFormData();
  46 + };
  47 +</script>
  48 +<style lang="less" scoped>
  49 + @import url('/@/views/scriptmanage/converscript/ConverScriptModal.less');
  50 +</style>
  1 +import { FormSchema } from '/@/components/Form';
  2 +
  3 +export const tcpSchemas: FormSchema[] = [
  4 + {
  5 + field: 'script',
  6 + label: '转换脚本',
  7 + component: 'Input',
  8 + slot: 'script',
  9 + colProps: { span: 24 },
  10 + },
  11 +];
  12 +
  13 +// 新增编辑配置
  14 +export const formSchema: FormSchema[] = [
  15 + {
  16 + field: 'name',
  17 + label: '输入参数',
  18 + colProps: { span: 24 },
  19 + required: true,
  20 + component: 'Input',
  21 + componentProps: {
  22 + maxLength: 255,
  23 + placeholder: '请输入输入参数',
  24 + },
  25 + },
  26 + {
  27 + field: 'scriptContent',
  28 + label: '脚本内容',
  29 + required: true,
  30 + component: 'Input',
  31 + slot: 'scriptContent',
  32 + colProps: { span: 24 },
  33 + },
  34 + {
  35 + field: 'remark',
  36 + label: '输出参数',
  37 + colProps: { span: 24 },
  38 + component: 'InputTextArea',
  39 + componentProps: {
  40 + rows: 6,
  41 + maxLength: 255,
  42 + placeholder: '请输入输出参数',
  43 + },
  44 + },
  45 +];
  1 +<template>
  2 + <div>
  3 + <BasicForm :showResetButton="false" :showSubmitButton="false" @register="register">
  4 + <template #script>
  5 + <div style="display: flex; align-items: center">
  6 + <div>
  7 + <Select
  8 + placeholder="请选择转换脚本"
  9 + v-model:value="selectScript.script"
  10 + style="width: 305px"
  11 + :options="selectOptions"
  12 + allowClear
  13 + />
  14 + </div>
  15 + <div>
  16 + <span
  17 + @click="handleCreateOrEdit('add')"
  18 + class="ml-2"
  19 + style="color: #409eff; cursor: pointer"
  20 + type="primary"
  21 + size="small"
  22 + >新建转换脚本</span
  23 + >
  24 + </div>
  25 + </div>
  26 + <a-button @click="handleCreateOrEdit('test')" class="mt-4" type="primary"
  27 + >测试脚本</a-button
  28 + >
  29 + </template>
  30 + </BasicForm>
  31 + <ConverScriptModal @register="registerModal" />
  32 + </div>
  33 +</template>
  34 +<script lang="ts" setup>
  35 + import { ref, Ref, reactive, onMounted } from 'vue';
  36 + import { BasicForm, useForm } from '/@/components/Form';
  37 + import { tcpSchemas } from './config';
  38 + import { SelectTypes } from 'ant-design-vue/es/select';
  39 + import { Select } from 'ant-design-vue';
  40 + import { useModal } from '/@/components/Modal';
  41 + import ConverScriptModal from './ConverScriptModal.vue';
  42 +
  43 + const selectScript = reactive({
  44 + script: null,
  45 + });
  46 + const selectOptions: Ref<SelectTypes['options']> = ref([
  47 + {
  48 + label: '电表转换脚本',
  49 + value: 1,
  50 + },
  51 + {
  52 + label: '水表转换脚本',
  53 + value: 2,
  54 + },
  55 + ]);
  56 + onMounted(() => {});
  57 +
  58 + const [register] = useForm({
  59 + labelWidth: 180,
  60 + schemas: tcpSchemas,
  61 + actionColOptions: {
  62 + span: 14,
  63 + },
  64 + });
  65 + const [registerModal, { openModal }] = useModal();
  66 +
  67 + // 新增或编辑
  68 + const handleCreateOrEdit = (c) => {
  69 + if (c === 'add') {
  70 + openModal(true, {
  71 + isUpdate: true,
  72 + });
  73 + } else {
  74 + openModal(true, {
  75 + isUpdate: false,
  76 + });
  77 + }
  78 + };
  79 +
  80 + const getFormData = () => {
  81 + return selectScript;
  82 + };
  83 + const resetFormData = () => {
  84 + selectScript.script = null;
  85 + };
  86 + const setFormData = (v) => {
  87 + selectScript.script = v;
  88 + };
  89 + defineExpose({
  90 + getFormData,
  91 + resetFormData,
  92 + setFormData,
  93 + });
  94 +</script>
  95 +<style lang="less" scoped></style>
1 <template> 1 <template>
2 <div> 2 <div>
3 - <BasicForm @register="registerForm">  
4 - <template #scriptContent> 3 + <a-form
  4 + ref="formRef"
  5 + :model="scriptForm"
  6 + name="basic"
  7 + :label-col="{ span: 3 }"
  8 + :wrapper-col="{ span: 17 }"
  9 + autocomplete="off"
  10 + >
  11 + <a-form-item
  12 + :label="ifAdd ? '名称' : '输入参数'"
  13 + :name="ifAdd ? 'scriptName' : 'inputParams'"
  14 + :rules="[{ required: true, message: ifAdd ? '请输入脚本名称' : '请输入参数' }]"
  15 + >
  16 + <a-input v-if="ifAdd" v-model:value="scriptForm.scriptName" placeholder="请输入脚本名称" />
  17 + <a-input v-else v-model:value="scriptForm.inputParams" placeholder="请输入参数" />
  18 + </a-form-item>
  19 + <a-form-item
  20 + label="脚本内容"
  21 + name="scriptContent"
  22 + :rules="[{ required: true, message: '请输入脚本内容' }]"
  23 + >
5 <Card title="脚本内容" :bodyStyle="{ padding: 0, height: '280px' }"> 24 <Card title="脚本内容" :bodyStyle="{ padding: 0, height: '280px' }">
  25 + <template #extra>
  26 + <a-button @click="handleFormat" size="small">格式化</a-button>
  27 + </template>
6 <div ref="aceRef" class="overflow-hidden"></div> 28 <div ref="aceRef" class="overflow-hidden"></div>
7 </Card> 29 </Card>
8 <Button @click="handleCopy" class="mt-4"> 30 <Button @click="handleCopy" class="mt-4">
@@ -11,14 +33,29 @@ @@ -11,14 +33,29 @@
11 </template> 33 </template>
12 copy 34 copy
13 </Button> 35 </Button>
14 - </template>  
15 - </BasicForm> 36 + </a-form-item>
  37 + <a-form-item
  38 + :label="ifAdd ? '备注' : '输出参数'"
  39 + :name="ifAdd ? 'scriptRemark' : 'outputParams'"
  40 + >
  41 + <a-textarea
  42 + :rows="5"
  43 + v-if="ifAdd"
  44 + v-model:value="scriptForm.scriptRemark"
  45 + placeholder="请输入备注"
  46 + />
  47 + <a-textarea
  48 + :rows="5"
  49 + v-else
  50 + v-model:value="scriptForm.outputParams"
  51 + placeholder="请输入输出参数"
  52 + />
  53 + </a-form-item>
  54 + </a-form>
16 </div> 55 </div>
17 </template> 56 </template>
18 <script setup lang="ts"> 57 <script setup lang="ts">
19 - import { ref, unref } from 'vue';  
20 - import { formSchema } from './config.data';  
21 - import { BasicForm, useForm } from '/@/components/Form'; 58 + import { ref, unref, reactive } from 'vue';
22 import ace from 'ace-builds'; 59 import ace from 'ace-builds';
23 import { Card, Button } from 'ant-design-vue'; 60 import { Card, Button } from 'ant-design-vue';
24 import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题 61 import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题
@@ -29,15 +66,20 @@ @@ -29,15 +66,20 @@
29 import { useMessage } from '/@/hooks/web/useMessage'; 66 import { useMessage } from '/@/hooks/web/useMessage';
30 67
31 defineEmits(['register']); 68 defineEmits(['register']);
  69 + defineProps({
  70 + ifAdd: { type: Boolean, default: true },
  71 + });
  72 + const scriptForm = reactive({
  73 + scriptName: '',
  74 + scriptRemark: '',
  75 + scriptContent: '',
  76 + inputParams: '',
  77 + outputParams: '',
  78 + });
32 const { createMessage } = useMessage(); 79 const { createMessage } = useMessage();
33 const { clipboardRef, copiedRef } = useCopyToClipboard(); 80 const { clipboardRef, copiedRef } = useCopyToClipboard();
34 const aceEditor = ref(); 81 const aceEditor = ref();
35 const aceRef = ref(); 82 const aceRef = ref();
36 - const [registerForm, { validate, resetFields }] = useForm({  
37 - labelWidth: 120,  
38 - schemas: formSchema,  
39 - showActionButtonGroup: false,  
40 - });  
41 // 初始化编辑器 83 // 初始化编辑器
42 const initEditor = (jsScript?: string) => { 84 const initEditor = (jsScript?: string) => {
43 aceEditor.value = ace.edit(aceRef.value, { 85 aceEditor.value = ace.edit(aceRef.value, {
@@ -64,6 +106,7 @@ @@ -64,6 +106,7 @@
64 }` 106 }`
65 ); 107 );
66 beautify(aceEditor.value.session); 108 beautify(aceEditor.value.session);
  109 + scriptForm.scriptContent = aceEditor.value.getValue();
67 }; 110 };
68 const handleCopy = () => { 111 const handleCopy = () => {
69 const valueRef = aceEditor.value.getValue(); 112 const valueRef = aceEditor.value.getValue();
@@ -77,19 +120,29 @@ @@ -77,19 +120,29 @@
77 createMessage.success('复制成功!'); 120 createMessage.success('复制成功!');
78 } 121 }
79 }; 122 };
  123 + const formRef = ref();
80 const getFormData = async () => { 124 const getFormData = async () => {
81 - const value = await validate(); 125 + const value = await formRef.value.validateFields();
82 if (!value) return; 126 if (!value) return;
83 return value; 127 return value;
84 }; 128 };
  129 + const setFormData = (v) => {
  130 + for (let i in scriptForm) {
  131 + Reflect.set(scriptForm, i, v[i]);
  132 + }
  133 + };
85 const resetFormData = () => { 134 const resetFormData = () => {
86 - resetFields(); 135 + for (let i in scriptForm) {
  136 + Reflect.set(scriptForm, i, '');
  137 + }
87 }; 138 };
  139 + const handleFormat = () => beautify(aceEditor.value.session);
88 140
89 defineExpose({ 141 defineExpose({
90 initEditor, 142 initEditor,
91 getFormData, 143 getFormData,
92 resetFormData, 144 resetFormData,
  145 + setFormData,
93 }); 146 });
94 </script> 147 </script>
95 <style lang="less" scoped> 148 <style lang="less" scoped>
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 @cancel="handleCancel" 10 @cancel="handleCancel"
11 @ok="handleSubmit" 11 @ok="handleSubmit"
12 > 12 >
13 - <ConverScript ref="converScriptRef" /> 13 + <ConverScript :ifAdd="true" ref="converScriptRef" />
14 </BasicModal> 14 </BasicModal>
15 </div> 15 </div>
16 </template> 16 </template>
1 -/*  
2 - * @Author: fengtao 1400859700@qq.com  
3 - * @Date: 2022-10-12 09:29:11  
4 - * @LastEditors: fengtao 1400859700@qq.com  
5 - * @LastEditTime: 2022-10-13 17:28:24  
6 - * @FilePath: \yun-teng-iot-front\src\views\scriptmanage\converscript\config.data.ts  
7 - * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE  
8 - */  
9 import { BasicColumn, FormSchema } from '/@/components/Table'; 1 import { BasicColumn, FormSchema } from '/@/components/Table';
10 import moment from 'moment'; 2 import moment from 'moment';
11 import { h } from 'vue'; 3 import { h } from 'vue';
@@ -76,14 +68,11 @@ export const searchFormSchema: FormSchema[] = [ @@ -76,14 +68,11 @@ export const searchFormSchema: FormSchema[] = [
76 export const formSchema: FormSchema[] = [ 68 export const formSchema: FormSchema[] = [
77 { 69 {
78 field: 'name', 70 field: 'name',
79 - label: '名称',  
80 - colProps: { span: 24 }, 71 + label: '',
81 required: true, 72 required: true,
82 component: 'Input', 73 component: 'Input',
83 - componentProps: {  
84 - maxLength: 255,  
85 - placeholder: '请输入脚本名称',  
86 - }, 74 + slot: 'scriptName',
  75 + colProps: { span: 24 },
87 }, 76 },
88 { 77 {
89 field: 'scriptContent', 78 field: 'scriptContent',
@@ -95,13 +84,10 @@ export const formSchema: FormSchema[] = [ @@ -95,13 +84,10 @@ export const formSchema: FormSchema[] = [
95 }, 84 },
96 { 85 {
97 field: 'remark', 86 field: 'remark',
98 - label: '备注', 87 + label: '',
  88 + required: true,
  89 + component: 'Input',
  90 + slot: 'scriptRemark',
99 colProps: { span: 24 }, 91 colProps: { span: 24 },
100 - component: 'InputTextArea',  
101 - componentProps: {  
102 - rows: 6,  
103 - maxLength: 255,  
104 - placeholder: '请输入备注',  
105 - },  
106 }, 92 },
107 ]; 93 ];