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 | <template> | 1 | <template> | 
| 2 | - <div :class="prefixCls"> | 2 | + <div | 
| 3 | + :class="prefixCls" | ||
| 4 | + :style="{ backgroundColor: modeSwitch === 'dark' ? '#1f1f1f' : 'rgb(242, 242, 242)' }" | ||
| 5 | + > | ||
| 3 | <CollapseHeader | 6 | <CollapseHeader | 
| 4 | v-bind="$props" | 7 | v-bind="$props" | 
| 5 | :prefixCls="prefixCls" | 8 | :prefixCls="prefixCls" | 
| @@ -29,7 +32,7 @@ | @@ -29,7 +32,7 @@ | ||
| 29 | </template> | 32 | </template> | 
| 30 | <script lang="ts" setup> | 33 | <script lang="ts" setup> | 
| 31 | import type { PropType } from 'vue'; | 34 | import type { PropType } from 'vue'; | 
| 32 | - import { ref } from 'vue'; | 35 | + import { ref, computed } from 'vue'; | 
| 33 | // component | 36 | // component | 
| 34 | import { Skeleton } from 'ant-design-vue'; | 37 | import { Skeleton } from 'ant-design-vue'; | 
| 35 | import { CollapseTransition } from '/@/components/Transition'; | 38 | import { CollapseTransition } from '/@/components/Transition'; | 
| @@ -38,6 +41,7 @@ | @@ -38,6 +41,7 @@ | ||
| 38 | // hook | 41 | // hook | 
| 39 | import { useTimeoutFn } from '/@/hooks/core/useTimeout'; | 42 | import { useTimeoutFn } from '/@/hooks/core/useTimeout'; | 
| 40 | import { useDesign } from '/@/hooks/web/useDesign'; | 43 | import { useDesign } from '/@/hooks/web/useDesign'; | 
| 44 | + import { useAppStore } from '/@/store/modules/app'; | ||
| 41 | 45 | ||
| 42 | const props = defineProps({ | 46 | const props = defineProps({ | 
| 43 | isClose: { type: Boolean, default: true }, | 47 | isClose: { type: Boolean, default: true }, | 
| @@ -64,6 +68,11 @@ | @@ -64,6 +68,11 @@ | ||
| 64 | */ | 68 | */ | 
| 65 | lazyTime: { type: Number, default: 0 }, | 69 | lazyTime: { type: Number, default: 0 }, | 
| 66 | }); | 70 | }); | 
| 71 | + | ||
| 72 | + const userStore = useAppStore(); | ||
| 73 | + | ||
| 74 | + const modeSwitch = computed((): string => userStore.getDarkMode); | ||
| 75 | + | ||
| 67 | const emit = defineEmits(['expand', 'change', 'hchange']); | 76 | const emit = defineEmits(['expand', 'change', 'hchange']); | 
| 68 | 77 | ||
| 69 | const show = ref(true); | 78 | const show = ref(true); | 
| @@ -92,7 +101,7 @@ | @@ -92,7 +101,7 @@ | ||
| 92 | @prefix-cls: ~'@{namespace}-collapse-container'; | 101 | @prefix-cls: ~'@{namespace}-collapse-container'; | 
| 93 | 102 | ||
| 94 | .@{prefix-cls} { | 103 | .@{prefix-cls} { | 
| 95 | - background-color: @component-background; | 104 | + // background-color: @component-background; | 
| 96 | border-radius: 2px; | 105 | border-radius: 2px; | 
| 97 | transition: all 0.3s ease-in-out; | 106 | transition: all 0.3s ease-in-out; | 
| 98 | 107 | 
| @@ -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) => { | 
| @@ -132,7 +137,7 @@ | @@ -132,7 +137,7 @@ | ||
| 132 | element.value = ''; | 137 | element.value = ''; | 
| 133 | element.editDisabled = true; | 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 | ele.disabled = true; | 141 | ele.disabled = true; | 
| 137 | } | 142 | } | 
| 138 | }); | 143 | }); | 
| @@ -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 | ||
| @@ -132,13 +135,15 @@ | @@ -132,13 +135,15 @@ | ||
| 132 | element.value = ''; | 135 | element.value = ''; | 
| 133 | element.editDisabled = true; | 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 | ele.disabled = true; | 139 | ele.disabled = true; | 
| 137 | } | 140 | } | 
| 138 | }); | 141 | }); | 
| 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) => { | 
| @@ -31,6 +31,7 @@ | @@ -31,6 +31,7 @@ | ||
| 31 | import moment from 'moment'; | 31 | import moment from 'moment'; | 
| 32 | import { useUtils } from '../../../hooks/useUtils'; | 32 | import { useUtils } from '../../../hooks/useUtils'; | 
| 33 | import JsonEditor from '../../SimpleRequest/components/jsonEditor.vue'; | 33 | import JsonEditor from '../../SimpleRequest/components/jsonEditor.vue'; | 
| 34 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
| 34 | 35 | ||
| 35 | const emits = defineEmits(['testBodyInterface']); | 36 | const emits = defineEmits(['testBodyInterface']); | 
| 36 | 37 | ||
| @@ -40,6 +41,8 @@ | @@ -40,6 +41,8 @@ | ||
| 40 | }, | 41 | }, | 
| 41 | }); | 42 | }); | 
| 42 | 43 | ||
| 44 | + const { createMessage } = useMessage(); | ||
| 45 | + | ||
| 43 | const showTestEditCell = ref(false); | 46 | const showTestEditCell = ref(false); | 
| 44 | 47 | ||
| 45 | const excuteData = ref({}); | 48 | const excuteData = ref({}); | 
| @@ -63,13 +66,12 @@ | @@ -63,13 +66,12 @@ | ||
| 63 | const getValue = async () => { | 66 | const getValue = async () => { | 
| 64 | await nextTick(); | 67 | await nextTick(); | 
| 65 | await nextTick(() => { | 68 | await nextTick(() => { | 
| 66 | - console.log(props.data?.list); | ||
| 67 | if (props.data?.type === 'x-www-form-urlencoded' || props.data?.type === 'form-data') { | 69 | if (props.data?.type === 'x-www-form-urlencoded' || props.data?.type === 'form-data') { | 
| 68 | const getSingleKey = props.data?.list; | 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 | const getMuteKeys = getMultipleKeys(getMuteKey); | 72 | const getMuteKeys = getMultipleKeys(getMuteKey); | 
| 71 | const mergeKeys = [...getSingleKey, ...getMuteKeys]?.filter( | 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 | testEditCellTableRef.value?.setTableArray(mergeKeys); | 76 | testEditCellTableRef.value?.setTableArray(mergeKeys); | 
| 75 | } else if (props.data?.type === 'json') { | 77 | } else if (props.data?.type === 'json') { | 
| @@ -111,6 +113,7 @@ | @@ -111,6 +113,7 @@ | ||
| 111 | return { | 113 | return { | 
| 112 | key, | 114 | key, | 
| 113 | value, | 115 | value, | 
| 116 | + required: it.required, | ||
| 114 | }; | 117 | }; | 
| 115 | }); | 118 | }); | 
| 116 | }; | 119 | }; | 
| @@ -120,6 +123,11 @@ | @@ -120,6 +123,11 @@ | ||
| 120 | let params: any = {}; | 123 | let params: any = {}; | 
| 121 | if (props.data?.type === 'x-www-form-urlencoded' || props.data?.type === 'form-data') { | 124 | if (props.data?.type === 'x-www-form-urlencoded' || props.data?.type === 'form-data') { | 
| 122 | const getTable = getTestTableKeyValue(); | 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 | getTable?.map((it) => (params[it.key!] = it.value!)); | 131 | getTable?.map((it) => (params[it.key!] = it.value!)); | 
| 124 | } else if (props.data?.type === 'json') { | 132 | } else if (props.data?.type === 'json') { | 
| 125 | params = jsonEditorRef.value?.getJsonValue(); | 133 | params = jsonEditorRef.value?.getJsonValue(); | 
| @@ -228,6 +228,7 @@ | @@ -228,6 +228,7 @@ | ||
| 228 | }; | 228 | }; | 
| 229 | 229 | ||
| 230 | const getAttributeOptions = async (params) => { | 230 | const getAttributeOptions = async (params) => { | 
| 231 | + console.log(params); | ||
| 231 | const res = await getDeviceAttributes(params); | 232 | const res = await getDeviceAttributes(params); | 
| 232 | if (Object.keys(res).length === 0) return (attributeOptions.value.length = 0); | 233 | if (Object.keys(res).length === 0) return (attributeOptions.value.length = 0); | 
| 233 | attributeOptions.value = res?.map((item) => ({ label: item.name, value: item.identifier })); | 234 | attributeOptions.value = res?.map((item) => ({ label: item.name, value: item.identifier })); | 
| @@ -243,7 +244,9 @@ | @@ -243,7 +244,9 @@ | ||
| 243 | if (f.key === 'organizationId') organizationId = f.value; | 244 | if (f.key === 'organizationId') organizationId = f.value; | 
| 244 | if (f.key === 'entityId') f.value = null; | 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 | if (organizationId !== '') { | 250 | if (organizationId !== '') { | 
| 248 | getEntityOptions(organizationId, e.value); | 251 | getEntityOptions(organizationId, e.value); | 
| 249 | } | 252 | } | 
| @@ -261,6 +264,9 @@ | @@ -261,6 +264,9 @@ | ||
| 261 | </script> | 264 | </script> | 
| 262 | 265 | ||
| 263 | <style scoped lang="less"> | 266 | <style scoped lang="less"> | 
| 267 | + :deep(.ant-select-selector) { | ||
| 268 | + max-width: 16vw; | ||
| 269 | + } | ||
| 264 | @table-color: #e5e7eb; | 270 | @table-color: #e5e7eb; | 
| 265 | 271 | ||
| 266 | .table-border-color { | 272 | .table-border-color { | 
| @@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
| 36 | import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; | 36 | import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; | 
| 37 | import { getAuthCache } from '/@/utils/auth'; | 37 | import { getAuthCache } from '/@/utils/auth'; | 
| 38 | import { useMessage } from '/@/hooks/web/useMessage'; | 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 | ||
| @@ -56,8 +56,6 @@ | @@ -56,8 +56,6 @@ | ||
| 56 | 56 | ||
| 57 | const socketUrls = ref(''); | 57 | const socketUrls = ref(''); | 
| 58 | 58 | ||
| 59 | - // const { socketUrl } = useGlobSetting(); | ||
| 60 | - | ||
| 61 | const socketMessage: any = reactive({ | 59 | const socketMessage: any = reactive({ | 
| 62 | server: ``, | 60 | server: ``, | 
| 63 | sendValue: { | 61 | sendValue: { | 
| @@ -152,7 +150,7 @@ | @@ -152,7 +150,7 @@ | ||
| 152 | apiUrl, | 150 | apiUrl, | 
| 153 | headers = {}, | 151 | headers = {}, | 
| 154 | params = {}, | 152 | params = {}, | 
| 155 | - body, | 153 | + body = {}, | 
| 156 | joinPrefix = false | 154 | joinPrefix = false | 
| 157 | ) => { | 155 | ) => { | 
| 158 | switch (apiType) { | 156 | switch (apiType) { | 
| @@ -165,8 +163,9 @@ | @@ -165,8 +163,9 @@ | ||
| 165 | } | 163 | } | 
| 166 | ); | 164 | ); | 
| 167 | case 'POST': | 165 | case 'POST': | 
| 166 | + const { convertObj } = useUtils(); | ||
| 168 | return await otherHttp.post( | 167 | return await otherHttp.post( | 
| 169 | - { url: apiUrl, data: body, headers, params }, | 168 | + { url: `${apiUrl}?${convertObj(params)}`, data: body, headers }, | 
| 170 | { | 169 | { | 
| 171 | apiUrl: '', | 170 | apiUrl: '', | 
| 172 | joinPrefix, | 171 | joinPrefix, | 
| @@ -20,6 +20,7 @@ | @@ -20,6 +20,7 @@ | ||
| 20 | import { ref, nextTick } from 'vue'; | 20 | import { ref, nextTick } from 'vue'; | 
| 21 | import { Button } from 'ant-design-vue'; | 21 | import { Button } from 'ant-design-vue'; | 
| 22 | import TestHeaderEditCellTable from './testEditHeaderCellTable.vue'; | 22 | import TestHeaderEditCellTable from './testEditHeaderCellTable.vue'; | 
| 23 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
| 23 | 24 | ||
| 24 | const emits = defineEmits(['testHeaderInterface']); | 25 | const emits = defineEmits(['testHeaderInterface']); | 
| 25 | 26 | ||
| @@ -29,6 +30,8 @@ | @@ -29,6 +30,8 @@ | ||
| 29 | }, | 30 | }, | 
| 30 | }); | 31 | }); | 
| 31 | 32 | ||
| 33 | + const { createMessage } = useMessage(); | ||
| 34 | + | ||
| 32 | const showTestEditCell = ref(false); | 35 | const showTestEditCell = ref(false); | 
| 33 | 36 | ||
| 34 | const excuteData = ref({}); | 37 | const excuteData = ref({}); | 
| @@ -59,6 +62,11 @@ | @@ -59,6 +62,11 @@ | ||
| 59 | //获取数据 | 62 | //获取数据 | 
| 60 | const getTestValue = () => { | 63 | const getTestValue = () => { | 
| 61 | const getTable = getTestTableKeyValue(); | 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 | const params: any = {}; | 70 | const params: any = {}; | 
| 63 | getTable?.map((it: any) => (params[it.key!] = it.value!)); | 71 | getTable?.map((it: any) => (params[it.key!] = it.value!)); | 
| 64 | excuteData.value = { | 72 | excuteData.value = { | 
| @@ -22,6 +22,7 @@ | @@ -22,6 +22,7 @@ | ||
| 22 | import TestParamsCellTable from './testEditParamsCellTable.vue'; | 22 | import TestParamsCellTable from './testEditParamsCellTable.vue'; | 
| 23 | import moment from 'moment'; | 23 | import moment from 'moment'; | 
| 24 | import { useUtils } from '../../../hooks/useUtils'; | 24 | import { useUtils } from '../../../hooks/useUtils'; | 
| 25 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
| 25 | 26 | ||
| 26 | const emits = defineEmits(['testParamsInterface']); | 27 | const emits = defineEmits(['testParamsInterface']); | 
| 27 | 28 | ||
| @@ -31,6 +32,8 @@ | @@ -31,6 +32,8 @@ | ||
| 31 | }, | 32 | }, | 
| 32 | }); | 33 | }); | 
| 33 | 34 | ||
| 35 | + const { createMessage } = useMessage(); | ||
| 36 | + | ||
| 34 | const showTestEditCell = ref(false); | 37 | const showTestEditCell = ref(false); | 
| 35 | 38 | ||
| 36 | const excuteData = ref({}); | 39 | const excuteData = ref({}); | 
| @@ -92,6 +95,7 @@ | @@ -92,6 +95,7 @@ | ||
| 92 | return { | 95 | return { | 
| 93 | key, | 96 | key, | 
| 94 | value, | 97 | value, | 
| 98 | + required: it.required, | ||
| 95 | }; | 99 | }; | 
| 96 | }); | 100 | }); | 
| 97 | }; | 101 | }; | 
| @@ -99,6 +103,11 @@ | @@ -99,6 +103,11 @@ | ||
| 99 | //获取数据 | 103 | //获取数据 | 
| 100 | const getTestValue = () => { | 104 | const getTestValue = () => { | 
| 101 | const getTable = getTestTableKeyValue(); | 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 | const params: any = {}; | 111 | const params: any = {}; | 
| 103 | getTable?.map((it) => (params[it.key!] = it.value!)); | 112 | getTable?.map((it) => (params[it.key!] = it.value!)); | 
| 104 | if (params['keys']) { | 113 | if (params['keys']) { | 
| @@ -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 | } | 
| @@ -5,9 +5,14 @@ export const useUtils = () => { | @@ -5,9 +5,14 @@ export const useUtils = () => { | ||
| 5 | list?.forEach((it) => { | 5 | list?.forEach((it) => { | 
| 6 | const keys = it.key.split(','); | 6 | const keys = it.key.split(','); | 
| 7 | const temp = keys.map((item) => { | 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 | obj.key = item; | 13 | obj.key = item; | 
| 10 | obj.value = item === 'scope' ? it.value : ''; | 14 | obj.value = item === 'scope' ? it.value : ''; | 
| 15 | + obj.required = it.required; | ||
| 11 | return obj; | 16 | return obj; | 
| 12 | }); | 17 | }); | 
| 13 | temps = temp; | 18 | temps = temp; | 
| @@ -36,5 +41,20 @@ export const useUtils = () => { | @@ -36,5 +41,20 @@ export const useUtils = () => { | ||
| 36 | type: '0', | 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> | 1 | <template> | 
| 2 | <div> | 2 | <div> | 
| 3 | - <CollapseContainer style="background-color: #f2f2f2" :title="`${title} ${index + 1}`"> | 3 | + <CollapseContainer :title="`${title} ${index + 1}`"> | 
| 4 | <template #action> | 4 | <template #action> | 
| 5 | <div class="flex"> | 5 | <div class="flex"> | 
| 6 | <div class="flex"> | 6 | <div class="flex"> | 
| 1 | <template> | 1 | <template> | 
| 2 | - <CollapseContainer style="background-color: #f2f2f2" :title="`执行动作 ${actionIndex + 1}`"> | 2 | + <CollapseContainer :title="`执行动作 ${actionIndex + 1}`"> | 
| 3 | <template #action> | 3 | <template #action> | 
| 4 | <Tooltip title="移除" v-if="actionData.length > 1"> | 4 | <Tooltip title="移除" v-if="actionData.length > 1"> | 
| 5 | <Icon | 5 | <Icon | 
| 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 | +}; |