Commit cea7fdf23a38e81c2e96acf3f188d1d7f4e70e35
1 parent
7ddce7c2
Merge branch 'ft' into 'main_dev'
fix: 修复Teambition上的问题 See merge request yunteng/thingskit-front!533 (cherry picked from commit 6fee6dcc13983532958543c85383139aad19fdce) c62f9e54 pref:优化测试接口表格,只有一项时,清除对应项 85cc1230 fix:DEFECT-1122 分页接口测试错误提示,修复post传参问题 e2c049f2 fix:DEFECT-1112 提示输入参数值 表格选择是否必须为是,则对应测试接口参数若为空则增加提示 f8d25bcd fix:DEFECT-1112 提示输入参数值 表格选择是否必须为是,则对应测试接口参数若为空则增加提示 eaaa19ee pref:调整脚本管理 转换函数 dda4b267 fix:DEFECT-1078 修复暗黑模式场景联动白框问题 b8876e1a fix:DEFECT-1079 修复暗黑模式转换脚本白框问题
Showing
16 changed files
with
767 additions
and
622 deletions
1 | 1 | <template> |
2 | - <div :class="prefixCls"> | |
2 | + <div | |
3 | + :class="prefixCls" | |
4 | + :style="{ backgroundColor: modeSwitch === 'dark' ? '#1f1f1f' : 'rgb(242, 242, 242)' }" | |
5 | + > | |
3 | 6 | <CollapseHeader |
4 | 7 | v-bind="$props" |
5 | 8 | :prefixCls="prefixCls" |
... | ... | @@ -29,7 +32,7 @@ |
29 | 32 | </template> |
30 | 33 | <script lang="ts" setup> |
31 | 34 | import type { PropType } from 'vue'; |
32 | - import { ref } from 'vue'; | |
35 | + import { ref, computed } from 'vue'; | |
33 | 36 | // component |
34 | 37 | import { Skeleton } from 'ant-design-vue'; |
35 | 38 | import { CollapseTransition } from '/@/components/Transition'; |
... | ... | @@ -38,6 +41,7 @@ |
38 | 41 | // hook |
39 | 42 | import { useTimeoutFn } from '/@/hooks/core/useTimeout'; |
40 | 43 | import { useDesign } from '/@/hooks/web/useDesign'; |
44 | + import { useAppStore } from '/@/store/modules/app'; | |
41 | 45 | |
42 | 46 | const props = defineProps({ |
43 | 47 | isClose: { type: Boolean, default: true }, |
... | ... | @@ -64,6 +68,11 @@ |
64 | 68 | */ |
65 | 69 | lazyTime: { type: Number, default: 0 }, |
66 | 70 | }); |
71 | + | |
72 | + const userStore = useAppStore(); | |
73 | + | |
74 | + const modeSwitch = computed((): string => userStore.getDarkMode); | |
75 | + | |
67 | 76 | const emit = defineEmits(['expand', 'change', 'hchange']); |
68 | 77 | |
69 | 78 | const show = ref(true); |
... | ... | @@ -92,7 +101,7 @@ |
92 | 101 | @prefix-cls: ~'@{namespace}-collapse-container'; |
93 | 102 | |
94 | 103 | .@{prefix-cls} { |
95 | - background-color: @component-background; | |
104 | + // background-color: @component-background; | |
96 | 105 | border-radius: 2px; |
97 | 106 | transition: all 0.3s ease-in-out; |
98 | 107 | ... | ... |
... | ... | @@ -18,6 +18,7 @@ |
18 | 18 | placeholder="请选择" |
19 | 19 | :options="selectOptions" |
20 | 20 | @change="handleChange" |
21 | + @dropdownVisibleChange="hanldeDropdownVisibleChange" | |
21 | 22 | allowClear |
22 | 23 | /> |
23 | 24 | </td> |
... | ... | @@ -111,16 +112,20 @@ |
111 | 112 | |
112 | 113 | // 减少 |
113 | 114 | const remove = (item, index: number) => { |
114 | - if (tableArray.content.length !== 1) { | |
115 | + if (tableArray.content.length > 1) { | |
115 | 116 | selectOptions.value.forEach((ele) => { |
116 | 117 | if (ele.value == item.key) { |
117 | 118 | ele.disabled = false; |
118 | 119 | } |
119 | 120 | }); |
120 | 121 | tableArray.content.splice(index, 1); |
122 | + } else { | |
123 | + resetValue(); | |
121 | 124 | } |
122 | 125 | }; |
123 | 126 | |
127 | + const hanldeDropdownVisibleChange = () => handleChange(); | |
128 | + | |
124 | 129 | //Select互斥 |
125 | 130 | const handleChange = () => { |
126 | 131 | selectOptions.value.forEach((ele) => { |
... | ... | @@ -132,7 +137,7 @@ |
132 | 137 | element.value = ''; |
133 | 138 | element.editDisabled = true; |
134 | 139 | } |
135 | - if (element.key === ele.value && element.key !== 'scope' && element.key !== 'fixed_date') { | |
140 | + if (element.key === ele.value && element.key !== 'scope') { | |
136 | 141 | ele.disabled = true; |
137 | 142 | } |
138 | 143 | }); | ... | ... |
... | ... | @@ -18,6 +18,7 @@ |
18 | 18 | placeholder="请选择" |
19 | 19 | :options="selectOptions" |
20 | 20 | @change="handleChange" |
21 | + @dropdownVisibleChange="hanldeDropdownVisibleChange" | |
21 | 22 | allowClear |
22 | 23 | /> |
23 | 24 | </td> |
... | ... | @@ -111,13 +112,15 @@ |
111 | 112 | |
112 | 113 | // 减少 |
113 | 114 | const remove = (item, index: number) => { |
114 | - if (tableArray.content.length !== 1) { | |
115 | + if (tableArray.content.length > 1) { | |
115 | 116 | selectOptions.value.forEach((ele) => { |
116 | 117 | if (ele.value == item.key) { |
117 | 118 | ele.disabled = false; |
118 | 119 | } |
119 | 120 | }); |
120 | 121 | tableArray.content.splice(index, 1); |
122 | + } else { | |
123 | + resetValue(); | |
121 | 124 | } |
122 | 125 | }; |
123 | 126 | |
... | ... | @@ -132,13 +135,15 @@ |
132 | 135 | element.value = ''; |
133 | 136 | element.editDisabled = true; |
134 | 137 | } |
135 | - if (element.key === ele.value && element.key !== 'scope' && element.key !== 'fixed_date') { | |
138 | + if (element.key === ele.value && element.key !== 'scope') { | |
136 | 139 | ele.disabled = true; |
137 | 140 | } |
138 | 141 | }); |
139 | 142 | }); |
140 | 143 | }; |
141 | 144 | |
145 | + const hanldeDropdownVisibleChange = () => handleChange(); | |
146 | + | |
142 | 147 | //获取数据 |
143 | 148 | const getValue = () => { |
144 | 149 | const assemblyData = tableArray.content.map((it) => { | ... | ... |
... | ... | @@ -31,6 +31,7 @@ |
31 | 31 | import moment from 'moment'; |
32 | 32 | import { useUtils } from '../../../hooks/useUtils'; |
33 | 33 | import JsonEditor from '../../SimpleRequest/components/jsonEditor.vue'; |
34 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
34 | 35 | |
35 | 36 | const emits = defineEmits(['testBodyInterface']); |
36 | 37 | |
... | ... | @@ -40,6 +41,8 @@ |
40 | 41 | }, |
41 | 42 | }); |
42 | 43 | |
44 | + const { createMessage } = useMessage(); | |
45 | + | |
43 | 46 | const showTestEditCell = ref(false); |
44 | 47 | |
45 | 48 | const excuteData = ref({}); |
... | ... | @@ -63,13 +66,12 @@ |
63 | 66 | const getValue = async () => { |
64 | 67 | await nextTick(); |
65 | 68 | await nextTick(() => { |
66 | - console.log(props.data?.list); | |
67 | 69 | if (props.data?.type === 'x-www-form-urlencoded' || props.data?.type === 'form-data') { |
68 | 70 | const getSingleKey = props.data?.list; |
69 | - const getMuteKey = props.data?.list?.filter((it: any) => it.key.split(',').length > 1); | |
71 | + const getMuteKey = props.data?.list?.filter((it: any) => it.key?.split(',').length > 1); | |
70 | 72 | const getMuteKeys = getMultipleKeys(getMuteKey); |
71 | 73 | const mergeKeys = [...getSingleKey, ...getMuteKeys]?.filter( |
72 | - (it: any) => it.key.split(',').length === 1 | |
74 | + (it: any) => it.key?.split(',').length === 1 | |
73 | 75 | ); |
74 | 76 | testEditCellTableRef.value?.setTableArray(mergeKeys); |
75 | 77 | } else if (props.data?.type === 'json') { |
... | ... | @@ -111,6 +113,7 @@ |
111 | 113 | return { |
112 | 114 | key, |
113 | 115 | value, |
116 | + required: it.required, | |
114 | 117 | }; |
115 | 118 | }); |
116 | 119 | }; |
... | ... | @@ -120,6 +123,11 @@ |
120 | 123 | let params: any = {}; |
121 | 124 | if (props.data?.type === 'x-www-form-urlencoded' || props.data?.type === 'form-data') { |
122 | 125 | const getTable = getTestTableKeyValue(); |
126 | + const hasRequired = getTable?.some((it) => it.required === true && !it.value); | |
127 | + if (hasRequired) { | |
128 | + createMessage.error('选择项为必须的,参数不能为空'); | |
129 | + throw new Error('选择项为必须的,参数不能为空'); | |
130 | + } | |
123 | 131 | getTable?.map((it) => (params[it.key!] = it.value!)); |
124 | 132 | } else if (props.data?.type === 'json') { |
125 | 133 | params = jsonEditorRef.value?.getJsonValue(); | ... | ... |
... | ... | @@ -228,6 +228,7 @@ |
228 | 228 | }; |
229 | 229 | |
230 | 230 | const getAttributeOptions = async (params) => { |
231 | + console.log(params); | |
231 | 232 | const res = await getDeviceAttributes(params); |
232 | 233 | if (Object.keys(res).length === 0) return (attributeOptions.value.length = 0); |
233 | 234 | attributeOptions.value = res?.map((item) => ({ label: item.name, value: item.identifier })); |
... | ... | @@ -243,7 +244,9 @@ |
243 | 244 | if (f.key === 'organizationId') organizationId = f.value; |
244 | 245 | if (f.key === 'entityId') f.value = null; |
245 | 246 | }); |
246 | - getAttributeOptions({ deviceProfileId: e.value }); | |
247 | + if (e.value) { | |
248 | + getAttributeOptions({ deviceProfileId: e.value }); | |
249 | + } | |
247 | 250 | if (organizationId !== '') { |
248 | 251 | getEntityOptions(organizationId, e.value); |
249 | 252 | } |
... | ... | @@ -261,6 +264,9 @@ |
261 | 264 | </script> |
262 | 265 | |
263 | 266 | <style scoped lang="less"> |
267 | + :deep(.ant-select-selector) { | |
268 | + max-width: 16vw; | |
269 | + } | |
264 | 270 | @table-color: #e5e7eb; |
265 | 271 | |
266 | 272 | .table-border-color { | ... | ... |
... | ... | @@ -36,7 +36,7 @@ |
36 | 36 | import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; |
37 | 37 | import { getAuthCache } from '/@/utils/auth'; |
38 | 38 | import { useMessage } from '/@/hooks/web/useMessage'; |
39 | - // import { useGlobSetting } from '/@/hooks/setting'; | |
39 | + import { useUtils } from '../../../hooks/useUtils'; | |
40 | 40 | |
41 | 41 | const emits = defineEmits(['emitExcute']); |
42 | 42 | |
... | ... | @@ -56,8 +56,6 @@ |
56 | 56 | |
57 | 57 | const socketUrls = ref(''); |
58 | 58 | |
59 | - // const { socketUrl } = useGlobSetting(); | |
60 | - | |
61 | 59 | const socketMessage: any = reactive({ |
62 | 60 | server: ``, |
63 | 61 | sendValue: { |
... | ... | @@ -152,7 +150,7 @@ |
152 | 150 | apiUrl, |
153 | 151 | headers = {}, |
154 | 152 | params = {}, |
155 | - body, | |
153 | + body = {}, | |
156 | 154 | joinPrefix = false |
157 | 155 | ) => { |
158 | 156 | switch (apiType) { |
... | ... | @@ -165,8 +163,9 @@ |
165 | 163 | } |
166 | 164 | ); |
167 | 165 | case 'POST': |
166 | + const { convertObj } = useUtils(); | |
168 | 167 | return await otherHttp.post( |
169 | - { url: apiUrl, data: body, headers, params }, | |
168 | + { url: `${apiUrl}?${convertObj(params)}`, data: body, headers }, | |
170 | 169 | { |
171 | 170 | apiUrl: '', |
172 | 171 | joinPrefix, | ... | ... |
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | import { ref, nextTick } from 'vue'; |
21 | 21 | import { Button } from 'ant-design-vue'; |
22 | 22 | import TestHeaderEditCellTable from './testEditHeaderCellTable.vue'; |
23 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
23 | 24 | |
24 | 25 | const emits = defineEmits(['testHeaderInterface']); |
25 | 26 | |
... | ... | @@ -29,6 +30,8 @@ |
29 | 30 | }, |
30 | 31 | }); |
31 | 32 | |
33 | + const { createMessage } = useMessage(); | |
34 | + | |
32 | 35 | const showTestEditCell = ref(false); |
33 | 36 | |
34 | 37 | const excuteData = ref({}); |
... | ... | @@ -59,6 +62,11 @@ |
59 | 62 | //获取数据 |
60 | 63 | const getTestValue = () => { |
61 | 64 | const getTable = getTestTableKeyValue(); |
65 | + const hasRequired = getTable?.some((it) => it.required === true && !it.value); | |
66 | + if (hasRequired) { | |
67 | + createMessage.error('选择项为必须的,参数不能为空'); | |
68 | + throw new Error('选择项为必须的,参数不能为空'); | |
69 | + } | |
62 | 70 | const params: any = {}; |
63 | 71 | getTable?.map((it: any) => (params[it.key!] = it.value!)); |
64 | 72 | excuteData.value = { | ... | ... |
... | ... | @@ -22,6 +22,7 @@ |
22 | 22 | import TestParamsCellTable from './testEditParamsCellTable.vue'; |
23 | 23 | import moment from 'moment'; |
24 | 24 | import { useUtils } from '../../../hooks/useUtils'; |
25 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
25 | 26 | |
26 | 27 | const emits = defineEmits(['testParamsInterface']); |
27 | 28 | |
... | ... | @@ -31,6 +32,8 @@ |
31 | 32 | }, |
32 | 33 | }); |
33 | 34 | |
35 | + const { createMessage } = useMessage(); | |
36 | + | |
34 | 37 | const showTestEditCell = ref(false); |
35 | 38 | |
36 | 39 | const excuteData = ref({}); |
... | ... | @@ -92,6 +95,7 @@ |
92 | 95 | return { |
93 | 96 | key, |
94 | 97 | value, |
98 | + required: it.required, | |
95 | 99 | }; |
96 | 100 | }); |
97 | 101 | }; |
... | ... | @@ -99,6 +103,11 @@ |
99 | 103 | //获取数据 |
100 | 104 | const getTestValue = () => { |
101 | 105 | const getTable = getTestTableKeyValue(); |
106 | + const hasRequired = getTable?.some((it) => it.required === true && !it.value); | |
107 | + if (hasRequired) { | |
108 | + createMessage.error('选择项为必须的,参数不能为空'); | |
109 | + throw new Error('选择项为必须的,参数不能为空'); | |
110 | + } | |
102 | 111 | const params: any = {}; |
103 | 112 | getTable?.map((it) => (params[it.key!] = it.value!)); |
104 | 113 | if (params['keys']) { | ... | ... |
... | ... | @@ -235,7 +235,9 @@ |
235 | 235 | if (f.key === 'organizationId') organizationId = f.value; |
236 | 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 | 241 | if (organizationId !== '') { |
240 | 242 | getEntityOptions(organizationId, e.value); |
241 | 243 | } | ... | ... |
... | ... | @@ -5,9 +5,14 @@ export const useUtils = () => { |
5 | 5 | list?.forEach((it) => { |
6 | 6 | const keys = it.key.split(','); |
7 | 7 | const temp = keys.map((item) => { |
8 | - const obj: { key: string; value: string } = { key: '', value: '' }; | |
8 | + const obj: { key: string; value: string; required: boolean } = { | |
9 | + key: '', | |
10 | + value: '', | |
11 | + required: false, | |
12 | + }; | |
9 | 13 | obj.key = item; |
10 | 14 | obj.value = item === 'scope' ? it.value : ''; |
15 | + obj.required = it.required; | |
11 | 16 | return obj; |
12 | 17 | }); |
13 | 18 | temps = temp; |
... | ... | @@ -36,5 +41,20 @@ export const useUtils = () => { |
36 | 41 | type: '0', |
37 | 42 | }, |
38 | 43 | }; |
39 | - return { getMultipleKeys, pushObj, resetReqHttpType, resetUpdateSchema }; | |
44 | + //对象转get params参数 | |
45 | + const convertObj = (data: object) => { | |
46 | + const _result: any = []; | |
47 | + for (const key in data) { | |
48 | + const value = data[key]; | |
49 | + if (value.constructor == Array) { | |
50 | + value.forEach(function (_value) { | |
51 | + _result.push(key + '=' + _value); | |
52 | + }); | |
53 | + } else { | |
54 | + _result.push(key + '=' + value); | |
55 | + } | |
56 | + } | |
57 | + return _result.join('&'); | |
58 | + }; | |
59 | + return { getMultipleKeys, pushObj, resetReqHttpType, resetUpdateSchema, convertObj }; | |
40 | 60 | }; | ... | ... |
1 | -<template> | |
2 | - <div> | |
3 | - <BasicDrawer | |
4 | - v-bind="$attrs" | |
5 | - :title="getTitle" | |
6 | - @register="register" | |
7 | - width="500px" | |
8 | - @ok="handleSubmit" | |
9 | - showFooter | |
10 | - > | |
11 | - <BasicForm @register="registerForm"> | |
12 | - <template #function> | |
13 | - <Card title="转换函数" :bodyStyle="{ padding: 0, height: '280px' }"> | |
14 | - <template #extra> | |
15 | - <Tag color="blue">Transform Function</Tag> | |
16 | - <a-button @click="handleFormat" size="small">格式化</a-button> | |
17 | - </template> | |
18 | - <div class="ml-8">function Transform(msg, metadata) {</div> | |
19 | - <div ref="aceRef" class="overflow-hidden"></div> | |
20 | - <div class="ml-7">}</div> | |
21 | - </Card> | |
22 | - <a-button type="primary" class="mt-4" @click="testTransformFunc">测试转换功能</a-button> | |
23 | - </template> | |
24 | - </BasicForm> | |
25 | - </BasicDrawer> | |
26 | - </div> | |
27 | -</template> | |
28 | - | |
29 | -<script lang="ts" setup> | |
30 | - import { ref, computed, unref } from 'vue'; | |
31 | - import { useDrawerInner, BasicDrawer } from '/@/components/Drawer/index'; | |
32 | - import { useForm, BasicForm } from '/@/components/Form/index'; | |
33 | - import { formSchema } from '../config/config.data'; | |
34 | - import { Card, Tag } from 'ant-design-vue'; | |
35 | - import { createOrEditTransformScriptApi } from '/@/api/device/TransformScriptApi'; | |
36 | - import { useMessage } from '/@/hooks/web/useMessage'; | |
37 | - import ace from 'ace-builds'; | |
38 | - import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题 | |
39 | - import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式 | |
40 | - import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js'; | |
41 | - | |
42 | - const emit = defineEmits(['register', 'isStatus', 'success']); | |
43 | - const isUpdate: any = ref(false); | |
44 | - const isView = ref(true); | |
45 | - const aceEditor = ref(); | |
46 | - const aceRef = ref(); | |
47 | - const getTitle = computed(() => (isUpdate.value ? '编辑转换脚本' : '新增转换脚本')); | |
48 | - const editId = ref(''); | |
49 | - const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { | |
50 | - resetFields(); | |
51 | - setDrawerProps({ confirmLoading: false }); | |
52 | - isUpdate.value = data.isUpdate; | |
53 | - initEditor(data.record?.configuration.jsScript); | |
54 | - switch (isUpdate.value) { | |
55 | - case 'view': | |
56 | - isView.value = false; | |
57 | - setDrawerProps({ | |
58 | - showFooter: unref(isView), | |
59 | - title: '查看转换脚本', | |
60 | - loading: false, | |
61 | - }); | |
62 | - editId.value = data.record.id; | |
63 | - setFieldsValue(data.record); | |
64 | - break; | |
65 | - case true: | |
66 | - isView.value = true; | |
67 | - setDrawerProps({ | |
68 | - showFooter: unref(isView), | |
69 | - title: '编辑转换脚本', | |
70 | - loading: false, | |
71 | - }); | |
72 | - editId.value = data.record.id; | |
73 | - setFieldsValue(data.record); | |
74 | - break; | |
75 | - case false: | |
76 | - isView.value = true; | |
77 | - setDrawerProps({ | |
78 | - showFooter: unref(isView), | |
79 | - title: '新增转换脚本', | |
80 | - loading: false, | |
81 | - }); | |
82 | - break; | |
83 | - } | |
84 | - }); | |
85 | - const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({ | |
86 | - showActionButtonGroup: false, | |
87 | - colProps: { span: 24 }, | |
88 | - schemas: formSchema, | |
89 | - }); | |
90 | - | |
91 | - // 初始化编辑器 | |
92 | - const initEditor = (jsScript?: string) => { | |
93 | - aceEditor.value = ace.edit(aceRef.value, { | |
94 | - maxLines: 12, // 最大行数,超过会自动出现滚动条 | |
95 | - minLines: 12, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小 | |
96 | - fontSize: 14, // 编辑器内字体大小 | |
97 | - theme: 'ace/theme/chrome', // 默认设置的主题 | |
98 | - mode: 'ace/mode/javascript', // 默认设置的语言模式 | |
99 | - tabSize: 2, // 制表符设置为 4 个空格大小 | |
100 | - }); | |
101 | - | |
102 | - aceEditor.value.setOptions({ | |
103 | - enableBasicAutocompletion: true, | |
104 | - enableLiveAutocompletion: true, | |
105 | - }); | |
106 | - aceEditor.value.setValue(jsScript ?? 'return {msg: msg, metadata: metadata};'); | |
107 | - beautify(aceEditor.value.session); | |
108 | - }; | |
109 | - | |
110 | - const testTransformFunc = () => { | |
111 | - closeDrawer(); | |
112 | - const jsCode = aceEditor.value.getValue(); | |
113 | - emit('isStatus', { status: 1, jsCode }); | |
114 | - }; | |
115 | - const handleSubmit = async () => { | |
116 | - const editIdPost = isUpdate.value ? { id: editId.value } : {}; | |
117 | - try { | |
118 | - setDrawerProps({ confirmLoading: true }); | |
119 | - const fieldsValue = await validate(); | |
120 | - if (!fieldsValue) return; | |
121 | - await createOrEditTransformScriptApi({ | |
122 | - configuration: { | |
123 | - jsScript: aceEditor.value.getValue(), | |
124 | - }, | |
125 | - type: 'org.thingsboard.rule.engine.transform.TbTransformMsgNode', | |
126 | - ...fieldsValue, | |
127 | - ...editIdPost, | |
128 | - }); | |
129 | - closeDrawer(); | |
130 | - emit('success'); | |
131 | - const { createMessage } = useMessage(); | |
132 | - createMessage.success('保存成功'); | |
133 | - } catch (e) { | |
134 | - } finally { | |
135 | - setTimeout(() => { | |
136 | - setDrawerProps({ confirmLoading: false }); | |
137 | - }, 300); | |
138 | - } | |
139 | - }; | |
140 | - const handleFormat = () => { | |
141 | - beautify(aceEditor.value.session); | |
142 | - }; | |
143 | - defineExpose({ aceEditor }); | |
144 | -</script> | |
1 | +<template> | |
2 | + <div> | |
3 | + <BasicDrawer | |
4 | + v-bind="$attrs" | |
5 | + :title="getTitle" | |
6 | + @register="register" | |
7 | + width="500px" | |
8 | + @ok="handleSubmit" | |
9 | + showFooter | |
10 | + > | |
11 | + <BasicForm @register="registerForm"> | |
12 | + <template #function> | |
13 | + <Card title="转换函数" :bodyStyle="{ padding: 0, height: '280px' }"> | |
14 | + <template #extra> | |
15 | + <Tag color="blue">Transform Function</Tag> | |
16 | + <a-button @click="handleFormat" size="small">格式化</a-button> | |
17 | + </template> | |
18 | + <div class="ml-8">function Transform(msg, metadata) {</div> | |
19 | + <div ref="aceRef" class="overflow-hidden"></div> | |
20 | + <div class="ml-7">}</div> | |
21 | + </Card> | |
22 | + <a-button type="primary" class="mt-4" @click="testTransformFunc">测试转换功能</a-button> | |
23 | + </template> | |
24 | + </BasicForm> | |
25 | + </BasicDrawer> | |
26 | + </div> | |
27 | +</template> | |
28 | + | |
29 | +<script lang="ts" setup> | |
30 | + import { ref, computed, unref } from 'vue'; | |
31 | + import { useDrawerInner, BasicDrawer } from '/@/components/Drawer/index'; | |
32 | + import { useForm, BasicForm } from '/@/components/Form/index'; | |
33 | + import { formSchema } from '../config/config.data'; | |
34 | + import { Card, Tag } from 'ant-design-vue'; | |
35 | + import { createOrEditTransformScriptApi } from '/@/api/device/TransformScriptApi'; | |
36 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
37 | + import ace from 'ace-builds'; | |
38 | + import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题 | |
39 | + import 'ace-builds/src-noconflict/theme-terminal'; // 默认设置的主题 | |
40 | + import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式 | |
41 | + import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js'; | |
42 | + import { useAppStore } from '/@/store/modules/app'; | |
43 | + | |
44 | + const emit = defineEmits(['register', 'isStatus', 'success']); | |
45 | + const userStore = useAppStore(); | |
46 | + const getAceClass = computed((): string => userStore.getDarkMode); | |
47 | + const isUpdate: any = ref(false); | |
48 | + const isView = ref(true); | |
49 | + const aceEditor = ref(); | |
50 | + const aceRef = ref(); | |
51 | + const getTitle = computed(() => (isUpdate.value ? '编辑转换脚本' : '新增转换脚本')); | |
52 | + const editId = ref(''); | |
53 | + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { | |
54 | + resetFields(); | |
55 | + setDrawerProps({ confirmLoading: false }); | |
56 | + isUpdate.value = data.isUpdate; | |
57 | + initEditor(data.record?.configuration.jsScript); | |
58 | + switch (isUpdate.value) { | |
59 | + case 'view': | |
60 | + isView.value = false; | |
61 | + setDrawerProps({ | |
62 | + showFooter: unref(isView), | |
63 | + title: '查看转换脚本', | |
64 | + loading: false, | |
65 | + }); | |
66 | + editId.value = data.record.id; | |
67 | + setFieldsValue(data.record); | |
68 | + break; | |
69 | + case true: | |
70 | + isView.value = true; | |
71 | + setDrawerProps({ | |
72 | + showFooter: unref(isView), | |
73 | + title: '编辑转换脚本', | |
74 | + loading: false, | |
75 | + }); | |
76 | + editId.value = data.record.id; | |
77 | + setFieldsValue(data.record); | |
78 | + break; | |
79 | + case false: | |
80 | + isView.value = true; | |
81 | + setDrawerProps({ | |
82 | + showFooter: unref(isView), | |
83 | + title: '新增转换脚本', | |
84 | + loading: false, | |
85 | + }); | |
86 | + break; | |
87 | + } | |
88 | + }); | |
89 | + const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({ | |
90 | + showActionButtonGroup: false, | |
91 | + colProps: { span: 24 }, | |
92 | + schemas: formSchema, | |
93 | + }); | |
94 | + | |
95 | + // 初始化编辑器 | |
96 | + const initEditor = (jsScript?: string) => { | |
97 | + aceEditor.value = ace.edit(aceRef.value, { | |
98 | + maxLines: 12, // 最大行数,超过会自动出现滚动条 | |
99 | + minLines: 12, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小 | |
100 | + fontSize: 14, // 编辑器内字体大小 | |
101 | + theme: 'ace/theme/chrome', // 默认设置的主题 | |
102 | + mode: 'ace/mode/javascript', // 默认设置的语言模式 | |
103 | + tabSize: 2, // 制表符设置为 4 个空格大小 | |
104 | + }); | |
105 | + | |
106 | + aceEditor.value.setOptions({ | |
107 | + enableBasicAutocompletion: true, | |
108 | + enableLiveAutocompletion: true, | |
109 | + theme: getAceClass.value === 'dark' ? 'ace/theme/terminal' : 'ace/theme/chrome', | |
110 | + }); | |
111 | + aceEditor.value.setValue(jsScript ?? 'return {msg: msg, metadata: metadata};'); | |
112 | + beautify(aceEditor.value.session); | |
113 | + }; | |
114 | + | |
115 | + const testTransformFunc = () => { | |
116 | + closeDrawer(); | |
117 | + const jsCode = aceEditor.value.getValue(); | |
118 | + emit('isStatus', { status: 1, jsCode }); | |
119 | + }; | |
120 | + const handleSubmit = async () => { | |
121 | + const editIdPost = isUpdate.value ? { id: editId.value } : {}; | |
122 | + try { | |
123 | + setDrawerProps({ confirmLoading: true }); | |
124 | + const fieldsValue = await validate(); | |
125 | + if (!fieldsValue) return; | |
126 | + await createOrEditTransformScriptApi({ | |
127 | + configuration: { | |
128 | + jsScript: aceEditor.value.getValue(), | |
129 | + }, | |
130 | + type: 'org.thingsboard.rule.engine.transform.TbTransformMsgNode', | |
131 | + ...fieldsValue, | |
132 | + ...editIdPost, | |
133 | + }); | |
134 | + closeDrawer(); | |
135 | + emit('success'); | |
136 | + const { createMessage } = useMessage(); | |
137 | + createMessage.success('保存成功'); | |
138 | + } catch (e) { | |
139 | + } finally { | |
140 | + setTimeout(() => { | |
141 | + setDrawerProps({ confirmLoading: false }); | |
142 | + }, 300); | |
143 | + } | |
144 | + }; | |
145 | + const handleFormat = () => { | |
146 | + beautify(aceEditor.value.session); | |
147 | + }; | |
148 | + defineExpose({ aceEditor }); | |
149 | +</script> | ... | ... |
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 | - v-model:value="scriptForm.name" | |
20 | - placeholder="请输入脚本名称" | |
21 | - /> | |
22 | - <a-input | |
23 | - @change="handleInputChange" | |
24 | - v-else | |
25 | - v-model:value="scriptForm.params" | |
26 | - placeholder="请输入参数" | |
27 | - /> | |
28 | - </a-form-item> | |
29 | - <a-form-item | |
30 | - label="上报数据类型" | |
31 | - name="dataType" | |
32 | - :rules="[{ required: true, message: '请选择上报数据类型' }]" | |
33 | - > | |
34 | - <a-space direction="vertical"> | |
35 | - <a-radio-group v-model:value="scriptForm.dataType" :options="typeOptions" /> | |
36 | - </a-space> | |
37 | - </a-form-item> | |
38 | - <a-form-item | |
39 | - label="保存原始数据" | |
40 | - name="saveOriginalData" | |
41 | - :rules="[{ required: true, message: '请选择保存原始数据' }]" | |
42 | - > | |
43 | - <a-space direction="vertical"> | |
44 | - <a-radio-group v-model:value="scriptForm.saveOriginalData" :options="originalOptions" /> | |
45 | - </a-space> | |
46 | - </a-form-item> | |
47 | - <a-form-item label="脚本内容" :name="ifAdd ? 'convertJs' : 'script'"> | |
48 | - <Card title="脚本内容" :bodyStyle="{ padding: 0, height: '280px' }"> | |
49 | - <template #extra> | |
50 | - <a-button @click="handleFormat" size="small">格式化</a-button> | |
51 | - <Tooltip :title="defaultTitle" class="ml-2"> | |
52 | - <QuestionCircleOutlined style="font-size: 1rem" /> | |
53 | - </Tooltip> | |
54 | - </template> | |
55 | - <div ref="aceRef" class="overflow-hidden"></div> | |
56 | - </Card> | |
57 | - <Button @click="handleCopy" class="mt-4"> | |
58 | - <template #icon> | |
59 | - <CopyOutlined /> | |
60 | - </template> | |
61 | - copy | |
62 | - </Button> | |
63 | - </a-form-item> | |
64 | - <a-form-item | |
65 | - :label="ifAdd ? '备注' : '输出参数(output)'" | |
66 | - :name="ifAdd ? 'description' : 'output'" | |
67 | - > | |
68 | - <a-textarea | |
69 | - :rows="3" | |
70 | - v-if="ifAdd" | |
71 | - v-model:value="scriptForm.description" | |
72 | - placeholder="请输入备注" | |
73 | - :maxlength="255" | |
74 | - /> | |
75 | - <a-textarea | |
76 | - :rows="3" | |
77 | - v-else | |
78 | - v-model:value="scriptForm.output" | |
79 | - placeholder="输出参数为服务端返回的内容" | |
80 | - :maxlength="255" | |
81 | - /> | |
82 | - </a-form-item> | |
83 | - </a-form> | |
84 | - </div> | |
85 | -</template> | |
86 | -<script setup lang="ts"> | |
87 | - import { ref, unref, reactive, onMounted, toRefs, nextTick } from 'vue'; | |
88 | - import ace from 'ace-builds'; | |
89 | - import { Card, Button, Tooltip } from 'ant-design-vue'; | |
90 | - import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题 | |
91 | - import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式 | |
92 | - import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js'; | |
93 | - import { CopyOutlined } from '@ant-design/icons-vue'; | |
94 | - import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; | |
95 | - import { useMessage } from '/@/hooks/web/useMessage'; | |
96 | - import { findDictItemByCode } from '/@/api/system/dict'; | |
97 | - import { QuestionCircleOutlined } from '@ant-design/icons-vue'; | |
98 | - import { defaultTitle } from './config.data'; | |
99 | - | |
100 | - defineEmits(['register']); | |
101 | - const props = defineProps({ | |
102 | - ifAdd: { type: Boolean, default: true }, | |
103 | - }); | |
104 | - const scriptForm = reactive({ | |
105 | - name: '', | |
106 | - description: '', | |
107 | - convertJs: '', | |
108 | - script: '', | |
109 | - params: '', | |
110 | - output: '', | |
111 | - dataType: 'HEX', | |
112 | - saveOriginalData: 'true', | |
113 | - }); | |
114 | - const reportTypeOptions = reactive({ | |
115 | - typeOptions: [], | |
116 | - originalOptions: [], | |
117 | - }); | |
118 | - const { originalOptions, typeOptions } = toRefs(reportTypeOptions); | |
119 | - const { createMessage } = useMessage(); | |
120 | - const { clipboardRef, copiedRef } = useCopyToClipboard(); | |
121 | - const aceEditor = ref(); | |
122 | - const aceRef = ref(); | |
123 | - const setDefaultRadio = (p1, p2) => { | |
124 | - scriptForm.dataType = p1; | |
125 | - scriptForm.saveOriginalData = p2; | |
126 | - }; | |
127 | - onMounted(async () => { | |
128 | - const res: any = await findDictItemByCode({ | |
129 | - dictCode: 'report_data_type', | |
130 | - }); | |
131 | - const resOriginal: any = await findDictItemByCode({ | |
132 | - dictCode: 'original_data', | |
133 | - }); | |
134 | - reportTypeOptions.typeOptions = res.map((m) => { | |
135 | - return { label: m.itemText, value: m.itemValue }; | |
136 | - }); | |
137 | - reportTypeOptions.originalOptions = resOriginal.map((m) => { | |
138 | - return { label: m.itemText, value: m.itemValue }; | |
139 | - }); | |
140 | - }); | |
141 | - // 初始化编辑器 | |
142 | - const initEditor = () => { | |
143 | - aceEditor.value = ace.edit(aceRef.value, { | |
144 | - maxLines: 12, // 最大行数,超过会自动出现滚动条 | |
145 | - minLines: 12, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小 | |
146 | - fontSize: 14, // 编辑器内字体大小 | |
147 | - theme: 'ace/theme/chrome', // 默认设置的主题 | |
148 | - mode: 'ace/mode/javascript', // 默认设置的语言模式 | |
149 | - tabSize: 2, // 制表符设置为 4 个空格大小 | |
150 | - }); | |
151 | - | |
152 | - aceEditor.value.setOptions({ | |
153 | - enableBasicAutocompletion: true, | |
154 | - enableLiveAutocompletion: true, | |
155 | - }); | |
156 | - aceEditor.value.setValue(''); | |
157 | - beautify(aceEditor.value.session); | |
158 | - // scriptForm.convertJs = aceEditor.value.getValue(); | |
159 | - }; | |
160 | - const handleCopy = () => { | |
161 | - const valueRef = aceEditor.value.getValue(); | |
162 | - const value = unref(valueRef); | |
163 | - if (!value) { | |
164 | - createMessage.warning('请输入要拷贝的内容!'); | |
165 | - return; | |
166 | - } | |
167 | - clipboardRef.value = value; | |
168 | - if (unref(copiedRef)) { | |
169 | - createMessage.success('复制成功!'); | |
170 | - } | |
171 | - }; | |
172 | - const formRef = ref(); | |
173 | - const getFormData = async () => { | |
174 | - const value = await formRef.value.validateFields(); | |
175 | - if (props.ifAdd) { | |
176 | - scriptForm.convertJs = aceEditor.value.getValue(); | |
177 | - if (scriptForm.convertJs == '') { | |
178 | - createMessage.error('请编写脚本内容'); | |
179 | - throw '请编写脚本内容'; | |
180 | - } | |
181 | - } else { | |
182 | - scriptForm.script = aceEditor.value.getValue(); | |
183 | - if (scriptForm.script == '') { | |
184 | - createMessage.error('请编写脚本内容'); | |
185 | - throw '请编写脚本内容'; | |
186 | - } | |
187 | - } | |
188 | - if (!value) return; | |
189 | - if (scriptForm.params) { | |
190 | - const trimParams = scriptForm.params.replace(/\s*/g, ''); | |
191 | - Reflect.set(value, 'params', trimParams); | |
192 | - } | |
193 | - if (scriptForm.convertJs.length > 1000) { | |
194 | - createMessage.error('脚本内容长度不能大于1000'); | |
195 | - throw '脚本内容长度不能大于1000'; | |
196 | - } | |
197 | - return { | |
198 | - ...value, | |
199 | - ...{ convertJs: props.ifAdd ? scriptForm.convertJs : null }, | |
200 | - ...{ script: !props.ifAdd ? scriptForm.script : null }, | |
201 | - ...{ saveOriginalData: scriptForm.saveOriginalData === 'false' ? false : true }, | |
202 | - }; | |
203 | - }; | |
204 | - const handleInputChange = (e) => { | |
205 | - const trimParams = e.target.value.replace(/\s*/g, ''); | |
206 | - Reflect.set(scriptForm, 'params', trimParams); | |
207 | - }; | |
208 | - const setFormData = (v) => { | |
209 | - if (v) { | |
210 | - for (let i in scriptForm) { | |
211 | - Reflect.set(scriptForm, i, v[i]); | |
212 | - } | |
213 | - nextTick(() => { | |
214 | - setTimeout(() => { | |
215 | - scriptForm.saveOriginalData = v.saveOriginalData === false ? 'false' : 'true'; | |
216 | - scriptForm.dataType = v.dataType; | |
217 | - }, 10); | |
218 | - }); | |
219 | - aceEditor.value.setValue(v.convertJs); | |
220 | - handleFormat(); | |
221 | - } | |
222 | - }; | |
223 | - const setScriptContentData = (v) => { | |
224 | - aceEditor.value.setValue(v); | |
225 | - handleFormat(); | |
226 | - }; | |
227 | - const resetFormData = () => { | |
228 | - for (let i in scriptForm) { | |
229 | - Reflect.set(scriptForm, i, ''); | |
230 | - } | |
231 | - }; | |
232 | - const setScriptOutputData = (v) => { | |
233 | - scriptForm.output = v; | |
234 | - }; | |
235 | - const handleFormat = () => beautify(aceEditor.value.session); | |
236 | - | |
237 | - defineExpose({ | |
238 | - initEditor, | |
239 | - getFormData, | |
240 | - resetFormData, | |
241 | - setFormData, | |
242 | - setScriptContentData, | |
243 | - setScriptOutputData, | |
244 | - setDefaultRadio, | |
245 | - }); | |
246 | -</script> | |
247 | -<style lang="less" scoped> | |
248 | - @import url('./ConverScriptModal.less'); | |
249 | -</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 | |
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="dataType" | |
33 | + :rules="[{ required: false, message: '请选择上报数据类型' }]" | |
34 | + > | |
35 | + <a-space direction="vertical"> | |
36 | + <a-radio-group v-model:value="scriptForm.dataType" :options="typeOptions" /> | |
37 | + </a-space> | |
38 | + </a-form-item> | |
39 | + <a-form-item | |
40 | + label="脚本类型" | |
41 | + name="scriptType" | |
42 | + :rules="[{ required: true, message: '请选择脚本类型' }]" | |
43 | + > | |
44 | + <a-space direction="vertical"> | |
45 | + <a-radio-group | |
46 | + @change="handleScriptType" | |
47 | + v-model:value="scriptForm.scriptType" | |
48 | + :options="scriptTypeOptions" | |
49 | + /> | |
50 | + </a-space> | |
51 | + </a-form-item> | |
52 | + <a-form-item | |
53 | + label="保存原始数据" | |
54 | + name="saveOriginalData" | |
55 | + :rules="[{ required: true, message: '请选择保存原始数据' }]" | |
56 | + > | |
57 | + <a-space direction="vertical"> | |
58 | + <a-radio-group v-model:value="scriptForm.saveOriginalData" :options="originalOptions" /> | |
59 | + </a-space> | |
60 | + </a-form-item> | |
61 | + <a-form-item label="脚本内容" :name="ifAdd ? 'convertJs' : 'script'"> | |
62 | + <Card title="脚本内容" :bodyStyle="{ padding: 0, height: '280px' }"> | |
63 | + <template #extra> | |
64 | + <a-button @click="handleFormat" size="small">格式化</a-button> | |
65 | + <Tooltip :title="defaultTitle" class="ml-2"> | |
66 | + <QuestionCircleOutlined style="font-size: 1rem" /> | |
67 | + </Tooltip> | |
68 | + </template> | |
69 | + {{ getAceClass }} | |
70 | + <div ref="aceRef" class="overflow-hidden"></div> | |
71 | + </Card> | |
72 | + <Button @click="handleCopy" class="mt-4"> | |
73 | + <template #icon> | |
74 | + <CopyOutlined /> | |
75 | + </template> | |
76 | + copy | |
77 | + </Button> | |
78 | + </a-form-item> | |
79 | + <a-form-item | |
80 | + :label="ifAdd ? '备注' : '输出参数(output)'" | |
81 | + :name="ifAdd ? 'description' : 'output'" | |
82 | + > | |
83 | + <a-textarea | |
84 | + :rows="3" | |
85 | + v-if="ifAdd" | |
86 | + v-model:value="scriptForm.description" | |
87 | + placeholder="请输入备注" | |
88 | + :maxlength="255" | |
89 | + /> | |
90 | + <a-textarea | |
91 | + :rows="3" | |
92 | + v-else | |
93 | + v-model:value="scriptForm.output" | |
94 | + placeholder="输出参数为服务端返回的内容" | |
95 | + :maxlength="255" | |
96 | + /> | |
97 | + </a-form-item> | |
98 | + </a-form> | |
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 { defaultTitle, defaultScriptTypeContent } from './config.data'; | |
115 | + import { useAppStore } from '/@/store/modules/app'; | |
116 | + | |
117 | + defineEmits(['register']); | |
118 | + const props = defineProps({ | |
119 | + ifAdd: { type: Boolean, default: true }, | |
120 | + }); | |
121 | + | |
122 | + const scriptForm = reactive({ | |
123 | + name: '', | |
124 | + description: '', | |
125 | + convertJs: '', | |
126 | + script: '', | |
127 | + params: '', | |
128 | + output: '', | |
129 | + dataType: 'HEX', | |
130 | + scriptType: 'TRANSPORT_TCP_UP', | |
131 | + saveOriginalData: 'true', | |
132 | + }); | |
133 | + | |
134 | + const reportTypeOptions = reactive({ | |
135 | + typeOptions: [], | |
136 | + originalOptions: [], | |
137 | + scriptTypeOptions: [], | |
138 | + }); | |
139 | + | |
140 | + const { originalOptions, typeOptions, scriptTypeOptions } = toRefs(reportTypeOptions); | |
141 | + | |
142 | + const { createMessage } = useMessage(); | |
143 | + | |
144 | + const { clipboardRef, copiedRef } = useCopyToClipboard(); | |
145 | + | |
146 | + const aceEditor = ref(); | |
147 | + | |
148 | + const aceRef = ref(); | |
149 | + | |
150 | + const userStore = useAppStore(); | |
151 | + | |
152 | + const getAceClass = computed((): string => userStore.getDarkMode); | |
153 | + | |
154 | + const setDefaultRadio = (p1, p2, p3) => { | |
155 | + scriptForm.dataType = p1; | |
156 | + scriptForm.saveOriginalData = p2; | |
157 | + scriptForm.scriptType = p3; | |
158 | + }; | |
159 | + | |
160 | + const getDictValue = async (dict_type) => { | |
161 | + const res = await findDictItemByCode({ | |
162 | + dictCode: dict_type, | |
163 | + }); | |
164 | + return res.map((m) => { | |
165 | + return { label: m.itemText, value: m.itemValue }; | |
166 | + }); | |
167 | + }; | |
168 | + | |
169 | + onMounted(async () => { | |
170 | + reportTypeOptions.typeOptions = (await getDictValue('report_data_type')) as never as any; | |
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 | + if (type === 'TRANSPORT_TCP_DOWN') | |
203 | + Reflect.set( | |
204 | + defaultScriptTypeContent, | |
205 | + 'TRANSPORT_TCP_DOWN', | |
206 | + `out.datas = "${scriptForm.params}";out.deviceName = "sensor";` | |
207 | + ); | |
208 | + aceEditor.value.setValue(defaultScriptTypeContent[type]); | |
209 | + }; | |
210 | + | |
211 | + const handleCopy = () => { | |
212 | + const valueRef = aceEditor.value.getValue(); | |
213 | + const value = unref(valueRef); | |
214 | + if (!value) { | |
215 | + createMessage.warning('请输入要拷贝的内容!'); | |
216 | + return; | |
217 | + } | |
218 | + clipboardRef.value = value; | |
219 | + if (unref(copiedRef)) { | |
220 | + createMessage.success('复制成功!'); | |
221 | + } | |
222 | + }; | |
223 | + | |
224 | + const formRef = ref(); | |
225 | + | |
226 | + const getFormData = async () => { | |
227 | + const value = await formRef.value.validateFields(); | |
228 | + if (props.ifAdd) { | |
229 | + scriptForm.convertJs = aceEditor.value.getValue(); | |
230 | + if (scriptForm.convertJs == '') { | |
231 | + createMessage.error('请编写脚本内容'); | |
232 | + throw '请编写脚本内容'; | |
233 | + } | |
234 | + } else { | |
235 | + scriptForm.script = aceEditor.value.getValue(); | |
236 | + if (scriptForm.script == '') { | |
237 | + createMessage.error('请编写脚本内容'); | |
238 | + throw '请编写脚本内容'; | |
239 | + } | |
240 | + } | |
241 | + if (!value) return; | |
242 | + if (scriptForm.params) { | |
243 | + const trimParams = scriptForm.params.replace(/\s*/g, ''); | |
244 | + Reflect.set(value, 'params', trimParams); | |
245 | + } | |
246 | + if (scriptForm.convertJs.length > 1000) { | |
247 | + createMessage.error('脚本内容长度不能大于1000'); | |
248 | + throw '脚本内容长度不能大于1000'; | |
249 | + } | |
250 | + return { | |
251 | + ...value, | |
252 | + ...{ convertJs: props.ifAdd ? scriptForm.convertJs : null }, | |
253 | + ...{ script: !props.ifAdd ? scriptForm.script : null }, | |
254 | + ...{ saveOriginalData: scriptForm.saveOriginalData === 'false' ? false : true }, | |
255 | + }; | |
256 | + }; | |
257 | + | |
258 | + const handleInputChange = (e) => { | |
259 | + const trimParams = e.target.value.replace(/\s*/g, ''); | |
260 | + Reflect.set(scriptForm, 'params', trimParams); | |
261 | + if (scriptForm.scriptType === 'TRANSPORT_TCP_DOWN') { | |
262 | + aceEditor.value.setValue(`out.datas = "${scriptForm.params}";out.deviceName = "sensor";`); | |
263 | + } | |
264 | + }; | |
265 | + | |
266 | + const setFormData = (v) => { | |
267 | + if (v) { | |
268 | + for (let i in scriptForm) { | |
269 | + Reflect.set(scriptForm, i, v[i]); | |
270 | + } | |
271 | + nextTick(() => { | |
272 | + setTimeout(() => { | |
273 | + scriptForm.saveOriginalData = v.saveOriginalData === false ? 'false' : 'true'; | |
274 | + scriptForm.dataType = v.dataType; | |
275 | + }, 10); | |
276 | + }); | |
277 | + aceEditor.value.setValue(v.convertJs); | |
278 | + handleFormat(); | |
279 | + } | |
280 | + }; | |
281 | + | |
282 | + const setScriptContentData = (v) => { | |
283 | + aceEditor.value.setValue(v); | |
284 | + handleFormat(); | |
285 | + }; | |
286 | + | |
287 | + const resetFormData = () => { | |
288 | + for (let i in scriptForm) { | |
289 | + Reflect.set(scriptForm, i, ''); | |
290 | + } | |
291 | + }; | |
292 | + | |
293 | + const setScriptOutputData = (v) => { | |
294 | + scriptForm.output = v; | |
295 | + }; | |
296 | + | |
297 | + const handleFormat = () => beautify(aceEditor.value.session); | |
298 | + | |
299 | + defineExpose({ | |
300 | + initEditor, | |
301 | + getFormData, | |
302 | + resetFormData, | |
303 | + setFormData, | |
304 | + setScriptContentData, | |
305 | + setScriptOutputData, | |
306 | + setDefaultRadio, | |
307 | + }); | |
308 | +</script> | |
309 | +<style lang="less" scoped> | |
310 | + @import url('./ConverScriptModal.less'); | |
311 | +</style> | ... | ... |
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="isTest ? false : true" ref="converScriptRef" /> | |
14 | - </BasicModal> | |
15 | - </div> | |
16 | -</template> | |
17 | -<script setup lang="ts"> | |
18 | - import { ref, computed, unref, reactive } from 'vue'; | |
19 | - import { BasicModal, useModalInner } from '/@/components/Modal'; | |
20 | - import ConverScript from './ConverScript.vue'; | |
21 | - import { | |
22 | - createOrEditScriptManage, | |
23 | - getScriptManageDetail, | |
24 | - testScriptManage, | |
25 | - } from '/@/api/scriptmanage/scriptManager'; | |
26 | - import { useMessage } from '/@/hooks/web/useMessage'; | |
27 | - | |
28 | - const emits = defineEmits(['success', 'register']); | |
29 | - const { createMessage } = useMessage(); | |
30 | - const converScriptRef = ref<InstanceType<typeof ConverScript>>(); | |
31 | - const getTitle = computed(() => (isUpdate.value ? '编辑转换脚本' : '新增转换脚本')); | |
32 | - const isUpdate = ref(false); | |
33 | - const isViewDetail = ref(''); | |
34 | - const isTest = ref(false); | |
35 | - const isText = ref(''); | |
36 | - const isTitle = ref(''); | |
37 | - const editData = reactive({ | |
38 | - data: {}, | |
39 | - }); | |
40 | - const [register, { setModalProps, closeModal }] = useModalInner(async (data) => { | |
41 | - setModalProps({ loading: true }); | |
42 | - handleCancel(false); | |
43 | - isUpdate.value = data.isUpdate; | |
44 | - isViewDetail.value = data.isView; | |
45 | - isTest.value = data.isTest; | |
46 | - isText.value = data.isText; | |
47 | - isTitle.value = data.isTitle; | |
48 | - editData.data = data.record; | |
49 | - setModalProps({ loading: false }); | |
50 | - converScriptRef.value?.initEditor(); | |
51 | - if (!unref(isViewDetail)) { | |
52 | - const title = | |
53 | - unref(isTitle) == 'edit' | |
54 | - ? '编辑转换脚本' | |
55 | - : unref(isTitle) == 'add' | |
56 | - ? '新增转换脚本' | |
57 | - : '测试转换脚本'; | |
58 | - const okText = isText.value == 'test' ? '测试' : '确定'; | |
59 | - if (unref(isTitle) == 'add') { | |
60 | - converScriptRef.value?.setDefaultRadio('HEX', 'true'); | |
61 | - } | |
62 | - if (unref(isTitle) == 'edit') { | |
63 | - converScriptRef.value?.setFormData(data.record); | |
64 | - } | |
65 | - if (unref(isTitle) == 'test') { | |
66 | - if (data.record) { | |
67 | - const res = await getScriptManageDetail(data.record); | |
68 | - converScriptRef.value?.setFormData(res); | |
69 | - } else { | |
70 | - converScriptRef.value?.setDefaultRadio('HEX', 'true'); | |
71 | - } | |
72 | - } | |
73 | - setModalProps({ title, showOkBtn: true, showCancelBtn: true, okText }); | |
74 | - if (!unref(isUpdate)) { | |
75 | - } | |
76 | - } else { | |
77 | - setModalProps({ showOkBtn: false, showCancelBtn: false, title: '查看转换脚本' }); | |
78 | - const res = await getScriptManageDetail(data.record.id); | |
79 | - converScriptRef.value?.setFormData(res || {}); | |
80 | - } | |
81 | - }); | |
82 | - | |
83 | - const handleSubmit = async () => { | |
84 | - setModalProps({ confirmLoading: true }); | |
85 | - try { | |
86 | - const val = await converScriptRef.value?.getFormData(); | |
87 | - const tempObj = { | |
88 | - ...editData.data, | |
89 | - ...val, | |
90 | - }; | |
91 | - const res: any = | |
92 | - isText.value == 'test' | |
93 | - ? await testScriptManage(val) | |
94 | - : await createOrEditScriptManage(tempObj); | |
95 | - createMessage.success( | |
96 | - unref(isTitle) == 'edit' | |
97 | - ? '编辑转换脚本成功' | |
98 | - : unref(isTitle) == 'add' | |
99 | - ? '新增转换脚本成功' | |
100 | - : '测试转换脚本成功' | |
101 | - ); | |
102 | - if (unref(isTitle) == 'add' || unref(isTitle) == 'edit') { | |
103 | - setTimeout(() => { | |
104 | - closeModal(); | |
105 | - }, 10); | |
106 | - emits('success', { | |
107 | - res, | |
108 | - text: isText.value, | |
109 | - }); | |
110 | - } else { | |
111 | - if (res) { | |
112 | - converScriptRef.value?.setScriptOutputData(res?.output || res?.error); | |
113 | - } | |
114 | - } | |
115 | - } finally { | |
116 | - setModalProps({ confirmLoading: false }); | |
117 | - } | |
118 | - }; | |
119 | - const handleCancel = (flag) => { | |
120 | - if (flag) { | |
121 | - closeModal(); | |
122 | - } | |
123 | - converScriptRef.value?.resetFormData(); | |
124 | - }; | |
125 | -</script> | |
126 | -<style lang="less" scoped> | |
127 | - @import url('./ConverScriptModal.less'); | |
128 | -</style> | |
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="isTest ? false : true" ref="converScriptRef" /> | |
14 | + </BasicModal> | |
15 | + </div> | |
16 | +</template> | |
17 | +<script setup lang="ts"> | |
18 | + import { ref, computed, unref, reactive } from 'vue'; | |
19 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | |
20 | + import ConverScript from './ConverScript.vue'; | |
21 | + import { | |
22 | + createOrEditScriptManage, | |
23 | + getScriptManageDetail, | |
24 | + testScriptManage, | |
25 | + } from '/@/api/scriptmanage/scriptManager'; | |
26 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
27 | + | |
28 | + const emits = defineEmits(['success', 'register']); | |
29 | + const { createMessage } = useMessage(); | |
30 | + const converScriptRef = ref<InstanceType<typeof ConverScript>>(); | |
31 | + const getTitle = computed(() => (isUpdate.value ? '编辑转换脚本' : '新增转换脚本')); | |
32 | + const isUpdate = ref(false); | |
33 | + const isViewDetail = ref(''); | |
34 | + const isTest = ref(false); | |
35 | + const isText = ref(''); | |
36 | + const isTitle = ref(''); | |
37 | + const editData = reactive({ | |
38 | + data: {}, | |
39 | + }); | |
40 | + const [register, { setModalProps, closeModal }] = useModalInner(async (data) => { | |
41 | + setModalProps({ loading: true }); | |
42 | + handleCancel(false); | |
43 | + isUpdate.value = data.isUpdate; | |
44 | + isViewDetail.value = data.isView; | |
45 | + isTest.value = data.isTest; | |
46 | + isText.value = data.isText; | |
47 | + isTitle.value = data.isTitle; | |
48 | + editData.data = data.record; | |
49 | + setModalProps({ loading: false }); | |
50 | + converScriptRef.value?.initEditor(); | |
51 | + if (!unref(isViewDetail)) { | |
52 | + const title = | |
53 | + unref(isTitle) == 'edit' | |
54 | + ? '编辑转换脚本' | |
55 | + : unref(isTitle) == 'add' | |
56 | + ? '新增转换脚本' | |
57 | + : '测试转换脚本'; | |
58 | + const okText = isText.value == 'test' ? '测试' : '确定'; | |
59 | + if (unref(isTitle) == 'add') { | |
60 | + converScriptRef.value?.setDefaultRadio('HEX', 'true', 'TRANSPORT_TCP_UP'); | |
61 | + } | |
62 | + if (unref(isTitle) == 'edit') { | |
63 | + converScriptRef.value?.setFormData(data.record); | |
64 | + } | |
65 | + if (unref(isTitle) == 'test') { | |
66 | + if (data.record) { | |
67 | + const res = await getScriptManageDetail(data.record); | |
68 | + converScriptRef.value?.setFormData(res); | |
69 | + } else { | |
70 | + converScriptRef.value?.setDefaultRadio('HEX', 'true', 'TRANSPORT_TCP_UP'); | |
71 | + } | |
72 | + } | |
73 | + setModalProps({ title, showOkBtn: true, showCancelBtn: true, okText }); | |
74 | + if (!unref(isUpdate)) { | |
75 | + } | |
76 | + } else { | |
77 | + setModalProps({ showOkBtn: false, showCancelBtn: false, title: '查看转换脚本' }); | |
78 | + const res = await getScriptManageDetail(data.record.id); | |
79 | + converScriptRef.value?.setFormData(res || {}); | |
80 | + } | |
81 | + }); | |
82 | + | |
83 | + const handleSubmit = async () => { | |
84 | + setModalProps({ confirmLoading: true }); | |
85 | + try { | |
86 | + const val = await converScriptRef.value?.getFormData(); | |
87 | + const tempObj = { | |
88 | + ...editData.data, | |
89 | + ...val, | |
90 | + }; | |
91 | + const res: any = | |
92 | + isText.value == 'test' | |
93 | + ? await testScriptManage(val) | |
94 | + : await createOrEditScriptManage(tempObj); | |
95 | + createMessage.success( | |
96 | + unref(isTitle) == 'edit' | |
97 | + ? '编辑转换脚本成功' | |
98 | + : unref(isTitle) == 'add' | |
99 | + ? '新增转换脚本成功' | |
100 | + : '测试转换脚本成功' | |
101 | + ); | |
102 | + if (unref(isTitle) == 'add' || unref(isTitle) == 'edit') { | |
103 | + setTimeout(() => { | |
104 | + closeModal(); | |
105 | + }, 10); | |
106 | + emits('success', { | |
107 | + res, | |
108 | + text: isText.value, | |
109 | + }); | |
110 | + } else { | |
111 | + if (res) { | |
112 | + converScriptRef.value?.setScriptOutputData(res?.output || res?.error); | |
113 | + } | |
114 | + } | |
115 | + } finally { | |
116 | + setModalProps({ confirmLoading: false }); | |
117 | + } | |
118 | + }; | |
119 | + const handleCancel = (flag) => { | |
120 | + if (flag) { | |
121 | + closeModal(); | |
122 | + } | |
123 | + converScriptRef.value?.resetFormData(); | |
124 | + }; | |
125 | +</script> | |
126 | +<style lang="less" scoped> | |
127 | + @import url('./ConverScriptModal.less'); | |
128 | +</style> | ... | ... |
1 | -import { BasicColumn, FormSchema } from '/@/components/Table'; | |
2 | -import moment from 'moment'; | |
3 | -import { h } from 'vue'; | |
4 | - | |
5 | -// 表格配置 | |
6 | -export const columns: BasicColumn[] = [ | |
7 | - { | |
8 | - title: '脚本名称', | |
9 | - dataIndex: 'name', | |
10 | - width: 80, | |
11 | - }, | |
12 | - { | |
13 | - title: '脚本状态', | |
14 | - dataIndex: 'status', | |
15 | - width: 120, | |
16 | - slots: { customRender: 'status' }, | |
17 | - }, | |
18 | - { | |
19 | - title: '脚本内容', | |
20 | - dataIndex: 'convertJs', | |
21 | - width: 120, | |
22 | - slots: { customRender: 'convertJs' }, | |
23 | - }, | |
24 | - { | |
25 | - title: '备注', | |
26 | - dataIndex: 'description', | |
27 | - width: 120, | |
28 | - }, | |
29 | - { | |
30 | - title: '创建时间', | |
31 | - dataIndex: 'createTime', | |
32 | - width: 180, | |
33 | - }, | |
34 | -]; | |
35 | - | |
36 | -// 查询配置 | |
37 | -export const searchFormSchema: FormSchema[] = [ | |
38 | - { | |
39 | - field: 'name', | |
40 | - label: '脚本名称', | |
41 | - component: 'Input', | |
42 | - colProps: { span: 6 }, | |
43 | - componentProps: { | |
44 | - maxLength: 36, | |
45 | - placeholder: '请输入配置名称', | |
46 | - }, | |
47 | - }, | |
48 | - { | |
49 | - field: 'sendTime', | |
50 | - label: '创建时间', | |
51 | - component: 'RangePicker', | |
52 | - componentProps: { | |
53 | - showTime: { | |
54 | - defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')], | |
55 | - }, | |
56 | - }, | |
57 | - colProps: { span: 6 }, | |
58 | - }, | |
59 | -]; | |
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 | - ]), | |
80 | -]); | |
1 | +import { BasicColumn, FormSchema } from '/@/components/Table'; | |
2 | +import moment from 'moment'; | |
3 | +import { h } from 'vue'; | |
4 | + | |
5 | +// 表格配置 | |
6 | +export const columns: BasicColumn[] = [ | |
7 | + { | |
8 | + title: '脚本名称', | |
9 | + dataIndex: 'name', | |
10 | + width: 80, | |
11 | + }, | |
12 | + { | |
13 | + title: '脚本状态', | |
14 | + dataIndex: 'status', | |
15 | + width: 120, | |
16 | + slots: { customRender: 'status' }, | |
17 | + }, | |
18 | + { | |
19 | + title: '脚本内容', | |
20 | + dataIndex: 'convertJs', | |
21 | + width: 120, | |
22 | + slots: { customRender: 'convertJs' }, | |
23 | + }, | |
24 | + { | |
25 | + title: '备注', | |
26 | + dataIndex: 'description', | |
27 | + width: 120, | |
28 | + }, | |
29 | + { | |
30 | + title: '创建时间', | |
31 | + dataIndex: 'createTime', | |
32 | + width: 180, | |
33 | + }, | |
34 | +]; | |
35 | + | |
36 | +// 查询配置 | |
37 | +export const searchFormSchema: FormSchema[] = [ | |
38 | + { | |
39 | + field: 'name', | |
40 | + label: '脚本名称', | |
41 | + component: 'Input', | |
42 | + colProps: { span: 6 }, | |
43 | + componentProps: { | |
44 | + maxLength: 36, | |
45 | + placeholder: '请输入配置名称', | |
46 | + }, | |
47 | + }, | |
48 | + { | |
49 | + field: 'sendTime', | |
50 | + label: '创建时间', | |
51 | + component: 'RangePicker', | |
52 | + componentProps: { | |
53 | + showTime: { | |
54 | + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')], | |
55 | + }, | |
56 | + }, | |
57 | + colProps: { span: 6 }, | |
58 | + }, | |
59 | +]; | |
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 | + ]), | |
80 | +]); | |
81 | + | |
82 | +export const defaultScriptTypeContent = { | |
83 | + TRANSPORT_TCP_UP: | |
84 | + 'var attrData = {};var teleData = {};teleData.source= params;out.datas = teleData;out.telemetry =true;out.ackMsg = params;out.deviceName = "sensor";out.ts = Date.now();', | |
85 | + TRANSPORT_TCP_DOWN: 'out.datas = "";out.deviceName = "sensor";', | |
86 | + TRANSPORT_TCP_AUTH: 'out.password = params;out.success = params;', | |
87 | +}; | ... | ... |