Commit be4155d1b60f8c27a60318a3d9f85b4caa73fdd7

Authored by xp.Huang
2 parents c5077dc9 07ef1fd2

Merge branch 'ft' into 'main_dev'

fix: 修改Teambition上的问题

See merge request yunteng/thingskit-front!542
@@ -10,6 +10,8 @@ export type SchedueParam = { @@ -10,6 +10,8 @@ export type SchedueParam = {
10 data?: any; 10 data?: any;
11 code?: number; 11 code?: number;
12 jobId?: string; 12 jobId?: string;
  13 + startTime?: number;
  14 + endTime?: number;
13 }; 15 };
14 16
15 export interface ReportModel { 17 export interface ReportModel {
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 placeholder="请选择" 18 placeholder="请选择"
19 :options="selectOptions" 19 :options="selectOptions"
20 @change="handleChange" 20 @change="handleChange"
  21 + @dropdownVisibleChange="hanldeDropdownVisibleChange"
21 allowClear 22 allowClear
22 /> 23 />
23 </td> 24 </td>
@@ -111,16 +112,20 @@ @@ -111,16 +112,20 @@
111 112
112 // 减少 113 // 减少
113 const remove = (item, index: number) => { 114 const remove = (item, index: number) => {
114 - if (tableArray.content.length !== 1) { 115 + if (tableArray.content.length > 1) {
115 selectOptions.value.forEach((ele) => { 116 selectOptions.value.forEach((ele) => {
116 if (ele.value == item.key) { 117 if (ele.value == item.key) {
117 ele.disabled = false; 118 ele.disabled = false;
118 } 119 }
119 }); 120 });
120 tableArray.content.splice(index, 1); 121 tableArray.content.splice(index, 1);
  122 + } else {
  123 + resetValue();
121 } 124 }
122 }; 125 };
123 126
  127 + const hanldeDropdownVisibleChange = () => handleChange();
  128 +
124 //Select互斥 129 //Select互斥
125 const handleChange = () => { 130 const handleChange = () => {
126 selectOptions.value.forEach((ele) => { 131 selectOptions.value.forEach((ele) => {
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 placeholder="请选择" 18 placeholder="请选择"
19 :options="selectOptions" 19 :options="selectOptions"
20 @change="handleChange" 20 @change="handleChange"
  21 + @dropdownVisibleChange="hanldeDropdownVisibleChange"
21 allowClear 22 allowClear
22 /> 23 />
23 </td> 24 </td>
@@ -111,13 +112,15 @@ @@ -111,13 +112,15 @@
111 112
112 // 减少 113 // 减少
113 const remove = (item, index: number) => { 114 const remove = (item, index: number) => {
114 - if (tableArray.content.length !== 1) { 115 + if (tableArray.content.length > 1) {
115 selectOptions.value.forEach((ele) => { 116 selectOptions.value.forEach((ele) => {
116 if (ele.value == item.key) { 117 if (ele.value == item.key) {
117 ele.disabled = false; 118 ele.disabled = false;
118 } 119 }
119 }); 120 });
120 tableArray.content.splice(index, 1); 121 tableArray.content.splice(index, 1);
  122 + } else {
  123 + resetValue();
121 } 124 }
122 }; 125 };
123 126
@@ -139,6 +142,8 @@ @@ -139,6 +142,8 @@
139 }); 142 });
140 }; 143 };
141 144
  145 + const hanldeDropdownVisibleChange = () => handleChange();
  146 +
142 //获取数据 147 //获取数据
143 const getValue = () => { 148 const getValue = () => {
144 const assemblyData = tableArray.content.map((it) => { 149 const assemblyData = tableArray.content.map((it) => {
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 <ParamsTable ref="paramsCellTableRef" :method="method" /> 6 <ParamsTable ref="paramsCellTableRef" :method="method" />
7 <ParamsTest 7 <ParamsTest
8 @testParamsInterface="handleTestParamsInterface" 8 @testParamsInterface="handleTestParamsInterface"
  9 + @closeTest="onCloseTest"
9 ref="testParamsRequestRef" 10 ref="testParamsRequestRef"
10 :data="dataMap.mapParamsObj" 11 :data="dataMap.mapParamsObj"
11 /> 12 />
@@ -21,6 +22,7 @@ @@ -21,6 +22,7 @@
21 <BodyTest 22 <BodyTest
22 v-if="bodyType !== 'none'" 23 v-if="bodyType !== 'none'"
23 @testBodyInterface="handleTestBodyInterface" 24 @testBodyInterface="handleTestBodyInterface"
  25 + @closeTest="onCloseTest"
24 ref="testBodyRequestRef" 26 ref="testBodyRequestRef"
25 :data="dataMap.mapBodyObj" 27 :data="dataMap.mapBodyObj"
26 /> 28 />
@@ -29,6 +31,7 @@ @@ -29,6 +31,7 @@
29 <HeaderTable ref="editHeaderCellTableRef" :method="method" /> 31 <HeaderTable ref="editHeaderCellTableRef" :method="method" />
30 <HeaderTest 32 <HeaderTest
31 @testHeaderInterface="handleTestHeaderInterface" 33 @testHeaderInterface="handleTestHeaderInterface"
  34 + @closeTest="onCloseTest"
32 ref="testHeaderRequestRef" 35 ref="testHeaderRequestRef"
33 :data="dataMap.mapHeaderObj" 36 :data="dataMap.mapHeaderObj"
34 /> 37 />
@@ -107,6 +110,8 @@ @@ -107,6 +110,8 @@
107 excuteTestRef.value?.resetValue(true); 110 excuteTestRef.value?.resetValue(true);
108 }; 111 };
109 112
  113 + const onCloseTest = () => excuteTestRef.value?.resetValue(true);
  114 +
110 //if-else-if-else分支优化 115 //if-else-if-else分支优化
111 const dataForTypeMap = [ 116 const dataForTypeMap = [
112 [(type) => type === 'Params', (data) => paramsCellTableRef.value?.setValue(data)], 117 [(type) => type === 'Params', (data) => paramsCellTableRef.value?.setValue(data)],
1 <template> 1 <template>
2 <div> 2 <div>
3 <div class="mt-8"> 3 <div class="mt-8">
4 - <div>  
5 - <Button @click="handleTest" type="primary"> 测试接口 </Button> 4 + <div class="flex">
  5 + <Button @click="handleTest" type="primary"> 打开测试接口 </Button>
  6 + <Button class="ml-2" @click="onCloseTest" type="primary"> 关闭测试接口 </Button>
6 </div> 7 </div>
7 <div v-if="showTestEditCell" class="mt-8"> 8 <div v-if="showTestEditCell" class="mt-8">
8 <a-row type="flex" justify="center"> 9 <a-row type="flex" justify="center">
@@ -31,8 +32,9 @@ @@ -31,8 +32,9 @@
31 import moment from 'moment'; 32 import moment from 'moment';
32 import { useUtils } from '../../../hooks/useUtils'; 33 import { useUtils } from '../../../hooks/useUtils';
33 import JsonEditor from '../../SimpleRequest/components/jsonEditor.vue'; 34 import JsonEditor from '../../SimpleRequest/components/jsonEditor.vue';
  35 + import { useMessage } from '/@/hooks/web/useMessage';
34 36
35 - const emits = defineEmits(['testBodyInterface']); 37 + const emits = defineEmits(['testBodyInterface', 'closeTest']);
36 38
37 const props = defineProps({ 39 const props = defineProps({
38 data: { 40 data: {
@@ -40,6 +42,8 @@ @@ -40,6 +42,8 @@
40 }, 42 },
41 }); 43 });
42 44
  45 + const { createMessage } = useMessage();
  46 +
43 const showTestEditCell = ref(false); 47 const showTestEditCell = ref(false);
44 48
45 const excuteData = ref({}); 49 const excuteData = ref({});
@@ -111,6 +115,7 @@ @@ -111,6 +115,7 @@
111 return { 115 return {
112 key, 116 key,
113 value, 117 value,
  118 + required: it.required,
114 }; 119 };
115 }); 120 });
116 }; 121 };
@@ -120,6 +125,11 @@ @@ -120,6 +125,11 @@
120 let params: any = {}; 125 let params: any = {};
121 if (props.data?.type === 'x-www-form-urlencoded' || props.data?.type === 'form-data') { 126 if (props.data?.type === 'x-www-form-urlencoded' || props.data?.type === 'form-data') {
122 const getTable = getTestTableKeyValue(); 127 const getTable = getTestTableKeyValue();
  128 + const hasRequired = getTable?.some((it) => it.required === true && !it.value);
  129 + if (hasRequired) {
  130 + createMessage.error('参数不能为空');
  131 + throw new Error('参数不能为空');
  132 + }
123 getTable?.map((it) => (params[it.key!] = it.value!)); 133 getTable?.map((it) => (params[it.key!] = it.value!));
124 } else if (props.data?.type === 'json') { 134 } else if (props.data?.type === 'json') {
125 params = jsonEditorRef.value?.getJsonValue(); 135 params = jsonEditorRef.value?.getJsonValue();
@@ -141,6 +151,11 @@ @@ -141,6 +151,11 @@
141 testResult.value = ''; 151 testResult.value = '';
142 }; 152 };
143 153
  154 + const onCloseTest = () => {
  155 + showTestEditCell.value = false;
  156 + emits('closeTest');
  157 + };
  158 +
144 defineExpose({ 159 defineExpose({
145 setValue, 160 setValue,
146 handleTest, 161 handleTest,
@@ -243,7 +243,9 @@ @@ -243,7 +243,9 @@
243 if (f.key === 'organizationId') organizationId = f.value; 243 if (f.key === 'organizationId') organizationId = f.value;
244 if (f.key === 'entityId') f.value = null; 244 if (f.key === 'entityId') f.value = null;
245 }); 245 });
246 - getAttributeOptions({ deviceProfileId: e.value }); 246 + if (e.value) {
  247 + getAttributeOptions({ deviceProfileId: e.value });
  248 + }
247 if (organizationId !== '') { 249 if (organizationId !== '') {
248 getEntityOptions(organizationId, e.value); 250 getEntityOptions(organizationId, e.value);
249 } 251 }
@@ -5,10 +5,10 @@ @@ -5,10 +5,10 @@
5 </div> 5 </div>
6 <div class="mt-8"> 6 <div class="mt-8">
7 <a-row type="flex" justify="center"> 7 <a-row type="flex" justify="center">
8 - <a-col :span="2"> 测试结果 </a-col>  
9 - <a-col :span="22"> 8 + <a-col :span="24">
10 <a-textarea 9 <a-textarea
11 - v-if="ifWebSocket === '2'" 10 + disabled
  11 + v-if="isWebSocketType === '2'"
12 allow-clear 12 allow-clear
13 show-count 13 show-count
14 v-model:value="testResult" 14 v-model:value="testResult"
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 :rows="8" 16 :rows="8"
17 /> 17 />
18 <a-textarea 18 <a-textarea
  19 + disabled
19 v-else 20 v-else
20 allow-clear 21 allow-clear
21 show-count 22 show-count
@@ -29,14 +30,13 @@ @@ -29,14 +30,13 @@
29 </div> 30 </div>
30 </template> 31 </template>
31 <script lang="ts" setup name="testRequest"> 32 <script lang="ts" setup name="testRequest">
32 - import { nextTick, ref, reactive } from 'vue'; 33 + import { nextTick, ref, reactive, onUnmounted } from 'vue';
33 import { Button } from 'ant-design-vue'; 34 import { Button } from 'ant-design-vue';
34 import { otherHttp } from '/@/utils/http/axios'; 35 import { otherHttp } from '/@/utils/http/axios';
35 import { useWebSocket } from '@vueuse/core'; 36 import { useWebSocket } from '@vueuse/core';
36 import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; 37 import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum';
37 import { getAuthCache } from '/@/utils/auth'; 38 import { getAuthCache } from '/@/utils/auth';
38 - import { useMessage } from '/@/hooks/web/useMessage';  
39 - // import { useGlobSetting } from '/@/hooks/setting'; 39 + import { useUtils } from '../../../hooks/useUtils';
40 40
41 const emits = defineEmits(['emitExcute']); 41 const emits = defineEmits(['emitExcute']);
42 42
@@ -48,16 +48,10 @@ @@ -48,16 +48,10 @@
48 48
49 const showTestFlag = ref(false); 49 const showTestFlag = ref(false);
50 50
51 - const ifWebSocket = ref('');  
52 -  
53 - const { createMessage } = useMessage();  
54 -  
55 const token = getAuthCache(JWT_TOKEN_KEY); 51 const token = getAuthCache(JWT_TOKEN_KEY);
56 52
57 const socketUrls = ref(''); 53 const socketUrls = ref('');
58 54
59 - // const { socketUrl } = useGlobSetting();  
60 -  
61 const socketMessage: any = reactive({ 55 const socketMessage: any = reactive({
62 server: ``, 56 server: ``,
63 sendValue: { 57 sendValue: {
@@ -89,6 +83,8 @@ @@ -89,6 +83,8 @@
89 83
90 const httpResult = ref(''); 84 const httpResult = ref('');
91 85
  86 + const isWebSocketType = ref('');
  87 +
92 //执行测试接口 88 //执行测试接口
93 const handleExcute = () => { 89 const handleExcute = () => {
94 emits('emitExcute'); 90 emits('emitExcute');
@@ -99,18 +95,23 @@ @@ -99,18 +95,23 @@
99 await nextTick(); 95 await nextTick();
100 //获取Params和Header和Body 96 //获取Params和Header和Body
101 const Objects = props.data; 97 const Objects = props.data;
102 - const isWebSocketType = Objects?.method; 98 + isWebSocketType.value = Objects?.method;
103 const apiType = Objects?.apiType; 99 const apiType = Objects?.apiType;
104 const url = Objects?.apiGetUrl; 100 const url = Objects?.apiGetUrl;
105 const headers = Objects?.Header?.params; 101 const headers = Objects?.Header?.params;
106 const params = Objects?.Params?.params; 102 const params = Objects?.Params?.params;
107 const body = Objects?.Body?.params; 103 const body = Objects?.Body?.params;
108 const apiUrl = url?.restfulFormat(params); 104 const apiUrl = url?.restfulFormat(params);
109 - ifWebSocket.value = isWebSocketType;  
110 - if (isWebSocketType === '2') { 105 + if (isWebSocketType.value === '2') {
111 socketUrls.value = url; 106 socketUrls.value = url;
112 socketMessage.server = `${socketUrls.value}?token=${token}`; 107 socketMessage.server = `${socketUrls.value}?token=${token}`;
113 - websocketRequest(params); 108 + const list = Object.values(params);
  109 + const isEmpty = list.some((it) => it === '' || null || undefined);
  110 + if (!isEmpty) {
  111 + websocketRequest(params);
  112 + } else {
  113 + resetValue(false);
  114 + }
114 } else { 115 } else {
115 const resp = await otherHttpRequest(apiType, apiUrl?.split('{?')[0], headers, params, body); 116 const resp = await otherHttpRequest(apiType, apiUrl?.split('{?')[0], headers, params, body);
116 if (!resp) return; 117 if (!resp) return;
@@ -119,7 +120,7 @@ @@ -119,7 +120,7 @@
119 }; 120 };
120 121
121 //websocket请求 122 //websocket请求
122 - const websocketRequest = (params) => { 123 + const websocketRequest = (params, destroy = false) => {
123 //websocket请求 124 //websocket请求
124 Reflect.deleteProperty(params, 'deviceProfileId'); 125 Reflect.deleteProperty(params, 'deviceProfileId');
125 Reflect.deleteProperty(params, 'organizationId'); 126 Reflect.deleteProperty(params, 'organizationId');
@@ -140,12 +141,17 @@ @@ -140,12 +141,17 @@
140 console.log('断开连接了'); 141 console.log('断开连接了');
141 close(); 142 close();
142 }, 143 },
143 - onError() {  
144 - createMessage.error('webSocket连接超时,请联系管理员');  
145 - }, 144 + onError() {},
146 }); 145 });
  146 + if (destroy) close();
147 }; 147 };
148 148
  149 + onUnmounted(() => {
  150 + if (isWebSocketType.value === '2') {
  151 + websocketRequest(null, true);
  152 + }
  153 + });
  154 +
149 //TODO: 待优化 项目自带第三方请求 155 //TODO: 待优化 项目自带第三方请求
150 const otherHttpRequest = async ( 156 const otherHttpRequest = async (
151 apiType, 157 apiType,
@@ -165,8 +171,9 @@ @@ -165,8 +171,9 @@
165 } 171 }
166 ); 172 );
167 case 'POST': 173 case 'POST':
  174 + const { convertObj } = useUtils();
168 return await otherHttp.post( 175 return await otherHttp.post(
169 - { url: apiUrl, data: body, headers, params }, 176 + { url: `${apiUrl}?${convertObj(params)}`, data: body, headers },
170 { 177 {
171 apiUrl: '', 178 apiUrl: '',
172 joinPrefix, 179 joinPrefix,
@@ -189,7 +196,7 @@ @@ -189,7 +196,7 @@
189 } 196 }
190 httpResult.value = '测试结果为:'; 197 httpResult.value = '测试结果为:';
191 testResult.value = '测试结果为:'; 198 testResult.value = '测试结果为:';
192 - ifWebSocket.value = '0'; 199 + isWebSocketType.value = '0';
193 }; 200 };
194 201
195 const showTest = () => (showTestFlag.value = true); 202 const showTest = () => (showTestFlag.value = true);
1 <template> 1 <template>
2 <div> 2 <div>
3 <div class="mt-8"> 3 <div class="mt-8">
4 - <div>  
5 - <Button @click="handleTest" type="primary"> 测试接口 </Button> 4 + <div class="flex">
  5 + <Button @click="handleTest" type="primary"> 打开测试接口 </Button>
  6 + <Button class="ml-2" @click="onCloseTest" type="primary"> 关闭测试接口 </Button>
6 </div> 7 </div>
7 <div v-if="showTestEditCell" class="mt-8"> 8 <div v-if="showTestEditCell" class="mt-8">
8 <a-row type="flex" justify="center"> 9 <a-row type="flex" justify="center">
@@ -20,8 +21,9 @@ @@ -20,8 +21,9 @@
20 import { ref, nextTick } from 'vue'; 21 import { ref, nextTick } from 'vue';
21 import { Button } from 'ant-design-vue'; 22 import { Button } from 'ant-design-vue';
22 import TestHeaderEditCellTable from './testEditHeaderCellTable.vue'; 23 import TestHeaderEditCellTable from './testEditHeaderCellTable.vue';
  24 + import { useMessage } from '/@/hooks/web/useMessage';
23 25
24 - const emits = defineEmits(['testHeaderInterface']); 26 + const emits = defineEmits(['testHeaderInterface', 'closeTest']);
25 27
26 const props = defineProps({ 28 const props = defineProps({
27 data: { 29 data: {
@@ -29,6 +31,8 @@ @@ -29,6 +31,8 @@
29 }, 31 },
30 }); 32 });
31 33
  34 + const { createMessage } = useMessage();
  35 +
32 const showTestEditCell = ref(false); 36 const showTestEditCell = ref(false);
33 37
34 const excuteData = ref({}); 38 const excuteData = ref({});
@@ -59,6 +63,11 @@ @@ -59,6 +63,11 @@
59 //获取数据 63 //获取数据
60 const getTestValue = () => { 64 const getTestValue = () => {
61 const getTable = getTestTableKeyValue(); 65 const getTable = getTestTableKeyValue();
  66 + const hasRequired = getTable?.some((it) => it.required === true && !it.value);
  67 + if (hasRequired) {
  68 + createMessage.error('参数不能为空');
  69 + throw new Error('参数不能为空');
  70 + }
62 const params: any = {}; 71 const params: any = {};
63 getTable?.map((it: any) => (params[it.key!] = it.value!)); 72 getTable?.map((it: any) => (params[it.key!] = it.value!));
64 excuteData.value = { 73 excuteData.value = {
@@ -73,6 +82,11 @@ @@ -73,6 +82,11 @@
73 testResult.value = ''; 82 testResult.value = '';
74 }; 83 };
75 84
  85 + const onCloseTest = () => {
  86 + showTestEditCell.value = false;
  87 + emits('closeTest');
  88 + };
  89 +
76 defineExpose({ 90 defineExpose({
77 setValue, 91 setValue,
78 handleTest, 92 handleTest,
1 <template> 1 <template>
2 <div> 2 <div>
3 <div class="mt-8"> 3 <div class="mt-8">
4 - <div>  
5 - <Button @click="handleTest" type="primary"> 测试接口 </Button> 4 + <div class="flex">
  5 + <Button @click="handleTest" type="primary"> 打开测试接口 </Button>
  6 + <Button class="ml-2" @click="onCloseTest" type="primary"> 关闭测试接口 </Button>
6 </div> 7 </div>
7 <div v-if="showTestEditCell" class="mt-8"> 8 <div v-if="showTestEditCell" class="mt-8">
8 <a-row type="flex" justify="center"> 9 <a-row type="flex" justify="center">
@@ -22,8 +23,9 @@ @@ -22,8 +23,9 @@
22 import TestParamsCellTable from './testEditParamsCellTable.vue'; 23 import TestParamsCellTable from './testEditParamsCellTable.vue';
23 import moment from 'moment'; 24 import moment from 'moment';
24 import { useUtils } from '../../../hooks/useUtils'; 25 import { useUtils } from '../../../hooks/useUtils';
  26 + import { useMessage } from '/@/hooks/web/useMessage';
25 27
26 - const emits = defineEmits(['testParamsInterface']); 28 + const emits = defineEmits(['testParamsInterface', 'closeTest']);
27 29
28 const props = defineProps({ 30 const props = defineProps({
29 data: { 31 data: {
@@ -31,6 +33,8 @@ @@ -31,6 +33,8 @@
31 }, 33 },
32 }); 34 });
33 35
  36 + const { createMessage } = useMessage();
  37 +
34 const showTestEditCell = ref(false); 38 const showTestEditCell = ref(false);
35 39
36 const excuteData = ref({}); 40 const excuteData = ref({});
@@ -92,6 +96,7 @@ @@ -92,6 +96,7 @@
92 return { 96 return {
93 key, 97 key,
94 value, 98 value,
  99 + required: it.required,
95 }; 100 };
96 }); 101 });
97 }; 102 };
@@ -99,6 +104,11 @@ @@ -99,6 +104,11 @@
99 //获取数据 104 //获取数据
100 const getTestValue = () => { 105 const getTestValue = () => {
101 const getTable = getTestTableKeyValue(); 106 const getTable = getTestTableKeyValue();
  107 + const hasRequired = getTable?.some((it) => it.required === true && !it.value);
  108 + if (hasRequired) {
  109 + createMessage.error('参数不能为空');
  110 + throw new Error('参数不能为空');
  111 + }
102 const params: any = {}; 112 const params: any = {};
103 getTable?.map((it) => (params[it.key!] = it.value!)); 113 getTable?.map((it) => (params[it.key!] = it.value!));
104 if (params['keys']) { 114 if (params['keys']) {
@@ -116,6 +126,11 @@ @@ -116,6 +126,11 @@
116 testResult.value = ''; 126 testResult.value = '';
117 }; 127 };
118 128
  129 + const onCloseTest = () => {
  130 + showTestEditCell.value = false;
  131 + emits('closeTest');
  132 + };
  133 +
119 defineExpose({ 134 defineExpose({
120 setValue, 135 setValue,
121 handleTest, 136 handleTest,
@@ -235,7 +235,9 @@ @@ -235,7 +235,9 @@
235 if (f.key === 'organizationId') organizationId = f.value; 235 if (f.key === 'organizationId') organizationId = f.value;
236 if (f.key === 'entityId') f.value = null; 236 if (f.key === 'entityId') f.value = null;
237 }); 237 });
238 - getAttributeOptions({ deviceProfileId: e.value }); 238 + if (e.value) {
  239 + getAttributeOptions({ deviceProfileId: e.value });
  240 + }
239 if (organizationId !== '') { 241 if (organizationId !== '') {
240 getEntityOptions(organizationId, e.value); 242 getEntityOptions(organizationId, e.value);
241 } 243 }
@@ -46,7 +46,7 @@ @@ -46,7 +46,7 @@
46 import { useMessage } from '/@/hooks/web/useMessage'; 46 import { useMessage } from '/@/hooks/web/useMessage';
47 import { useUtils } from './hooks/useUtils'; 47 import { useUtils } from './hooks/useUtils';
48 48
49 - const { resetReqHttpType, resetUpdateSchema } = useUtils(); 49 + const { resetReqHttpType } = useUtils();
50 50
51 const emits = defineEmits(['success', 'register']); 51 const emits = defineEmits(['success', 'register']);
52 52
@@ -69,10 +69,15 @@ @@ -69,10 +69,15 @@
69 const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { 69 const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
70 await resetFields(); 70 await resetFields();
71 await nextTick(); 71 await nextTick();
72 - updateSchema(resetUpdateSchema);  
73 setFieldsValue(resetReqHttpType); 72 setFieldsValue(resetReqHttpType);
74 const title = `${!data.isUpdate ? '新增' : '修改'}公共接口`; 73 const title = `${!data.isUpdate ? '新增' : '修改'}公共接口`;
75 setDrawerProps({ title }); 74 setDrawerProps({ title });
  75 + updateSchema({
  76 + field: 'requestHttpTypeAndUrl',
  77 + componentProps: {
  78 + type: '0',
  79 + },
  80 + });
76 isUpdate.value = data.isUpdate; 81 isUpdate.value = data.isUpdate;
77 !isUpdate.value ? (putId.value = '') : (putId.value = data.record.id); 82 !isUpdate.value ? (putId.value = '') : (putId.value = data.record.id);
78 simpleRequestRef.value?.resetValue() && testSqlRef.value?.resetValue(); 83 simpleRequestRef.value?.resetValue() && testSqlRef.value?.resetValue();
@@ -104,6 +109,14 @@ @@ -104,6 +109,14 @@
104 try { 109 try {
105 const values = await validate(); 110 const values = await validate();
106 if (!values) return; 111 if (!values) return;
  112 + const isRequestHttpTypeAndUrlEmpty = values?.requestHttpTypeAndUrl;
  113 + if (
  114 + !Reflect.get(isRequestHttpTypeAndUrlEmpty, 'requestHttpType') ||
  115 + !Reflect.get(isRequestHttpTypeAndUrlEmpty, 'requestUrl')
  116 + ) {
  117 + createMessage.error('请填写请求类型&地址');
  118 + throw Error('请填写请求类型&地址');
  119 + }
107 const Objects = simpleRequestRef.value?.getValue(true); 120 const Objects = simpleRequestRef.value?.getValue(true);
108 const requestOriginUrl = 121 const requestOriginUrl =
109 values['originUrlType'] === 'server_url' ? 'localhost' : values['requestOriginUrl']; 122 values['originUrlType'] === 'server_url' ? 'localhost' : values['requestOriginUrl'];
@@ -36,5 +36,20 @@ export const useUtils = () => { @@ -36,5 +36,20 @@ export const useUtils = () => {
36 type: '0', 36 type: '0',
37 }, 37 },
38 }; 38 };
39 - return { getMultipleKeys, pushObj, resetReqHttpType, resetUpdateSchema }; 39 + //对象转get params参数
  40 + const convertObj = (data: object) => {
  41 + const _result: any = [];
  42 + for (const key in data) {
  43 + const value = data[key];
  44 + if (value.constructor == Array) {
  45 + value.forEach(function (_value) {
  46 + _result.push(key + '=' + _value);
  47 + });
  48 + } else {
  49 + _result.push(key + '=' + value);
  50 + }
  51 + }
  52 + return _result.join('&');
  53 + };
  54 + return { getMultipleKeys, pushObj, resetReqHttpType, resetUpdateSchema, convertObj };
40 }; 55 };
@@ -39,7 +39,7 @@ @@ -39,7 +39,7 @@
39 icon: 'ant-design:node-expand-outlined', 39 icon: 'ant-design:node-expand-outlined',
40 onClick: handlePublish.bind(null, 'publish', record), 40 onClick: handlePublish.bind(null, 'publish', record),
41 ifShow: () => { 41 ifShow: () => {
42 - return record.state === 0; 42 + return record.state === 0 && record.creator === userId;
43 }, 43 },
44 }, 44 },
45 { 45 {
@@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
47 icon: 'ant-design:node-collapse-outlined', 47 icon: 'ant-design:node-collapse-outlined',
48 onClick: handlePublish.bind(null, 'canelPublish', record), 48 onClick: handlePublish.bind(null, 'canelPublish', record),
49 ifShow: () => { 49 ifShow: () => {
50 - return record.state === 1; 50 + return record.state === 1 && record.creator === userId;
51 }, 51 },
52 }, 52 },
53 { 53 {
@@ -55,7 +55,7 @@ @@ -55,7 +55,7 @@
55 icon: 'clarity:note-edit-line', 55 icon: 'clarity:note-edit-line',
56 onClick: handleCreateOrEdit.bind(null, record), 56 onClick: handleCreateOrEdit.bind(null, record),
57 ifShow: () => { 57 ifShow: () => {
58 - return record.state === 0; 58 + return record.state === 0 && record.creator === userId;
59 }, 59 },
60 }, 60 },
61 { 61 {
@@ -63,7 +63,7 @@ @@ -63,7 +63,7 @@
63 icon: 'ant-design:delete-outlined', 63 icon: 'ant-design:delete-outlined',
64 color: 'error', 64 color: 'error',
65 ifShow: () => { 65 ifShow: () => {
66 - return record.state === 0; 66 + return record.state === 0 && record.creator === userId;
67 }, 67 },
68 popConfirm: { 68 popConfirm: {
69 title: '是否确认删除', 69 title: '是否确认删除',
@@ -93,6 +93,12 @@ @@ -93,6 +93,12 @@
93 import { Popconfirm, Modal } from 'ant-design-vue'; 93 import { Popconfirm, Modal } from 'ant-design-vue';
94 import { JsonPreview } from '/@/components/CodeEditor'; 94 import { JsonPreview } from '/@/components/CodeEditor';
95 import { useMessage } from '/@/hooks/web/useMessage'; 95 import { useMessage } from '/@/hooks/web/useMessage';
  96 + import { USER_INFO_KEY } from '/@/enums/cacheEnum';
  97 + import { getAuthCache } from '/@/utils/auth';
  98 +
  99 + const userInfo = getAuthCache(USER_INFO_KEY) as any;
  100 +
  101 + const userId = ref(userInfo?.userId);
96 102
97 const [registerTable, { reload, clearSelectedRowKeys }] = useTable({ 103 const [registerTable, { reload, clearSelectedRowKeys }] = useTable({
98 api: getDataViewInterfacePage, 104 api: getDataViewInterfacePage,
@@ -52,6 +52,9 @@ @@ -52,6 +52,9 @@
52 compact: true, 52 compact: true,
53 baseColProps: { span: 8 }, 53 baseColProps: { span: 8 },
54 schemas: searchFormSchema, 54 schemas: searchFormSchema,
  55 + resetFunc: async () => {
  56 + getDataSource({ name: '' });
  57 + },
55 submitFunc: async () => { 58 submitFunc: async () => {
56 getDataSource({ pageSize: pagination.pageSize, page: 1 }); 59 getDataSource({ pageSize: pagination.pageSize, page: 1 });
57 }, 60 },
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 import { Button, Tag } from 'ant-design-vue'; 2 import { Button, Tag } from 'ant-design-vue';
3 - import { h, onMounted, ref, unref } from 'vue'; 3 + import { h, onMounted, ref, unref, Ref } from 'vue';
4 import { DeviceRecord } from '/@/api/device/model/deviceModel'; 4 import { DeviceRecord } from '/@/api/device/model/deviceModel';
5 - import { ScriptRecord } from '/@/api/scriptmanage/model/scriptModel'; 5 + // import { ScriptRecord } from '/@/api/scriptmanage/model/scriptModel';
6 import { getScriptManageMeList } from '/@/api/scriptmanage/scriptManager'; 6 import { getScriptManageMeList } from '/@/api/scriptmanage/scriptManager';
7 import { Description, useDescription } from '/@/components/Description'; 7 import { Description, useDescription } from '/@/components/Description';
8 import { useModal } from '/@/components/Modal'; 8 import { useModal } from '/@/components/Modal';
9 import CoverScriptModal from '/@/views/scriptmanage/converscript/ConverScriptModal.vue'; 9 import CoverScriptModal from '/@/views/scriptmanage/converscript/ConverScriptModal.vue';
  10 + import { SelectTypes } from 'ant-design-vue/es/select';
10 11
11 const props = defineProps<{ 12 const props = defineProps<{
12 record: DeviceRecord['profileData']['transportConfiguration']; 13 record: DeviceRecord['profileData']['transportConfiguration'];
13 }>(); 14 }>();
14 15
15 - const scriptInfo = ref<ScriptRecord>({} as unknown as ScriptRecord); 16 + // const scriptInfo = ref<ScriptRecord>({} as unknown as ScriptRecord);
  17 + const authScriptIdStr = ref('');
  18 +
  19 + const upScriptIdStr = ref('');
  20 +
  21 + const selectUpOptions: Ref<SelectTypes['options']> = ref([]);
  22 +
  23 + const selectAuthOptions: Ref<SelectTypes['options']> = ref([]);
  24 +
  25 + onMounted(async () => {
  26 + selectUpOptions.value = await getAllScriptType('TRANSPORT_TCP_UP');
  27 + selectAuthOptions.value = await getAllScriptType('TRANSPORT_TCP_AUTH');
  28 + setDescProps({
  29 + data: Object.assign(props.record),
  30 + });
  31 + });
  32 +
  33 + const getAllScriptType = async (type) => {
  34 + const rest = await getScriptManageMeList({ scriptType: type });
  35 + return rest.map((m) => ({ label: m.name, value: m.id }));
  36 + };
  37 +
  38 + const findScriptUpName = (scriptId) => {
  39 + upScriptIdStr.value = scriptId;
  40 + return selectUpOptions.value?.find((it) => it.value === scriptId)?.label;
  41 + };
  42 +
  43 + const findScriptAuthName = (scriptId) => {
  44 + authScriptIdStr.value = scriptId;
  45 + return selectAuthOptions.value?.find((it) => it.value === scriptId)?.label;
  46 + };
16 47
17 const [register, { setDescProps }] = useDescription({ 48 const [register, { setDescProps }] = useDescription({
18 layout: 'vertical', 49 layout: 'vertical',
@@ -25,14 +56,27 @@ @@ -25,14 +56,27 @@
25 span: 2, 56 span: 2,
26 }, 57 },
27 { 58 {
28 - field: 'scriptName',  
29 - label: '转换脚本', 59 + field: 'authScriptId',
  60 + label: '鉴权脚本',
30 render: (value: string) => { 61 render: (value: string) => {
31 return ( 62 return (
32 value && 63 value &&
33 h('div', [ 64 h('div', [
34 - h(Tag, { color: 'blue' }, () => value),  
35 - h(Button, { type: 'link', onClick: handleTestScript }, () => '测试脚本'), 65 + h(Tag, { color: 'blue' }, () => findScriptAuthName(value)),
  66 + h(Button, { type: 'link', onClick: handleTestAuthScript }, () => '测试脚本'),
  67 + ])
  68 + );
  69 + },
  70 + },
  71 + {
  72 + field: 'upScriptId',
  73 + label: '上行脚本',
  74 + render: (value: string) => {
  75 + return (
  76 + value &&
  77 + h('div', [
  78 + h(Tag, { color: 'blue' }, () => findScriptUpName(value)),
  79 + h(Button, { type: 'link', onClick: handleTestUpScript }, () => '测试脚本'),
36 ]) 80 ])
37 ); 81 );
38 }, 82 },
@@ -42,29 +86,24 @@ @@ -42,29 +86,24 @@
42 86
43 const [registerModal, { openModal }] = useModal(); 87 const [registerModal, { openModal }] = useModal();
44 88
45 - const handleTestScript = () => { 89 + const handleTestAuthScript = () => {
46 openModal(true, { 90 openModal(true, {
47 isUpdate: false, 91 isUpdate: false,
48 isTest: true, 92 isTest: true,
49 - record: unref(scriptInfo).id, 93 + record: unref(authScriptIdStr),
50 isText: 'test', 94 isText: 'test',
51 isTitle: 'test', 95 isTitle: 'test',
52 }); 96 });
53 }; 97 };
54 98
55 - onMounted(() => {  
56 - getTransforScriptInfo();  
57 - });  
58 -  
59 - const getTransforScriptInfo = async () => {  
60 - try {  
61 - const list = await getScriptManageMeList();  
62 - const record = list.find((item) => item.id === props.record.scriptId);  
63 - scriptInfo.value = record!;  
64 - setDescProps({  
65 - data: Object.assign(props.record, record, { scriptName: record?.name || '' }),  
66 - });  
67 - } catch (error) {} 99 + const handleTestUpScript = () => {
  100 + openModal(true, {
  101 + isUpdate: false,
  102 + isTest: true,
  103 + record: unref(upScriptIdStr),
  104 + isText: 'test',
  105 + isTitle: 'test',
  106 + });
68 }; 107 };
69 </script> 108 </script>
70 109
@@ -41,7 +41,7 @@ @@ -41,7 +41,7 @@
41 </BasicDrawer> 41 </BasicDrawer>
42 </template> 42 </template>
43 <script lang="ts" setup> 43 <script lang="ts" setup>
44 - import { ref, computed, unref, reactive, watch, Ref } from 'vue'; 44 + import { ref, computed, unref, reactive, watch, Ref, nextTick } from 'vue';
45 import { BasicForm, useForm } from '/@/components/Form'; 45 import { BasicForm, useForm } from '/@/components/Form';
46 import { formSchema, organizationId } from './config.data'; 46 import { formSchema, organizationId } from './config.data';
47 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; 47 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
@@ -198,6 +198,7 @@ @@ -198,6 +198,7 @@
198 const isViewDetail = ref(false); 198 const isViewDetail = ref(false);
199 199
200 const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { 200 const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
  201 + await nextTick();
201 await resetFields(); 202 await resetFields();
202 setDrawerProps({ confirmLoading: false }); 203 setDrawerProps({ confirmLoading: false });
203 isUpdate.value = !!data?.isUpdate; 204 isUpdate.value = !!data?.isUpdate;
@@ -222,6 +223,10 @@ @@ -222,6 +223,10 @@
222 await setFieldsValue(editResData.data); 223 await setFieldsValue(editResData.data);
223 //回显嵌套数据 224 //回显嵌套数据
224 await setFieldsValue({ 225 await setFieldsValue({
  226 + dateGroupGap:
  227 + editResData.data.queryCondition?.queryMode === 1
  228 + ? editResData.data.queryCondition?.interval
  229 + : null,
225 agg: editResData.data.queryCondition?.agg, 230 agg: editResData.data.queryCondition?.agg,
226 interval: editResData.data.queryCondition?.interval, 231 interval: editResData.data.queryCondition?.interval,
227 limit: editResData.data.queryCondition?.limit, 232 limit: editResData.data.queryCondition?.limit,
@@ -266,6 +271,7 @@ @@ -266,6 +271,7 @@
266 { label: '最大值', value: AggregateDataEnum.MAX }, 271 { label: '最大值', value: AggregateDataEnum.MAX },
267 { label: '平均值', value: AggregateDataEnum.AVG }, 272 { label: '平均值', value: AggregateDataEnum.AVG },
268 { label: '求和', value: AggregateDataEnum.SUM }, 273 { label: '求和', value: AggregateDataEnum.SUM },
  274 + { label: '计数', value: AggregateDataEnum.COUNT },
269 { label: '空', value: AggregateDataEnum.NONE }, 275 { label: '空', value: AggregateDataEnum.NONE },
270 ]; 276 ];
271 const updateSchemaAgg = (options: {}) => { 277 const updateSchemaAgg = (options: {}) => {
@@ -276,8 +282,8 @@ @@ -276,8 +282,8 @@
276 }, 282 },
277 }); 283 });
278 }; 284 };
279 - if (editResData.data.dataType == 1) updateSchemaAgg(dataCompareOpions.slice(0, 4));  
280 - else updateSchemaAgg(dataCompareOpions.slice(4, 5)); 285 + if (editResData.data.dataType == 1) updateSchemaAgg(dataCompareOpions.slice(0, 5));
  286 + else updateSchemaAgg(dataCompareOpions.slice(5, 6));
281 //回显执行方式和查询周期 287 //回显执行方式和查询周期
282 const dataQueryOpions = [ 288 const dataQueryOpions = [
283 { label: '固定周期', value: QueryWay.LATEST }, 289 { label: '固定周期', value: QueryWay.LATEST },
@@ -442,7 +448,7 @@ @@ -442,7 +448,7 @@
442 } 448 }
443 queryCondition = { 449 queryCondition = {
444 agg: values.agg, 450 agg: values.agg,
445 - interval: values.interval, 451 + interval: values?.queryMode === 'latest' ? values.interval : values.dateGroupGap,
446 limit: values.limit, 452 limit: values.limit,
447 ...{ 453 ...{
448 startTs: startTs.value, 454 startTs: startTs.value,
1 import { ref } from 'vue'; 1 import { ref } from 'vue';
2 import { BasicColumn, FormSchema } from '/@/components/Table'; 2 import { BasicColumn, FormSchema } from '/@/components/Table';
3 import type { FormSchema as QFormSchema } from '/@/components/Form/index'; 3 import type { FormSchema as QFormSchema } from '/@/components/Form/index';
4 -import moment from 'moment';  
5 import { getOrganizationList } from '/@/api/system/system'; 4 import { getOrganizationList } from '/@/api/system/system';
6 import { copyTransFun } from '/@/utils/fnUtils'; 5 import { copyTransFun } from '/@/utils/fnUtils';
7 import { findDictItemByCode } from '/@/api/system/dict'; 6 import { findDictItemByCode } from '/@/api/system/dict';
@@ -12,6 +11,7 @@ import { @@ -12,6 +11,7 @@ import {
12 getPacketIntervalByValue, 11 getPacketIntervalByValue,
13 intervalOption, 12 intervalOption,
14 } from '../../device/localtion/cpns/TimePeriodForm/helper'; 13 } from '../../device/localtion/cpns/TimePeriodForm/helper';
  14 +import moment, { Moment } from 'moment';
15 15
16 export enum QueryWay { 16 export enum QueryWay {
17 LATEST = 'latest', 17 LATEST = 'latest',
@@ -433,16 +433,70 @@ export const formSchema: QFormSchema[] = [ @@ -433,16 +433,70 @@ export const formSchema: QFormSchema[] = [
433 ifShow({ values }) { 433 ifShow({ values }) {
434 return values[SchemaFiled.WAY] === QueryWay.TIME_PERIOD && !isFixedTime(values.executeWay); 434 return values[SchemaFiled.WAY] === QueryWay.TIME_PERIOD && !isFixedTime(values.executeWay);
435 }, 435 },
436 - componentProps: {  
437 - showTime: {  
438 - defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],  
439 - }, 436 + // componentProps: {
  437 + // showTime: {
  438 + // defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
  439 + // },
  440 + // },
  441 + componentProps({ formActionType }) {
  442 + const { setFieldsValue } = formActionType;
  443 + let dates: Moment[] = [];
  444 + return {
  445 + showTime: {
  446 + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
  447 + },
  448 + onCalendarChange(value: Moment[]) {
  449 + dates = value;
  450 + },
  451 + disabledDate(current: Moment) {
  452 + if (!dates || dates.length === 0 || !current) {
  453 + return false;
  454 + }
  455 + const diffDate = current.diff(dates[0], 'years', true);
  456 + return Math.abs(diffDate) > 1;
  457 + },
  458 + onChange() {
  459 + dates = [];
  460 + setFieldsValue({ dateGroupGap: null });
  461 + },
  462 + getPopupContainer: () => document.body,
  463 + };
440 }, 464 },
441 colProps: { 465 colProps: {
442 span: 10, 466 span: 10,
443 }, 467 },
444 }, 468 },
445 { 469 {
  470 + field: 'dateGroupGap',
  471 + label: '分组间隔',
  472 + component: 'Select',
  473 + dynamicRules: ({ model }) => {
  474 + return [
  475 + {
  476 + required: model[SchemaFiled.AGG] !== AggregateDataEnum.NONE,
  477 + message: '分组间隔为必填项',
  478 + type: 'number',
  479 + },
  480 + ];
  481 + },
  482 + ifShow({ values }) {
  483 + return values[SchemaFiled.WAY] === QueryWay.TIME_PERIOD && !isFixedTime(values.executeWay);
  484 + },
  485 + componentProps({ formModel, formActionType }) {
  486 + const options =
  487 + formModel[SchemaFiled.WAY] === QueryWay.LATEST
  488 + ? getPacketIntervalByValue(formModel[SchemaFiled.START_TS])
  489 + : getPacketIntervalByRange(formModel[SchemaFiled.DATE_RANGE]);
  490 + if (formModel[SchemaFiled.AGG] !== AggregateDataEnum.NONE) {
  491 + formActionType.setFieldsValue({ [SchemaFiled.LIMIT]: null });
  492 + }
  493 + return {
  494 + options,
  495 + getPopupContainer: () => document.body,
  496 + };
  497 + },
  498 + },
  499 + {
446 field: SchemaFiled.START_TS, 500 field: SchemaFiled.START_TS,
447 label: '最近时间', 501 label: '最近时间',
448 component: 'Select', 502 component: 'Select',
@@ -128,6 +128,7 @@ @@ -128,6 +128,7 @@
128 import { findOperation } from './config/formatData'; 128 import { findOperation } from './config/formatData';
129 import { formatToDateTime } from '/@/utils/dateUtil'; 129 import { formatToDateTime } from '/@/utils/dateUtil';
130 import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/components/ObjectModelValidateForm/ObjectModelValidateForm.vue'; 130 import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/components/ObjectModelValidateForm/ObjectModelValidateForm.vue';
  131 + import { isEmpty } from '/@/utils/is';
131 import { add } from '/@/components/Form/src/componentMap'; 132 import { add } from '/@/components/Form/src/componentMap';
132 133
133 add('ObjectModelValidateForm', ObjectModelValidateForm); 134 add('ObjectModelValidateForm', ObjectModelValidateForm);
@@ -156,7 +157,7 @@ @@ -156,7 +157,7 @@
156 const id = ref(undefined); 157 const id = ref(undefined);
157 const tenantId = ref(undefined); 158 const tenantId = ref(undefined);
158 const isView = ref(true); 159 const isView = ref(true);
159 - const [registerForm, { resetFields, validate, setFieldsValue }] = useForm({ 160 + const [registerForm, { resetFields, validate, setFieldsValue, getFieldsValue }] = useForm({
160 labelWidth: 120, 161 labelWidth: 120,
161 schemas: formSchema, 162 schemas: formSchema,
162 showActionButtonGroup: false, 163 showActionButtonGroup: false,
@@ -617,12 +618,25 @@ @@ -617,12 +618,25 @@
617 // item.updateFieldAlarmConfig(alarmConfigList); 618 // item.updateFieldAlarmConfig(alarmConfigList);
618 // }); 619 // });
619 // } 620 // }
  621 +
  622 + const isEmptyThrowError = (obj) => {
  623 + if (isEmpty(obj)) {
  624 + createMessage.error('请选择组织');
  625 + throw Error('请选择组织');
  626 + }
  627 + if (!Reflect.get(obj, 'organizationId')) {
  628 + createMessage.error('请选择组织');
  629 + throw Error('请选择组织');
  630 + }
  631 + };
  632 +
620 // 添加触发器 633 // 添加触发器
621 const addTrigger = () => { 634 const addTrigger = () => {
622 unref(triggerData).push(Date.now()); 635 unref(triggerData).push(Date.now());
623 nextTick(() => { 636 nextTick(() => {
624 setFields(skipUnwrap.triggerItemRefs); 637 setFields(skipUnwrap.triggerItemRefs);
625 }); 638 });
  639 + isEmptyThrowError(getFieldsValue());
626 }; 640 };
627 // 添加执行条件 641 // 添加执行条件
628 const addCondition = () => { 642 const addCondition = () => {
@@ -630,6 +644,7 @@ @@ -630,6 +644,7 @@
630 nextTick(() => { 644 nextTick(() => {
631 setFields(skipUnwrap.conditionItemRefs); 645 setFields(skipUnwrap.conditionItemRefs);
632 }); 646 });
  647 + isEmptyThrowError(getFieldsValue());
633 }; 648 };
634 // 添加执行动作 649 // 添加执行动作
635 const addAction = () => { 650 const addAction = () => {
@@ -637,6 +652,7 @@ @@ -637,6 +652,7 @@
637 nextTick(() => { 652 nextTick(() => {
638 setFields(skipUnwrap.actionItemRefs); 653 setFields(skipUnwrap.actionItemRefs);
639 }); 654 });
  655 + isEmptyThrowError(getFieldsValue());
640 }; 656 };
641 657
642 /** 658 /**
1 -<template>  
2 - <div>  
3 - <a-form  
4 - ref="formRef"  
5 - :model="scriptForm"  
6 - name="basic"  
7 - :label-col="{ span: 4 }"  
8 - :wrapper-col="{ span: 16 }"  
9 - autocomplete="off"  
10 - >  
11 - <a-form-item  
12 - :label="ifAdd ? '名称' : '输入参数(params)'"  
13 - :name="ifAdd ? 'name' : 'params'"  
14 - :rules="[{ required: true, message: ifAdd ? '请输入脚本名称' : '请输入参数' }]"  
15 - >  
16 - <a-input  
17 - v-if="ifAdd"  
18 - :maxlength="36"  
19 - @change="handleInputChange"  
20 - v-model:value="scriptForm.name"  
21 - placeholder="请输入脚本名称"  
22 - />  
23 - <a-input  
24 - @change="handleInputChange"  
25 - v-else  
26 - v-model:value="scriptForm.params"  
27 - placeholder="请输入参数"  
28 - />  
29 - </a-form-item>  
30 - <a-form-item  
31 - label="脚本类型"  
32 - name="scriptType"  
33 - :rules="[{ required: true, message: '请选择脚本类型' }]"  
34 - >  
35 - <a-space direction="vertical">  
36 - <a-radio-group  
37 - @change="handleScriptType"  
38 - v-model:value="scriptForm.scriptType"  
39 - :options="scriptTypeOptions"  
40 - />  
41 - </a-space>  
42 - </a-form-item>  
43 - <a-form-item  
44 - label="保存原始数据"  
45 - name="saveOriginalData"  
46 - :rules="[{ required: true, message: '请选择保存原始数据' }]"  
47 - >  
48 - <a-space direction="vertical">  
49 - <a-radio-group v-model:value="scriptForm.saveOriginalData" :options="originalOptions" />  
50 - </a-space>  
51 - </a-form-item>  
52 - <a-form-item label="脚本内容" :name="ifAdd ? 'convertJs' : 'script'">  
53 - <Card title="脚本内容" :bodyStyle="{ padding: 0, height: '280px' }">  
54 - <template #extra>  
55 - <a-button @click="handleFormat" size="small">格式化</a-button>  
56 - <Tooltip :title="defaultTitle" class="ml-2">  
57 - <QuestionCircleOutlined style="font-size: 1rem" />  
58 - </Tooltip>  
59 - </template>  
60 - <div ref="aceRef" class="overflow-hidden"></div>  
61 - </Card>  
62 - <Button @click="handleCopy" class="mt-4">  
63 - <template #icon>  
64 - <CopyOutlined />  
65 - </template>  
66 - copy  
67 - </Button>  
68 - </a-form-item>  
69 - <a-form-item  
70 - :label="ifAdd ? '备注' : '输出参数(output)'"  
71 - :name="ifAdd ? 'description' : 'output'"  
72 - >  
73 - <a-textarea  
74 - :rows="3"  
75 - v-if="ifAdd"  
76 - v-model:value="scriptForm.description"  
77 - placeholder="请输入备注"  
78 - :maxlength="255"  
79 - />  
80 - <a-textarea  
81 - disabled  
82 - :rows="5"  
83 - v-else  
84 - v-model:value="scriptForm.output"  
85 - placeholder="输出参数为服务端返回的内容"  
86 - :maxlength="255"  
87 - />  
88 - </a-form-item>  
89 - </a-form>  
90 - </div>  
91 -</template>  
92 -<script setup lang="ts">  
93 - import { ref, unref, reactive, onMounted, toRefs, nextTick, computed } from 'vue';  
94 - import ace from 'ace-builds';  
95 - import { Card, Button, Tooltip } from 'ant-design-vue';  
96 - import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题  
97 - import 'ace-builds/src-noconflict/theme-terminal'; // 默认设置的主题  
98 - import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式  
99 - import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js';  
100 - import { CopyOutlined } from '@ant-design/icons-vue';  
101 - import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';  
102 - import { useMessage } from '/@/hooks/web/useMessage';  
103 - import { findDictItemByCode } from '/@/api/system/dict';  
104 - import { QuestionCircleOutlined } from '@ant-design/icons-vue';  
105 - import { defaultTitle, defaultScriptTypeContent } from './config.data';  
106 - import { useAppStore } from '/@/store/modules/app';  
107 -  
108 - defineEmits(['register']);  
109 - const props = defineProps({  
110 - ifAdd: { type: Boolean, default: true },  
111 - });  
112 -  
113 - const scriptForm = reactive({  
114 - name: '',  
115 - description: '',  
116 - convertJs: '',  
117 - script: '',  
118 - params: '',  
119 - output: '',  
120 - scriptType: 'TRANSPORT_TCP_UP',  
121 - saveOriginalData: 'true',  
122 - });  
123 -  
124 - const reportTypeOptions = reactive({  
125 - originalOptions: [],  
126 - scriptTypeOptions: [],  
127 - });  
128 -  
129 - const { originalOptions, scriptTypeOptions } = toRefs(reportTypeOptions);  
130 -  
131 - const { createMessage } = useMessage();  
132 -  
133 - const { clipboardRef, copiedRef } = useCopyToClipboard();  
134 -  
135 - const aceEditor = ref();  
136 -  
137 - const aceRef = ref();  
138 -  
139 - const userStore = useAppStore();  
140 -  
141 - const getAceClass = computed((): string => userStore.getDarkMode);  
142 -  
143 - const setDefaultRadio = (p2, p3) => {  
144 - scriptForm.saveOriginalData = p2;  
145 - scriptForm.scriptType = p3;  
146 - };  
147 -  
148 - const getDictValue = async (dict_type) => {  
149 - const res = await findDictItemByCode({  
150 - dictCode: dict_type,  
151 - });  
152 - return res.map((m) => {  
153 - return { label: m.itemText, value: m.itemValue };  
154 - });  
155 - };  
156 -  
157 - onMounted(async () => {  
158 - reportTypeOptions.originalOptions = (await getDictValue('original_data')) as never as any;  
159 - reportTypeOptions.scriptTypeOptions = (await getDictValue('script_type')) as never as any;  
160 - });  
161 -  
162 - // 初始化编辑器  
163 - const initEditor = () => {  
164 - aceEditor.value = ace.edit(aceRef.value, {  
165 - maxLines: 12, // 最大行数,超过会自动出现滚动条  
166 - minLines: 12, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小  
167 - fontSize: 14, // 编辑器内字体大小  
168 - theme: 'ace/theme/chrome', // 默认设置的主题  
169 - mode: 'ace/mode/javascript', // 默认设置的语言模式  
170 - tabSize: 2, // 制表符设置为 4 个空格大小  
171 - });  
172 -  
173 - aceEditor.value.setOptions({  
174 - enableBasicAutocompletion: true,  
175 - enableLiveAutocompletion: true,  
176 - theme: getAceClass.value === 'dark' ? 'ace/theme/terminal' : 'ace/theme/chrome',  
177 - });  
178 - aceEditor.value.setValue('');  
179 - beautify(aceEditor.value.session);  
180 - switchScriptTypeGetContent('TRANSPORT_TCP_UP');  
181 - };  
182 -  
183 - const handleScriptType = ({ target }) => {  
184 - const { value } = target;  
185 - switchScriptTypeGetContent(value);  
186 - };  
187 -  
188 - const switchScriptTypeGetContent = (type) => {  
189 - aceEditor.value.setValue(defaultScriptTypeContent[type]);  
190 - };  
191 -  
192 - const handleCopy = () => {  
193 - const valueRef = aceEditor.value.getValue();  
194 - const value = unref(valueRef);  
195 - if (!value) {  
196 - createMessage.warning('请输入要拷贝的内容!');  
197 - return;  
198 - }  
199 - clipboardRef.value = value;  
200 - if (unref(copiedRef)) {  
201 - createMessage.success('复制成功!');  
202 - }  
203 - };  
204 -  
205 - const formRef = ref();  
206 -  
207 - const getFormData = async () => {  
208 - const value = await formRef.value.validateFields();  
209 - if (props.ifAdd) {  
210 - scriptForm.convertJs = aceEditor.value.getValue();  
211 - if (scriptForm.convertJs == '') {  
212 - createMessage.error('请编写脚本内容');  
213 - throw '请编写脚本内容';  
214 - }  
215 - } else {  
216 - scriptForm.script = aceEditor.value.getValue();  
217 - if (scriptForm.script == '') {  
218 - createMessage.error('请编写脚本内容');  
219 - throw '请编写脚本内容';  
220 - }  
221 - }  
222 - if (!value) return;  
223 - if (scriptForm.params) {  
224 - const trimParams = scriptForm.params.replace(/\s*/g, '');  
225 - Reflect.set(value, 'params', trimParams);  
226 - }  
227 - if (scriptForm.convertJs.length > 1000) {  
228 - createMessage.error('脚本内容长度不能大于1000');  
229 - throw '脚本内容长度不能大于1000';  
230 - }  
231 - return {  
232 - ...value,  
233 - ...{ convertJs: props.ifAdd ? scriptForm.convertJs : null },  
234 - ...{ script: !props.ifAdd ? scriptForm.script : null },  
235 - ...{ saveOriginalData: scriptForm.saveOriginalData === 'false' ? false : true },  
236 - };  
237 - };  
238 -  
239 - const handleInputChange = (e) => {  
240 - const trimParams = e.target.value.replace(/\s*/g, '');  
241 - Reflect.set(scriptForm, 'params', trimParams);  
242 - if (scriptForm.scriptType === 'TRANSPORT_TCP_DOWN') {  
243 - aceEditor.value.setValue(`out.datas = "${scriptForm.params}";out.deviceName = "sensor";`);  
244 - }  
245 - };  
246 -  
247 - const setFormData = (v) => {  
248 - if (v) {  
249 - for (let i in scriptForm) {  
250 - Reflect.set(scriptForm, i, v[i]);  
251 - }  
252 - nextTick(() => {  
253 - setTimeout(() => {  
254 - scriptForm.saveOriginalData = v.saveOriginalData === false ? 'false' : 'true';  
255 - }, 10);  
256 - });  
257 - aceEditor.value.setValue(v.convertJs);  
258 - handleFormat();  
259 - }  
260 - };  
261 -  
262 - const setScriptContentData = (v) => {  
263 - aceEditor.value.setValue(v);  
264 - handleFormat();  
265 - };  
266 -  
267 - const resetFormData = () => {  
268 - for (let i in scriptForm) {  
269 - Reflect.set(scriptForm, i, '');  
270 - }  
271 - };  
272 -  
273 - const setScriptOutputData = (v) => {  
274 - scriptForm.output = v;  
275 - };  
276 -  
277 - const handleFormat = () => {  
278 - beautify(aceEditor.value.session);  
279 - aceEditor.value.getSession().setUseWrapMode(true);  
280 - };  
281 -  
282 - defineExpose({  
283 - initEditor,  
284 - getFormData,  
285 - resetFormData,  
286 - setFormData,  
287 - setScriptContentData,  
288 - setScriptOutputData,  
289 - setDefaultRadio,  
290 - });  
291 -</script>  
292 -<style lang="less" scoped>  
293 - @import url('./ConverScriptModal.less');  
294 -</style> 1 +<template>
  2 + <div>
  3 + <a-form
  4 + ref="formRef"
  5 + :model="scriptForm"
  6 + name="basic"
  7 + :label-col="{ span: 4 }"
  8 + :wrapper-col="{ span: 16 }"
  9 + autocomplete="off"
  10 + >
  11 + <a-form-item
  12 + :label="ifAdd ? '名称' : '输入参数(params)'"
  13 + :name="ifAdd ? 'name' : 'params'"
  14 + :rules="[{ required: true, message: ifAdd ? '请输入脚本名称' : '请输入参数' }]"
  15 + >
  16 + <a-input-group compact>
  17 + <a-input
  18 + style="width: calc(100% - 200px)"
  19 + v-if="ifAdd"
  20 + :maxlength="36"
  21 + @change="handleInputChange"
  22 + v-model:value="scriptForm.name"
  23 + placeholder="请输入脚本名称"
  24 + />
  25 + <a-input
  26 + @change="handleInputChange"
  27 + v-else
  28 + v-model:value="scriptForm.params"
  29 + placeholder="请输入参数"
  30 + />
  31 + <a-button @click="onHandleClick(text)" v-show="ifAdd && !view" type="primary">
  32 + 测试
  33 + </a-button>
  34 + </a-input-group>
  35 + </a-form-item>
  36 + <a-form-item
  37 + label="脚本类型"
  38 + name="scriptType"
  39 + :rules="[{ required: true, message: '请选择脚本类型' }]"
  40 + >
  41 + <a-space direction="vertical">
  42 + <a-radio-group
  43 + @change="handleScriptType"
  44 + v-model:value="scriptForm.scriptType"
  45 + :options="scriptTypeOptions"
  46 + />
  47 + </a-space>
  48 + </a-form-item>
  49 + <a-form-item
  50 + label="保存原始数据"
  51 + name="saveOriginalData"
  52 + :rules="[{ required: true, message: '请选择保存原始数据' }]"
  53 + >
  54 + <a-space direction="vertical">
  55 + <a-radio-group v-model:value="scriptForm.saveOriginalData" :options="originalOptions" />
  56 + </a-space>
  57 + </a-form-item>
  58 + <a-form-item label="脚本内容" :name="ifAdd ? 'convertJs' : 'script'">
  59 + <Card title="脚本内容" :bodyStyle="{ padding: 0, height: '280px' }">
  60 + <template #extra>
  61 + <a-button @click="handleFormat" size="small">格式化</a-button>
  62 + <Tooltip v-if="!ifAdd" :title="defaultAuthTitle" class="ml-2">
  63 + <QuestionCircleOutlined style="font-size: 1rem" />
  64 + </Tooltip>
  65 + <Tooltip v-if="!ifAdd" :title="defaultUpTitle" class="ml-2">
  66 + <QuestionCircleOutlined style="font-size: 1rem" />
  67 + </Tooltip>
  68 + </template>
  69 + <div ref="aceRef" class="overflow-hidden"></div>
  70 + </Card>
  71 + <Button @click="handleCopy" class="mt-4">
  72 + <template #icon>
  73 + <CopyOutlined />
  74 + </template>
  75 + copy
  76 + </Button>
  77 + </a-form-item>
  78 + <a-form-item
  79 + :label="ifAdd ? '备注' : '输出参数(output)'"
  80 + :name="ifAdd ? 'description' : 'output'"
  81 + >
  82 + <a-textarea
  83 + :rows="3"
  84 + v-if="ifAdd"
  85 + v-model:value="scriptForm.description"
  86 + placeholder="请输入备注"
  87 + :maxlength="255"
  88 + />
  89 + <a-textarea
  90 + :rows="5"
  91 + v-else
  92 + v-model:value="scriptForm.output"
  93 + placeholder="输出参数为服务端返回的内容"
  94 + :maxlength="255"
  95 + />
  96 + </a-form-item>
  97 + </a-form>
  98 + <TestScriptModal @register="registerModal" @success="handleSuccess" />
  99 + </div>
  100 +</template>
  101 +<script setup lang="ts">
  102 + import { ref, unref, reactive, onMounted, toRefs, nextTick, computed } from 'vue';
  103 + import ace from 'ace-builds';
  104 + import { Card, Button, Tooltip } from 'ant-design-vue';
  105 + import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题
  106 + import 'ace-builds/src-noconflict/theme-terminal'; // 默认设置的主题
  107 + import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式
  108 + import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js';
  109 + import { CopyOutlined } from '@ant-design/icons-vue';
  110 + import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
  111 + import { useMessage } from '/@/hooks/web/useMessage';
  112 + import { findDictItemByCode } from '/@/api/system/dict';
  113 + import { QuestionCircleOutlined } from '@ant-design/icons-vue';
  114 + import { defaultAuthTitle, defaultUpTitle, defaultScriptTypeContent } from './config.data';
  115 + import { useAppStore } from '/@/store/modules/app';
  116 + import TestScriptModal from './TestScriptModal.vue';
  117 + import { useModal } from '/@/components/Modal';
  118 +
  119 + defineEmits(['register']);
  120 + const props = defineProps({
  121 + ifAdd: { type: Boolean, default: true },
  122 + text: { type: String, default: '' },
  123 + view: { type: Boolean, default: false },
  124 + });
  125 +
  126 + const scriptForm = reactive({
  127 + name: '',
  128 + description: '',
  129 + convertJs: '',
  130 + script: '',
  131 + params: '',
  132 + output: '',
  133 + scriptType: 'TRANSPORT_TCP_UP',
  134 + saveOriginalData: 'true',
  135 + });
  136 +
  137 + const reportTypeOptions = reactive({
  138 + originalOptions: [],
  139 + scriptTypeOptions: [],
  140 + });
  141 +
  142 + const { originalOptions, scriptTypeOptions } = toRefs(reportTypeOptions);
  143 +
  144 + const { createMessage } = useMessage();
  145 +
  146 + const { clipboardRef, copiedRef } = useCopyToClipboard();
  147 +
  148 + const aceEditor = ref();
  149 +
  150 + const aceRef = ref();
  151 +
  152 + const userStore = useAppStore();
  153 +
  154 + const getAceClass = computed((): string => userStore.getDarkMode);
  155 +
  156 + const setDefaultRadio = (p2, p3) => {
  157 + scriptForm.saveOriginalData = p2;
  158 + scriptForm.scriptType = p3;
  159 + };
  160 +
  161 + const getDictValue = async (dict_type) => {
  162 + const res = await findDictItemByCode({
  163 + dictCode: dict_type,
  164 + });
  165 + return res.map((m) => {
  166 + return { label: m.itemText, value: m.itemValue };
  167 + });
  168 + };
  169 +
  170 + onMounted(async () => {
  171 + reportTypeOptions.originalOptions = (await getDictValue('original_data')) as never as any;
  172 + reportTypeOptions.scriptTypeOptions = (await getDictValue('script_type')) as never as any;
  173 + });
  174 +
  175 + // 初始化编辑器
  176 + const initEditor = () => {
  177 + aceEditor.value = ace.edit(aceRef.value, {
  178 + maxLines: 12, // 最大行数,超过会自动出现滚动条
  179 + minLines: 12, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小
  180 + fontSize: 14, // 编辑器内字体大小
  181 + theme: 'ace/theme/chrome', // 默认设置的主题
  182 + mode: 'ace/mode/javascript', // 默认设置的语言模式
  183 + tabSize: 2, // 制表符设置为 4 个空格大小
  184 + });
  185 +
  186 + aceEditor.value.setOptions({
  187 + enableBasicAutocompletion: true,
  188 + enableLiveAutocompletion: true,
  189 + theme: getAceClass.value === 'dark' ? 'ace/theme/terminal' : 'ace/theme/chrome',
  190 + });
  191 + aceEditor.value.setValue('');
  192 + beautify(aceEditor.value.session);
  193 + switchScriptTypeGetContent('TRANSPORT_TCP_UP');
  194 + };
  195 +
  196 + const handleScriptType = ({ target }) => {
  197 + const { value } = target;
  198 + switchScriptTypeGetContent(value);
  199 + };
  200 +
  201 + const switchScriptTypeGetContent = (type) => {
  202 + aceEditor.value.setValue(defaultScriptTypeContent[type]);
  203 + };
  204 +
  205 + const handleCopy = () => {
  206 + const valueRef = aceEditor.value.getValue();
  207 + const value = unref(valueRef);
  208 + if (!value) {
  209 + createMessage.warning('请输入要拷贝的内容!');
  210 + return;
  211 + }
  212 + clipboardRef.value = value;
  213 + if (unref(copiedRef)) {
  214 + createMessage.success('复制成功!');
  215 + }
  216 + };
  217 +
  218 + const formRef = ref();
  219 +
  220 + const getFormData = async () => {
  221 + const value = await formRef.value.validateFields();
  222 + if (props.ifAdd) {
  223 + scriptForm.convertJs = aceEditor.value.getValue();
  224 + if (scriptForm.convertJs == '') {
  225 + createMessage.error('请编写脚本内容');
  226 + throw '请编写脚本内容';
  227 + }
  228 + } else {
  229 + scriptForm.script = aceEditor.value.getValue();
  230 + if (scriptForm.script == '') {
  231 + createMessage.error('请编写脚本内容');
  232 + throw '请编写脚本内容';
  233 + }
  234 + }
  235 + if (!value) return;
  236 + if (scriptForm.params) {
  237 + const trimParams = scriptForm.params.replace(/\s*/g, '');
  238 + Reflect.set(value, 'params', trimParams);
  239 + }
  240 + if (scriptForm.convertJs.length > 1000) {
  241 + createMessage.error('脚本内容长度不能大于1000');
  242 + throw '脚本内容长度不能大于1000';
  243 + }
  244 + return {
  245 + ...value,
  246 + ...{ convertJs: props.ifAdd ? scriptForm.convertJs : null },
  247 + ...{ script: !props.ifAdd ? scriptForm.script : null },
  248 + ...{ saveOriginalData: scriptForm.saveOriginalData === 'false' ? false : true },
  249 + };
  250 + };
  251 +
  252 + const handleInputChange = (e) => {
  253 + const trimParams = e.target.value.replace(/\s*/g, '');
  254 + Reflect.set(scriptForm, 'params', trimParams);
  255 + if (scriptForm.scriptType === 'TRANSPORT_TCP_DOWN') {
  256 + aceEditor.value.setValue(`out.datas = "${scriptForm.params}";out.deviceName = "sensor";`);
  257 + }
  258 + };
  259 +
  260 + const getRecordId = ref('');
  261 +
  262 + const setFormData = (v) => {
  263 + if (v) {
  264 + getRecordId.value = v?.id;
  265 + for (let i in scriptForm) {
  266 + Reflect.set(scriptForm, i, v[i]);
  267 + }
  268 + nextTick(() => {
  269 + setTimeout(() => {
  270 + scriptForm.saveOriginalData = v.saveOriginalData === false ? 'false' : 'true';
  271 + }, 10);
  272 + });
  273 + aceEditor.value.setValue(v.convertJs);
  274 + handleFormat();
  275 + }
  276 + };
  277 +
  278 + const setScriptContentData = (v) => {
  279 + aceEditor.value.setValue(v);
  280 + handleFormat();
  281 + };
  282 +
  283 + const resetFormData = () => {
  284 + for (let i in scriptForm) {
  285 + Reflect.set(scriptForm, i, '');
  286 + }
  287 + };
  288 +
  289 + const setScriptOutputData = (v) => {
  290 + scriptForm.output = v;
  291 + };
  292 +
  293 + const handleFormat = () => {
  294 + beautify(aceEditor.value.session);
  295 + aceEditor.value.getSession().setUseWrapMode(true);
  296 + };
  297 +
  298 + const [registerModal, { openModal }] = useModal();
  299 +
  300 + const onHandleClick = (o) => {
  301 + openModal(true, {
  302 + isAuth: '',
  303 + isUpdate: false,
  304 + record: o === 'add' ? null : getRecordId.value,
  305 + isTest: true,
  306 + isText: 'test',
  307 + isTitle: 'test',
  308 + });
  309 + };
  310 +
  311 + defineExpose({
  312 + initEditor,
  313 + getFormData,
  314 + resetFormData,
  315 + setFormData,
  316 + setScriptContentData,
  317 + setScriptOutputData,
  318 + setDefaultRadio,
  319 + });
  320 +</script>
  321 +<style lang="less" scoped>
  322 + @import url('./ConverScriptModal.less');
  323 +</style>
@@ -10,7 +10,12 @@ @@ -10,7 +10,12 @@
10 @cancel="handleCancel" 10 @cancel="handleCancel"
11 @ok="handleSubmit" 11 @ok="handleSubmit"
12 > 12 >
13 - <ConverScript :ifAdd="isTest ? false : true" ref="converScriptRef" /> 13 + <ConverScript
  14 + :view="isViewDetail"
  15 + :text="isTitle"
  16 + :ifAdd="isTest ? false : true"
  17 + ref="converScriptRef"
  18 + />
14 </BasicModal> 19 </BasicModal>
15 </div> 20 </div>
16 </template> 21 </template>
  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
  14 + :view="isViewDetail"
  15 + :text="isTitle"
  16 + :ifAdd="isTest ? false : true"
  17 + ref="converScriptRef"
  18 + />
  19 + </BasicModal>
  20 + </div>
  21 +</template>
  22 +<script setup lang="ts">
  23 + import { ref, computed, unref, reactive } from 'vue';
  24 + import { BasicModal, useModalInner } from '/@/components/Modal';
  25 + import ConverScript from './ConverScript.vue';
  26 + import {
  27 + createOrEditScriptManage,
  28 + getScriptManageDetail,
  29 + testScriptManage,
  30 + } from '/@/api/scriptmanage/scriptManager';
  31 + import { useMessage } from '/@/hooks/web/useMessage';
  32 +
  33 + const emits = defineEmits(['success', 'register']);
  34 + const { createMessage } = useMessage();
  35 + const converScriptRef = ref<InstanceType<typeof ConverScript>>();
  36 + const getTitle = computed(() => (isUpdate.value ? '编辑转换脚本' : '新增转换脚本'));
  37 + const isUpdate = ref(false);
  38 + const isViewDetail = ref('');
  39 + const isTest = ref(false);
  40 + const isText = ref('');
  41 + const isTitle = ref('');
  42 + const editData = reactive({
  43 + data: {},
  44 + });
  45 + const [register, { setModalProps, closeModal }] = useModalInner(async (data) => {
  46 + setModalProps({ loading: true });
  47 + handleCancel(false);
  48 + isUpdate.value = data.isUpdate;
  49 + isViewDetail.value = data.isView;
  50 + isTest.value = data.isTest;
  51 + isText.value = data.isText;
  52 + isTitle.value = data.isTitle;
  53 + editData.data = data.record;
  54 + setModalProps({ loading: false });
  55 + converScriptRef.value?.initEditor();
  56 + if (!unref(isViewDetail)) {
  57 + const title =
  58 + unref(isTitle) == 'edit'
  59 + ? '编辑转换脚本'
  60 + : unref(isTitle) == 'add'
  61 + ? '新增转换脚本'
  62 + : '测试转换脚本';
  63 + const okText = isText.value == 'test' ? '测试' : '确定';
  64 + if (unref(isTitle) == 'add') {
  65 + converScriptRef.value?.setDefaultRadio('true', 'TRANSPORT_TCP_UP');
  66 + }
  67 + if (unref(isTitle) == 'edit') {
  68 + converScriptRef.value?.setFormData(data.record);
  69 + }
  70 + if (unref(isTitle) == 'test') {
  71 + if (data.record) {
  72 + const res = await getScriptManageDetail(data.record);
  73 + converScriptRef.value?.setFormData(res);
  74 + } else {
  75 + converScriptRef.value?.setDefaultRadio('true', 'TRANSPORT_TCP_UP');
  76 + }
  77 + }
  78 + setModalProps({ title, showOkBtn: true, showCancelBtn: true, okText });
  79 + if (!unref(isUpdate)) {
  80 + }
  81 + } else {
  82 + setModalProps({ showOkBtn: false, showCancelBtn: false, title: '查看转换脚本' });
  83 + const res = await getScriptManageDetail(data.record.id);
  84 + converScriptRef.value?.setFormData(res || {});
  85 + }
  86 + });
  87 +
  88 + const handleSubmit = async () => {
  89 + setModalProps({ confirmLoading: true });
  90 + try {
  91 + const val = await converScriptRef.value?.getFormData();
  92 + const tempObj = {
  93 + ...editData.data,
  94 + ...val,
  95 + };
  96 + const res: any =
  97 + isText.value == 'test'
  98 + ? await testScriptManage(val)
  99 + : await createOrEditScriptManage(tempObj);
  100 + createMessage.success(
  101 + unref(isTitle) == 'edit'
  102 + ? '编辑转换脚本成功'
  103 + : unref(isTitle) == 'add'
  104 + ? '新增转换脚本成功'
  105 + : '测试转换脚本成功'
  106 + );
  107 + if (unref(isTitle) == 'add' || unref(isTitle) == 'edit') {
  108 + setTimeout(() => {
  109 + closeModal();
  110 + }, 10);
  111 + emits('success', {
  112 + res,
  113 + text: isText.value,
  114 + });
  115 + } else {
  116 + if (res) {
  117 + converScriptRef.value?.setScriptOutputData(res?.output || res?.error);
  118 + }
  119 + }
  120 + } finally {
  121 + setModalProps({ confirmLoading: false });
  122 + }
  123 + };
  124 + const handleCancel = (flag) => {
  125 + if (flag) {
  126 + closeModal();
  127 + }
  128 + converScriptRef.value?.resetFormData();
  129 + };
  130 +</script>
  131 +<style lang="less" scoped>
  132 + @import url('./ConverScriptModal.less');
  133 +</style>
@@ -58,25 +58,30 @@ export const searchFormSchema: FormSchema[] = [ @@ -58,25 +58,30 @@ export const searchFormSchema: FormSchema[] = [
58 }, 58 },
59 ]; 59 ];
60 60
61 -export const defaultTitle = h('div', { style: 'background:#404040' }, [  
62 - h('h3', { style: 'color:white' }, '示例'),  
63 - h('h3', { style: 'color:white' }, '输入参数:'),  
64 - h('h3', { style: 'color:white' }, '0103040150008D3BBB'),  
65 - h('h3', { style: 'color:white' }, [  
66 - h('h3', { style: 'color:white' }, '脚本内容:'),  
67 - h(  
68 - 'h3',  
69 - { style: 'color:white' },  
70 - "out.humidity = (parseInt('0x'+params.substr(6, 4))*0.1).toFixed(2);"  
71 - ),  
72 - h(  
73 - 'h3',  
74 - { style: 'color:white' },  
75 - "out.temperature = (parseInt('0x'+params.substr(10, 4))*0.1).toFixed(2);"  
76 - ),  
77 - h('h3', { style: 'color:white' }, '输出参数:'),  
78 - h('h3', { style: 'color:white' }, "{'humidity':'33.60','temperature':'14.10'}"),  
79 - ]), 61 +export const defaultAuthTitle = h('div', { style: 'background:#404040' }, [
  62 + h('h3', { style: 'color:white' }, '设备鉴权示例'),
  63 + h('h3', { style: 'color:white' }, '输入参数:为16进制字符串'),
  64 + h('h3', { style: 'color:white' }, '输出参数:{"password":"","success":""}'),
  65 + h('h3', { style: 'color:white' }, 'password为设备鉴权信息,success为鉴权成功后响应给设备的内容'),
  66 +]);
  67 +
  68 +export const defaultUpTitle = h('div', { style: 'background:#404040' }, [
  69 + h('h3', { style: 'color:white' }, '上行数据解析示例'),
  70 + h('h3', { style: 'color:white' }, '输入参数:为字符串'),
  71 + h(
  72 + 'h3',
  73 + { style: 'color:white' },
  74 + `输出参数:{"datas":{"source":""},"telemetry":true,"ackMsg":"","deviceName":"","ts":1681701034289}`
  75 + ),
  76 + h(
  77 + 'h3',
  78 + { style: 'color:white' },
  79 + `datas:json对象,属性名为遥测指标或子设备名称
  80 + telemetry: datas内容是否为遥测数据
  81 + ackMsg: 响应给设备的确认消息
  82 + deviceName: 设备名称
  83 + ts: 数据采集时间`
  84 + ),
80 ]); 85 ]);
81 86
82 // TRANSPORT_TCP_DOWN: 'out.datas = "";out.deviceName = "sensor";', 87 // TRANSPORT_TCP_DOWN: 'out.datas = "";out.deviceName = "sensor";',
@@ -273,6 +273,8 @@ @@ -273,6 +273,8 @@
273 status: searchInfo.status, 273 status: searchInfo.status,
274 page: pagination.current, 274 page: pagination.current,
275 pageSize: pagination.pageSize, 275 pageSize: pagination.pageSize,
  276 + startTime: moment(searchInfo.sendTime.at(-2)).valueOf(),
  277 + endTime: moment(searchInfo.sendTime.at(-1)).valueOf(),
276 }); 278 });
277 setTableData(res.items); 279 setTableData(res.items);
278 pagination.total = res.total; 280 pagination.total = res.total;