Commit e099bdc042d190ff5e3fc14fb2949b5b6e4089ac

Authored by ww
1 parent c174e0ab

fix: DEFECT-1339转换脚本新增messageType参数

... ... @@ -8,6 +8,31 @@ export enum StatusEnum {
8 8 DISABLE = 0,
9 9 }
10 10
  11 +export enum ScriptMessageTypeEnum {
  12 + 'Post attributes' = 'POST_ATTRIBUTES',
  13 + 'Post telemetry' = 'POST_TELEMETRY',
  14 + 'RPC Request from Device' = 'RPC_REQUEST_FROM_DEVICE',
  15 + 'RPC Request to Device' = 'RPC_REQUEST_TO_DEVICE',
  16 + 'Activity Event' = 'ACTIVITY_EVENT',
  17 + 'Inactivity Event' = 'INACTIVITY_EVENT',
  18 + 'Connect Event' = 'CONNECT_EVENT',
  19 + 'Disconnect Event' = 'DISCONNECT_EVENT',
  20 + 'Entity Created' = 'ENTITY_CREATED',
  21 + 'Entity Updated' = 'ENTITY_UPDATED',
  22 + 'Entity Deleted' = 'ENTITY_DELETED',
  23 + 'Entity Assigned' = 'ENTITY_ASSIGNED',
  24 + 'Entity Unassigned' = 'ENTITY_UNASSIGNED',
  25 + 'Attributes Updated' = 'ATTRIBUTES_UPDATED',
  26 + 'Attributes Deleted' = 'ATTRIBUTES_DELETED',
  27 + 'Timeseries Updated' = 'TIMESERIES_UPDATED',
  28 + 'Timeseries Deleted' = 'TIMESERIES_DELETED',
  29 + 'RPC Queued' = 'RPC_QUEUED',
  30 + 'RPC Delivered' = 'RPC_DELIVERED',
  31 + 'RPC Successful' = 'RPC_SUCCESSFUL',
  32 + 'RPC Timeout' = 'RPC_TIMEOUT',
  33 + 'RPC Failed' = 'RPC_FAILED',
  34 +}
  35 +
