Showing
12 changed files
with
617 additions
and
13 deletions
@@ -39,6 +39,7 @@ | @@ -39,6 +39,7 @@ | ||
39 | "@logicflow/extension": "^0.6.9", | 39 | "@logicflow/extension": "^0.6.9", |
40 | "@vueuse/core": "^5.3.0", | 40 | "@vueuse/core": "^5.3.0", |
41 | "@zxcvbn-ts/core": "^1.0.0-beta.0", | 41 | "@zxcvbn-ts/core": "^1.0.0-beta.0", |
42 | + "ace-builds": "^1.4.14", | ||
42 | "ant-design-vue": "2.2.6", | 43 | "ant-design-vue": "2.2.6", |
43 | "axios": "^0.21.1", | 44 | "axios": "^0.21.1", |
44 | "codemirror": "^5.62.2", | 45 | "codemirror": "^5.62.2", |
@@ -60,12 +61,10 @@ | @@ -60,12 +61,10 @@ | ||
60 | "tinymce": "^5.8.2", | 61 | "tinymce": "^5.8.2", |
61 | "vditor": "^3.8.6", | 62 | "vditor": "^3.8.6", |
62 | "vue": "3.2.2", | 63 | "vue": "3.2.2", |
63 | - "vue-baidu-map": "^0.21.22", | ||
64 | "vue-i18n": "9.1.7", | 64 | "vue-i18n": "9.1.7", |
65 | "vue-json-pretty": "^2.0.4", | 65 | "vue-json-pretty": "^2.0.4", |
66 | "vue-router": "^4.0.11", | 66 | "vue-router": "^4.0.11", |
67 | "vue-types": "^4.0.3", | 67 | "vue-types": "^4.0.3", |
68 | - "vue3-ace-editor": "^2.2.2", | ||
69 | "xlsx": "^0.17.0" | 68 | "xlsx": "^0.17.0" |
70 | }, | 69 | }, |
71 | "devDependencies": { | 70 | "devDependencies": { |
src/api/device/TransformScriptApi.ts
0 → 100644
1 | +import { defHttp } from '/@/utils/http/axios'; | ||
2 | +import { TTransFormScriptParams } from './model/transformScriptModel'; | ||
3 | +enum TransformScriptApi { | ||
4 | + TransformScript_Page = '/convert', | ||
5 | + TransformScript_Delete_Edit = '/convert/js', | ||
6 | + TransformScript_ENABLE_OR_DISABLED = '/convert/update/js', | ||
7 | +} | ||
8 | + | ||
9 | +// 脚本转换分页查询 | ||
10 | +export const getConvertApi = (params: TTransFormScriptParams) => { | ||
11 | + return defHttp.get({ | ||
12 | + url: TransformScriptApi.TransformScript_Page, | ||
13 | + params: { | ||
14 | + ...params, | ||
15 | + nodeType: 0, | ||
16 | + }, | ||
17 | + }); | ||
18 | +}; | ||
19 | + | ||
20 | +export const deleteTransformApi = (ids: string[]) => { | ||
21 | + return defHttp.delete({ | ||
22 | + url: TransformScriptApi.TransformScript_Delete_Edit, | ||
23 | + data: { | ||
24 | + ids, | ||
25 | + }, | ||
26 | + }); | ||
27 | +}; | ||
28 | +export const createOrEditTransformScriptApi = (data) => { | ||
29 | + return defHttp.post({ | ||
30 | + url: TransformScriptApi.TransformScript_Delete_Edit, | ||
31 | + data, | ||
32 | + }); | ||
33 | +}; | ||
34 | + | ||
35 | +export const updateTransformScriptStatusApi = (status: number, id: string) => { | ||
36 | + return defHttp.post({ | ||
37 | + url: TransformScriptApi.TransformScript_ENABLE_OR_DISABLED, | ||
38 | + data: { | ||
39 | + convertIds: ['string'], | ||
40 | + nodeType: 0, | ||
41 | + status, | ||
42 | + id, | ||
43 | + }, | ||
44 | + }); | ||
45 | +}; |
src/api/device/model/transformScriptModel.ts
0 → 100644
@@ -223,7 +223,7 @@ | @@ -223,7 +223,7 @@ | ||
223 | const point = new BMap.Point(longitude, latitude); | 223 | const point = new BMap.Point(longitude, latitude); |
224 | let options = { | 224 | let options = { |
225 | width: 300, // 信息窗口宽度 | 225 | width: 300, // 信息窗口宽度 |
226 | - height: 220, // 信息窗口高度 | 226 | + height: 230, // 信息窗口高度 |
227 | }; | 227 | }; |
228 | map.centerAndZoom(point, 15); | 228 | map.centerAndZoom(point, 15); |
229 | map.enableScrollWheelZoom(true); | 229 | map.enableScrollWheelZoom(true); |
@@ -11,12 +11,7 @@ | @@ -11,12 +11,7 @@ | ||
11 | :customRequest="customUpload" | 11 | :customRequest="customUpload" |
12 | :before-upload="beforeUpload" | 12 | :before-upload="beforeUpload" |
13 | > | 13 | > |
14 | - <img | ||
15 | - v-if="devicePic" | ||
16 | - :src="devicePic" | ||
17 | - alt="avatar" | ||
18 | - style="width: 6.25rem; height: 6.25rem" | ||
19 | - /> | 14 | + <img v-if="devicePic" :src="devicePic" alt="avatar" /> |
20 | <div v-else> | 15 | <div v-else> |
21 | <PlusOutlined /> | 16 | <PlusOutlined /> |
22 | <div class="ant-upload-text">图片上传</div> | 17 | <div class="ant-upload-text">图片上传</div> |
@@ -93,7 +93,6 @@ | @@ -93,7 +93,6 @@ | ||
93 | }, | 93 | }, |
94 | }, | 94 | }, |
95 | setup(props) { | 95 | setup(props) { |
96 | - console.log(props.deviceDetail); | ||
97 | const [register] = useDescription({ | 96 | const [register] = useDescription({ |
98 | layout: 'vertical', | 97 | layout: 'vertical', |
99 | schema: descSchema, | 98 | schema: descSchema, |
1 | +import { BasicColumn, FormSchema } from '/@/components/Table'; | ||
2 | +import { h } from 'vue'; | ||
3 | +import { Tag, Switch } from 'ant-design-vue'; | ||
4 | +import { useMessage } from '/@/hooks/web/useMessage'; | ||
5 | +import { updateTransformScriptStatusApi } from '/@/api/device/TransformScriptApi'; | ||
6 | +export const columns: BasicColumn[] = [ | ||
7 | + { | ||
8 | + title: '名称', | ||
9 | + dataIndex: 'name', | ||
10 | + width: 100, | ||
11 | + }, | ||
12 | + { | ||
13 | + title: '用途', | ||
14 | + dataIndex: 'type', | ||
15 | + width: 200, | ||
16 | + customRender: () => h(Tag, { color: 'blue' }, () => '消息格式化'), | ||
17 | + }, | ||
18 | + { | ||
19 | + title: '状态', | ||
20 | + dataIndex: 'status', | ||
21 | + width: 120, | ||
22 | + customRender: ({ record }) => { | ||
23 | + if (!Reflect.has(record, 'pendingStatus')) { | ||
24 | + record.pendingStatus = false; | ||
25 | + } | ||
26 | + return h(Switch, { | ||
27 | + checked: record.status === 1, | ||
28 | + checkedChildren: '已启用', | ||
29 | + unCheckedChildren: '已禁用', | ||
30 | + loading: record.pendingStatus, | ||
31 | + onChange(checked: boolean) { | ||
32 | + record.pendingStatus = true; | ||
33 | + const newStatus = checked ? 1 : 0; | ||
34 | + const { createMessage } = useMessage(); | ||
35 | + updateTransformScriptStatusApi(newStatus, record.id) | ||
36 | + .then(() => { | ||
37 | + record.status = newStatus; | ||
38 | + createMessage.success(`${record.status ? '启用' : '禁用'}成功`); | ||
39 | + }) | ||
40 | + .finally(() => { | ||
41 | + record.pendingStatus = false; | ||
42 | + }); | ||
43 | + }, | ||
44 | + }); | ||
45 | + }, | ||
46 | + }, | ||
47 | + { | ||
48 | + title: '创建时间', | ||
49 | + dataIndex: 'createTime', | ||
50 | + width: 180, | ||
51 | + }, | ||
52 | +]; | ||
53 | + | ||
54 | +export const searchFormSchema: FormSchema[] = [ | ||
55 | + { | ||
56 | + field: 'name', | ||
57 | + label: '名称', | ||
58 | + component: 'Input', | ||
59 | + colProps: { span: 6 }, | ||
60 | + componentProps: { | ||
61 | + maxLength: 36, | ||
62 | + placeholder: '请输入名称', | ||
63 | + }, | ||
64 | + }, | ||
65 | + { | ||
66 | + field: 'status', | ||
67 | + label: '状态', | ||
68 | + component: 'Select', | ||
69 | + componentProps: { | ||
70 | + placeholder: '请选择状态', | ||
71 | + options: [ | ||
72 | + { label: '已启用', value: '1' }, | ||
73 | + { label: '未启用', value: '0' }, | ||
74 | + ], | ||
75 | + }, | ||
76 | + colProps: { span: 6 }, | ||
77 | + }, | ||
78 | +]; | ||
79 | + | ||
80 | +export const formSchema: FormSchema[] = [ | ||
81 | + { | ||
82 | + field: 'name', | ||
83 | + label: '名称', | ||
84 | + required: true, | ||
85 | + component: 'Input', | ||
86 | + componentProps: { | ||
87 | + maxLength: 36, | ||
88 | + placeholder: '请输入名称', | ||
89 | + }, | ||
90 | + }, | ||
91 | + { | ||
92 | + field: 'remark', | ||
93 | + label: '说明', | ||
94 | + component: 'InputTextArea', | ||
95 | + componentProps: { | ||
96 | + maxLength: 255, | ||
97 | + autoSize: { minRows: 5, maxRows: 8 }, | ||
98 | + placeholder: '请输入说明', | ||
99 | + }, | ||
100 | + }, | ||
101 | + { | ||
102 | + field: 'function', | ||
103 | + label: '', | ||
104 | + component: 'Input', | ||
105 | + slot: 'function', | ||
106 | + }, | ||
107 | + { | ||
108 | + field: 'id', | ||
109 | + label: 'id', | ||
110 | + component: 'Input', | ||
111 | + ifShow: false, | ||
112 | + }, | ||
113 | +]; |
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicDrawer | ||
4 | + v-bind="$attrs" | ||
5 | + :title="getTitle" | ||
6 | + @register="register" | ||
7 | + width="500px" | ||
8 | + showFooter | ||
9 | + @ok="handleSubmit" | ||
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 } 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.ts'; | ||
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 | + const emit = defineEmits(['register', 'isStatus', 'success']); | ||
42 | + const isUpdate = ref(false); | ||
43 | + const aceEditor = ref(); | ||
44 | + const aceRef = ref(); | ||
45 | + const getTitle = computed(() => (isUpdate.value ? '编辑转换脚本' : '新增转换脚本')); | ||
46 | + const [register, { closeDrawer }] = useDrawerInner((data) => { | ||
47 | + resetFields(); | ||
48 | + isUpdate.value = data.isUpdate; | ||
49 | + initEditor(data.record?.configuration.jsScript); | ||
50 | + if (isUpdate.value) { | ||
51 | + setFieldsValue(data.record); | ||
52 | + } | ||
53 | + }); | ||
54 | + const [registerForm, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ | ||
55 | + showActionButtonGroup: false, | ||
56 | + colProps: { span: 24 }, | ||
57 | + schemas: formSchema, | ||
58 | + }); | ||
59 | + | ||
60 | + const initEditor = (jsScript?: string) => { | ||
61 | + aceEditor.value = ace.edit(aceRef.value, { | ||
62 | + maxLines: 12, // 最大行数,超过会自动出现滚动条 | ||
63 | + minLines: 12, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小 | ||
64 | + fontSize: 14, // 编辑器内字体大小 | ||
65 | + theme: 'ace/theme/chrome', // 默认设置的主题 | ||
66 | + mode: 'ace/mode/javascript', // 默认设置的语言模式 | ||
67 | + tabSize: 2, // 制表符设置为 4 个空格大小 | ||
68 | + }); | ||
69 | + aceEditor.value.setOptions({ | ||
70 | + enableBasicAutocompletion: true, | ||
71 | + enableSnippets: true, | ||
72 | + enableLiveAutocompletion: true, | ||
73 | + }); | ||
74 | + aceEditor.value.setValue(jsScript ?? 'return {msg: msg, metadata: metadata};'); | ||
75 | + beautify(aceEditor.value.session); | ||
76 | + }; | ||
77 | + | ||
78 | + const testTransformFunc = () => { | ||
79 | + closeDrawer(); | ||
80 | + const jsCode = aceEditor.value.getValue(); | ||
81 | + emit('isStatus', { status: 1, jsCode }); | ||
82 | + }; | ||
83 | + const handleSubmit = async () => { | ||
84 | + const fieldsValue = getFieldsValue(); | ||
85 | + try { | ||
86 | + await createOrEditTransformScriptApi({ | ||
87 | + configuration: { | ||
88 | + jsScript: aceEditor.value.getValue(), | ||
89 | + }, | ||
90 | + type: 'org.thingsboard.rule.engine.transform.TbTransformMsgNode', | ||
91 | + ...fieldsValue, | ||
92 | + }); | ||
93 | + closeDrawer(); | ||
94 | + emit('success'); | ||
95 | + const { createMessage } = useMessage(); | ||
96 | + createMessage.success('保存成功'); | ||
97 | + } catch (e) { | ||
98 | + const { createMessage } = useMessage(); | ||
99 | + createMessage.success('保存失败'); | ||
100 | + } | ||
101 | + }; | ||
102 | + const handleFormat = () => { | ||
103 | + beautify(aceEditor.value.session); | ||
104 | + }; | ||
105 | + defineExpose({ aceEditor }); | ||
106 | +</script> |
1 | +<template> | ||
2 | + <div> | ||
3 | + <PageWrapper title="测试脚本功能" class="pl-4 pr-4 pt-4" :contentStyle="{ display: 'none' }" /> | ||
4 | + <div class="h-full flex p-4"> | ||
5 | + <div class="flex flex-col w-1/2"> | ||
6 | + <div class="flex-1 mr-4 mb-4"> | ||
7 | + <Card title="消息" :bodyStyle="cardStyle"> | ||
8 | + <template #extra> | ||
9 | + <Tag color="blue">Message</Tag> | ||
10 | + <a-button @click="handleFormatJson" size="small">格式化</a-button> | ||
11 | + <a-button @click="handleMiniJson" size="small" class="ml-2">收起</a-button> | ||
12 | + </template> | ||
13 | + <div ref="jsoneditorRef" style="height: 100%"></div> | ||
14 | + </Card> | ||
15 | + </div> | ||
16 | + <div class="flex-1 mr-4"> | ||
17 | + <Card title="转换函数" :bodyStyle="cardStyle"> | ||
18 | + <template #extra> | ||
19 | + <Tag color="blue">Transform Function</Tag> | ||
20 | + <a-button @click="handleFormatJScript" size="small">格式化</a-button> | ||
21 | + | ||
22 | + <Tooltip title="帮助文档" @click="openModal"> | ||
23 | + <QuestionCircleOutlined class="ml-2" style="font-size: 1rem" /> | ||
24 | + </Tooltip> | ||
25 | + </template> | ||
26 | + <div class="ml-8">function Transform(msg, metadata) {</div> | ||
27 | + <div ref="aceRef" style="height: calc(100% - 44px)"></div> | ||
28 | + <div class="ml-7">}</div> | ||
29 | + </Card> | ||
30 | + </div> | ||
31 | + </div> | ||
32 | + <div class="flex flex-col w-1/2"> | ||
33 | + <div class="flex-1 mb-4"> | ||
34 | + <Card title="元数据" :bodyStyle="cardStyle"> | ||
35 | + <template #extra> | ||
36 | + <Tag color="blue">Meta Data</Tag> | ||
37 | + </template> | ||
38 | + <Description @register="registerDesc" /> | ||
39 | + </Card> | ||
40 | + </div> | ||
41 | + <div class="flex-1"> | ||
42 | + <Card title="输出" :bodyStyle="cardStyle"> | ||
43 | + <template #extra> | ||
44 | + <Tag color="blue">Output</Tag> | ||
45 | + <a-button @click="handleFormatOutPutJson" size="small">格式化</a-button> | ||
46 | + <a-button @click="handleCompactJson" size="small" class="ml-2">收起</a-button> | ||
47 | + </template> | ||
48 | + <div class="ml-8 opacity-0">site</div> | ||
49 | + <div ref="outputRef" style="height: calc(100% - 44px)"></div> | ||
50 | + <div class="ml-7 opacity-0">site</div> | ||
51 | + </Card> | ||
52 | + </div> | ||
53 | + </div> | ||
54 | + </div> | ||
55 | + <div class="flex justify-between pl-4 pr-4"> | ||
56 | + <div> | ||
57 | + <a-button class="" type="primary" @click="handleTestFunc"> 测试</a-button> | ||
58 | + </div> | ||
59 | + <div> | ||
60 | + <a-button class="ml-4" @click="handleCancel"> 取消</a-button> | ||
61 | + <a-button class="ml-4" type="primary" @click="handleOk"> 保存</a-button> | ||
62 | + </div> | ||
63 | + </div> | ||
64 | + <BasicModal | ||
65 | + @register="registerModal" | ||
66 | + title="转换消息功能" | ||
67 | + :footer="null" | ||
68 | + width="800px" | ||
69 | + centered | ||
70 | + v-bind="$attrs" | ||
71 | + > | ||
72 | + <h2> function Transform(msg,metadata): {msg: object, metadata: object} </h2> | ||
73 | + <li> 将输入消息、元数据转换为输出消息的 JavaScript 函数 </li> | ||
74 | + <h2>参数:</h2> | ||
75 | + <ul> | ||
76 | + <li>msg: {[key: string]: any} - 是消息有效负载键/值对象。</li> | ||
77 | + <li>metadata: {[key: string]: string} - 是消息元数据键/值映射,其中键和值都是字符串。</li> | ||
78 | + </ul> | ||
79 | + <h2>返回值:</h2> | ||
80 | + <ul> | ||
81 | + <li> { msg?: {[key: string]: any}, metadata?: {[key: string]: string} } </li> | ||
82 | + <li> 结果对象中的所有字段都是可选的,如果未指定,将从原始消息中获取。 </li> | ||
83 | + </ul> | ||
84 | + </BasicModal> | ||
85 | + </div> | ||
86 | +</template> | ||
87 | +<script lang="ts" setup> | ||
88 | + import { ref, onMounted, defineComponent } from 'vue'; | ||
89 | + import { Card, Tag, Tooltip } from 'ant-design-vue'; | ||
90 | + import { PageWrapper } from '/@/components/Page'; | ||
91 | + import { Description, DescItem, useDescription } from '/@/components/Description/index'; | ||
92 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
93 | + import { QuestionCircleOutlined } from '@ant-design/icons-vue'; | ||
94 | + import { BasicModal, useModal } from '/@/components/Modal/index'; | ||
95 | + | ||
96 | + import jsoneditor from 'jsoneditor'; | ||
97 | + import 'jsoneditor/dist/jsoneditor.min.css'; | ||
98 | + import ace from 'ace-builds'; | ||
99 | + import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题 | ||
100 | + import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式 | ||
101 | + import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js'; | ||
102 | + | ||
103 | + defineComponent({ | ||
104 | + Tooltip, | ||
105 | + }); | ||
106 | + | ||
107 | + const jsonValue = ref({ | ||
108 | + temperature: 22.4, | ||
109 | + humidity: 78, | ||
110 | + }); | ||
111 | + const cardStyle = { padding: 0, height: '280px' }; | ||
112 | + | ||
113 | + // json 以及初始化JSON | ||
114 | + const jsoneditorRef = ref(); | ||
115 | + const JsonEditor = ref(); | ||
116 | + const outputRef = ref(); | ||
117 | + const outputEditor = ref(); | ||
118 | + const aceEditor = ref(); | ||
119 | + const aceRef = ref(); | ||
120 | + const emit = defineEmits(['isStatus']); | ||
121 | + function initEditor() { | ||
122 | + let options = { | ||
123 | + mode: 'code', | ||
124 | + mainMenuBar: false, | ||
125 | + statusBar: false, | ||
126 | + onError: function (err) { | ||
127 | + alert('EF1 ->' + err.toString()); | ||
128 | + }, | ||
129 | + }; | ||
130 | + let editor = new jsoneditor(jsoneditorRef.value, options); | ||
131 | + editor.set(jsonValue.value); | ||
132 | + JsonEditor.value = editor; | ||
133 | + let outEditor = new jsoneditor(outputRef.value, options); | ||
134 | + outEditor.set(true); | ||
135 | + outputEditor.value = outEditor; | ||
136 | + | ||
137 | + aceEditor.value = ace.edit(aceRef.value, { | ||
138 | + maxLines: 12, // 最大行数,超过会自动出现滚动条 | ||
139 | + minLines: 12, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小 | ||
140 | + fontSize: 14, // 编辑器内字体大小 | ||
141 | + theme: 'ace/theme/chrome', // 默认设置的主题 | ||
142 | + mode: 'ace/mode/javascript', // 默认设置的语言模式 | ||
143 | + tabSize: 2, // 制表符设置为 2 个空格大小 | ||
144 | + }); | ||
145 | + aceEditor.value.setOptions({ | ||
146 | + enableBasicAutocompletion: true, | ||
147 | + enableSnippets: true, | ||
148 | + enableLiveAutocompletion: true, | ||
149 | + }); | ||
150 | + } | ||
151 | + const mataData: any = { | ||
152 | + deviceName: 'Test Device', | ||
153 | + deviceType: 'default', | ||
154 | + ts: Date.now(), | ||
155 | + }; | ||
156 | + const schema: DescItem[] = [ | ||
157 | + { | ||
158 | + field: 'deviceName', | ||
159 | + label: 'deviceName', | ||
160 | + }, | ||
161 | + { | ||
162 | + field: 'deviceType', | ||
163 | + label: 'deviceType', | ||
164 | + }, | ||
165 | + { | ||
166 | + field: 'ts', | ||
167 | + label: 'ts', | ||
168 | + }, | ||
169 | + ]; | ||
170 | + const [registerDesc] = useDescription({ | ||
171 | + column: 1, | ||
172 | + data: mataData, | ||
173 | + schema, | ||
174 | + }); | ||
175 | + // 格式化json | ||
176 | + const handleFormatJson = () => { | ||
177 | + JsonEditor.value.repair(); | ||
178 | + JsonEditor.value.format(); | ||
179 | + }; | ||
180 | + // 迷你json | ||
181 | + const handleMiniJson = () => { | ||
182 | + JsonEditor.value.repair(); | ||
183 | + JsonEditor.value.compact(); | ||
184 | + }; | ||
185 | + // format json | ||
186 | + const handleFormatOutPutJson = () => { | ||
187 | + outputEditor.value.repair(); | ||
188 | + outputEditor.value.format(); | ||
189 | + }; | ||
190 | + // 迷你json | ||
191 | + const handleCompactJson = () => { | ||
192 | + outputEditor.value.repair(); | ||
193 | + outputEditor.value.compact(); | ||
194 | + }; | ||
195 | + | ||
196 | + // 测试 | ||
197 | + const handleTestFunc = () => { | ||
198 | + // 收集3方数据 | ||
199 | + const msg = JsonEditor.value.get(); | ||
200 | + const metadata = mataData; | ||
201 | + const jsCode = aceEditor.value.getValue(); | ||
202 | + try { | ||
203 | + // 执行动态Javascript脚本 | ||
204 | + let result = Function('msg', 'metadata', jsCode)(msg, metadata); | ||
205 | + // 设置输出值 | ||
206 | + outputEditor.value.set(result); | ||
207 | + } catch (e) { | ||
208 | + console.log(e); | ||
209 | + const { createMessage } = useMessage(); | ||
210 | + createMessage.error(e.toString()); | ||
211 | + } | ||
212 | + }; | ||
213 | + const [registerModal, { openModal }] = useModal(); | ||
214 | + const handleCancel = () => { | ||
215 | + emit('isStatus', { status: 0, emitType: 'cancel' }); | ||
216 | + }; | ||
217 | + const handleOk = () => { | ||
218 | + emit('isStatus', { status: 0, emitType: 'ok' }); | ||
219 | + }; | ||
220 | + const handleFormatJScript = () => { | ||
221 | + beautify(aceEditor.value.session); | ||
222 | + }; | ||
223 | + onMounted(() => { | ||
224 | + initEditor(); | ||
225 | + }); | ||
226 | + defineExpose({ aceEditor }); | ||
227 | +</script> |
src/views/device/transferScript/index.vue
0 → 100644
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicTable @register="registerTable" v-show="isStatus === 0"> | ||
4 | + <template #toolbar> | ||
5 | + <a-button type="primary" @click="handleCreate"> 新增转换脚本 </a-button> | ||
6 | + <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete"> | ||
7 | + 批量删除 | ||
8 | + </a-button> | ||
9 | + </template> | ||
10 | + <template #action="{ record }"> | ||
11 | + <TableAction | ||
12 | + :actions="[ | ||
13 | + { | ||
14 | + label: '编辑', | ||
15 | + icon: 'clarity:note-edit-line', | ||
16 | + | ||
17 | + onClick: handleEdit.bind(null, record), | ||
18 | + }, | ||
19 | + { | ||
20 | + label: '删除', | ||
21 | + icon: 'ant-design:delete-outlined', | ||
22 | + ifShow: record.status == 0, | ||
23 | + color: 'error', | ||
24 | + popConfirm: { | ||
25 | + title: '是否确认删除', | ||
26 | + confirm: handleDeleteOrBatchDelete.bind(null, record), | ||
27 | + }, | ||
28 | + }, | ||
29 | + ]" | ||
30 | + /> | ||
31 | + </template> | ||
32 | + </BasicTable> | ||
33 | + <ScriptDrawer | ||
34 | + @register="registerDrawer" | ||
35 | + @isStatus="handleIsStatus" | ||
36 | + ref="scriptDrawerRef" | ||
37 | + @success="handleSuccess" | ||
38 | + /> | ||
39 | + <TestScript v-show="isStatus === 1" @isStatus="handleCancelStatus" ref="testScriptRef" /> | ||
40 | + </div> | ||
41 | +</template> | ||
42 | + | ||
43 | +<script lang="ts" setup> | ||
44 | + import { ref } from 'vue'; | ||
45 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; | ||
46 | + import { columns, searchFormSchema } from './config/config.data.ts'; | ||
47 | + import { getConvertApi, deleteTransformApi } from '/@/api/device/TransformScriptApi'; | ||
48 | + import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; | ||
49 | + import { useDrawer } from '/@/components/Drawer/index'; | ||
50 | + import ScriptDrawer from './cpns/ScriptDrawer.vue'; | ||
51 | + import TestScript from './cpns/TestScript.vue'; | ||
52 | + const handleSuccess = () => { | ||
53 | + reload(); | ||
54 | + }; | ||
55 | + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete( | ||
56 | + deleteTransformApi, | ||
57 | + handleSuccess | ||
58 | + ); | ||
59 | + const [registerTable, { reload }] = useTable({ | ||
60 | + api: getConvertApi, | ||
61 | + title: '转换脚本列表', | ||
62 | + columns, | ||
63 | + useSearchForm: true, | ||
64 | + showTableSetting: true, | ||
65 | + bordered: true, | ||
66 | + showIndexColumn: false, | ||
67 | + formConfig: { | ||
68 | + labelWidth: 100, | ||
69 | + schemas: searchFormSchema, | ||
70 | + }, | ||
71 | + actionColumn: { | ||
72 | + width: 180, | ||
73 | + title: '操作', | ||
74 | + dataIndex: 'action', | ||
75 | + slots: { customRender: 'action' }, | ||
76 | + fixed: 'right', | ||
77 | + }, | ||
78 | + ...selectionOptions, | ||
79 | + }); | ||
80 | + const [registerDrawer, { openDrawer }] = useDrawer({}); | ||
81 | + | ||
82 | + const isStatus = ref(0); | ||
83 | + const testScriptRef = ref(); | ||
84 | + const scriptDrawerRef = ref(); | ||
85 | + const handleIsStatus = ({ status, jsCode }) => { | ||
86 | + isStatus.value = status; | ||
87 | + testScriptRef.value.aceEditor.setValue(jsCode); | ||
88 | + }; | ||
89 | + const handleCancelStatus = ({ status, emitType }) => { | ||
90 | + openDrawer(true); | ||
91 | + isStatus.value = status; | ||
92 | + if (emitType === 'ok') { | ||
93 | + const jsCode = testScriptRef.value.aceEditor.getValue(); | ||
94 | + scriptDrawerRef.value.aceEditor.setValue(jsCode); | ||
95 | + } | ||
96 | + }; | ||
97 | + const handleCreate = () => { | ||
98 | + openDrawer(true, { | ||
99 | + isUpdate: false, | ||
100 | + }); | ||
101 | + }; | ||
102 | + const handleEdit = (record: Recordable) => { | ||
103 | + openDrawer(true, { isUpdate: true, record }); | ||
104 | + }; | ||
105 | +</script> |
@@ -39,12 +39,16 @@ | @@ -39,12 +39,16 @@ | ||
39 | /> | 39 | /> |
40 | </template> | 40 | </template> |
41 | </BasicTable> | 41 | </BasicTable> |
42 | - <NotifyManagerDrawer @register="registerAdd" @success="handleSuccess" /> | 42 | + <NotifyManagerDrawer |
43 | + @register="registerAdd" | ||
44 | + @success="handleSuccess" | ||
45 | + ref="NotifyManagerDrawerRef" | ||
46 | + /> | ||
43 | <tableViewChild @register="registerDrawer" /> | 47 | <tableViewChild @register="registerDrawer" /> |
44 | </div> | 48 | </div> |
45 | </template> | 49 | </template> |
46 | <script lang="ts"> | 50 | <script lang="ts"> |
47 | - import { defineComponent } from 'vue'; | 51 | + import { defineComponent, ref } from 'vue'; |
48 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 52 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
49 | import { useDrawer } from '/@/components/Drawer'; | 53 | import { useDrawer } from '/@/components/Drawer'; |
50 | import NotifyManagerDrawer from './useDrawer.vue'; | 54 | import NotifyManagerDrawer from './useDrawer.vue'; |
@@ -52,7 +56,6 @@ | @@ -52,7 +56,6 @@ | ||
52 | import { columns, searchFormSchema } from './config.d'; | 56 | import { columns, searchFormSchema } from './config.d'; |
53 | import { notifyGetTableApi, notifyDeleteApi } from '/@/api/stationnotification/stationnotifyApi'; | 57 | import { notifyGetTableApi, notifyDeleteApi } from '/@/api/stationnotification/stationnotifyApi'; |
54 | import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; | 58 | import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; |
55 | - | ||
56 | export default defineComponent({ | 59 | export default defineComponent({ |
57 | name: 'Notificationmannager', | 60 | name: 'Notificationmannager', |
58 | components: { BasicTable, NotifyManagerDrawer, TableAction, tableViewChild }, | 61 | components: { BasicTable, NotifyManagerDrawer, TableAction, tableViewChild }, |
@@ -65,6 +68,7 @@ | @@ -65,6 +68,7 @@ | ||
65 | notifyDeleteApi, | 68 | notifyDeleteApi, |
66 | handleSuccess | 69 | handleSuccess |
67 | ); | 70 | ); |
71 | + const NotifyManagerDrawerRef = ref(); | ||
68 | const [registerTable, { reload }] = useTable({ | 72 | const [registerTable, { reload }] = useTable({ |
69 | api: notifyGetTableApi, | 73 | api: notifyGetTableApi, |
70 | columns, | 74 | columns, |
@@ -90,6 +94,7 @@ | @@ -90,6 +94,7 @@ | ||
90 | openDrawerAdd(true, { | 94 | openDrawerAdd(true, { |
91 | isUpdate: false, | 95 | isUpdate: false, |
92 | }); | 96 | }); |
97 | + NotifyManagerDrawerRef.value.setFieldsValue({ content: '' }); | ||
93 | } | 98 | } |
94 | 99 | ||
95 | const handleView = (record: Recordable) => { | 100 | const handleView = (record: Recordable) => { |
@@ -116,6 +121,7 @@ | @@ -116,6 +121,7 @@ | ||
116 | handleEdit, | 121 | handleEdit, |
117 | handleSuccess, | 122 | handleSuccess, |
118 | handleDeleteOrBatchDelete, | 123 | handleDeleteOrBatchDelete, |
124 | + NotifyManagerDrawerRef, | ||
119 | }; | 125 | }; |
120 | }, | 126 | }, |
121 | }); | 127 | }); |