Commit 5fdfd88b1aa1b5d867c1cea8e0b2109c475a5902

Authored by fengtao
1 parent 26f450d6

refractor:修改设备配置

... ... @@ -62,7 +62,7 @@ export const step1Schemas: FormSchema[] = [
62 62 componentProps: {
63 63 api: findDictItemByCode,
64 64 params: {
65   - dictCode: 'DEVICE_BRAND_GATEWAY',
  65 + dictCode: 'device_brand_gateway',
66 66 },
67 67 labelField: 'itemText',
68 68 valueField: 'itemValue',
... ...
... ... @@ -8,23 +8,50 @@
8 8 @ok="handleSubmit"
9 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 55 </BasicModal>
29 56 </div>
30 57 </template>
... ... @@ -33,6 +60,7 @@
33 60 import { BasicModal, useModalInner } from '/@/components/Modal';
34 61 import { deviceConfigAddOrEdit, deviceConfigGetDetail } from '/@/api/device/deviceConfigApi';
35 62 import { useMessage } from '/@/hooks/web/useMessage';
  63 + import { steps } from './device.profile.data';
36 64 import { isEmpty } from '/@/utils/is';
37 65 import { Tabs, TabPane } from 'ant-design-vue';
38 66 import DeviceConfigurationStep from './step/DeviceConfigurationStep.vue';
... ... @@ -47,6 +75,7 @@
47 75 const { createMessage } = useMessage();
48 76 const isViewDetail = ref(false);
49 77 const isUpdate = ref(false);
  78 + const current = ref(0);
50 79 const DevConStRef = ref<InstanceType<typeof DeviceConfigurationStep>>();
51 80 const TransConStRef = ref<InstanceType<typeof TransportConfigurationStep>>();
52 81 const PhysicalModManRef = ref<InstanceType<typeof PhysicalModelManagementStep>>();
... ... @@ -59,6 +88,7 @@
59 88 const transportTypeStr = ref('');
60 89 const [register, { closeModal, setModalProps }] = useModalInner(async (data) => {
61 90 setModalProps({ confirmLoading: false });
  91 + current.value = 0;
62 92 isUpdate.value = data.isUpdate;
63 93 isViewDetail.value = data.isView;
64 94 const res = data.record !== undefined ? await deviceConfigGetDetail(data.record.id) : {};
... ... @@ -73,7 +103,7 @@
73 103 handleStepNext(false, res);
74 104 }
75 105 } else {
76   - setModalProps({ showOkBtn: false, showCancelBtn: false, title: '查看设备配置' });
  106 + setModalProps({ showOkBtn: false, showCancelBtn: false, title: '设备配置详情' });
77 107 await setDeviceConfEditFormData(res);
78 108 await setTransConfEditFormData(res);
79 109 handleStepNext(false, res);
... ... @@ -86,10 +116,14 @@
86 116 };
87 117 const handleStepNext = (e, data) => {
88 118 if (e) {
  119 + current.value++;
89 120 } else {
90 121 setTransConfEditFormData(data);
91 122 }
92 123 };
  124 + const handleStepPrev = () => {
  125 + current.value--;
  126 + };
93 127
94 128 const setDeviceConfEditFormData = async (res) => {
95 129 await DevConStRef.value?.setFormData(res);
... ...
... ... @@ -8,6 +8,17 @@ import { h } from 'vue';
8 8
9 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 22 export const physicalColumn: BasicColumn[] = [
12 23 {
13 24 title: '功能名称',
... ... @@ -61,6 +72,24 @@ export const step1Schemas: FormSchema[] = [
61 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 93 field: 'name',
65 94 label: '配置名称',
66 95 required: true,
... ...
... ... @@ -37,9 +37,13 @@
37 37 import { useMessage } from '/@/hooks/web/useMessage';
38 38 import type { FileItem } from '/@/components/Upload/src/typing';
39 39
  40 + const emits = defineEmits(['next']);
40 41 const loading = ref(false);
41 42 const { createMessage } = useMessage();
42 43 const deviceConfigPic = ref('');
  44 + const props = defineProps({
  45 + ifShowBtn: { type: Boolean, default: true },
  46 + });
43 47
44 48 const [register, { validate, setFieldsValue, resetFields, updateSchema }] = useForm({
45 49 labelWidth: 100,
... ... @@ -48,8 +52,11 @@
48 52 span: 14,
49 53 },
50 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 61 const editOrAddNameStatus = (nameStatus) =>
55 62 updateSchema({
... ... @@ -83,6 +90,11 @@
83 90 }
84 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 99 const setFormData = (v) => {
88 100 setFieldsValue(v);
... ...
1 1 <template>
2   - <div>
  2 + <div class="p-style">
3 3 <BasicTable
4 4 :rowSelection="{ type: 'checkbox' }"
5 5 :clickToRowSelect="false"
6 6 @register="registerTable"
7 7 >
8 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 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 31 <a-button
36   - style="display: none"
  32 + v-if="isShowBtn"
  33 + style="margin-left: -20px"
37 34 type="primary"
38   - color="error"
39   - :disabled="hasBatchDelete"
  35 + @click="handleCreateOrEdit(null)"
40 36 >
41   - 批量删除
  37 + 新增物模型
42 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 88 </div>
47 89 </div>
48 90 </template>
... ... @@ -53,18 +95,21 @@
53 95 label: '查看',
54 96 icon: 'ant-design:eye-outlined',
55 97 onClick: handleViewDetail.bind(null, record),
  98 + ifShow: isShowBtn ? false : true,
56 99 },
57 100 {
58 101 label: '编辑',
59 102 icon: 'clarity:note-edit-line',
60 103 auth: '',
61 104 onClick: handleCreateOrEdit.bind(null, record),
  105 + ifShow: !isShowBtn ? false : true,
62 106 },
63 107 {
64 108 label: '删除',
65 109 icon: 'ant-design:delete-outlined',
66 110 auth: '',
67 111 color: 'error',
  112 + ifShow: !isShowBtn ? false : true,
68 113 popConfirm: {
69 114 title: '是否确认删除',
70 115 confirm: handleDeleteOrBatchDelete.bind(null, record),
... ... @@ -79,6 +124,7 @@
79 124 </div>
80 125 </template>
81 126 <script lang="ts" setup>
  127 + import { ref } from 'vue';
82 128 import { BasicTable, useTable, TableAction } from '/@/components/Table';
83 129 import { useModal } from '/@/components/Modal';
84 130 import { physicalColumn } from '../device.profile.data';
... ... @@ -89,8 +135,11 @@
89 135 import PhysicalModelModal from './cpns/physical/PhysicalModelModal.vue';
90 136 import PhysicalModelTsl from './cpns/physical/PhysicalModelTsl.vue';
91 137 import { Popconfirm } from 'ant-design-vue';
  138 + import { useMessage } from '/@/hooks/web/useMessage';
92 139
93 140 defineEmits(['register']);
  141 + const { createMessage } = useMessage();
  142 + const isShowBtn = ref(false);
94 143 const [registerModal, { openModal }] = useModal();
95 144 const [registerModalTsl, { openModal: openModalTsl }] = useModal();
96 145
... ... @@ -158,10 +207,27 @@
158 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 217 defineExpose({});
162 218 </script>
163 219 <style lang="less" scoped>
  220 + @import url('./common/PhysicalModelManagementStep.less');
  221 +
164 222 :deep(.ant-table-body) {
165 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 233 </style>
... ...
... ... @@ -13,6 +13,8 @@
13 13 ? { minHeight: 55 + 'vh' }
14 14 : isMqttType == 'SNMP'
15 15 ? { minHeight: 60 + 'vh' }
  16 + : isMqttType == 'TCP'
  17 + ? { minHeight: 15 + 'vh' }
16 18 : { minHeight: 25 + 'vh' },
17 19 ]"
18 20 >
... ... @@ -29,6 +31,16 @@
29 31 <div style="margin-top: 5vh" v-else-if="isMqttType == 'SNMP'">
30 32 <SnmpCpns ref="snmpRef" />
31 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 44 </div>
33 45 </div>
34 46 </template>
... ... @@ -36,15 +48,22 @@
36 48 import { reactive, ref, onUnmounted, nextTick } from 'vue';
37 49 import { BasicForm, useForm } from '/@/components/Form';
38 50 import { step2Schemas } from '../device.profile.data';
  51 + import { Button } from '/@/components/Button';
39 52 import MqttCpns from './cpns/mqtt/Mqtt.vue';
40 53 import CoapCpns from './cpns/coap/Coap.vue';
41 54 import Lwm2mCpns from './cpns/lwm2m/index.vue';
42 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 62 const mqttRef = ref<InstanceType<typeof MqttCpns>>();
45 63 const coapRef = ref<InstanceType<typeof CoapCpns>>();
46 64 const lwm2mRef = ref<InstanceType<typeof Lwm2mCpns>>();
47 65 const snmpRef = ref<InstanceType<typeof SnmpCpns>>();
  66 + const tcpRef = ref<InstanceType<typeof TcpCpns>>();
48 67 const isMqttType = ref('DEFAULT');
49 68 let step2Data = reactive({
50 69 transportConfiguration: {},
... ... @@ -57,7 +76,7 @@
57 76 },
58 77 showResetButton: false,
59 78 submitOnReset: false,
60   - showActionButtonGroup: false,
  79 + showActionButtonGroup: props.ifShowBtn ? true : false,
61 80 });
62 81 const setFormData = (v) => {
63 82 setFieldsValue({
... ... @@ -68,6 +87,7 @@
68 87 coapRef.value?.setFormData(v?.profileData?.transportConfiguration);
69 88 lwm2mRef.value?.setFormData(v?.profileData?.transportConfiguration);
70 89 snmpRef.value?.setFormData(v?.profileData?.transportConfiguration);
  90 + tcpRef.value?.setFormData(v?.profileData?.transportConfiguration);
71 91 };
72 92
73 93 const resetFormData = () => {
... ... @@ -78,8 +98,12 @@
78 98 coapRef.value?.resetFormData();
79 99 lwm2mRef.value?.resetFormData();
80 100 snmpRef.value?.resetFormData();
  101 + tcpRef.value?.resetFormData();
81 102 });
82 103 };
  104 + async function customResetFunc() {
  105 + emits('prev');
  106 + }
83 107 nextTick(() => {
84 108 updateSchema({
85 109 field: 'transportType',
... ... @@ -91,6 +115,7 @@
91 115 { label: 'CoAP', value: 'COAP' },
92 116 { label: 'LWM2M', value: 'LWM2M' },
93 117 { label: 'SNMP', value: 'SNMP' },
  118 + { label: 'TCP', value: 'TCP' },
94 119 ],
95 120 onChange(e) {
96 121 isMqttType.value = e;
... ... @@ -109,11 +134,13 @@
109 134 const getCoapVal = await coapRef.value?.getFormData();
110 135 const getLwm2mVal = await lwm2mRef.value?.getFormData();
111 136 const getSnmpVal = await snmpRef.value?.getFormData();
  137 + const getTcpVal = await tcpRef.value?.getFormData();
112 138 step2Data.transportConfiguration = {
113 139 ...getMqttVal,
114 140 ...getCoapVal,
115 141 ...getLwm2mVal,
116 142 ...getSnmpVal,
  143 + ...getTcpVal,
117 144 ...val,
118 145 };
119 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 8 @ok="handleSubmit"
9 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 34 </BasicModal>
23 35 </div>
24 36 </template>
25 37 <script lang="ts" setup>
26 38 import { ref, unref } from 'vue';
27 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 42 import Service from './cpns/Service.vue';
31 43 import Events from './cpns/Events.vue';
32 44
33 45 defineEmits(['register']);
  46 + const blockContent = `属性一般是设备的运行状态,如当前温度等;服务是设备可被调用的方法,支持定义参数,如执行某项任务;事件则是设备上报的
  47 +通知,如告警,需要被及时处理。`;
34 48 const activeKey = ref('1');
35 49 const size = ref('small');
36   - const AttrRef = ref<InstanceType<typeof Attr>>();
  50 + const AttrRef = ref<InstanceType<typeof Attribute>>();
37 51 const ServiceRef = ref<InstanceType<typeof Service>>();
38 52 const EventsRef = ref<InstanceType<typeof Events>>();
39 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 1 <template>
2 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 11 <div>模型内容</div>
5 12 <div>
6 13 <Button @click="handlePremitter">
... ... @@ -29,10 +36,13 @@
29 36 import { useMessage } from '/@/hooks/web/useMessage';
30 37 import jsoneditor from 'jsoneditor';
31 38 import 'jsoneditor/dist/jsoneditor.min.css';
32   - import { Button } from 'ant-design-vue';
  39 + import { Button, Typography, TypographyParagraph } from 'ant-design-vue';
33 40 import { defaultTslContent } from './config';
34 41
35 42 const { createMessage } = useMessage();
  43 + const blockContent = `物模型是对设备在云端的功能描述,包括设备的属性、服务和事件。物联网平台通过定义一种物的描述语言来描述物模型,称之为 TSL(即 Thing
  44 +Specification Language),采用 JSON 格式,您可以根据 TSL 组装上报设备的数据。您可以导出完整物模型,用于云端应用开发;您也可以只导出
  45 +精简物模型,配合设备端 SDK 实现设备开发。`;
36 46 const jsonValue = ref(defaultTslContent);
37 47 const jsonInstance = ref();
38 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 1 <template>
2 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 24 <Card title="脚本内容" :bodyStyle="{ padding: 0, height: '280px' }">
  25 + <template #extra>
  26 + <a-button @click="handleFormat" size="small">格式化</a-button>
  27 + </template>
6 28 <div ref="aceRef" class="overflow-hidden"></div>
7 29 </Card>
8 30 <Button @click="handleCopy" class="mt-4">
... ... @@ -11,14 +33,29 @@
11 33 </template>
12 34 copy
13 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 55 </div>
17 56 </template>
18 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 59 import ace from 'ace-builds';
23 60 import { Card, Button } from 'ant-design-vue';
24 61 import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题
... ... @@ -29,15 +66,20 @@
29 66 import { useMessage } from '/@/hooks/web/useMessage';
30 67
31 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 79 const { createMessage } = useMessage();
33 80 const { clipboardRef, copiedRef } = useCopyToClipboard();
34 81 const aceEditor = ref();
35 82 const aceRef = ref();
36   - const [registerForm, { validate, resetFields }] = useForm({
37   - labelWidth: 120,
38   - schemas: formSchema,
39   - showActionButtonGroup: false,
40   - });
41 83 // 初始化编辑器
42 84 const initEditor = (jsScript?: string) => {
43 85 aceEditor.value = ace.edit(aceRef.value, {
... ... @@ -64,6 +106,7 @@
64 106 }`
65 107 );
66 108 beautify(aceEditor.value.session);
  109 + scriptForm.scriptContent = aceEditor.value.getValue();
67 110 };
68 111 const handleCopy = () => {
69 112 const valueRef = aceEditor.value.getValue();
... ... @@ -77,19 +120,29 @@
77 120 createMessage.success('复制成功!');
78 121 }
79 122 };
  123 + const formRef = ref();
80 124 const getFormData = async () => {
81   - const value = await validate();
  125 + const value = await formRef.value.validateFields();
82 126 if (!value) return;
83 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 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 141 defineExpose({
90 142 initEditor,
91 143 getFormData,
92 144 resetFormData,
  145 + setFormData,
93 146 });
94 147 </script>
95 148 <style lang="less" scoped>
... ...
... ... @@ -10,7 +10,7 @@
10 10 @cancel="handleCancel"
11 11 @ok="handleSubmit"
12 12 >
13   - <ConverScript ref="converScriptRef" />
  13 + <ConverScript :ifAdd="true" ref="converScriptRef" />
14 14 </BasicModal>
15 15 </div>
16 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 1 import { BasicColumn, FormSchema } from '/@/components/Table';
10 2 import moment from 'moment';
11 3 import { h } from 'vue';
... ... @@ -76,14 +68,11 @@ export const searchFormSchema: FormSchema[] = [
76 68 export const formSchema: FormSchema[] = [
77 69 {
78 70 field: 'name',
79   - label: '名称',
80   - colProps: { span: 24 },
  71 + label: '',
81 72 required: true,
82 73 component: 'Input',
83   - componentProps: {
84   - maxLength: 255,
85   - placeholder: '请输入脚本名称',
86   - },
  74 + slot: 'scriptName',
  75 + colProps: { span: 24 },
87 76 },
88 77 {
89 78 field: 'scriptContent',
... ... @@ -95,13 +84,10 @@ export const formSchema: FormSchema[] = [
95 84 },
96 85 {
97 86 field: 'remark',
98   - label: '备注',
  87 + label: '',
  88 + required: true,
  89 + component: 'Input',
  90 + slot: 'scriptRemark',
99 91 colProps: { span: 24 },
100   - component: 'InputTextArea',
101   - componentProps: {
102   - rows: 6,
103   - maxLength: 255,
104   - placeholder: '请输入备注',
105   - },
106 92 },
107 93 ];
... ...