11 36 export const columns: BasicColumn[] = [
12 37 {
13 38 title: '名称',
... ...
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 + <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, msgType) {</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(
  112 + jsScript ?? 'return {msg: msg, metadata: metadata, msgType: msgType};'
  113 + );
  114 + beautify(aceEditor.value.session);
  115 + };
  116 +
  117 + const testTransformFunc = () => {
  118 + closeDrawer();
  119 + const jsCode = aceEditor.value.getValue();
  120 + emit('isStatus', { status: 1, jsCode });
  121 + };
  122 + const handleSubmit = async () => {
  123 + const editIdPost = isUpdate.value ? { id: editId.value } : {};
  124 + try {
  125 + setDrawerProps({ confirmLoading: true });
  126 + const fieldsValue = await validate();
  127 + if (!fieldsValue) return;
  128 + await createOrEditTransformScriptApi({
  129 + configuration: {
  130 + jsScript: aceEditor.value.getValue(),
  131 + },
  132 + type: 'org.thingsboard.rule.engine.transform.TbTransformMsgNode',
  133 + ...fieldsValue,
  134 + ...editIdPost,
  135 + });
  136 + closeDrawer();
  137 + emit('success');
  138 + const { createMessage } = useMessage();
  139 + createMessage.success('保存成功');
  140 + } catch (e) {
  141 + } finally {
  142 + setTimeout(() => {
  143 + setDrawerProps({ confirmLoading: false });
  144 + }, 300);
  145 + }
  146 + };
  147 + const handleFormat = () => {
  148 + beautify(aceEditor.value.session);
  149 + };
  150 + defineExpose({ aceEditor });
  151 +</script>
... ...
... ... @@ -4,11 +4,25 @@
4 4 <div class="h-full flex p-4">
5 5 <div class="flex flex-col w-1/2">
6 6 <div class="flex-1 mr-4 mb-4">
7   - <Card title="消息" :bodyStyle="cardStyle">
  7 + <Card :bodyStyle="cardStyle">
  8 + <template #title>
  9 + <div class="w-3/4 flex">
  10 + <span class="mr-2">消息类型</span>
  11 + <Select
  12 + v-model:value="messageType"
  13 + class="flex-1 mr-2"
  14 + :options="getScriptMessageTypeOptions"
  15 + placeholder="请选择消息类型"
  16 + />
  17 + </div>
  18 + <div>消息</div>
  19 + </template>
8 20 <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>
  21 + <div>
  22 + <Tag color="blue">Message</Tag>
  23 + <a-button @click="handleFormatJson" size="small">格式化</a-button>
  24 + <a-button @click="handleMiniJson" size="small" class="ml-2">收起</a-button>
  25 + </div>
12 26 </template>
13 27 <div ref="jsoneditorRef" style="height: 100%"></div>
14 28 </Card>
... ... @@ -23,7 +37,7 @@
23 37 <QuestionCircleOutlined class="ml-2" style="font-size: 1rem" />
24 38 </Tooltip>
25 39 </template>
26   - <div class="ml-8">function Transform(msg, metadata) {</div>
  40 + <div class="ml-8">function Transform(msg, metadata, msgType) {</div>
27 41 <div ref="aceRef" style="height: calc(100% - 44px)"></div>
28 42 <div class="ml-7">}</div>
29 43 </Card>
... ... @@ -69,24 +83,27 @@
69 83 centered
70 84 v-bind="$attrs"
71 85 >
72   - <h2> function Transform(msg,metadata): {msg: object, metadata: object} </h2>
  86 + <h2> function Transform(msg,metadata): {msg: object, metadata: object, msgType: string} </h2>
73 87 <li> 将输入消息、元数据转换为输出消息的 JavaScript 函数 </li>
74 88 <h2>参数:</h2>
75 89 <ul>
76 90 <li>msg: {[key: string]: any} - 是消息有效负载键/值对象。</li>
77   - <li>metadata: {[key: string]: string} - 是消息元数据键/值映射,其中键和值都是字符串。</li>
  91 + <li>metadata: {[key: string]: string} - 是消息元数据键/值映射, 其中键和值都是字符串。</li>
  92 + <li>msgType: string - 是包含消息类型的字符串。有关常用值, 请参见MessageType enum。</li>
78 93 </ul>
79 94 <h2>返回值:</h2>
80 95 <ul>
81   - <li> { msg?: {[key: string]: any}, metadata?: {[key: string]: string} } </li>
  96 + <li>
  97 + { msg?: {[key: string]: any}, metadata?: {[key: string]: string}, msgType?: string }
  98 + </li>
82 99 <li> 结果对象中的所有字段都是可选的,如果未指定,将从原始消息中获取。 </li>
83 100 </ul>
84 101 </BasicModal>
85 102 </div>
86 103 </template>
87 104 <script lang="ts" setup>
88   - import { ref, onMounted, defineComponent } from 'vue';
89   - import { Card, Tag, Tooltip } from 'ant-design-vue';
  105 + import { ref, onMounted, defineComponent, computed, unref } from 'vue';
  106 + import { Card, Tag, Tooltip, Select } from 'ant-design-vue';
90 107 import { PageWrapper } from '/@/components/Page';
91 108 import { Description, DescItem, useDescription } from '/@/components/Description/index';
92 109 import { useMessage } from '/@/hooks/web/useMessage';
... ... @@ -100,6 +117,7 @@
100 117 import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式
101 118 import 'ace-builds/src-noconflict/ext-language_tools.js'; //语言提示
102 119 import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js'; //格式化
  120 + import { ScriptMessageTypeEnum } from '../config/config.data';
103 121 // !!!important 重要,配置ace编辑器的错误提示,基础路径。否则会加载不到相关web Worker,就没有syntax validation提示
104 122 ace.config.set('basePath', 'https://cdn.jsdelivr.net/npm/ace-builds@1.4.14/src-noconflict/');
105 123 defineComponent({
... ... @@ -120,6 +138,15 @@
120 138 const aceEditor = ref();
121 139 const aceRef = ref();
122 140 const emit = defineEmits(['isStatus']);
  141 +
  142 + const messageType = ref(ScriptMessageTypeEnum['Post telemetry']);
  143 + const getScriptMessageTypeOptions = computed(() =>
  144 + Object.keys(ScriptMessageTypeEnum).map((item) => ({
  145 + label: item,
  146 + value: ScriptMessageTypeEnum[item],
  147 + }))
  148 + );
  149 +
123 150 function initEditor() {
124 151 let options = {
125 152 mode: 'code',
... ... @@ -200,7 +227,12 @@
200 227 const metadata = mataData;
201 228 const jsCode = aceEditor.value.getValue();
202 229 // 执行动态Javascript脚本
203   - let result = Function('msg', 'metadata', jsCode)(msg, metadata);
  230 + let result = Function(
  231 + 'msg',
  232 + 'metadata',
  233 + 'msgType',
  234 + jsCode
  235 + )(msg, metadata, unref(messageType));
204 236 // 设置输出值
205 237 outputEditor.value.set(result);
206 238 } catch (e) {
... ...