Showing
71 changed files
with
4122 additions
and
123 deletions
Too many changes to show.
To preserve performance only 71 of 398 files are displayed.
@@ -5,22 +5,28 @@ | @@ -5,22 +5,28 @@ | ||
5 | "public/resource/tinymce/langs" | 5 | "public/resource/tinymce/langs" |
6 | ], | 6 | ], |
7 | "cSpell.words": [ | 7 | "cSpell.words": [ |
8 | + "ACKS", | ||
9 | + "clazz", | ||
8 | "Cmds", | 10 | "Cmds", |
9 | "COAP", | 11 | "COAP", |
10 | "echarts", | 12 | "echarts", |
11 | "edrx", | 13 | "edrx", |
12 | - "EFENTO", | 14 | + "EFENTO", |
13 | "fingerprintjs", | 15 | "fingerprintjs", |
14 | "flvjs", | 16 | "flvjs", |
15 | - "flvjs", | ||
16 | "inited", | 17 | "inited", |
17 | "liveui", | 18 | "liveui", |
18 | "MQTT", | 19 | "MQTT", |
20 | + "noconflict", | ||
19 | "notif", | 21 | "notif", |
20 | "PROTOBUF", | 22 | "PROTOBUF", |
23 | + "Rabbitmq", | ||
21 | "rtsp", | 24 | "rtsp", |
22 | "SCADA", | 25 | "SCADA", |
26 | + "SMTPS", | ||
23 | "SNMP", | 27 | "SNMP", |
28 | + "TSLV", | ||
29 | + "UNACK", | ||
24 | "unref", | 30 | "unref", |
25 | "vben", | 31 | "vben", |
26 | "videojs", | 32 | "videojs", |
build/generate/ruleChain/components.ts
0 → 100644
build/generate/ruleChain/index.ts
0 → 100644
1 | +import { join } from 'path'; | ||
2 | +import { pathExists, ensureFile, writeFile } from 'fs-extra'; | ||
3 | +import { NodeItemConfigType } from '/@/views/rule/designer/types/node'; | ||
4 | +import { camelCase, upperFirst, snakeCase } from 'lodash-es'; | ||
5 | +import { components } from './components'; | ||
6 | +type GroupNodeType = { [key: string]: NodeItemConfigType[] }; | ||
7 | + | ||
8 | +const RULE_CHAIN_FILE_PATH = join(process.cwd(), '/src/views/rule/designer'); | ||
9 | + | ||
10 | +const list: NodeItemConfigType[] = components; | ||
11 | + | ||
12 | +const getCategoryConfigName = (name: string) => { | ||
13 | + return `${upperFirst(camelCase(name))}CategoryConfig`; | ||
14 | +}; | ||
15 | + | ||
16 | +const getNodeConfigName = (name: string) => { | ||
17 | + return `${upperFirst(camelCase(name))}Config`; | ||
18 | +}; | ||
19 | + | ||
20 | +const getCagegoryEnumName = (name: string) => { | ||
21 | + return `${upperFirst(name.toLowerCase())}CategoryComponentEnum`; | ||
22 | +}; | ||
23 | + | ||
24 | +const getEnumKeyName = (name: string) => { | ||
25 | + return snakeCase(name).toUpperCase(); | ||
26 | +}; | ||
27 | + | ||
28 | +const createFile = async (fileName: string, fileContent?: string, replace = false) => { | ||
29 | + const path = join(RULE_CHAIN_FILE_PATH, './packages', fileName); | ||
30 | + | ||
31 | + const flag = await pathExists(path); | ||
32 | + | ||
33 | + if (flag && !replace) return false; | ||
34 | + | ||
35 | + await ensureFile(path); | ||
36 | + | ||
37 | + fileContent && (await writeFile(path, fileContent, { encoding: 'utf-8' })); | ||
38 | +}; | ||
39 | + | ||
40 | +const groupByType = () => { | ||
41 | + const group: { [key: string]: NodeItemConfigType[] } = {}; | ||
42 | + | ||
43 | + list.forEach((item) => { | ||
44 | + if (!group[item.type]) group[item.type] = []; | ||
45 | + group[item.type].push(item); | ||
46 | + }); | ||
47 | + | ||
48 | + return group; | ||
49 | +}; | ||
50 | + | ||
51 | +const generateCategoryEnumFile = async (data: GroupNodeType) => { | ||
52 | + const defaultContent = ` | ||
53 | +export enum EntryCategoryComponentEnum { | ||
54 | + INPUT = 'Input', | ||
55 | +} | ||
56 | + `; | ||
57 | + | ||
58 | + const fileContent = Object.keys(data).reduce((prev, next) => { | ||
59 | + const enumName = getCagegoryEnumName(next); | ||
60 | + | ||
61 | + const enumKeys = data[next].map((item) => getEnumKeyName(item.name)); | ||
62 | + | ||
63 | + const content = `export enum ${enumName} { | ||
64 | + ${enumKeys.map((name) => `${name} = '${upperFirst(camelCase(name))}'`)} | ||
65 | + }`; | ||
66 | + | ||
67 | + return `${prev} \n ${content}`; | ||
68 | + }, defaultContent); | ||
69 | + | ||
70 | + createFile('../enum/category.ts', fileContent, true); | ||
71 | + return fileContent; | ||
72 | +}; | ||
73 | + | ||
74 | +const generateRuleNodeEnumFile = async (data: GroupNodeType) => { | ||
75 | + const categoryKeys = Object.keys(data).map((type) => type.toUpperCase()); | ||
76 | + const filePath = join(RULE_CHAIN_FILE_PATH, './packages/index.type.ts'); | ||
77 | + const fileContent = ` | ||
78 | +export enum RuleNodeTypeEnum { | ||
79 | + ${categoryKeys.map((item) => `${item} = '${item}'`).join(',\n')} | ||
80 | +} | ||
81 | + `; | ||
82 | + | ||
83 | + await writeFile(filePath, fileContent, { | ||
84 | + encoding: 'utf-8', | ||
85 | + }); | ||
86 | + | ||
87 | + return fileContent; | ||
88 | +}; | ||
89 | + | ||
90 | +const generateCategoryIndexFile = async (type: string, data: NodeItemConfigType[]) => { | ||
91 | + const getComponentsName = data.map((temp) => `${upperFirst(camelCase(temp.name))}`); | ||
92 | + const importContent = getComponentsName.map( | ||
93 | + (name) => `import { ${name}Config } from './${name}';\n` | ||
94 | + ); | ||
95 | + | ||
96 | + const components = getComponentsName.map((item) => `${item}Config`); | ||
97 | + | ||
98 | + const content = `import type { CategoryConfigType, NodeItemConfigType } from '../../types/node'; | ||
99 | +import { RuleNodeTypeEnum } from '../index.type'; | ||
100 | +${importContent.join('')} | ||
101 | + | ||
102 | +export const ${getCategoryConfigName(type)}: CategoryConfigType = { | ||
103 | + category: RuleNodeTypeEnum.${type.toUpperCase()}, | ||
104 | + title: '${type}', | ||
105 | + icon: 'tabler:circuit-ground', | ||
106 | + description: '使用配置条件筛选传入消息', | ||
107 | +}; | ||
108 | + | ||
109 | +export const ${upperFirst(type.toLowerCase())}Components: NodeItemConfigType[] = [${components}]; | ||
110 | +`; | ||
111 | + | ||
112 | + createFile(`./${upperFirst(type.toLowerCase())}/index.ts`, content, true); | ||
113 | + | ||
114 | + return content; | ||
115 | +}; | ||
116 | + | ||
117 | +const generateNodeIndexFile = async (type: string, data: NodeItemConfigType) => { | ||
118 | + const categoryEnumName = getCagegoryEnumName(type); | ||
119 | + | ||
120 | + const nodeConfigName = getNodeConfigName(data.name); | ||
121 | + | ||
122 | + const content = ` | ||
123 | + import { ${categoryEnumName} } from '../../../enum/category'; | ||
124 | + import { useCreateNodeKey } from '../../../hook/useCreateNodeKey'; | ||
125 | + import type { NodeItemConfigType } from '../../../types/node'; | ||
126 | + import { RuleNodeTypeEnum } from '../../index.type'; | ||
127 | + | ||
128 | + const keys = useCreateNodeKey(${categoryEnumName}.${getEnumKeyName(data.name)}); | ||
129 | + | ||
130 | + export interface ${upperFirst(camelCase(data.name))}DataType { | ||
131 | + someConfiguration?: Recordable | ||
132 | + } | ||
133 | + | ||
134 | + export const ${nodeConfigName}: NodeItemConfigType = { | ||
135 | + ...keys, | ||
136 | + clazz: '${data.clazz}', | ||
137 | + categoryType: RuleNodeTypeEnum.${type.toUpperCase()}, | ||
138 | + name: '${data.name}', | ||
139 | + configurationDescriptor: ${JSON.stringify(data.configurationDescriptor, null, 2)} | ||
140 | + }; | ||
141 | + `; | ||
142 | + | ||
143 | + createFile( | ||
144 | + `./${upperFirst(type.toLowerCase())}/${upperFirst(camelCase(data.name))}/index.ts`, | ||
145 | + content | ||
146 | + ); | ||
147 | + | ||
148 | + return content; | ||
149 | +}; | ||
150 | + | ||
151 | +const generateNodeVueTemplateFile = async (type: string, data: NodeItemConfigType) => { | ||
152 | + const content = ` | ||
153 | + <script lang="ts" setup> | ||
154 | + import type { CreateModalDefineExposeType } from '../../../types'; | ||
155 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
156 | + import { formSchemas } from './create.config'; | ||
157 | + import { NodeData } from '../../../types/node'; | ||
158 | + | ||
159 | + defineProps<{ | ||
160 | + config: NodeData; | ||
161 | + }>(); | ||
162 | + | ||
163 | + const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | ||
164 | + schemas: formSchemas, | ||
165 | + showActionButtonGroup: false, | ||
166 | + }); | ||
167 | + | ||
168 | + const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | ||
169 | + await validate(); | ||
170 | + const value = getFieldsValue() || {}; | ||
171 | + return value; | ||
172 | + }; | ||
173 | + | ||
174 | + const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | ||
175 | + resetFields(); | ||
176 | + setFieldsValue(value); | ||
177 | + }; | ||
178 | + | ||
179 | + defineExpose({ | ||
180 | + setFieldsValue: setValue, | ||
181 | + getFieldsValue: getValue, | ||
182 | + } as CreateModalDefineExposeType); | ||
183 | + </script> | ||
184 | + | ||
185 | + <template> | ||
186 | + <BasicForm @register="register" /> | ||
187 | + </template> | ||
188 | + `; | ||
189 | + | ||
190 | + createFile( | ||
191 | + `./${upperFirst(type.toLowerCase())}/${upperFirst(camelCase(data.name))}/create.vue`, | ||
192 | + content | ||
193 | + ); | ||
194 | + return content; | ||
195 | +}; | ||
196 | + | ||
197 | +const generateNodeVueConfigFile = async (type: string, data: NodeItemConfigType) => { | ||
198 | + const content = ` | ||
199 | + import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | ||
200 | + import { FormSchema } from '/@/components/Form'; | ||
201 | + | ||
202 | + export const formSchemas: FormSchema[] = [ | ||
203 | + { | ||
204 | + field: NodeBindDataFieldEnum.NAME, | ||
205 | + component: 'Input', | ||
206 | + label: NodeBindDataFieldNameEnum.NAME, | ||
207 | + } | ||
208 | + ]; | ||
209 | + `; | ||
210 | + | ||
211 | + createFile( | ||
212 | + `./${upperFirst(type.toLowerCase())}/${upperFirst(camelCase(data.name))}/create.config.ts`, | ||
213 | + content | ||
214 | + ); | ||
215 | + return content; | ||
216 | +}; | ||
217 | + | ||
218 | +const generateNodeConfigFile = async (type: string, data: NodeItemConfigType) => { | ||
219 | + const nodeConfigName = getNodeConfigName(data.name); | ||
220 | + const categoryConfigName = getCategoryConfigName(type); | ||
221 | + const content = ` | ||
222 | + import { cloneDeep } from 'lodash-es'; | ||
223 | + import { PublicNodeItemClass } from '../../../types/node'; | ||
224 | + import type { | ||
225 | + CategoryConfigType, | ||
226 | + CreateComponentType, | ||
227 | + NodeItemConfigType, | ||
228 | + } from '../../../types/node'; | ||
229 | + import { ${categoryConfigName} } from '..'; | ||
230 | + import { ${nodeConfigName} } from '.'; | ||
231 | + | ||
232 | + export class Config extends PublicNodeItemClass implements CreateComponentType { | ||
233 | + public config: NodeItemConfigType = cloneDeep(${nodeConfigName}); | ||
234 | + | ||
235 | + public categoryConfig: CategoryConfigType = cloneDeep(${categoryConfigName}); | ||
236 | + | ||
237 | + constructor() { | ||
238 | + super(); | ||
239 | + } | ||
240 | + } | ||
241 | + `; | ||
242 | + | ||
243 | + createFile( | ||
244 | + `./${upperFirst(type.toLowerCase())}/${upperFirst(camelCase(data.name))}/config.ts`, | ||
245 | + content | ||
246 | + ); | ||
247 | + return content; | ||
248 | +}; | ||
249 | + | ||
250 | +const bootstrap = async () => { | ||
251 | + const groupData = groupByType(); | ||
252 | + await generateRuleNodeEnumFile(groupData); | ||
253 | + await generateCategoryEnumFile(groupData); | ||
254 | + for (const type of Object.keys(groupData)) { | ||
255 | + const item = groupData[type]; | ||
256 | + await generateCategoryIndexFile(type, item); | ||
257 | + for (const temp of item) { | ||
258 | + await generateNodeConfigFile(type, temp); | ||
259 | + await generateNodeIndexFile(type, temp); | ||
260 | + await generateNodeVueConfigFile(type, temp); | ||
261 | + await generateNodeVueTemplateFile(type, temp); | ||
262 | + } | ||
263 | + } | ||
264 | +}; | ||
265 | + | ||
266 | +bootstrap(); |
@@ -32,13 +32,18 @@ | @@ -32,13 +32,18 @@ | ||
32 | "reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap", | 32 | "reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap", |
33 | "prepare": "husky install", | 33 | "prepare": "husky install", |
34 | "gen:icon": "esno ./build/generate/icon/index.ts", | 34 | "gen:icon": "esno ./build/generate/icon/index.ts", |
35 | - "gen:iconfont": "esno ./build/generate/iconfont/index.ts" | 35 | + "gen:iconfont": "esno ./build/generate/iconfont/index.ts", |
36 | + "gen:rule": "esno ./build/generate/ruleChain/index.ts && npx eslint \"src/views/rule/designer/**/*.{vue,ts,tsx}\" --fix" | ||
36 | }, | 37 | }, |
37 | "dependencies": { | 38 | "dependencies": { |
38 | "@fingerprintjs/fingerprintjs": "^3.4.1", | 39 | "@fingerprintjs/fingerprintjs": "^3.4.1", |
39 | "@iconify/iconify": "^2.0.3", | 40 | "@iconify/iconify": "^2.0.3", |
40 | "@logicflow/core": "^0.6.9", | 41 | "@logicflow/core": "^0.6.9", |
41 | "@logicflow/extension": "^0.6.9", | 42 | "@logicflow/extension": "^0.6.9", |
43 | + "@vue-flow/background": "^1.2.0", | ||
44 | + "@vue-flow/controls": "^1.1.0", | ||
45 | + "@vue-flow/core": "^1.22.1", | ||
46 | + "@vue-flow/node-toolbar": "^1.1.0", | ||
42 | "@vueuse/core": "^10.1.0", | 47 | "@vueuse/core": "^10.1.0", |
43 | "@zxcvbn-ts/core": "^1.0.0-beta.0", | 48 | "@zxcvbn-ts/core": "^1.0.0-beta.0", |
44 | "ace-builds": "^1.4.14", | 49 | "ace-builds": "^1.4.14", |
@@ -53,6 +58,7 @@ | @@ -53,6 +58,7 @@ | ||
53 | "flv.js": "^1.6.2", | 58 | "flv.js": "^1.6.2", |
54 | "hls.js": "^1.0.10", | 59 | "hls.js": "^1.0.10", |
55 | "intro.js": "^4.1.0", | 60 | "intro.js": "^4.1.0", |
61 | + "js-beautify": "^1.14.9", | ||
56 | "jsoneditor": "^9.7.2", | 62 | "jsoneditor": "^9.7.2", |
57 | "jwt-decode": "^3.1.2", | 63 | "jwt-decode": "^3.1.2", |
58 | "lodash-es": "^4.17.21", | 64 | "lodash-es": "^4.17.21", |
@@ -68,7 +74,7 @@ | @@ -68,7 +74,7 @@ | ||
68 | "vditor": "^3.8.6", | 74 | "vditor": "^3.8.6", |
69 | "video.js": "^7.20.3", | 75 | "video.js": "^7.20.3", |
70 | "videojs-flvjs-es6": "^1.0.1", | 76 | "videojs-flvjs-es6": "^1.0.1", |
71 | - "vue": "3.2.31", | 77 | + "vue": "3.3.4", |
72 | "vue-i18n": "9.1.7", | 78 | "vue-i18n": "9.1.7", |
73 | "vue-json-pretty": "^2.0.4", | 79 | "vue-json-pretty": "^2.0.4", |
74 | "vue-router": "^4.0.11", | 80 | "vue-router": "^4.0.11", |
src/api/ruleChainDesigner/index.ts
0 → 100644
1 | +import { DeviceInfoItemType, DeviceTypeItem, PageParams } from './model'; | ||
2 | +import { TBPaginationResult } from '/#/axios'; | ||
3 | +import { defHttp } from '/@/utils/http/axios'; | ||
4 | + | ||
5 | +enum Api { | ||
6 | + GET_DEVICE_INFOS = '/tenant/deviceInfos', | ||
7 | + GET_DEVICE_TYPE = '/device/types', | ||
8 | + TENANT_QUEUE = '/tenant/queues', | ||
9 | +} | ||
10 | + | ||
11 | +enum Entity { | ||
12 | + DEVICES = '/tenant/devices', | ||
13 | + ASSETS = '/tenant/assets', | ||
14 | + ENTITY_VIEW = '/tenant/entityViews', | ||
15 | + TENANT = '/tenant', | ||
16 | + CUSTOMER = '/customers', | ||
17 | + DASHBOARD = '/tenant/dashboards', | ||
18 | + USER = '/users', | ||
19 | + EDGE = '/tenant/edges', | ||
20 | +} | ||
21 | + | ||
22 | +export const getDeviceInfos = () => { | ||
23 | + return defHttp.get<TBPaginationResult<DeviceInfoItemType>>( | ||
24 | + { | ||
25 | + url: Api.GET_DEVICE_INFOS, | ||
26 | + }, | ||
27 | + { joinPrefix: false } | ||
28 | + ); | ||
29 | +}; | ||
30 | + | ||
31 | +export const getDeviceTypes = () => { | ||
32 | + return defHttp.get<TBPaginationResult<DeviceTypeItem[]>>( | ||
33 | + { | ||
34 | + url: Api.GET_DEVICE_TYPE, | ||
35 | + }, | ||
36 | + { joinPrefix: false } | ||
37 | + ); | ||
38 | +}; | ||
39 | + | ||
40 | +export const getTenantQueue = (params: Recordable) => { | ||
41 | + return defHttp.get<string[]>( | ||
42 | + { | ||
43 | + url: Api.TENANT_QUEUE, | ||
44 | + params, | ||
45 | + }, | ||
46 | + { joinPrefix: false } | ||
47 | + ); | ||
48 | +}; | ||
49 | + | ||
50 | +export const getEntityDevice = (params: PageParams) => { | ||
51 | + return defHttp.get( | ||
52 | + { | ||
53 | + url: Entity.DEVICES, | ||
54 | + params, | ||
55 | + }, | ||
56 | + { | ||
57 | + joinPrefix: false, | ||
58 | + } | ||
59 | + ); | ||
60 | +}; | ||
61 | + | ||
62 | +export const getEntityAssets = (params: PageParams) => { | ||
63 | + return defHttp.get( | ||
64 | + { | ||
65 | + url: Entity.ASSETS, | ||
66 | + params, | ||
67 | + }, | ||
68 | + { | ||
69 | + joinPrefix: false, | ||
70 | + } | ||
71 | + ); | ||
72 | +}; | ||
73 | + | ||
74 | +export const getEntityViews = (params: PageParams) => { | ||
75 | + return defHttp.get( | ||
76 | + { | ||
77 | + url: Entity.ENTITY_VIEW, | ||
78 | + params, | ||
79 | + }, | ||
80 | + { | ||
81 | + joinPrefix: false, | ||
82 | + } | ||
83 | + ); | ||
84 | +}; | ||
85 | + | ||
86 | +export const getEntityTenant = (params: Record<'tenantId', string>) => { | ||
87 | + return defHttp.get( | ||
88 | + { | ||
89 | + url: `${Entity.TENANT}/${params.tenantId}`, | ||
90 | + params, | ||
91 | + }, | ||
92 | + { | ||
93 | + joinPrefix: false, | ||
94 | + } | ||
95 | + ); | ||
96 | +}; | ||
97 | + | ||
98 | +export const getEntityCustomer = (params: PageParams) => { | ||
99 | + return defHttp.get( | ||
100 | + { | ||
101 | + url: Entity.CUSTOMER, | ||
102 | + params, | ||
103 | + }, | ||
104 | + { | ||
105 | + joinPrefix: false, | ||
106 | + } | ||
107 | + ); | ||
108 | +}; | ||
109 | + | ||
110 | +export const getEntityUser = (params: PageParams) => { | ||
111 | + return defHttp.get( | ||
112 | + { | ||
113 | + url: Entity.USER, | ||
114 | + params, | ||
115 | + }, | ||
116 | + { | ||
117 | + joinPrefix: false, | ||
118 | + } | ||
119 | + ); | ||
120 | +}; | ||
121 | + | ||
122 | +export const getEntityDashboard = (params: PageParams) => { | ||
123 | + return defHttp.get( | ||
124 | + { | ||
125 | + url: Entity.DASHBOARD, | ||
126 | + params, | ||
127 | + }, | ||
128 | + { | ||
129 | + joinPrefix: false, | ||
130 | + } | ||
131 | + ); | ||
132 | +}; | ||
133 | + | ||
134 | +export const getEntityEdge = (params: PageParams) => { | ||
135 | + return defHttp.get( | ||
136 | + { | ||
137 | + url: Entity.EDGE, | ||
138 | + params, | ||
139 | + }, | ||
140 | + { | ||
141 | + joinPrefix: false, | ||
142 | + } | ||
143 | + ); | ||
144 | +}; |
src/api/ruleChainDesigner/model/index.ts
0 → 100644
1 | +export interface DeviceInfoItemType { | ||
2 | + id: Id; | ||
3 | + createdTime: number; | ||
4 | + additionalInfo: AdditionalInfo; | ||
5 | + tenantId: Id; | ||
6 | + customerId: Id; | ||
7 | + name: string; | ||
8 | + type: string; | ||
9 | + label: string; | ||
10 | + deviceProfileId: Id; | ||
11 | + deviceData: DeviceData; | ||
12 | + firmwareId: any; | ||
13 | + softwareId: any; | ||
14 | + customerTitle: any; | ||
15 | + customerIsPublic: boolean; | ||
16 | + deviceProfileName: string; | ||
17 | +} | ||
18 | + | ||
19 | +export interface Id { | ||
20 | + entityType: string; | ||
21 | + id: string; | ||
22 | +} | ||
23 | + | ||
24 | +export interface DeviceData { | ||
25 | + configuration: Configuration; | ||
26 | + transportConfiguration: TransportConfiguration; | ||
27 | +} | ||
28 | + | ||
29 | +export interface AdditionalInfo { | ||
30 | + gateway: boolean; | ||
31 | + description: string; | ||
32 | + overwriteActivityTime: boolean; | ||
33 | +} | ||
34 | +export interface Configuration { | ||
35 | + type: string; | ||
36 | +} | ||
37 | + | ||
38 | +export interface TransportConfiguration { | ||
39 | + type: string; | ||
40 | +} | ||
41 | + | ||
42 | +export interface DeviceTypeItem { | ||
43 | + tenantId: Id; | ||
44 | + entityType: string; | ||
45 | + type: string; | ||
46 | +} | ||
47 | + | ||
48 | +export interface PageParams { | ||
49 | + pageSize?: number; | ||
50 | + page?: number; | ||
51 | + textSearch?: string; | ||
52 | + sortProperty?: string; | ||
53 | + sortOrder?: string; | ||
54 | +} |
src/api/ruleDesigner/index.ts
0 → 100644
1 | +import { RuleChainPaginationItemType } from './model/type'; | ||
2 | +import { TBPaginationResult } from '/#/axios'; | ||
3 | +import { defHttp } from '/@/utils/http/axios'; | ||
4 | +import { RuleChainType } from '/@/views/rule/designer/types/ruleNode'; | ||
5 | + | ||
6 | +enum Api { | ||
7 | + SAVE = '/ruleChain/metadata', | ||
8 | + GET_RULE_CHAINES = '/ruleChains', | ||
9 | + GET_RULE_NODE_EVENTS = '/events/RULE_NODE', | ||
10 | +} | ||
11 | + | ||
12 | +export const getRuleChainData = (id: string) => { | ||
13 | + return defHttp.get<RuleChainType>( | ||
14 | + { | ||
15 | + url: `/ruleChain/${id}/metadata`, | ||
16 | + }, | ||
17 | + { joinPrefix: false } | ||
18 | + ); | ||
19 | +}; | ||
20 | + | ||
21 | +export const saveRuleChainData = (data: RuleChainType) => { | ||
22 | + return defHttp.post( | ||
23 | + { | ||
24 | + url: Api.SAVE, | ||
25 | + data, | ||
26 | + }, | ||
27 | + { joinPrefix: false } | ||
28 | + ); | ||
29 | +}; | ||
30 | + | ||
31 | +export const getRuleChains = (params: Recordable) => { | ||
32 | + return defHttp.get<TBPaginationResult<RuleChainPaginationItemType>>( | ||
33 | + { | ||
34 | + url: Api.GET_RULE_CHAINES, | ||
35 | + params, | ||
36 | + }, | ||
37 | + { | ||
38 | + joinPrefix: false, | ||
39 | + } | ||
40 | + ); | ||
41 | +}; | ||
42 | + | ||
43 | +export const getRuleNodeEventList = ( | ||
44 | + ruleNodeId: string, | ||
45 | + params: Recordable, | ||
46 | + data: Recordable & Record<'eventType', string> | ||
47 | +) => { | ||
48 | + return defHttp.post<TBPaginationResult>( | ||
49 | + { | ||
50 | + url: `${Api.GET_RULE_NODE_EVENTS}/${ruleNodeId}`, | ||
51 | + params, | ||
52 | + data, | ||
53 | + }, | ||
54 | + { joinPrefix: false } | ||
55 | + ); | ||
56 | +}; |
src/api/ruleDesigner/model/type.ts
0 → 100644
1 | +export interface RuleChainPaginationItemType { | ||
2 | + id: Id; | ||
3 | + createdTime: number; | ||
4 | + additionalInfo?: AdditionalInfo; | ||
5 | + tenantId: Id; | ||
6 | + name: string; | ||
7 | + type: string; | ||
8 | + firstRuleNodeId: Id; | ||
9 | + root: boolean; | ||
10 | + debugMode: boolean; | ||
11 | + configuration: any; | ||
12 | +} | ||
13 | + | ||
14 | +export interface Id { | ||
15 | + entityType: string; | ||
16 | + id: string; | ||
17 | +} | ||
18 | + | ||
19 | +export interface AdditionalInfo { | ||
20 | + description: string; | ||
21 | +} |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | - import { ref, watch } from 'vue'; | ||
3 | - import JSONEditor, { JSONEditorOptions } from 'jsoneditor'; | ||
4 | - import 'jsoneditor/dist/jsoneditor.min.css'; | ||
5 | - import { unref } from 'vue'; | ||
6 | - import { onMounted } from 'vue'; | ||
7 | - import { computed } from '@vue/reactivity'; | ||
8 | - import { onUnmounted } from 'vue'; | 2 | + import { onMounted, computed, onUnmounted, unref, ref, watch } from 'vue'; |
3 | + import { Tooltip } from 'ant-design-vue'; | ||
4 | + import { Icon } from '/@/components/Icon'; | ||
5 | + import { useFullscreen } from '@vueuse/core'; | ||
6 | + import { isNumber, isObject, isString } from '/@/utils/is'; | ||
7 | + import AceEditor, { Ace } from 'ace-builds'; | ||
8 | + import workerJsonUrl from 'ace-builds/src-noconflict/worker-json?url'; | ||
9 | + import githubTheme from 'ace-builds/src-noconflict/theme-github?url'; | ||
10 | + import 'ace-builds/src-noconflict/mode-json'; | ||
9 | 11 | ||
10 | enum EventEnum { | 12 | enum EventEnum { |
11 | UPDATE_VALUE = 'update:value', | 13 | UPDATE_VALUE = 'update:value', |
@@ -16,89 +18,134 @@ | @@ -16,89 +18,134 @@ | ||
16 | 18 | ||
17 | const props = withDefaults( | 19 | const props = withDefaults( |
18 | defineProps<{ | 20 | defineProps<{ |
19 | - value?: string; | ||
20 | - options?: JSONEditorOptions; | ||
21 | - height?: number; | 21 | + value?: string | Recordable; |
22 | + height?: number | string; | ||
23 | + title?: string; | ||
24 | + disabled?: boolean; | ||
22 | }>(), | 25 | }>(), |
23 | { | 26 | { |
24 | - options: () => | ||
25 | - ({ | ||
26 | - mode: 'code', | ||
27 | - mainMenuBar: false, | ||
28 | - statusBar: false, | ||
29 | - } as JSONEditorOptions), | ||
30 | height: 150, | 27 | height: 150, |
31 | } | 28 | } |
32 | ); | 29 | ); |
33 | 30 | ||
34 | const emit = defineEmits<{ | 31 | const emit = defineEmits<{ |
35 | - (e: EventEnum.UPDATE_VALUE, value: any, instance?: JSONEditor): void; | ||
36 | - (e: EventEnum.CHANGE, value: any, instance?: JSONEditor): void; | ||
37 | - (e: EventEnum.BLUR, event: Event, instance?: JSONEditor): void; | ||
38 | - (e: EventEnum.FOCUS, event: Event, instance?: JSONEditor): void; | 32 | + (e: EventEnum.UPDATE_VALUE, value: any, instance?: Ace.Editor): void; |
33 | + (e: EventEnum.CHANGE, value: any, instance?: Ace.Editor): void; | ||
34 | + (e: EventEnum.BLUR, event: Event, instance?: Ace.Editor): void; | ||
35 | + (e: EventEnum.FOCUS, event: Event, instance?: Ace.Editor): void; | ||
39 | }>(); | 36 | }>(); |
40 | 37 | ||
41 | const jsonEditorElRef = ref<Nullable<any>>(); | 38 | const jsonEditorElRef = ref<Nullable<any>>(); |
42 | 39 | ||
43 | - const editoreRef = ref<JSONEditor>(); | 40 | + const editoreRef = ref<Ace.Editor>(); |
44 | 41 | ||
45 | const isFocus = ref(false); | 42 | const isFocus = ref(false); |
46 | 43 | ||
47 | - const handleChange = (value: any) => { | 44 | + const handleOnChange = () => { |
45 | + const value = get(); | ||
48 | emit(EventEnum.UPDATE_VALUE, value, unref(editoreRef)); | 46 | emit(EventEnum.UPDATE_VALUE, value, unref(editoreRef)); |
49 | emit(EventEnum.CHANGE, value, unref(editoreRef)); | 47 | emit(EventEnum.CHANGE, value, unref(editoreRef)); |
50 | }; | 48 | }; |
51 | 49 | ||
52 | - const handleEmit = (event: Event, key: EventEnum) => { | ||
53 | - emit(key as EventEnum[keyof EventEnum], event, unref(editoreRef)); | 50 | + const handleOnBlur = (event: Event) => { |
51 | + isFocus.value = false; | ||
52 | + emit(EventEnum.BLUR, event, unref(editoreRef)); | ||
54 | }; | 53 | }; |
55 | 54 | ||
56 | - const getOptions = computed(() => { | ||
57 | - const { options } = props; | ||
58 | - return { | ||
59 | - ...options, | ||
60 | - onChangeText: handleChange, | ||
61 | - onBlur: (event: Event) => { | ||
62 | - isFocus.value = false; | ||
63 | - handleEmit(event, EventEnum.BLUR); | ||
64 | - }, | ||
65 | - onFocus: (event: Event) => { | ||
66 | - isFocus.value = true; | ||
67 | - handleEmit(event, EventEnum.FOCUS); | ||
68 | - }, | ||
69 | - } as JSONEditorOptions; | ||
70 | - }); | 55 | + const handleOnFocus = (event: Event) => { |
56 | + isFocus.value = true; | ||
57 | + emit(EventEnum.FOCUS, event, unref(editoreRef)); | ||
58 | + }; | ||
59 | + | ||
60 | + const getFormatValue = (value: Recordable | string = '') => { | ||
61 | + return isObject(value) ? JSON.stringify(value, null, 2) : value; | ||
62 | + }; | ||
71 | 63 | ||
72 | const initialize = () => { | 64 | const initialize = () => { |
73 | - editoreRef.value = new JSONEditor(unref(jsonEditorElRef), unref(getOptions)); | 65 | + AceEditor.config.setModuleUrl('ace/mode/json_worker', workerJsonUrl); |
66 | + AceEditor.config.setModuleUrl('ace/theme/github', githubTheme); | ||
67 | + const editor = AceEditor.edit(unref(jsonEditorElRef)!, { | ||
68 | + mode: 'ace/mode/json', | ||
69 | + }); | ||
70 | + editor.setTheme('ace/theme/github'); | ||
71 | + editor.setOptions({ | ||
72 | + fontSize: 14, | ||
73 | + }); | ||
74 | + | ||
75 | + editor.on('change', handleOnChange); | ||
76 | + editor.on('blur', handleOnBlur); | ||
77 | + editor.on('focus', handleOnFocus); | ||
78 | + | ||
79 | + editoreRef.value = editor; | ||
80 | + unref(editoreRef)?.setValue(getFormatValue(props.value), 1); | ||
81 | + unref(editoreRef)?.setReadOnly(props.disabled); | ||
74 | }; | 82 | }; |
75 | 83 | ||
76 | watch( | 84 | watch( |
77 | () => props.value, | 85 | () => props.value, |
78 | (target) => { | 86 | (target) => { |
87 | + // const position = unref(editoreRef)?.getCursorPosition(); | ||
79 | if (unref(isFocus)) return; | 88 | if (unref(isFocus)) return; |
80 | - unref(editoreRef)?.setText(target || ''); | 89 | + unref(editoreRef)?.setValue(getFormatValue(target)); |
90 | + unref(editoreRef)?.clearSelection(); | ||
91 | + // position && unref(editoreRef)?.moveCursorToPosition(position!); | ||
81 | }, | 92 | }, |
82 | { | 93 | { |
83 | immediate: true, | 94 | immediate: true, |
84 | } | 95 | } |
85 | ); | 96 | ); |
86 | 97 | ||
98 | + watch( | ||
99 | + () => props.disabled, | ||
100 | + (value) => { | ||
101 | + unref(editoreRef)?.setReadOnly(value); | ||
102 | + } | ||
103 | + ); | ||
104 | + | ||
87 | const get = (): string => { | 105 | const get = (): string => { |
88 | - return unref(editoreRef)?.getText() || ''; | 106 | + return unref(editoreRef)?.getValue() || ''; |
89 | }; | 107 | }; |
90 | 108 | ||
91 | const set = (data: any) => { | 109 | const set = (data: any) => { |
92 | - return unref(editoreRef)?.set(data); | 110 | + return unref(editoreRef)?.setValue(getFormatValue(data)); |
93 | }; | 111 | }; |
94 | 112 | ||
95 | onMounted(() => { | 113 | onMounted(() => { |
96 | initialize(); | 114 | initialize(); |
97 | - unref(editoreRef)?.setText(props.value || ''); | 115 | + unref(editoreRef)?.setValue(getFormatValue(props.value)); |
98 | }); | 116 | }); |
99 | 117 | ||
100 | onUnmounted(() => { | 118 | onUnmounted(() => { |
119 | + unref(editoreRef)?.off('change', handleOnChange); | ||
120 | + unref(editoreRef)?.off('blur', handleOnBlur); | ||
121 | + unref(editoreRef)?.off('focus', handleOnFocus); | ||
101 | unref(editoreRef)?.destroy(); | 122 | unref(editoreRef)?.destroy(); |
123 | + unref(editoreRef)?.container.remove(); | ||
124 | + }); | ||
125 | + | ||
126 | + const handleFormat = () => { | ||
127 | + const value = get(); | ||
128 | + if (isString(value) && !value) return; | ||
129 | + unref(editoreRef)?.setValue(JSON.stringify(JSON.parse(value), null, 2)); | ||
130 | + unref(editoreRef)?.clearSelection(); | ||
131 | + }; | ||
132 | + | ||
133 | + const handleCompress = () => { | ||
134 | + const value = get(); | ||
135 | + if (isString(value) && !value) return; | ||
136 | + unref(editoreRef)?.setValue(JSON.stringify(JSON.parse(value))); | ||
137 | + unref(editoreRef)?.clearSelection(); | ||
138 | + }; | ||
139 | + | ||
140 | + const jsonEditorContainerElRef = ref<Nullable<HTMLDivElement>>(); | ||
141 | + const { isFullscreen, isSupported, toggle } = useFullscreen(jsonEditorContainerElRef); | ||
142 | + const handleFullScreen = () => { | ||
143 | + toggle(); | ||
144 | + }; | ||
145 | + | ||
146 | + const getHeight = computed(() => { | ||
147 | + const { height } = props; | ||
148 | + return isNumber(height) ? `${height}px` : height; | ||
102 | }); | 149 | }); |
103 | 150 | ||
104 | defineExpose({ | 151 | defineExpose({ |
@@ -108,22 +155,41 @@ | @@ -108,22 +155,41 @@ | ||
108 | </script> | 155 | </script> |
109 | 156 | ||
110 | <template> | 157 | <template> |
111 | - <div class="p-2 bg-gray-200" :style="{ height: `${height}px` }"> | ||
112 | - <div ref="jsonEditorElRef" class="jsoneditor"></div> | 158 | + <div |
159 | + ref="jsonEditorContainerElRef" | ||
160 | + class="p-2 bg-gray-200 flex flex-col" | ||
161 | + :style="{ height: getHeight }" | ||
162 | + > | ||
163 | + <div class="w-full h-8 flex justify-between items-center"> | ||
164 | + <div> | ||
165 | + {{ title }} | ||
166 | + </div> | ||
167 | + <slot name="header"></slot> | ||
168 | + <div class="flex h-8 gap-3 justify-end items-center text-dark-500 svg:text-2xl"> | ||
169 | + <slot name="beforeFormat"></slot> | ||
170 | + <Tooltip title="整洁"> | ||
171 | + <Icon @click="handleFormat" class="cursor-pointer" icon="gg:format-left" /> | ||
172 | + </Tooltip> | ||
173 | + <slot name="beforeCompress"></slot> | ||
174 | + | ||
175 | + <Tooltip title="迷你"> | ||
176 | + <Icon @click="handleCompress" class="cursor-pointer" icon="material-symbols:compress" /> | ||
177 | + </Tooltip> | ||
178 | + <slot name="beforeFullScreen"></slot> | ||
179 | + | ||
180 | + <Tooltip title="全屏"> | ||
181 | + <Icon | ||
182 | + v-if="isSupported" | ||
183 | + class="cursor-pointer" | ||
184 | + :icon=" | ||
185 | + isFullscreen ? 'material-symbols:fullscreen-exit' : 'material-symbols:fullscreen' | ||
186 | + " | ||
187 | + @click="handleFullScreen" | ||
188 | + /> | ||
189 | + </Tooltip> | ||
190 | + <slot name="afterFullScreen"></slot> | ||
191 | + </div> | ||
192 | + </div> | ||
193 | + <div ref="jsonEditorElRef" class="flex-auto"></div> | ||
113 | </div> | 194 | </div> |
114 | </template> | 195 | </template> |
115 | - | ||
116 | -<style lang="less" scoped> | ||
117 | - .jsoneditor { | ||
118 | - border: none !important; | ||
119 | - | ||
120 | - :deep(.jsoneditor) { | ||
121 | - border: none !important; | ||
122 | - | ||
123 | - .ace-jsoneditor, | ||
124 | - textarea.jsoneditor-text { | ||
125 | - min-height: auto; | ||
126 | - } | ||
127 | - } | ||
128 | - } | ||
129 | -</style> |
@@ -13,6 +13,7 @@ export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue'; | @@ -13,6 +13,7 @@ export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue'; | ||
13 | export { default as ApiUpload } from './src/components/ApiUpload.vue'; | 13 | export { default as ApiUpload } from './src/components/ApiUpload.vue'; |
14 | 14 | ||
15 | export { default as StructForm } from './src/externalCompns/components/StructForm/StructForm.vue'; | 15 | export { default as StructForm } from './src/externalCompns/components/StructForm/StructForm.vue'; |
16 | +export { default as JavaScriptFunctionEditor } from './src/components/JavaScriptFunctionEditor.vue'; | ||
16 | 17 | ||
17 | //注册自定义组件 | 18 | //注册自定义组件 |
18 | export { | 19 | export { |
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | :formProps="getProps" | 16 | :formProps="getProps" |
17 | :allDefaultValues="defaultValueRef" | 17 | :allDefaultValues="defaultValueRef" |
18 | :formModel="formModel" | 18 | :formModel="formModel" |
19 | + :validateFields="validateFields" | ||
19 | :setFormModel="setFormModel" | 20 | :setFormModel="setFormModel" |
20 | > | 21 | > |
21 | <template #[item]="data" v-for="item in Object.keys($slots)"> | 22 | <template #[item]="data" v-for="item in Object.keys($slots)"> |
@@ -229,10 +230,10 @@ | @@ -229,10 +230,10 @@ | ||
229 | 230 | ||
230 | function setFormModel(key: string, value: any) { | 231 | function setFormModel(key: string, value: any) { |
231 | formModel[key] = value; | 232 | formModel[key] = value; |
232 | - const { validateTrigger } = unref(getBindValue); | ||
233 | - if (!validateTrigger || validateTrigger === 'change') { | ||
234 | - validateFields([key]).catch((_) => {}); | ||
235 | - } | 233 | + // const { validateTrigger } = unref(getBindValue); |
234 | + // if (!validateTrigger || validateTrigger === 'change') { | ||
235 | + // validateFields([key]).catch((_) => {}); | ||
236 | + // } | ||
236 | } | 237 | } |
237 | 238 | ||
238 | function handleEnterPress(e: KeyboardEvent) { | 239 | function handleEnterPress(e: KeyboardEvent) { |
@@ -14,6 +14,7 @@ | @@ -14,6 +14,7 @@ | ||
14 | import { get, omit } from 'lodash-es'; | 14 | import { get, omit } from 'lodash-es'; |
15 | import { LoadingOutlined } from '@ant-design/icons-vue'; | 15 | import { LoadingOutlined } from '@ant-design/icons-vue'; |
16 | import { useI18n } from '/@/hooks/web/useI18n'; | 16 | import { useI18n } from '/@/hooks/web/useI18n'; |
17 | + import { useDebounceFn } from '@vueuse/shared'; | ||
17 | 18 | ||
18 | const emit = defineEmits(['options-change', 'change']); | 19 | const emit = defineEmits(['options-change', 'change']); |
19 | const props = withDefaults( | 20 | const props = withDefaults( |
@@ -27,6 +28,7 @@ | @@ -27,6 +28,7 @@ | ||
27 | labelField?: string; | 28 | labelField?: string; |
28 | valueField?: string; | 29 | valueField?: string; |
29 | immediate?: boolean; | 30 | immediate?: boolean; |
31 | + searchField?: string; | ||
30 | queryEmptyDataAgin?: boolean; | 32 | queryEmptyDataAgin?: boolean; |
31 | onChangeHook?: ({ options }: OnChangeHookParams) => void; | 33 | onChangeHook?: ({ options }: OnChangeHookParams) => void; |
32 | dropdownVisibleChangeHook?: ({ options }: OnChangeHookParams) => void; | 34 | dropdownVisibleChangeHook?: ({ options }: OnChangeHookParams) => void; |
@@ -35,6 +37,7 @@ | @@ -35,6 +37,7 @@ | ||
35 | resultField: '', | 37 | resultField: '', |
36 | labelField: 'label', | 38 | labelField: 'label', |
37 | valueField: 'value', | 39 | valueField: 'value', |
40 | + searchField: 'text', | ||
38 | immediate: true, | 41 | immediate: true, |
39 | queryEmptyDataAgin: true, | 42 | queryEmptyDataAgin: true, |
40 | } | 43 | } |
@@ -53,17 +56,27 @@ | @@ -53,17 +56,27 @@ | ||
53 | const { labelField, valueField = 'value', numberToString } = props; | 56 | const { labelField, valueField = 'value', numberToString } = props; |
54 | return unref(options).reduce((prev, next: Recordable) => { | 57 | return unref(options).reduce((prev, next: Recordable) => { |
55 | if (next) { | 58 | if (next) { |
56 | - const value = next[valueField]; | 59 | + const value = get(next, valueField); |
60 | + const label = get(next, labelField); | ||
57 | prev.push({ | 61 | prev.push({ |
58 | - label: next[labelField], | ||
59 | - value: numberToString ? `${value}` : value, | ||
60 | ...omit(next, [labelField, valueField]), | 62 | ...omit(next, [labelField, valueField]), |
63 | + label, | ||
64 | + value: numberToString ? `${value}` : value, | ||
61 | }); | 65 | }); |
62 | } | 66 | } |
63 | return prev; | 67 | return prev; |
64 | }, [] as OptionsItem[]); | 68 | }, [] as OptionsItem[]); |
65 | }); | 69 | }); |
66 | 70 | ||
71 | + const getBindProps = computed(() => { | ||
72 | + const { searchApi } = props; | ||
73 | + return { | ||
74 | + ...attrs, | ||
75 | + showSearch: true, | ||
76 | + filterOption: !searchApi, | ||
77 | + }; | ||
78 | + }); | ||
79 | + | ||
67 | watchEffect(() => { | 80 | watchEffect(() => { |
68 | props.immediate && fetch(); | 81 | props.immediate && fetch(); |
69 | }); | 82 | }); |
@@ -122,8 +135,9 @@ | @@ -122,8 +135,9 @@ | ||
122 | onChangeHook({ options }); | 135 | onChangeHook({ options }); |
123 | } | 136 | } |
124 | 137 | ||
138 | + const debounceSearchFunction = useDebounceFn(handleSearch, 300); | ||
125 | async function handleSearch(params?: string) { | 139 | async function handleSearch(params?: string) { |
126 | - let { searchApi, api } = props; | 140 | + let { searchApi, api, searchField } = props; |
127 | if (!searchApi || !isFunction(searchApi)) { | 141 | if (!searchApi || !isFunction(searchApi)) { |
128 | if (!api || !isFunction(api)) return; | 142 | if (!api || !isFunction(api)) return; |
129 | searchApi = api; | 143 | searchApi = api; |
@@ -131,7 +145,7 @@ | @@ -131,7 +145,7 @@ | ||
131 | options.value = []; | 145 | options.value = []; |
132 | try { | 146 | try { |
133 | loading.value = true; | 147 | loading.value = true; |
134 | - const res = await searchApi({ ...props.params, text: params }); | 148 | + const res = await searchApi({ ...props.params, [searchField]: params }); |
135 | if (Array.isArray(res)) { | 149 | if (Array.isArray(res)) { |
136 | options.value = res; | 150 | options.value = res; |
137 | emitChange(); | 151 | emitChange(); |
@@ -152,11 +166,10 @@ | @@ -152,11 +166,10 @@ | ||
152 | <template> | 166 | <template> |
153 | <Select | 167 | <Select |
154 | @dropdownVisibleChange="handleFetch" | 168 | @dropdownVisibleChange="handleFetch" |
155 | - v-bind="attrs" | ||
156 | - show-search | 169 | + v-bind="getBindProps" |
157 | @change="handleChange" | 170 | @change="handleChange" |
158 | :options="getOptions" | 171 | :options="getOptions" |
159 | - @search="handleSearch" | 172 | + @search="debounceSearchFunction" |
160 | v-model:value="state" | 173 | v-model:value="state" |
161 | > | 174 | > |
162 | <template #[item]="data" v-for="item in Object.keys($slots)"> | 175 | <template #[item]="data" v-for="item in Object.keys($slots)"> |
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | <script lang="ts" setup> | 6 | <script lang="ts" setup> |
7 | import { ref, watchEffect, computed, unref, watch, reactive } from 'vue'; | 7 | import { ref, watchEffect, computed, unref, watch, reactive } from 'vue'; |
8 | import { Select, Spin } from 'ant-design-vue'; | 8 | import { Select, Spin } from 'ant-design-vue'; |
9 | - import { isFunction } from '/@/utils/is'; | 9 | + import { isFunction, isNullAndUnDef } from '/@/utils/is'; |
10 | import { useRuleFormItem } from '/@/hooks/component/useFormItem'; | 10 | import { useRuleFormItem } from '/@/hooks/component/useFormItem'; |
11 | import { useAttrs } from '/@/hooks/core/useAttrs'; | 11 | import { useAttrs } from '/@/hooks/core/useAttrs'; |
12 | import { get, omit } from 'lodash-es'; | 12 | import { get, omit } from 'lodash-es'; |
@@ -30,8 +30,11 @@ | @@ -30,8 +30,11 @@ | ||
30 | labelField?: string; | 30 | labelField?: string; |
31 | valueField?: string; | 31 | valueField?: string; |
32 | immediate?: boolean; | 32 | immediate?: boolean; |
33 | - pagenation?: Pagination; | 33 | + searchField?: string; |
34 | + pagination?: Pagination; | ||
34 | queryEmptyDataAgin?: boolean; | 35 | queryEmptyDataAgin?: boolean; |
36 | + fetchSearch?: boolean; | ||
37 | + filterOption?: (inputValue: string, options: Recordable) => boolean; | ||
35 | }>(), | 38 | }>(), |
36 | { | 39 | { |
37 | resultField: '', | 40 | resultField: '', |
@@ -39,14 +42,15 @@ | @@ -39,14 +42,15 @@ | ||
39 | valueField: 'value', | 42 | valueField: 'value', |
40 | immediate: true, | 43 | immediate: true, |
41 | queryEmptyDataAgin: true, | 44 | queryEmptyDataAgin: true, |
42 | - pagenation: () => ({ page: 1, pageSize: 10 }), | 45 | + pagination: () => ({ page: 1, pageSize: 10 }), |
46 | + fetchSearch: false, | ||
43 | } | 47 | } |
44 | ); | 48 | ); |
45 | 49 | ||
46 | const OptionsItem = (_, { attrs }: { attrs: { vNode: any } }) => attrs.vNode; | 50 | const OptionsItem = (_, { attrs }: { attrs: { vNode: any } }) => attrs.vNode; |
47 | 51 | ||
48 | const options = ref<OptionsItem[]>([]); | 52 | const options = ref<OptionsItem[]>([]); |
49 | - const pagination = reactive(Object.assign({ total: 0, page: 1, pageSize: 10 }, props.pagenation)); | 53 | + const pagination = reactive<Record<'total' | 'page' | 'pageSize', number>>({} as any); |
50 | const scrollLoading = ref(false); | 54 | const scrollLoading = ref(false); |
51 | const lock = ref(false); | 55 | const lock = ref(false); |
52 | const loading = ref(false); | 56 | const loading = ref(false); |
@@ -55,6 +59,13 @@ | @@ -55,6 +59,13 @@ | ||
55 | const attrs = useAttrs(); | 59 | const attrs = useAttrs(); |
56 | const { t } = useI18n(); | 60 | const { t } = useI18n(); |
57 | 61 | ||
62 | + const getPagination = computed(() => { | ||
63 | + return { | ||
64 | + ...props.pagination, | ||
65 | + ...unref(pagination), | ||
66 | + }; | ||
67 | + }); | ||
68 | + | ||
58 | // Embedded in the form, just use the hook binding to perform form verification | 69 | // Embedded in the form, just use the hook binding to perform form verification |
59 | const [state] = useRuleFormItem(props, 'value', 'change', emitData); | 70 | const [state] = useRuleFormItem(props, 'value', 'change', emitData); |
60 | 71 | ||
@@ -86,16 +97,18 @@ | @@ -86,16 +97,18 @@ | ||
86 | { deep: true } | 97 | { deep: true } |
87 | ); | 98 | ); |
88 | 99 | ||
89 | - async function fetch() { | ||
90 | - const api = props.api; | 100 | + async function fetch(searchText?: string) { |
101 | + const { api, searchField, fetchSearch } = props; | ||
91 | if (!api || !isFunction(api)) return; | 102 | if (!api || !isFunction(api)) return; |
103 | + const isFetchSearchFlag = fetchSearch && !isNullAndUnDef(searchText) && searchField; | ||
92 | try { | 104 | try { |
93 | !unref(getOptions).length ? (loading.value = true) : (scrollLoading.value = true); | 105 | !unref(getOptions).length ? (loading.value = true) : (scrollLoading.value = true); |
94 | lock.value = true; | 106 | lock.value = true; |
95 | const { total, items } = await api({ | 107 | const { total, items } = await api({ |
96 | ...props.params, | 108 | ...props.params, |
97 | - page: pagination.page, | ||
98 | - pageSize: pagination.pageSize, | 109 | + page: unref(getPagination).page, |
110 | + pageSize: unref(getPagination).pageSize, | ||
111 | + ...(isFetchSearchFlag ? { [searchField!]: searchText } : {}), | ||
99 | }); | 112 | }); |
100 | 113 | ||
101 | pagination.total = total; | 114 | pagination.total = total; |
@@ -105,11 +118,13 @@ | @@ -105,11 +118,13 @@ | ||
105 | return; | 118 | return; |
106 | } | 119 | } |
107 | if (props.resultField) { | 120 | if (props.resultField) { |
108 | - options.value = [...options.value, ...(get(items, props.resultField) || [])]; | 121 | + options.value = isFetchSearchFlag |
122 | + ? get(items, props.resultField) || [] | ||
123 | + : [...options.value, ...(get(items, props.resultField) || [])]; | ||
109 | } | 124 | } |
110 | emitChange(); | 125 | emitChange(); |
111 | } catch (error) { | 126 | } catch (error) { |
112 | - pagination.page = Math.ceil(unref(getOptions).length / pagination.pageSize); | 127 | + pagination.page = Math.ceil(unref(getOptions).length / unref(getPagination).pageSize); |
113 | console.warn(error); | 128 | console.warn(error); |
114 | } finally { | 129 | } finally { |
115 | isFirstLoad.value = false; | 130 | isFirstLoad.value = false; |
@@ -134,17 +149,39 @@ | @@ -134,17 +149,39 @@ | ||
134 | emitData.value = args; | 149 | emitData.value = args; |
135 | } | 150 | } |
136 | 151 | ||
152 | + const sleep = async (number: number) => { | ||
153 | + return new Promise((resolve) => { | ||
154 | + setTimeout(() => { | ||
155 | + resolve(number); | ||
156 | + }, number); | ||
157 | + }); | ||
158 | + }; | ||
159 | + | ||
137 | async function handlePopupScroll(event: MouseEvent) { | 160 | async function handlePopupScroll(event: MouseEvent) { |
138 | const { scrollHeight, scrollTop, clientHeight } = event.target as HTMLDivElement; | 161 | const { scrollHeight, scrollTop, clientHeight } = event.target as HTMLDivElement; |
139 | if (scrollTop + clientHeight >= scrollHeight) { | 162 | if (scrollTop + clientHeight >= scrollHeight) { |
140 | - if (unref(getOptions).length < pagination.total && !unref(lock)) { | ||
141 | - pagination.page = pagination.page + 1; | 163 | + if (unref(getOptions).length < unref(getPagination).total && !unref(lock)) { |
164 | + pagination.page = unref(getPagination).page + 1; | ||
165 | + scrollLoading.value = true; | ||
166 | + await sleep(500); | ||
142 | await fetch(); | 167 | await fetch(); |
143 | } | 168 | } |
144 | } | 169 | } |
145 | } | 170 | } |
146 | 171 | ||
147 | const debounceHandlePopupScroll = useDebounceFn(handlePopupScroll, 100); | 172 | const debounceHandlePopupScroll = useDebounceFn(handlePopupScroll, 100); |
173 | + | ||
174 | + const handleFilterOption = async (inputValue: string, option: Recordable) => { | ||
175 | + const { filterOption, fetchSearch } = props; | ||
176 | + if (filterOption && isFunction(filterOption)) { | ||
177 | + filterOption?.(inputValue, option); | ||
178 | + return; | ||
179 | + } | ||
180 | + | ||
181 | + if (fetchSearch) { | ||
182 | + await fetch(inputValue); | ||
183 | + } | ||
184 | + }; | ||
148 | </script> | 185 | </script> |
149 | 186 | ||
150 | <template> | 187 | <template> |
@@ -153,6 +190,8 @@ | @@ -153,6 +190,8 @@ | ||
153 | v-bind="attrs" | 190 | v-bind="attrs" |
154 | @change="handleChange" | 191 | @change="handleChange" |
155 | :options="getOptions" | 192 | :options="getOptions" |
193 | + :filterOption="handleFilterOption" | ||
194 | + :showSearch="true" | ||
156 | v-model:value="state" | 195 | v-model:value="state" |
157 | @popup-scroll="debounceHandlePopupScroll" | 196 | @popup-scroll="debounceHandlePopupScroll" |
158 | > | 197 | > |
@@ -40,16 +40,19 @@ | @@ -40,16 +40,19 @@ | ||
40 | accept?: string; | 40 | accept?: string; |
41 | maxSize?: number; | 41 | maxSize?: number; |
42 | disabled?: boolean; | 42 | disabled?: boolean; |
43 | - listType?: string; | 43 | + listType?: 'text' | 'picture-card' | 'picture'; |
44 | multiple?: boolean; | 44 | multiple?: boolean; |
45 | maxFileLimit?: number; | 45 | maxFileLimit?: number; |
46 | - showUploadList?: boolean | { showPreviewIcon?: boolean; showRemoveIcon?: boolean }; | 46 | + showUploadList?: InstanceType<typeof Upload>['$props']['showUploadList']; |
47 | transformFile?: (file: File) => string | Blob | Promise<string | Blob | File>; | 47 | transformFile?: (file: File) => string | Blob | Promise<string | Blob | File>; |
48 | api: (file: string | Blob | Promise<string | Blob | File>) => Promise<FileItem>; | 48 | api: (file: string | Blob | Promise<string | Blob | File>) => Promise<FileItem>; |
49 | + overFileLimitHiddenUploadEntry?: boolean; | ||
49 | }>(), | 50 | }>(), |
50 | { | 51 | { |
51 | fileList: () => [], | 52 | fileList: () => [], |
52 | maxSize: 5 * 1024 * 1024, | 53 | maxSize: 5 * 1024 * 1024, |
54 | + overFileLimitHiddenUploadEntry: true, | ||
55 | + listType: 'text', | ||
53 | showUploadList: () => ({ showPreviewIcon: true, showRemoveIcon: true }), | 56 | showUploadList: () => ({ showPreviewIcon: true, showRemoveIcon: true }), |
54 | } | 57 | } |
55 | ); | 58 | ); |
@@ -75,7 +78,7 @@ | @@ -75,7 +78,7 @@ | ||
75 | 78 | ||
76 | const getMaxFileLimit = computed(() => { | 79 | const getMaxFileLimit = computed(() => { |
77 | const { maxFileLimit } = props; | 80 | const { maxFileLimit } = props; |
78 | - return isPictureCard.value ? 1 : maxFileLimit; | 81 | + return isPictureCard.value ? 1 : maxFileLimit || 1; |
79 | }); | 82 | }); |
80 | 83 | ||
81 | const handleUpload = async (file: File | string | Blob | Promise<string | Blob | File>) => { | 84 | const handleUpload = async (file: File | string | Blob | Promise<string | Blob | File>) => { |
@@ -131,11 +134,15 @@ | @@ -131,11 +134,15 @@ | ||
131 | :list-type="props.listType" | 134 | :list-type="props.listType" |
132 | :disabled="getDisabled" | 135 | :disabled="getDisabled" |
133 | :before-upload="handleBeforeUpload" | 136 | :before-upload="handleBeforeUpload" |
137 | + :show-upload-list="showUploadList" | ||
134 | @preview="handlePreview" | 138 | @preview="handlePreview" |
135 | @download="handleDownload" | 139 | @download="handleDownload" |
136 | :remove="handleRemove" | 140 | :remove="handleRemove" |
137 | > | 141 | > |
138 | - <Spin v-if="!fileList.length" :spinning="loading"> | 142 | + <Spin |
143 | + v-if="!(fileList.length >= getMaxFileLimit) || overFileLimitHiddenUploadEntry" | ||
144 | + :spinning="loading" | ||
145 | + > | ||
139 | <div class="w-full h-full flex flex-col justify-center content-center"> | 146 | <div class="w-full h-full flex flex-col justify-center content-center"> |
140 | <Tooltip title="点击上传或拖拽上传"> | 147 | <Tooltip title="点击上传或拖拽上传"> |
141 | <InboxOutlined class="text-[3rem] !text-blue-500" /> | 148 | <InboxOutlined class="text-[3rem] !text-blue-500" /> |
@@ -14,6 +14,7 @@ | @@ -14,6 +14,7 @@ | ||
14 | import { upperFirst, cloneDeep } from 'lodash-es'; | 14 | import { upperFirst, cloneDeep } from 'lodash-es'; |
15 | import { useItemLabelWidth } from '../hooks/useLabelWidth'; | 15 | import { useItemLabelWidth } from '../hooks/useLabelWidth'; |
16 | import { useI18n } from '/@/hooks/web/useI18n'; | 16 | import { useI18n } from '/@/hooks/web/useI18n'; |
17 | + import { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface'; | ||
17 | 18 | ||
18 | export default defineComponent({ | 19 | export default defineComponent({ |
19 | name: 'BasicFormItem', | 20 | name: 'BasicFormItem', |
@@ -39,6 +40,12 @@ | @@ -39,6 +40,12 @@ | ||
39 | type: Function as PropType<(key: string, value: any) => void>, | 40 | type: Function as PropType<(key: string, value: any) => void>, |
40 | default: null, | 41 | default: null, |
41 | }, | 42 | }, |
43 | + validateFields: { | ||
44 | + type: Function as PropType< | ||
45 | + (nameList?: NamePath[], options?: ValidateOptions) => Promise<any> | ||
46 | + >, | ||
47 | + default: null, | ||
48 | + }, | ||
42 | tableAction: { | 49 | tableAction: { |
43 | type: Object as PropType<TableActionType>, | 50 | type: Object as PropType<TableActionType>, |
44 | }, | 51 | }, |
@@ -208,6 +215,7 @@ | @@ -208,6 +215,7 @@ | ||
208 | rules[characterInx].message || | 215 | rules[characterInx].message || |
209 | t('component.form.maxTip', [rules[characterInx].max] as Recordable); | 216 | t('component.form.maxTip', [rules[characterInx].max] as Recordable); |
210 | } | 217 | } |
218 | + rules.forEach((item) => !item.trigger && (item.trigger = 'change')); | ||
211 | return rules; | 219 | return rules; |
212 | } | 220 | } |
213 | 221 | ||
@@ -234,6 +242,10 @@ | @@ -234,6 +242,10 @@ | ||
234 | const value = target ? (isCheck ? target.checked : target.value) : e; | 242 | const value = target ? (isCheck ? target.checked : target.value) : e; |
235 | props.setFormModel(field, value); | 243 | props.setFormModel(field, value); |
236 | }, | 244 | }, |
245 | + onBlur: (...args) => { | ||
246 | + unref(getComponentsProps)?.onBlur?.(...args); | ||
247 | + props.validateFields([field], { triggerName: 'blur' }).catch((_) => {}); | ||
248 | + }, | ||
237 | }; | 249 | }; |
238 | const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>; | 250 | const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>; |
239 | 251 |
1 | +<script lang="ts" setup> | ||
2 | + import { Icon } from '/@/components/Icon'; | ||
3 | + import { Tooltip } from 'ant-design-vue'; | ||
4 | + import { computed, onMounted, onUnmounted, ref, shallowRef, unref, watch } from 'vue'; | ||
5 | + import AceEditor, { Ace } from 'ace-builds'; | ||
6 | + import workerJavascriptUrl from 'ace-builds/src-noconflict/worker-javascript?url'; | ||
7 | + import githubTheme from 'ace-builds/src-noconflict/theme-github?url'; | ||
8 | + import 'ace-builds/src-noconflict/mode-javascript'; | ||
9 | + import 'ace-builds/src-noconflict/ext-searchbox'; | ||
10 | + import 'ace-builds/src-noconflict/ext-language_tools'; | ||
11 | + import 'ace-builds/src-noconflict/snippets/javascript'; | ||
12 | + import { useBeautify } from '/@/hooks/business/useBeautify'; | ||
13 | + import { useFullscreen } from '@vueuse/core'; | ||
14 | + import { isNumber } from '/@/utils/is'; | ||
15 | + | ||
16 | + const emit = defineEmits(['update:value', 'focus', 'blur']); | ||
17 | + const props = withDefaults( | ||
18 | + defineProps<{ | ||
19 | + functionName?: string; | ||
20 | + paramsName?: string[]; | ||
21 | + height?: number | string; | ||
22 | + value?: string; | ||
23 | + disabled?: boolean; | ||
24 | + validateStatus?: boolean; | ||
25 | + }>(), | ||
26 | + { | ||
27 | + functionName: 'method', | ||
28 | + paramsName: () => [], | ||
29 | + height: 200, | ||
30 | + value: '', | ||
31 | + } | ||
32 | + ); | ||
33 | + | ||
34 | + const getHeight = computed(() => { | ||
35 | + const { height } = props; | ||
36 | + return isNumber(height) ? `${height}px` : height; | ||
37 | + }); | ||
38 | + | ||
39 | + const javaScriptEditorElRef = ref<Nullable<HTMLDivElement>>(); | ||
40 | + const editorInstance = shallowRef<Ace.Editor>(); | ||
41 | + const isFocus = ref(false); | ||
42 | + | ||
43 | + const handleFocus = () => { | ||
44 | + isFocus.value = true; | ||
45 | + emit('focus', unref(editorInstance)); | ||
46 | + }; | ||
47 | + | ||
48 | + const handleBlur = () => { | ||
49 | + isFocus.value = false; | ||
50 | + emit('update:value', get()); | ||
51 | + emit('blur', unref(editorInstance)); | ||
52 | + }; | ||
53 | + | ||
54 | + const handleChange = () => { | ||
55 | + emit('update:value', get()); | ||
56 | + }; | ||
57 | + | ||
58 | + const initEditor = () => { | ||
59 | + AceEditor.config.setModuleUrl('ace/mode/javascript_worker', workerJavascriptUrl); | ||
60 | + AceEditor.config.setModuleUrl('ace/theme/github', githubTheme); | ||
61 | + const editor = AceEditor.edit(unref(javaScriptEditorElRef)!, { | ||
62 | + mode: 'ace/mode/javascript', | ||
63 | + }); | ||
64 | + editor.setTheme('ace/theme/github'); | ||
65 | + editor.setOptions({ | ||
66 | + fontSize: 14, | ||
67 | + enableBasicAutocompletion: true, | ||
68 | + enableSnippets: true, | ||
69 | + enableLiveAutocompletion: true, | ||
70 | + }); | ||
71 | + | ||
72 | + editor.on('focus', handleFocus); | ||
73 | + editor.on('blur', handleBlur); | ||
74 | + editor.on('change', handleChange); | ||
75 | + editorInstance.value = editor; | ||
76 | + editor.setValue(props.value); | ||
77 | + editor?.clearSelection(); | ||
78 | + unref(editorInstance)?.setReadOnly(props.disabled); | ||
79 | + }; | ||
80 | + | ||
81 | + const get = () => { | ||
82 | + return unref(editorInstance)?.getValue(); | ||
83 | + }; | ||
84 | + | ||
85 | + const set = (val: string, cursorPos?: number) => { | ||
86 | + return unref(editorInstance)?.setValue(val, cursorPos); | ||
87 | + }; | ||
88 | + | ||
89 | + onMounted(() => { | ||
90 | + initEditor(); | ||
91 | + }); | ||
92 | + | ||
93 | + onUnmounted(() => { | ||
94 | + unref(editorInstance)?.off('change', handleChange); | ||
95 | + unref(editorInstance)?.off('focus', handleFocus); | ||
96 | + unref(editorInstance)?.off('blur', handleBlur); | ||
97 | + unref(editorInstance)?.destroy(); | ||
98 | + unref(editorInstance)?.container.remove(); | ||
99 | + }); | ||
100 | + | ||
101 | + const { beautifyJs } = useBeautify(); | ||
102 | + const handleFormatCode = async () => { | ||
103 | + const res = await beautifyJs(get() || '', { indent_size: 4, wrap_line_length: 60 }); | ||
104 | + set(res || '', -1); | ||
105 | + }; | ||
106 | + | ||
107 | + const jsFunctionContainerElRef = ref<Nullable<HTMLDivElement>>(); | ||
108 | + const { isFullscreen, isSupported, toggle } = useFullscreen(jsFunctionContainerElRef); | ||
109 | + const handleFullScreen = () => { | ||
110 | + toggle(); | ||
111 | + }; | ||
112 | + | ||
113 | + watch( | ||
114 | + () => props.value, | ||
115 | + (value) => { | ||
116 | + // const position = unref(editorInstance)?.getCursorPosition(); | ||
117 | + if (unref(isFocus)) return; | ||
118 | + set(value); | ||
119 | + unref(editorInstance)?.clearSelection(); | ||
120 | + // position && unref(editorInstance)?.moveCursorToPosition(position!); | ||
121 | + }, | ||
122 | + { | ||
123 | + immediate: true, | ||
124 | + } | ||
125 | + ); | ||
126 | + | ||
127 | + watch( | ||
128 | + () => props.disabled, | ||
129 | + (value) => { | ||
130 | + unref(editorInstance)?.setReadOnly(value); | ||
131 | + } | ||
132 | + ); | ||
133 | + | ||
134 | + defineExpose({ | ||
135 | + get, | ||
136 | + set, | ||
137 | + }); | ||
138 | +</script> | ||
139 | + | ||
140 | +<template> | ||
141 | + <section | ||
142 | + ref="jsFunctionContainerElRef" | ||
143 | + class="p-2 bg-gray-200 flex flex-col" | ||
144 | + :style="{ height: getHeight }" | ||
145 | + > | ||
146 | + <head class="flex justify-between h-8 items-center"> | ||
147 | + <div class="font-bold"> | ||
148 | + <span>function</span> | ||
149 | + <span class="ml-1">{{ functionName }}</span> | ||
150 | + <span>({{ paramsName.join(',') }})</span> | ||
151 | + <span class="ml-1">{</span> | ||
152 | + </div> | ||
153 | + <div class="flex gap-3 items-center svg:text-2xl"> | ||
154 | + <slot name="beforeFormat"></slot> | ||
155 | + | ||
156 | + <Tooltip title="整洁"> | ||
157 | + <Icon class="cursor-pointer" icon="gg:format-left" @click="handleFormatCode" /> | ||
158 | + </Tooltip> | ||
159 | + <slot name="beforeFullScreen"></slot> | ||
160 | + <Tooltip title="全屏"> | ||
161 | + <Icon | ||
162 | + v-if="isSupported" | ||
163 | + class="cursor-pointer" | ||
164 | + :icon=" | ||
165 | + isFullscreen ? 'material-symbols:fullscreen-exit' : 'material-symbols:fullscreen' | ||
166 | + " | ||
167 | + @click="handleFullScreen" | ||
168 | + /> | ||
169 | + </Tooltip> | ||
170 | + <slot name="afterFullScreen"></slot> | ||
171 | + </div> | ||
172 | + </head> | ||
173 | + <main ref="javaScriptEditorElRef" class="flex-auto"> </main> | ||
174 | + <footer class="font-bold">}</footer> | ||
175 | + </section> | ||
176 | +</template> |
1 | import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form'; | 1 | import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form'; |
2 | -import type { NamePath } from 'ant-design-vue/lib/form/interface'; | 2 | +import type { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface'; |
3 | import type { DynamicProps } from '/#/utils'; | 3 | import type { DynamicProps } from '/#/utils'; |
4 | import { ref, onUnmounted, unref, nextTick, watch } from 'vue'; | 4 | import { ref, onUnmounted, unref, nextTick, watch } from 'vue'; |
5 | import { isProdMode } from '/@/utils/env'; | 5 | import { isProdMode } from '/@/utils/env'; |
@@ -112,9 +112,12 @@ export function useForm(props?: Props): UseFormReturnType { | @@ -112,9 +112,12 @@ export function useForm(props?: Props): UseFormReturnType { | ||
112 | return form.validate(nameList); | 112 | return form.validate(nameList); |
113 | }, | 113 | }, |
114 | 114 | ||
115 | - validateFields: async (nameList?: NamePath[]): Promise<Recordable> => { | 115 | + validateFields: async ( |
116 | + nameList?: NamePath[], | ||
117 | + options?: ValidateOptions | ||
118 | + ): Promise<Recordable> => { | ||
116 | const form = await getForm(); | 119 | const form = await getForm(); |
117 | - return form.validateFields(nameList); | 120 | + return form.validateFields(nameList, options); |
118 | }, | 121 | }, |
119 | }; | 122 | }; |
120 | 123 |
1 | import type { ComputedRef, Ref } from 'vue'; | 1 | import type { ComputedRef, Ref } from 'vue'; |
2 | import type { FormProps, FormSchema, FormActionType } from '../types/form'; | 2 | import type { FormProps, FormSchema, FormActionType } from '../types/form'; |
3 | -import type { NamePath } from 'ant-design-vue/lib/form/interface'; | 3 | +import type { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface'; |
4 | import { unref, toRaw } from 'vue'; | 4 | import { unref, toRaw } from 'vue'; |
5 | import { isArray, isFunction, isObject, isString } from '/@/utils/is'; | 5 | import { isArray, isFunction, isObject, isString } from '/@/utils/is'; |
6 | import { deepMerge } from '/@/utils'; | 6 | import { deepMerge } from '/@/utils'; |
@@ -206,8 +206,8 @@ export function useFormEvents({ | @@ -206,8 +206,8 @@ export function useFormEvents({ | ||
206 | }); | 206 | }); |
207 | } | 207 | } |
208 | 208 | ||
209 | - async function validateFields(nameList?: NamePath[] | undefined) { | ||
210 | - return unref(formElRef)?.validateFields(nameList); | 209 | + async function validateFields(nameList?: NamePath[] | undefined, options?: ValidateOptions) { |
210 | + return unref(formElRef)?.validateFields(nameList, options); | ||
211 | } | 211 | } |
212 | 212 | ||
213 | async function validate(nameList?: NamePath[] | undefined) { | 213 | async function validate(nameList?: NamePath[] | undefined) { |
1 | -import type { NamePath, RuleObject } from 'ant-design-vue/lib/form/interface'; | 1 | +import type { NamePath, RuleObject, ValidateOptions } from 'ant-design-vue/lib/form/interface'; |
2 | import type { VNode } from 'vue'; | 2 | import type { VNode } from 'vue'; |
3 | import type { ButtonProps as AntdButtonProps } from '/@/components/Button'; | 3 | import type { ButtonProps as AntdButtonProps } from '/@/components/Button'; |
4 | import type { FormItem } from './formItem'; | 4 | import type { FormItem } from './formItem'; |
@@ -39,7 +39,7 @@ export interface FormActionType { | @@ -39,7 +39,7 @@ export interface FormActionType { | ||
39 | prefixField: string | undefined, | 39 | prefixField: string | undefined, |
40 | first?: boolean | undefined | 40 | first?: boolean | undefined |
41 | ) => Promise<void>; | 41 | ) => Promise<void>; |
42 | - validateFields: (nameList?: NamePath[]) => Promise<any>; | 42 | + validateFields: (nameList?: NamePath[], options?: ValidateOptions) => Promise<any>; |
43 | validate: (nameList?: NamePath[]) => Promise<any>; | 43 | validate: (nameList?: NamePath[]) => Promise<any>; |
44 | scrollToField: (name: NamePath, options?: ScrollOptions) => Promise<void>; | 44 | scrollToField: (name: NamePath, options?: ScrollOptions) => Promise<void>; |
45 | } | 45 | } |
@@ -130,4 +130,11 @@ export type ComponentType = | @@ -130,4 +130,11 @@ export type ComponentType = | ||
130 | | 'ControlGroup' | 130 | | 'ControlGroup' |
131 | | 'JSONEditor' | 131 | | 'JSONEditor' |
132 | | 'OrgTreeSelect' | 132 | | 'OrgTreeSelect' |
133 | - | 'ExtendDesc'; | 133 | + | 'ExtendDesc' |
134 | + | 'JavaScriptFunctionEditor' | ||
135 | + | 'JavascriptEditorWithTestModal' | ||
136 | + | 'AttributeConfiguration' | ||
137 | + | 'CorrelationFilters' | ||
138 | + | 'RelationsQuery' | ||
139 | + | 'CredentialsCard' | ||
140 | + | 'ApiComplete'; |
src/enums/alarmEnum.ts
0 → 100644
1 | +export enum AlarmStatus { | ||
2 | + CLEARED_UN_ACK = 'CLEARED_UNACK', | ||
3 | + ACTIVE_UN_ACK = 'ACTIVE_UNACK', | ||
4 | + CLEARED_ACK = 'CLEARED_ACK', | ||
5 | + ACTIVE_ACK = 'ACTIVE_ACK', | ||
6 | +} | ||
7 | + | ||
8 | +export enum AlarmStatusMean { | ||
9 | + CLEARED_UNACK = '清除未确认', | ||
10 | + ACTIVE_UNACK = '激活未确认', | ||
11 | + CLEARED_ACK = '清除已确认', | ||
12 | + ACTIVE_ACK = '激活已确认', | ||
13 | +} |
@@ -19,4 +19,8 @@ export enum DictEnum { | @@ -19,4 +19,8 @@ export enum DictEnum { | ||
19 | DISABLE_CUSTOMER_AUTH = 'disabled_customer_auth', | 19 | DISABLE_CUSTOMER_AUTH = 'disabled_customer_auth', |
20 | // 寄存器数据格式 | 20 | // 寄存器数据格式 |
21 | REGISTER_DATA_FORMAT = 'register_data_format', | 21 | REGISTER_DATA_FORMAT = 'register_data_format', |
22 | + // 消息类型 规则节点 Filter message type switch | ||
23 | + MESSAGE_TYPES_FILTER = 'message_types_filter', | ||
24 | + // 实体类型 规则节点 Filter originator types switch | ||
25 | + ORIGINATOR_TYPES = 'originator_types', | ||
22 | } | 26 | } |
src/hooks/business/useBatchSettingDict.ts
0 → 100644
1 | +import { saveOrEditDictItem } from '/@/api/system/dict'; | ||
2 | +import { SysDictItem } from '/@/api/system/model/dictModel'; | ||
3 | + | ||
4 | +interface BatchSettingParamsType { | ||
5 | + dictId: string; | ||
6 | + list: any[]; | ||
7 | + transformText: (item: any) => any; | ||
8 | + transformValue: (item: any) => any; | ||
9 | + update?: boolean; | ||
10 | +} | ||
11 | + | ||
12 | +export function useBatchSettingDict() { | ||
13 | + const batchSetting = async (options: BatchSettingParamsType) => { | ||
14 | + const { dictId, list, transformText, transformValue, update = false } = options; | ||
15 | + if (!transformText || !transformValue) return; | ||
16 | + let index = 1; | ||
17 | + for (const item of list) { | ||
18 | + const params: Partial<SysDictItem> & { dictId: string } = { | ||
19 | + dictId, | ||
20 | + sort: index++, | ||
21 | + status: 1, | ||
22 | + itemText: transformText(item), | ||
23 | + itemValue: transformValue(item), | ||
24 | + }; | ||
25 | + | ||
26 | + await saveOrEditDictItem(params as SysDictItem, update); | ||
27 | + } | ||
28 | + }; | ||
29 | + | ||
30 | + const batchDelete = () => {}; | ||
31 | + | ||
32 | + return { | ||
33 | + batchSetting, | ||
34 | + batchDelete, | ||
35 | + }; | ||
36 | +} |
src/hooks/business/useBeautify.ts
0 → 100644
1 | +export function useBeautify() { | ||
2 | + let jsBeautifyModule: any; | ||
3 | + | ||
4 | + async function loadJsBeautify() { | ||
5 | + if (jsBeautifyModule) return jsBeautifyModule; | ||
6 | + jsBeautifyModule = await import('js-beautify/js/lib/beautifier'); | ||
7 | + return jsBeautifyModule; | ||
8 | + } | ||
9 | + | ||
10 | + async function beautifyJs(source: string, options?: any) { | ||
11 | + const module = await loadJsBeautify(); | ||
12 | + return module.js(source, options); | ||
13 | + } | ||
14 | + return { beautifyJs }; | ||
15 | +} |
src/hooks/business/useJsonParse.ts
0 → 100644
1 | +import { isObject, isString } from '/@/utils/is'; | ||
2 | + | ||
3 | +export function useJsonParse(value: any, defaultValue = {}) { | ||
4 | + let flag = false; | ||
5 | + try { | ||
6 | + value = JSON.parse(value); | ||
7 | + if (isObject(value) || (isString(value) && value.trim() === '')) flag = true; | ||
8 | + } catch (error) { | ||
9 | + value = defaultValue; | ||
10 | + } | ||
11 | + return { flag, value }; | ||
12 | +} |
@@ -3,20 +3,7 @@ import { FormSchema } from '/@/components/Form'; | @@ -3,20 +3,7 @@ import { FormSchema } from '/@/components/Form'; | ||
3 | import { BasicColumn } from '/@/components/Table'; | 3 | import { BasicColumn } from '/@/components/Table'; |
4 | import moment from 'moment'; | 4 | import moment from 'moment'; |
5 | import { findDictItemByCode } from '/@/api/system/dict'; | 5 | import { findDictItemByCode } from '/@/api/system/dict'; |
6 | - | ||
7 | -export enum AlarmStatus { | ||
8 | - CLEARED_UN_ACK = 'CLEARED_UNACK', | ||
9 | - ACTIVE_UN_ACK = 'ACTIVE_UNACK', | ||
10 | - CLEARED_ACK = 'CLEARED_ACK', | ||
11 | - ACTIVE_ACK = 'ACTIVE_ACK', | ||
12 | -} | ||
13 | - | ||
14 | -export enum AlarmStatusMean { | ||
15 | - CLEARED_UNACK = '清除未确认', | ||
16 | - ACTIVE_UNACK = '激活未确认', | ||
17 | - CLEARED_ACK = '清除已确认', | ||
18 | - ACTIVE_ACK = '激活已确认', | ||
19 | -} | 6 | +import { AlarmStatus, AlarmStatusMean } from '/@/enums/alarmEnum'; |
20 | 7 | ||
21 | export const alarmSearchSchemas: FormSchema[] = [ | 8 | export const alarmSearchSchemas: FormSchema[] = [ |
22 | { | 9 | { |
1 | -import { AlarmStatus, AlarmStatusMean } from '../config/detail.config'; | ||
2 | import { clearOrAckAlarm, getDeviceAlarm } from '/@/api/device/deviceManager'; | 1 | import { clearOrAckAlarm, getDeviceAlarm } from '/@/api/device/deviceManager'; |
3 | import { notification, Button, Tag } from 'ant-design-vue'; | 2 | import { notification, Button, Tag } from 'ant-design-vue'; |
4 | import { h, onMounted, onUnmounted } from 'vue'; | 3 | import { h, onMounted, onUnmounted } from 'vue'; |
@@ -8,6 +7,7 @@ import { RoleEnum } from '/@/enums/roleEnum'; | @@ -8,6 +7,7 @@ import { RoleEnum } from '/@/enums/roleEnum'; | ||
8 | import { usePermission } from '/@/hooks/web/usePermission'; | 7 | import { usePermission } from '/@/hooks/web/usePermission'; |
9 | import { useUserStore } from '/@/store/modules/user'; | 8 | import { useUserStore } from '/@/store/modules/user'; |
10 | import { useGlobSetting } from '/@/hooks/setting'; | 9 | import { useGlobSetting } from '/@/hooks/setting'; |
10 | +import { AlarmStatus, AlarmStatusMean } from '/@/enums/alarmEnum'; | ||
11 | 11 | ||
12 | interface UseAlarmNotifyParams { | 12 | interface UseAlarmNotifyParams { |
13 | alarmNotifyStatus?: AlarmStatus; | 13 | alarmNotifyStatus?: AlarmStatus; |
@@ -91,7 +91,7 @@ export const formSchema: FormSchema[] = [ | @@ -91,7 +91,7 @@ export const formSchema: FormSchema[] = [ | ||
91 | valueField: 'fileList', | 91 | valueField: 'fileList', |
92 | componentProps: () => { | 92 | componentProps: () => { |
93 | return { | 93 | return { |
94 | - listType: 'picture-card', | 94 | + // listType: 'picture-card', |
95 | maxFileLimit: 1, | 95 | maxFileLimit: 1, |
96 | api: async (file: File) => { | 96 | api: async (file: File) => { |
97 | try { | 97 | try { |
@@ -110,6 +110,10 @@ export const formSchema: FormSchema[] = [ | @@ -110,6 +110,10 @@ export const formSchema: FormSchema[] = [ | ||
110 | onPreview: (fileList: FileItem) => { | 110 | onPreview: (fileList: FileItem) => { |
111 | createImgPreview({ imageList: [fileList.url!] }); | 111 | createImgPreview({ imageList: [fileList.url!] }); |
112 | }, | 112 | }, |
113 | + showUploadList: { | ||
114 | + showDownloadIcon: true, | ||
115 | + showRemoveIcon: true, | ||
116 | + }, | ||
113 | }; | 117 | }; |
114 | }, | 118 | }, |
115 | }, | 119 | }, |
@@ -57,7 +57,7 @@ export const formSchema: FormSchema[] = [ | @@ -57,7 +57,7 @@ export const formSchema: FormSchema[] = [ | ||
57 | valueField: 'fileList', | 57 | valueField: 'fileList', |
58 | componentProps: () => { | 58 | componentProps: () => { |
59 | return { | 59 | return { |
60 | - listType: 'picture-card', | 60 | + // listType: 'picture-card', |
61 | maxFileLimit: 1, | 61 | maxFileLimit: 1, |
62 | api: async (file: File) => { | 62 | api: async (file: File) => { |
63 | try { | 63 | try { |
@@ -73,6 +73,10 @@ export const formSchema: FormSchema[] = [ | @@ -73,6 +73,10 @@ export const formSchema: FormSchema[] = [ | ||
73 | return {}; | 73 | return {}; |
74 | } | 74 | } |
75 | }, | 75 | }, |
76 | + showUploadList: true, | ||
77 | + onDownload(file) { | ||
78 | + console.log(file); | ||
79 | + }, | ||
76 | onPreview: (fileList: FileItem) => { | 80 | onPreview: (fileList: FileItem) => { |
77 | createImgPreview({ imageList: [fileList.url!] }); | 81 | createImgPreview({ imageList: [fileList.url!] }); |
78 | }, | 82 | }, |
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | layout: 'vertical', | 23 | layout: 'vertical', |
24 | }); | 24 | }); |
25 | 25 | ||
26 | - const { genForm } = useGenDynamicForm(); | 26 | + const { genForm, transformValue } = useGenDynamicForm(); |
27 | 27 | ||
28 | const keys = ref<string[]>([]); | 28 | const keys = ref<string[]>([]); |
29 | 29 | ||
@@ -159,8 +159,8 @@ | @@ -159,8 +159,8 @@ | ||
159 | 159 | ||
160 | sendValue.value = await genModbusCommand(unref(modBUSForm)); | 160 | sendValue.value = await genModbusCommand(unref(modBUSForm)); |
161 | } else { | 161 | } else { |
162 | - const _value = getFieldsValue(); | ||
163 | - | 162 | + await validate(); |
163 | + const _value = transformValue(getFieldsValue()); | ||
164 | sendValue.value = unref(keys).reduce((prev, next) => { | 164 | sendValue.value = unref(keys).reduce((prev, next) => { |
165 | return { ...prev, [next]: _value[next] }; | 165 | return { ...prev, [next]: _value[next] }; |
166 | }, {}); | 166 | }, {}); |
1 | import { DataType, Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | 1 | import { DataType, Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
2 | import { JSONEditor } from '/@/components/CodeEditor'; | 2 | import { JSONEditor } from '/@/components/CodeEditor'; |
3 | import { FormSchema, useComponentRegister } from '/@/components/Form'; | 3 | import { FormSchema, useComponentRegister } from '/@/components/Form'; |
4 | +import { useJsonParse } from '/@/hooks/business/useJsonParse'; | ||
4 | import { DataTypeEnum } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | 5 | import { DataTypeEnum } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; |
5 | 6 | ||
6 | export interface BasicCreateFormParams { | 7 | export interface BasicCreateFormParams { |
@@ -106,6 +107,19 @@ export const useGenDynamicForm = () => { | @@ -106,6 +107,19 @@ export const useGenDynamicForm = () => { | ||
106 | field: identifier, | 107 | field: identifier, |
107 | label: functionName, | 108 | label: functionName, |
108 | component: 'JSONEditor', | 109 | component: 'JSONEditor', |
110 | + valueField: 'value', | ||
111 | + changeEvent: 'update:value', | ||
112 | + rules: [ | ||
113 | + { | ||
114 | + validator: (_rule, value: any) => { | ||
115 | + if (value) { | ||
116 | + const { flag } = useJsonParse(value); | ||
117 | + if (!flag) return Promise.reject(`${functionName} 不是一个有效的JSON对象`); | ||
118 | + } | ||
119 | + return Promise.resolve(); | ||
120 | + }, | ||
121 | + }, | ||
122 | + ], | ||
109 | }; | 123 | }; |
110 | }; | 124 | }; |
111 | 125 | ||
@@ -117,11 +131,14 @@ export const useGenDynamicForm = () => { | @@ -117,11 +131,14 @@ export const useGenDynamicForm = () => { | ||
117 | [DataTypeEnum.IS_STRUCT]: createInputJson, | 131 | [DataTypeEnum.IS_STRUCT]: createInputJson, |
118 | }; | 132 | }; |
119 | 133 | ||
134 | + const fieldTypeMap = new Map<string, DataTypeEnum>(); | ||
120 | const genForm = (schemas: StructJSON[]) => { | 135 | const genForm = (schemas: StructJSON[]) => { |
136 | + fieldTypeMap.clear(); | ||
121 | const formSchema = schemas.map((item) => { | 137 | const formSchema = schemas.map((item) => { |
122 | const { functionName, identifier, dataType } = item; | 138 | const { functionName, identifier, dataType } = item; |
123 | const { type } = dataType || {}; | 139 | const { type } = dataType || {}; |
124 | 140 | ||
141 | + fieldTypeMap.set(identifier!, dataType!.type); | ||
125 | const method = schemaMethod[type!]; | 142 | const method = schemaMethod[type!]; |
126 | 143 | ||
127 | const formSchema = method?.({ | 144 | const formSchema = method?.({ |
@@ -136,5 +153,21 @@ export const useGenDynamicForm = () => { | @@ -136,5 +153,21 @@ export const useGenDynamicForm = () => { | ||
136 | return formSchema.filter(Boolean); | 153 | return formSchema.filter(Boolean); |
137 | }; | 154 | }; |
138 | 155 | ||
139 | - return { genForm }; | 156 | + const transformValue = (value: Recordable) => { |
157 | + return Object.keys(value || {}).reduce((prev, next) => { | ||
158 | + const dataType = fieldTypeMap.get(next)!; | ||
159 | + | ||
160 | + let itemValue = value[next]; | ||
161 | + if (dataType === DataTypeEnum.IS_STRUCT) { | ||
162 | + const { value } = useJsonParse(itemValue); | ||
163 | + itemValue = value; | ||
164 | + } | ||
165 | + return { | ||
166 | + ...prev, | ||
167 | + [next]: itemValue, | ||
168 | + }; | ||
169 | + }, {} as Recordable); | ||
170 | + }; | ||
171 | + | ||
172 | + return { genForm, transformValue }; | ||
140 | }; | 173 | }; |
src/views/rule/designer/enum/category.ts
0 → 100644
1 | +export enum EntryCategoryComponentEnum { | ||
2 | + INPUT = 'Input', | ||
3 | +} | ||
4 | + | ||
5 | +export enum FlowCategoryComponentEnum { | ||
6 | + ACKNOWLEDGE = 'Acknowledge', | ||
7 | + CHECKPOINT = 'Checkpoint', | ||
8 | + RULE_CHAIN = 'RuleChain', | ||
9 | + OUTPUT = 'Output', | ||
10 | +} | ||
11 | +export enum EnrichmentCategoryComponentEnum { | ||
12 | + CUSTOMER_ATTRIBUTES = 'CustomerAttributes', | ||
13 | + ORIGINATOR_TELEMETRY = 'OriginatorTelemetry', | ||
14 | + ORIGINATOR_FIELDS = 'OriginatorFields', | ||
15 | + CALCULATE_DELTA = 'CalculateDelta', | ||
16 | + TENANT_ATTRIBUTES = 'TenantAttributes', | ||
17 | + RELATED_DEVICE_ATTRIBUTES = 'RelatedDeviceAttributes', | ||
18 | + RELATED_ATTRIBUTES = 'RelatedAttributes', | ||
19 | + TENANT_DETAILS = 'TenantDetails', | ||
20 | + ORIGINATOR_ATTRIBUTES = 'OriginatorAttributes', | ||
21 | + CUSTOMER_DETAILS = 'CustomerDetails', | ||
22 | +} | ||
23 | +export enum ExternalCategoryComponentEnum { | ||
24 | + ALARM_NOTICE = 'AlarmNotice', | ||
25 | + MQTT = 'Mqtt', | ||
26 | + GCP_PUBSUB = 'GcpPubsub', | ||
27 | + SEND_SMS = 'SendSms', | ||
28 | + AZURE_IOT_HUB = 'AzureIotHub', | ||
29 | + REST_API_CALL = 'RestApiCall', | ||
30 | + KAFKA = 'Kafka', | ||
31 | + AWS_SNS = 'AwsSns', | ||
32 | + SEND_EMAIL = 'SendEmail', | ||
33 | + RABBITMQ = 'Rabbitmq', | ||
34 | + AWS_SQS = 'AwsSqs', | ||
35 | +} | ||
36 | +export enum ActionCategoryComponentEnum { | ||
37 | + CREATE_ALARM = 'CreateAlarm', | ||
38 | + PUSH_TO_EDGE = 'PushToEdge', | ||
39 | + GENERATOR = 'Generator', | ||
40 | + ASSIGN_TO_CUSTOMER = 'AssignToCustomer', | ||
41 | + UNASSIGN_FROM_CUSTOMER = 'UnassignFromCustomer', | ||
42 | + SAVE_TIMESERIES = 'SaveTimeseries', | ||
43 | + GPS_GEOFENCING_EVENTS = 'GpsGeofencingEvents', | ||
44 | + DEVICE_PROFILE = 'DeviceProfile', | ||
45 | + RPC_CALL_REPLY = 'RpcCallReply', | ||
46 | + COPY_TO_VIEW = 'CopyToView', | ||
47 | + LOG = 'Log', | ||
48 | + SAVE_TO_CUSTOM_TABLE = 'SaveToCustomTable', | ||
49 | + CLEAR_ALARM = 'ClearAlarm', | ||
50 | + DELETE_RELATION = 'DeleteRelation', | ||
51 | + DELAY_DEPRECATED = 'DelayDeprecated', | ||
52 | + MESSAGE_COUNT = 'MessageCount', | ||
53 | + SAVE_EVENT = 'SaveEvent', | ||
54 | + RPC_CALL_REQUEST = 'RpcCallRequest', | ||
55 | + SYNCHRONIZATION_START = 'SynchronizationStart', | ||
56 | + SYNCHRONIZATION_END = 'SynchronizationEnd', | ||
57 | + SAVE_ATTRIBUTES = 'SaveAttributes', | ||
58 | + CREATE_RELATION = 'CreateRelation', | ||
59 | +} | ||
60 | +export enum FilterCategoryComponentEnum { | ||
61 | + SCRIPT = 'Script', | ||
62 | + SCENE_REACT = 'SceneReact', | ||
63 | + CHECK_EXISTENCE_FIELDS = 'CheckExistenceFields', | ||
64 | + ORIGINATOR_TYPE_SWITCH = 'OriginatorTypeSwitch', | ||
65 | + CHECK_RELATION = 'CheckRelation', | ||
66 | + MESSAGE_TYPE = 'MessageType', | ||
67 | + ORIGINATOR_TYPE = 'OriginatorType', | ||
68 | + MESSAGE_TYPE_SWITCH = 'MessageTypeSwitch', | ||
69 | + SWITCH = 'Switch', | ||
70 | + GPS_GEOFENCING_FILTER = 'GpsGeofencingFilter', | ||
71 | + CHECK_ALARM_STATUS = 'CheckAlarmStatus', | ||
72 | +} | ||
73 | +export enum TransformationCategoryComponentEnum { | ||
74 | + CHANGE_ORIGINATOR = 'ChangeOriginator', | ||
75 | + SCRIPT = 'Script', | ||
76 | + TO_EMAIL = 'ToEmail', | ||
77 | +} |
src/views/rule/designer/enum/form.ts
0 → 100644
1 | +/** | ||
2 | + * @description 方向 | ||
3 | + */ | ||
4 | +export enum DirectionEnum { | ||
5 | + FROM = 'FROM', | ||
6 | + TO = 'TO', | ||
7 | +} | ||
8 | + | ||
9 | +export enum DirectionNameEnum { | ||
10 | + FROM = '从', | ||
11 | + TO = '到', | ||
12 | +} | ||
13 | +/** | ||
14 | + * @description 关联类型 | ||
15 | + */ | ||
16 | +export enum RelationTypeEnum { | ||
17 | + CONTAINS = 'CONTAINS', | ||
18 | + MANAGES = 'MANAGES', | ||
19 | +} | ||
20 | + | ||
21 | +export enum RelationTypeNameEnum { | ||
22 | + CONTAINS = 'Contains', | ||
23 | + MANAGES = 'Manages', | ||
24 | +} | ||
25 | + | ||
26 | +/** | ||
27 | + * @description 类型 | ||
28 | + */ | ||
29 | +export enum EntityTypeEnum { | ||
30 | + DEVICE = 'DEVICE', | ||
31 | + ASSET = 'ASSET', | ||
32 | + ENTITY_VIEW = 'ENTITY_VIEW', | ||
33 | + TENANT = 'TENANT', | ||
34 | + CUSTOMER = 'CUSTOMER', | ||
35 | + USER = 'USER', | ||
36 | + DASHBOARD = 'DASHBOARD', | ||
37 | + EDGE = 'EDGE', | ||
38 | +} | ||
39 | + | ||
40 | +export enum EntityTypeNameEnum { | ||
41 | + DEVICE = '设备', | ||
42 | + ASSET = '资产', | ||
43 | + ENTITY_VIEW = '实体视图', | ||
44 | + TENANT = '租户', | ||
45 | + CUSTOMER = '客户', | ||
46 | + USER = '用户', | ||
47 | + DASHBOARD = '仪表板', | ||
48 | + EDGE = '边缘', | ||
49 | +} | ||
50 | + | ||
51 | +/** | ||
52 | + * @description Filter Perimeter type | ||
53 | + */ | ||
54 | +export enum PerimeterTypeEnum { | ||
55 | + POLYGON = 'POLYGON', | ||
56 | + CIRCLE = 'CIRCLE', | ||
57 | +} | ||
58 | + | ||
59 | +export enum MessageTypesEnum { | ||
60 | + POST_ATTRIBUTES_REQUEST = 'POST_ATTRIBUTES_REQUEST', | ||
61 | + POST_TELEMETRY_REQUEST = 'POST_TELEMETRY_REQUEST', | ||
62 | + TO_SERVER_RPC_REQUEST = 'TO_SERVER_RPC_REQUEST', | ||
63 | + RPC_CALL_FROM_SERVER_TO_DEVICE = 'RPC_CALL_FROM_SERVER_TO_DEVICE', | ||
64 | + ACTIVITY_EVENT = 'ACTIVITY_EVENT', | ||
65 | + INACTIVITY_EVENT = 'INACTIVITY_EVENT', | ||
66 | + CONNECT_EVENT = 'CONNECT_EVENT', | ||
67 | + DISCONNECT_EVENT = 'DISCONNECT_EVENT', | ||
68 | + ENTITY_CREATED = 'ENTITY_CREATED', | ||
69 | + ENTITY_UPDATED = 'ENTITY_UPDATED', | ||
70 | + ENTITY_DELETED = 'ENTITY_DELETED', | ||
71 | + ENTITY_ASSIGNED = 'ENTITY_ASSIGNED', | ||
72 | + ENTITY_UNASSIGNED = 'ENTITY_UNASSIGNED', | ||
73 | + ATTRIBUTES_UPDATED = 'ATTRIBUTES_UPDATED', | ||
74 | + ATTRIBUTES_DELETED = 'ATTRIBUTES_DELETED', | ||
75 | + TIMESERIES_UPDATED = 'TIMESERIES_UPDATED', | ||
76 | + TIMESERIES_DELETED = 'TIMESERIES_DELETED', | ||
77 | + RPC_QUEUED = 'RPC_QUEUED', | ||
78 | + RPC_DELIVERED = 'RPC_DELIVERED', | ||
79 | + RPC_SUCCESSFUL = 'RPC_SUCCESSFUL', | ||
80 | + RPC_TIMEOUT = 'RPC_TIMEOUT', | ||
81 | + RPC_FAILED = 'RPC_FAILED', | ||
82 | +} | ||
83 | + | ||
84 | +export enum MessageTypesNameEnum { | ||
85 | + POST_ATTRIBUTES_REQUEST = 'Post attributes', | ||
86 | + POST_TELEMETRY_REQUEST = 'Post telemetry', | ||
87 | + TO_SERVER_RPC_REQUEST = 'RPC Request from Device', | ||
88 | + RPC_CALL_FROM_SERVER_TO_DEVICE = 'RPC Request to Device', | ||
89 | + ACTIVITY_EVENT = 'Activity Event', | ||
90 | + INACTIVITY_EVENT = 'Inactivity Event', | ||
91 | + CONNECT_EVENT = 'Connect Event', | ||
92 | + DISCONNECT_EVENT = 'Disconnect Event', | ||
93 | + ENTITY_CREATED = 'Entity Created', | ||
94 | + ENTITY_UPDATED = 'Entity Updated', | ||
95 | + ENTITY_DELETED = 'Entity Deleted', | ||
96 | + ENTITY_ASSIGNED = 'Entity Assigned', | ||
97 | + ENTITY_UNASSIGNED = 'Entity Unassigned', | ||
98 | + ATTRIBUTES_UPDATED = 'Attributes Updated', | ||
99 | + ATTRIBUTES_DELETED = 'Attributes Deleted', | ||
100 | + TIMESERIES_UPDATED = 'Timeseries Updated', | ||
101 | + TIMESERIES_DELETED = 'Timeseries Deleted', | ||
102 | + RPC_QUEUED = 'RPC Queued', | ||
103 | + RPC_DELIVERED = 'RPC Delivered', | ||
104 | + RPC_SUCCESSFUL = 'RPC Successful', | ||
105 | + RPC_TIMEOUT = 'RPC Timeout', | ||
106 | + RPC_FAILED = 'RPC Failed', | ||
107 | +} | ||
108 | +/** | ||
109 | + * @description Filter Range util | ||
110 | + */ | ||
111 | +export enum RangeUtilEnum { | ||
112 | + METER = 'METER', | ||
113 | + KILOMETER = 'KILOMETER', | ||
114 | + FOOT = 'FOOT', | ||
115 | + MILE = 'MILE', | ||
116 | + NAUTICAL_MILE = 'NAUTICAL_MILE', | ||
117 | +} | ||
118 | + | ||
119 | +export enum RangeUtilNameEnum { | ||
120 | + METER = 'Meter', | ||
121 | + KILOMETER = 'Kilometer', | ||
122 | + FOOT = 'Foot', | ||
123 | + MILE = 'Mile', | ||
124 | + NAUTICAL_MILE = 'Nautical mile', | ||
125 | +} | ||
126 | + | ||
127 | +// Enrichment Customer details | ||
128 | +export enum DetailsListEnum { | ||
129 | + TITLE = 'TITLE', | ||
130 | + COUNTRY = 'COUNTRY', | ||
131 | + STATE = 'STATE', | ||
132 | + CITY = 'CITY', | ||
133 | + ZIP = 'ZIP', | ||
134 | + ADDRESS = 'ADDRESS', | ||
135 | + ADDRESS_2 = 'ADDRESS_2', | ||
136 | + PHONE = 'PHONE', | ||
137 | + EMAIL = 'EMAIL', | ||
138 | + ADDITIONAL_INFO = 'ADDITIONAL_INFO', | ||
139 | +} | ||
140 | + | ||
141 | +export enum DetailsListNameEnum { | ||
142 | + TITLE = 'Title', | ||
143 | + COUNTRY = 'Country', | ||
144 | + STATE = 'State', | ||
145 | + CITY = 'City', | ||
146 | + ZIP = 'Zip', | ||
147 | + ADDRESS = 'Address', | ||
148 | + ADDRESS_2 = 'Address2', | ||
149 | + PHONE = 'Phone', | ||
150 | + EMAIL = 'Email', | ||
151 | + ADDITIONAL_INFO = 'Additional Info', | ||
152 | +} | ||
153 | + | ||
154 | +// Enrichment Originator Telemetry FetchMode | ||
155 | +export enum FetchModeEnum { | ||
156 | + FIRST = 'FIRST', | ||
157 | + LAST = 'LAST', | ||
158 | + ALL = 'ALL', | ||
159 | +} | ||
160 | + | ||
161 | +// Enrichment Originator Telemetry Time interval unit | ||
162 | +export enum TimeIntervalUnitEnum { | ||
163 | + MILLISECONDS = 'MILLISECONDS', | ||
164 | + SECONDS = 'SECONDS', | ||
165 | + MINUTES = 'MINUTES', | ||
166 | + HOURS = 'HOURS', | ||
167 | + DAYS = 'DAYS', | ||
168 | +} | ||
169 | + | ||
170 | +export enum TimeIntervalUnitNameEnum { | ||
171 | + MILLISECONDS = 'Milliseconds', | ||
172 | + SECONDS = 'Seconds', | ||
173 | + MINUTES = 'Minutes', | ||
174 | + HOURS = 'Hours', | ||
175 | + DAYS = 'Days', | ||
176 | +} | ||
177 | + | ||
178 | +// Enrichment Originator Telemetry OrderBy | ||
179 | +export enum OrderByEnum { | ||
180 | + DESC = 'DESC', | ||
181 | + ASC = 'ASC', | ||
182 | +} | ||
183 | + | ||
184 | +// Enrichment Originator Telemetry Aggregation | ||
185 | +export enum AggregationEnum { | ||
186 | + MIN = 'MIN', | ||
187 | + MAX = 'MAX', | ||
188 | + AVG = 'AVG', | ||
189 | + SUM = 'SUM', | ||
190 | + COUNT = 'COUNT', | ||
191 | + NONE = 'NONE', | ||
192 | +} | ||
193 | + | ||
194 | +export enum AggregationNameEnum { | ||
195 | + MIN = '最少值', | ||
196 | + MAX = '最大值', | ||
197 | + AVG = '平均值', | ||
198 | + SUM = '求和', | ||
199 | + COUNT = '计数', | ||
200 | + NONE = '空', | ||
201 | +} | ||
202 | + | ||
203 | +// Originator source | ||
204 | +export enum OriginatorSourceEnum { | ||
205 | + CUSTOMER = 'CUSTOMER', | ||
206 | + TENANT = 'TENANT', | ||
207 | + RELATED = 'RELATED', | ||
208 | + ALARM_ORIGINATOR = 'ALARM_ORIGINATOR', | ||
209 | +} | ||
210 | + | ||
211 | +export enum OriginatorSourceNameEnum { | ||
212 | + CUSTOMER = 'Customer', | ||
213 | + TENANT = 'Tenant', | ||
214 | + RELATED = 'Related', | ||
215 | + ALARM_ORIGINATOR = 'Alarm Originator', | ||
216 | +} | ||
217 | + | ||
218 | +// Transformation To Email | ||
219 | +export enum MailBodyTypeEnum { | ||
220 | + DYNAMIC = 'dynamic', | ||
221 | + HTML = 'true', | ||
222 | + PLAIN_TEXT = 'false', | ||
223 | +} | ||
224 | + | ||
225 | +export enum MailBodyTypeNameEnum { | ||
226 | + DYNAMIC = 'Dynamic', | ||
227 | + HTML = 'HTML', | ||
228 | + PLAIN_TEXT = 'Plain Text', | ||
229 | +} | ||
230 | + | ||
231 | +// Action Push to edge | ||
232 | +export enum ScopeEnum { | ||
233 | + SERVER_SCOPE = 'SERVER_SCOPE', | ||
234 | + CLIENT_SCOPE = 'CLIENT_SCOPE', | ||
235 | + SHARED_SCOPE = 'SHARED_SCOPE', | ||
236 | +} | ||
237 | + | ||
238 | +export enum ScopeNameEnum { | ||
239 | + SERVER_SCOPE = '服务端属性', | ||
240 | + CLIENT_SCOPE = '客户端属性', | ||
241 | + SHARED_SCOPE = '共享属性', | ||
242 | +} | ||
243 | + | ||
244 | +// External Queue type | ||
245 | +export enum QueueTypeEnum { | ||
246 | + STANDARD = 'STANDARD', | ||
247 | + FIFO = 'FIFO', | ||
248 | +} | ||
249 | + | ||
250 | +export enum QueueTypeNameEnum { | ||
251 | + STANDARD = 'Standard', | ||
252 | + FIFO = 'FIFO', | ||
253 | +} | ||
254 | + | ||
255 | +// Charset encoding | ||
256 | +export enum CharsetEncodingEnum { | ||
257 | + US_ASCII = 'US_ASCII', | ||
258 | + ISO_8859_1 = 'ISO_8859_1', | ||
259 | + UTF_8 = 'UTF_8', | ||
260 | + UTF_16BE = 'UTF_16BE', | ||
261 | + UTF_16LE = 'UTF_16LE', | ||
262 | + UTF_16 = 'UTF_16', | ||
263 | +} | ||
264 | + | ||
265 | +export enum CharsetEncodingNameEnum { | ||
266 | + US_ASCII = 'US-ASCII', | ||
267 | + ISO_8859_1 = 'ISO-8859-1', | ||
268 | + UTF_8 = 'UTF-8', | ||
269 | + UTF_16BE = 'UTF-16BE', | ||
270 | + UTF_16LE = 'UTF-16LE', | ||
271 | + UTF_16 = 'UTF-16', | ||
272 | +} | ||
273 | + | ||
274 | +// Rabbitmq Message properties | ||
275 | +export enum MessagePropertiesEnum { | ||
276 | + BASIC = 'BASIC', | ||
277 | + TEXT_PLAIN = 'TEXT_PLAIN', | ||
278 | + MINIMAL_BASIC = 'MINIMAL_BASIC', | ||
279 | + MINIMAL_PERSISTENT_BASIC = 'MINIMAL_PERSISTENT_BASIC', | ||
280 | + PERSISTENT_BASIC = 'PERSISTENT_BASIC', | ||
281 | + PERSISTENT_TEXT_PLAIN = 'PERSISTENT_TEXT_PLAIN', | ||
282 | +} | ||
283 | + | ||
284 | +// rest api call Request method | ||
285 | +export enum RequestMethodEnum { | ||
286 | + GET = 'GET', | ||
287 | + POST = 'POST', | ||
288 | + PUT = 'PUT', | ||
289 | + DELETE = 'DELETE', | ||
290 | +} | ||
291 | + | ||
292 | +export enum ProtocolEnum { | ||
293 | + HTTP = 'HTTP', | ||
294 | + HTTPS = 'HTTPS', | ||
295 | +} | ||
296 | + | ||
297 | +export enum ProtocolNameEnum { | ||
298 | + HTTP = 'http', | ||
299 | + HTTPS = 'https', | ||
300 | +} | ||
301 | + | ||
302 | +export enum EmailProtocolEnum { | ||
303 | + SMTP = 'SMTP', | ||
304 | + SMTPS = 'SMTPS', | ||
305 | +} | ||
306 | + | ||
307 | +export enum EmailProtocolNameEnum { | ||
308 | + SMTP = 'smtp', | ||
309 | + SMTPS = 'smtps', | ||
310 | +} | ||
311 | + | ||
312 | +export enum TSLVersionEnum { | ||
313 | + TSLV1 = 'TSLV1', | ||
314 | + TSLV1_1 = 'TSLV1_1', | ||
315 | + TSLV1_2 = 'TSLV1_2', | ||
316 | + TSLV1_3 = 'TSLV1_3', | ||
317 | +} | ||
318 | + | ||
319 | +export enum TSLVersionNameEnum { | ||
320 | + TSLV1 = 'TSLV1', | ||
321 | + TSLV1_1 = 'TSLV1.1', | ||
322 | + TSLV1_2 = 'TSLV1.2', | ||
323 | + TSLV1_3 = 'TSLV1.3', | ||
324 | +} | ||
325 | + | ||
326 | +export enum SMSServiceProviderEnum { | ||
327 | + AWS_SNS = 'AWS_SNS', | ||
328 | + TWILIO = 'TWILIO', | ||
329 | +} | ||
330 | + | ||
331 | +export enum SMSServiceProviderNameEnum { | ||
332 | + AWS_SNS = '亚马逊社交网站', | ||
333 | + TWILIO = 'Twilio', | ||
334 | +} |
1 | +// Assign to customer | ||
2 | +export enum AssignToCustomerFieldsEnum { | ||
3 | + CUSTOMER_NAME_PATTERN = 'customerNamePattern', | ||
4 | + CREATE_CUSTOMER_IF_NOT_EXISTS = 'createCustomerIfNotExists', | ||
5 | + CUSTOMER_CACHE_EXPIRATION = 'customerCacheExpiration', | ||
6 | +} | ||
7 | + | ||
8 | +export enum AssignToCustomerFieldsNameEnum { | ||
9 | + CUSTOMER_NAME_PATTERN = 'Customer name pattern', | ||
10 | + CREATE_CUSTOMER_IF_NOT_EXISTS = 'Create new customer if not exists', | ||
11 | + CUSTOMER_CACHE_EXPIRATION = 'Customers cache expiration time(sec)', | ||
12 | +} | ||
13 | + | ||
14 | +// clear alarm | ||
15 | +export enum ClearAlarmFieldsEnum { | ||
16 | + ALARM_TYPE = 'alarmType', | ||
17 | + ALARM_DETAILS_BUILD_JS = 'alarmDetailsBuildJs', | ||
18 | +} | ||
19 | + | ||
20 | +export enum ClearAlarmFieldsNameEnum { | ||
21 | + ALARM_TYPE = 'Alarm type', | ||
22 | + ALARM_DETAILS_BUILD_JS = 'Alarm details builder', | ||
23 | +} | ||
24 | + | ||
25 | +// Create alarm | ||
26 | +export enum CreateAlarmFieldsEnum { | ||
27 | + ALARM_DETAILS_BUILD_JS = 'alarmDetailsBuildJs', | ||
28 | + USE_MESSAGE_ALARM_DATA = 'useMessageAlarmData', | ||
29 | + OVERWRITE_ALARM_DETAILS = 'overwriteAlarmDetails', | ||
30 | + ALARM_TYPE = 'alarmType', | ||
31 | + SEVERITY = 'severity', | ||
32 | + PROPAGATE = 'propagate', | ||
33 | + RELATION_TYPES = 'relationTypes', | ||
34 | + PROPAGATE_TO_OWNER = 'propagateToOwner', | ||
35 | + PROPAGATE_TO_TENANT = 'propagateToTenant', | ||
36 | + DYNAMIC_SEVERITY = 'dynamicSeverity', | ||
37 | +} | ||
38 | + | ||
39 | +export enum CreateAlarmFieldsNameEnum { | ||
40 | + ALARM_DETAILS_BUILD_JS = 'Alarm details builder', | ||
41 | + USE_MESSAGE_ALARM_DATA = 'Use message alarm data', | ||
42 | + OVERWRITE_ALARM_DETAILS = 'Overwrite alarm details', | ||
43 | + ALARM_TYPE = 'Alarm type', | ||
44 | + SEVERITY = 'Alarm severity pattern', | ||
45 | + PROPAGATE = 'Propagate alarm to related entities', | ||
46 | + RELATION_TYPES = 'Relation types to propagate', | ||
47 | + PROPAGATE_TO_OWNER = 'Propagate alarm to entity owner (Customer or Tenant)', | ||
48 | + PROPAGATE_TO_TENANT = 'Propagate alarm to Tenant', | ||
49 | + DYNAMIC_SEVERITY = 'Use alarm severity pattern', | ||
50 | +} | ||
51 | + | ||
52 | +// Create relation | ||
53 | +export enum CreateRelationFieldsEnum { | ||
54 | + DIRECTION = 'direction', | ||
55 | + ENTITY_TYPE = 'entityType', | ||
56 | + ENTITY_NAME_PATTERN = 'entityNamePattern', | ||
57 | + ENTITY_TYPE_PATTERN = 'entityTypePattern', | ||
58 | + RELATION_TYPE = 'relationType', | ||
59 | + CREATE_ENTITY_IF_NOT_EXISTS = 'createEntityIfNotExists', | ||
60 | + REMOVE_CURRENT_RELATIONS = 'removeCurrentRelations', | ||
61 | + CHANGE_ORIGINATOR_TO_RELATED_ENTITY = 'changeOriginatorToRelatedEntity', | ||
62 | + ENTITY_CACHE_EXPIRATION = 'entityCacheExpiration', | ||
63 | +} | ||
64 | + | ||
65 | +export enum CreateRelationFieldsNameEnum { | ||
66 | + DIRECTION = '方向', | ||
67 | + ENTITY_TYPE = '类型', | ||
68 | + ENTITY_NAME_PATTERN = 'Name pattern', | ||
69 | + ENTITY_TYPE_PATTERN = 'Type pattern', | ||
70 | + RELATION_TYPE = 'Relation type pattern', | ||
71 | + CREATE_ENTITY_IF_NOT_EXISTS = 'Create new entity if not exists', | ||
72 | + REMOVE_CURRENT_RELATIONS = 'Remove current relations', | ||
73 | + CHANGE_ORIGINATOR_TO_RELATED_ENTITY = 'Change originator to related entity', | ||
74 | + ENTITY_CACHE_EXPIRATION = 'Entities cache expiration time(sec)', | ||
75 | +} | ||
76 | + | ||
77 | +// Delay deprecated | ||
78 | +export enum DelayDeprecatedFieldsEnum { | ||
79 | + USE_METADATA_PERIOD_IN_SECONDS_PATTERNS = 'useMetadataPeriodInSecondsPatterns', | ||
80 | + PERIOD_IN_SECONDS = 'periodInSeconds', | ||
81 | + PERIOD_IN_SECONDS_PATTERN = 'periodInSecondsPattern', | ||
82 | + MAX_PENDING_MSGS = 'maxPendingMsgs', | ||
83 | +} | ||
84 | + | ||
85 | +export enum DelayDeprecatedFieldsNameEnum { | ||
86 | + USE_METADATA_PERIOD_IN_SECONDS_PATTERNS = 'Use period in seconds pattern', | ||
87 | + PERIOD_IN_SECONDS = 'Period in seconds', | ||
88 | + PERIOD_IN_SECONDS_PATTERN = 'Period in seconds pattern', | ||
89 | + MAX_PENDING_MSGS = 'Maximum pending messages', | ||
90 | +} | ||
91 | + | ||
92 | +export enum DeleteRelationFieldsEnum { | ||
93 | + DELETE_FOR_SINGLE_ENTITY = 'deleteForSingleEntity', | ||
94 | + DIRECTION = 'direction', | ||
95 | + ENTITY_TYPE = 'entityType', | ||
96 | + ENTITY_NAME_PATTERN = 'entityNamePattern', | ||
97 | + RELATION_TYPE = 'relationType', | ||
98 | + ENTITY_CACHE_EXPIRATION = 'entityCacheExpiration', | ||
99 | +} | ||
100 | + | ||
101 | +export enum DeleteRelationFieldsNameEnum { | ||
102 | + DELETE_FOR_SINGLE_ENTITY = 'Delete relation to specific entity', | ||
103 | + DIRECTION = '方向', | ||
104 | + ENTITY_TYPE = '类型', | ||
105 | + ENTITY_NAME_PATTERN = 'Name pattern', | ||
106 | + RELATION_TYPE = 'Relation type pattern', | ||
107 | + ENTITY_CACHE_EXPIRATION = 'Entities cache expiration time(sec)', | ||
108 | +} | ||
109 | + | ||
110 | +// device profile | ||
111 | +export enum DeviceProfileFieldsEnum { | ||
112 | + PERSIST_ALARM_RULES_STATE = 'persistAlarmRulesState', | ||
113 | + FETCH_ALARM_RULES_STATE_ON_START = 'fetchAlarmRulesStateOnStart', | ||
114 | +} | ||
115 | + | ||
116 | +export enum DeviceProfileFieldsNameEnum { | ||
117 | + PERSIST_ALARM_RULES_STATE = 'Persist state of alarm rules', | ||
118 | + FETCH_ALARM_RULES_STATE_ON_START = 'Fetch state of alarm rules', | ||
119 | +} | ||
120 | + | ||
121 | +// Generator | ||
122 | +export enum GeneratorFieldsEnum { | ||
123 | + MSG_COUNT = 'msgCount', | ||
124 | + PERIOD_IN_SECONDS = 'periodInSeconds', | ||
125 | + JS_SCRIPT = 'jsScript', | ||
126 | + ORIGINATOR_ID = 'originatorId', | ||
127 | + ORIGINATOR_TYPE = 'originatorType', | ||
128 | +} | ||
129 | + | ||
130 | +export enum GeneratorFieldsNameEnum { | ||
131 | + MSG_COUNT = 'Message count(0 - unlimited)', | ||
132 | + PERIOD_IN_SECONDS = 'Period in seconds', | ||
133 | + JS_SCRIPT = 'Generate', | ||
134 | + // ORIGINATOR_ID = '资产', | ||
135 | + ORIGINATOR_TYPE = '类型', | ||
136 | +} | ||
137 | + | ||
138 | +// Gps geofencing events | ||
139 | +export enum GpsGeofencingEventsFieldsEnum { | ||
140 | + LATITUDE_KEY_NAME = 'latitudeKeyName', | ||
141 | + LONGITUDE_KEY_NAME = 'longitudeKeyName', | ||
142 | + PERIMETER_TYPE = 'perimeterType', | ||
143 | + FETCH_PERIMETER_INFO_FROM_MESSAGE_METADATA = 'fetchPerimeterInfoFromMessageMetadata', | ||
144 | + PERIMETER_KEY_NAME = 'perimeterKeyName', | ||
145 | + CENTER_LATITUDE = 'centerLatitude', | ||
146 | + CENTER_LONGITUDE = 'centerLongitude', | ||
147 | + RANGE = 'range', | ||
148 | + RANGE_UNIT = 'rangeUnit', | ||
149 | + POLYGONS_DEFINITION = 'polygonsDefinition', | ||
150 | + MIN_INSIDE_DURATION = 'minInsideDuration', | ||
151 | + MIN_INSIDE_DURATION_TIME_UNIT = 'minInsideDurationTimeUnit', | ||
152 | + MIN_OUTSIDE_DURATION = 'minOutsideDuration', | ||
153 | + MIN_OUTSIDE_DURATION_TIME_UNIT = 'minOutsideDurationTimeUnit', | ||
154 | +} | ||
155 | + | ||
156 | +export enum GpsGeofencingEventsFieldsNameEnum { | ||
157 | + LATITUDE_KEY_NAME = 'Latitude key name', | ||
158 | + LONGITUDE_KEY_NAME = 'longitude key name', | ||
159 | + PERIMETER_TYPE = 'Perimeter type', | ||
160 | + FETCH_PERIMETER_INFO_FROM_MESSAGE_METADATA = 'Fetch perimeter information from message metadata', | ||
161 | + PERIMETER_KEY_NAME = 'Perimeter key name', | ||
162 | + CENTER_LATITUDE = 'Center Latitude', | ||
163 | + CENTER_LONGITUDE = 'Center Longitude', | ||
164 | + RANGE = 'Range', | ||
165 | + RANGE_UNIT = 'Range units', | ||
166 | + POLYGONS_DEFINITION = 'Polygon definition', | ||
167 | + MIN_INSIDE_DURATION = 'Minimal inside duration', | ||
168 | + MIN_INSIDE_DURATION_TIME_UNIT = 'Minimal inside duration time unit', | ||
169 | + MIN_OUTSIDE_DURATION = 'Minimal outside duration', | ||
170 | + MIN_OUTSIDE_DURATION_TIME_UNIT = 'Minimal outside duration time unit', | ||
171 | +} | ||
172 | + | ||
173 | +// Log | ||
174 | +export enum LogFieldsEnum { | ||
175 | + JS_SCRIPT = 'jsScript', | ||
176 | +} | ||
177 | + | ||
178 | +export enum LogFieldsNameEnum { | ||
179 | + JS_SCRIPT = 'To string', | ||
180 | +} | ||
181 | + | ||
182 | +// Message Count | ||
183 | +export enum MessageCountFieldsEnum { | ||
184 | + INTERVAL = 'interval', | ||
185 | + TELEMETRY_PREFIX = 'telemetryPrefix', | ||
186 | +} | ||
187 | + | ||
188 | +export enum MessageCountFieldsNameEnum { | ||
189 | + INTERVAL = 'Interval in seconds', | ||
190 | + TELEMETRY_PREFIX = 'Output timeseries key prefix', | ||
191 | +} | ||
192 | + | ||
193 | +// Push to edge | ||
194 | +export enum PushToEdgeFieldsEnum { | ||
195 | + SCOPE = 'scope', | ||
196 | +} | ||
197 | + | ||
198 | +export enum PushToEdgeFieldsNameEnum { | ||
199 | + SCOPE = '设备属性范围', | ||
200 | +} | ||
201 | +// Rpc call reply | ||
202 | +export enum RpcCallReplyFieldsEnum { | ||
203 | + REQUEST_ID_META_DATA_ATTRIBUTE = 'requestIdMetaDataAttribute', | ||
204 | +} | ||
205 | + | ||
206 | +export enum RpcCallReplyFieldsNameEnum { | ||
207 | + REQUEST_ID_META_DATA_ATTRIBUTE = 'Request Id Metadata attribute name', | ||
208 | +} | ||
209 | + | ||
210 | +// Rpc call request | ||
211 | +export enum RpcCallRequestFieldsEnum { | ||
212 | + TIMEOUT_IN_SECONDS = 'timeoutInSeconds', | ||
213 | +} | ||
214 | + | ||
215 | +export enum RpcCallRequestFieldsNameEnum { | ||
216 | + TIMEOUT_IN_SECONDS = 'Timeout in seconds', | ||
217 | +} | ||
218 | + | ||
219 | +// Save attribute | ||
220 | +export enum SaveAttributesFieldsEnum { | ||
221 | + NOTIFY_DEVICE = 'notifyDevice', | ||
222 | + SCOPE = 'scope', | ||
223 | +} | ||
224 | + | ||
225 | +export enum SaveAttributesFieldsNameEnum { | ||
226 | + NOTIFY_DEVICE = 'Notify Device', | ||
227 | + SCOPE = '设备属性范围', | ||
228 | +} | ||
229 | + | ||
230 | +// Save event | ||
231 | +export enum SaveEventFieldsEnum { | ||
232 | + CONFIGURATION = 'CONFIGURATION', | ||
233 | +} | ||
234 | + | ||
235 | +export enum SaveEventFieldsNameEnum { | ||
236 | + CONFIGURATION = '配置', | ||
237 | +} | ||
238 | + | ||
239 | +// Save timeseries | ||
240 | +export enum SaveTimeseriesFieldsEnum { | ||
241 | + DEFAULT_TTL = 'defaultTTL', | ||
242 | + SKIP_LATEST_PERSISTENCE = 'skipLatestPersistence', | ||
243 | + USE_SERVER_TS = 'useServerTs', | ||
244 | +} | ||
245 | + | ||
246 | +export enum SaveTimeseriesFieldsNameEnum { | ||
247 | + DEFAULT_TTL = 'Default TTL in seconds', | ||
248 | + SKIP_LATEST_PERSISTENCE = 'Skit latest persistence', | ||
249 | + USE_SERVER_TS = 'Use server ts', | ||
250 | +} | ||
251 | + | ||
252 | +// save to custom table | ||
253 | +export enum SaveToCustomTableFieldsEnum { | ||
254 | + FIELDS_MAPPING = 'fieldsMapping', | ||
255 | + TABLE_NAME = 'tableName', | ||
256 | +} | ||
257 | + | ||
258 | +export enum SaveToCustomTableFieldsNameEnum { | ||
259 | + FIELDS_MAPPING = 'Fields mapping', | ||
260 | + TABLE_NAME = 'Custom table name', | ||
261 | +} | ||
262 | + | ||
263 | +// Unassign from customer | ||
264 | +export enum UnassignFromCustomerFieldsEnum { | ||
265 | + CUSTOMER_NAME_PATTERN = 'customerNamePattern', | ||
266 | + CUSTOMER_CACHE_EXPIRATION = 'customerCacheExpiration', | ||
267 | +} | ||
268 | + | ||
269 | +export enum UnassignFromCustomerFieldsNameEnum { | ||
270 | + CUSTOMER_NAME_PATTERN = 'Customer name pattern', | ||
271 | + CUSTOMER_CACHE_EXPIRATION = 'Customer cache expiration time(sec)', | ||
272 | +} |
1 | +export enum CommonFieldsEnum { | ||
2 | + NAME = 'name', | ||
3 | + DESCRIPTION = 'description', | ||
4 | + DEBUG_MODE = 'debugMode', | ||
5 | +} | ||
6 | + | ||
7 | +export enum CommonFieldsNameEnum { | ||
8 | + NAME = '名称', | ||
9 | + DESCRIPTION = '说明', | ||
10 | + DEBUG_MODE = '调试模式', | ||
11 | +} | ||
12 | + | ||
13 | +export const CommonFields = { ...CommonFieldsEnum }; | ||
14 | +export const CommonFieldsName = { ...CommonFieldsNameEnum }; | ||
15 | +export type CommonFieldsType = typeof CommonFields; |
1 | +// Enrichment Calculate delta | ||
2 | +export enum CalculateDeltaFieldsEnum { | ||
3 | + INPUT_VALUE_KEY = 'inputValueKey', | ||
4 | + OUTPUT_VALUE_KEY = 'outputValueKey', | ||
5 | + ROUND = 'round', | ||
6 | + USE_CACHE = 'useCache', | ||
7 | + TELL_FAILURE_IF_DELTA_IS_NEGATIVE = 'tellFailureIfDeltaIsNegative', | ||
8 | + ADD_PERIOD_BETWEEN_MSGS = 'addPeriodBetweenMsgs', | ||
9 | + PERIOD_VALUE_KEY = 'periodValueKey', | ||
10 | +} | ||
11 | + | ||
12 | +export enum CalculateDeltaFieldsNameEnum { | ||
13 | + INPUT_VALUE_KEY = 'Input value key', | ||
14 | + OUTPUT_VALUE_KEY = 'Output value key', | ||
15 | + ROUND = 'Decimals', | ||
16 | + USE_CACHE = 'Use cache for latest value', | ||
17 | + TELL_FAILURE_IF_DELTA_IS_NEGATIVE = 'Tell Failure if delta is negative', | ||
18 | + ADD_PERIOD_BETWEEN_MSGS = 'Add period between messages', | ||
19 | + PERIOD_VALUE_KEY = 'Period value key', | ||
20 | +} | ||
21 | + | ||
22 | +// Enrichment Customer Attributes | ||
23 | +export enum CustomerAttributesFieldsEnum { | ||
24 | + ATTR_MAPING = 'attrMapping', | ||
25 | + TELEMETRY = 'telemetry', | ||
26 | +} | ||
27 | + | ||
28 | +export enum CustomerAttributesFieldsNameEnum { | ||
29 | + ATTR_MAPING = 'Attributes mapping', | ||
30 | + TELEMETRY = 'Latest telemetry', | ||
31 | +} | ||
32 | + | ||
33 | +// Enrichment Customer details | ||
34 | +export enum CustomerDetailsFieldsEnum { | ||
35 | + DETAILS_LIST = 'detailsList', | ||
36 | + ADD_TO_METADATA = 'addToMetadata', | ||
37 | +} | ||
38 | + | ||
39 | +export enum CustomerDetailsFieldsNameEnum { | ||
40 | + DETAILS_LIST = 'Select entity details', | ||
41 | + ADD_TO_METADATA = 'Add selected details to message metadata', | ||
42 | +} | ||
43 | + | ||
44 | +// Enrichment Originator attributes | ||
45 | +export enum OriginatorAttributesEnum { | ||
46 | + TELL_FAILURE_IF_ABSENT = 'tellFailureIfAbsent', | ||
47 | + CLIENT_ATTRIBUTE_NAMES = 'clientAttributeNames', | ||
48 | + SHARED_ATTRIBUTE_NAMES = 'sharedAttributeNames', | ||
49 | + SERVER_ATTRIBUTE_NAMES = 'serverAttributeNames', | ||
50 | + LATEST_TS_KEY_NAMES = 'latestTsKeyNames', | ||
51 | + GET_LATEST_VALUE_WITH_TS = 'getLatestValueWithTs', | ||
52 | +} | ||
53 | + | ||
54 | +export enum OriginatorAttributesNameEnum { | ||
55 | + TELL_FAILURE_IF_ABSENT = 'Tell Failure', | ||
56 | + CLIENT_ATTRIBUTE_NAMES = 'Client attributes', | ||
57 | + SHARED_ATTRIBUTE_NAMES = 'Shared attributes', | ||
58 | + SERVER_ATTRIBUTE_NAMES = 'Server attributes', | ||
59 | + LATEST_TS_KEY_NAMES = 'Latest timeseries', | ||
60 | + GET_LATEST_VALUE_WITH_TS = 'Fetch Latest telemetry with Timestamp', | ||
61 | +} | ||
62 | + | ||
63 | +// Enrichment Originator Fields | ||
64 | +export enum OriginatorFieldsEnum { | ||
65 | + FIELDS_MAPPING = 'fieldsMapping', | ||
66 | +} | ||
67 | + | ||
68 | +export enum OriginatorFieldsNameEnum { | ||
69 | + FIELDS_MAPPING = 'Fields mapping', | ||
70 | +} | ||
71 | + | ||
72 | +// Enrichment originator telemetry | ||
73 | +export enum OriginatorTelemetryFieldsEnum { | ||
74 | + LATEST_TS_KEY_NAMES = 'latestTsKeyNames', | ||
75 | + AGGREGATION = 'aggregation', | ||
76 | + FETCH_MODE = 'fetchMode', | ||
77 | + ORDER_BY = 'orderBy', | ||
78 | + LIMIT = 'limit', | ||
79 | + USE_METADATA_INTERVAL_PATTERNS = 'useMetadataIntervalPatterns', | ||
80 | + START_INTERVAL = 'startInterval', | ||
81 | + START_INTERVAL_TIME_UNIT = 'startIntervalTimeUnit', | ||
82 | + END_INTERVAL = 'endInterval', | ||
83 | + END_INTERVAL_TIME_UNIT = 'endIntervalTimeUnit', | ||
84 | + START_INTERVAL_PATTERN = 'startIntervalPattern', | ||
85 | + END_INTERVAL_PATTERN = 'endIntervalPattern', | ||
86 | +} | ||
87 | + | ||
88 | +export enum OriginatorTelemetryFieldsNameEnum { | ||
89 | + LATEST_TS_KEY_NAMES = 'Latest timeseries', | ||
90 | + AGGREGATION = '数据聚合功能', | ||
91 | + FETCH_MODE = 'Fetch Mode', | ||
92 | + ORDER_BY = 'Order by', | ||
93 | + LIMIT = 'Limit', | ||
94 | + USE_METADATA_INTERVAL_PATTERNS = 'useMetadataIntervalPatterns', | ||
95 | + START_INTERVAL = 'Start Interval', | ||
96 | + START_INTERVAL_TIME_UNIT = 'Start Interval Time Unit', | ||
97 | + END_INTERVAL = 'End Interval', | ||
98 | + END_INTERVAL_TIME_UNIT = 'End Interval Time Unit', | ||
99 | + START_INTERVAL_PATTERN = 'startIntervalPattern', | ||
100 | + END_INTERVAL_PATTERN = 'endIntervalPattern', | ||
101 | +} | ||
102 | + | ||
103 | +// Enrichment Related attributes | ||
104 | +export enum RelatedAttributesFieldsEnum { | ||
105 | + RELATIONS_QUERY = 'relationsQuery', | ||
106 | + ATTR_MAPPING = 'attrMapping', | ||
107 | + TELEMETRY = 'telemetry', | ||
108 | +} | ||
109 | + | ||
110 | +export enum RelatedAttributesFieldsNameEnum { | ||
111 | + RELATIONS_QUERY = 'Relations query', | ||
112 | + ATTR_MAPPING = 'Attributes mapping', | ||
113 | + TELEMETRY = 'Latest telemetry', | ||
114 | +} | ||
115 | + | ||
116 | +// Enrichment Related device Attributes | ||
117 | +export enum RelatedDeviceAttributeFieldsEnum { | ||
118 | + DEVICE_RELATIONS_QUERY = 'deviceRelationsQuery', | ||
119 | + TELL_FAILURE_IF_ABSENT = 'tellFailureIfAbsent', | ||
120 | + CLIENT_ATTRIBUTE_NAMES = 'clientAttributeNames', | ||
121 | + SHARED_ATTRIBUTE_NAMES = 'sharedAttributeNames', | ||
122 | + SERVER_ATTRIBUTE_NAMES = 'serverAttributeNames', | ||
123 | + LATEST_TS_KEY_NAMES = 'latestTsKeyNames', | ||
124 | + GET_LATEST_VALUE_WITH_TS = 'getLatestValueWithTs', | ||
125 | + FETCH_LAST_LEVEL_ONLY = 'fetchLastLevelOnly', | ||
126 | + | ||
127 | + // DEVICE_RELATIONS_QUERY | ||
128 | + DIRECTION = 'direction', | ||
129 | + MAX_LEVEL = 'maxLevel', | ||
130 | + RELATION_TYPE = 'relationType', | ||
131 | + DEVICE_TYPES = 'deviceTypes', | ||
132 | +} | ||
133 | + | ||
134 | +export enum RelatedDeviceAttributeFieldsNameEnum { | ||
135 | + DEVICE_RELATIONS_QUERY = 'deviceRelationsQuery', | ||
136 | + TELL_FAILURE_IF_ABSENT = 'Tell Failure', | ||
137 | + CLIENT_ATTRIBUTE_NAMES = 'Client attributes', | ||
138 | + SHARED_ATTRIBUTE_NAMES = 'Shared attributes', | ||
139 | + SERVER_ATTRIBUTE_NAMES = 'Server attributes', | ||
140 | + LATEST_TS_KEY_NAMES = 'Latest timeseries', | ||
141 | + GET_LATEST_VALUE_WITH_TS = 'Fetch Latest telemetry with Timestamp', | ||
142 | + FETCH_LAST_LEVEL_ONLY = '仅获取最后一级关联', | ||
143 | + | ||
144 | + // DEVICE_RELATIONS_QUERY | ||
145 | + DIRECTION = '方向', | ||
146 | + MAX_LEVEL = 'Max relation level', | ||
147 | + RELATION_TYPE = '关联类型', | ||
148 | + DEVICE_TYPES = '设备类型', | ||
149 | +} | ||
150 | + | ||
151 | +// Tenant attributes | ||
152 | +export enum TenantAttributesFieldsEnum { | ||
153 | + ATTR_MAPING = 'attrMapping', | ||
154 | + TELEMETRY = 'telemetry', | ||
155 | +} | ||
156 | + | ||
157 | +export enum TenantAttributesFieldsNameEnum { | ||
158 | + ATTR_MAPING = 'attrMapping', | ||
159 | + TELEMETRY = 'Latest telemetry', | ||
160 | +} | ||
161 | + | ||
162 | +// Enrichment Tenant details | ||
163 | +export enum TenantDetailsFieldsEnum { | ||
164 | + DETAILS_LIST = 'detailsList', | ||
165 | + ADD_TO_METADATA = 'addToMetadata', | ||
166 | +} | ||
167 | + | ||
168 | +export enum TenantDetailsFieldsNameEnum { | ||
169 | + DETAILS_LIST = 'Add selected details to message metadata', | ||
170 | + ADD_TO_METADATA = 'Select entity details', | ||
171 | +} |
1 | +// Alarm notice | ||
2 | +export enum AlarmNoticeFieldsEnum { | ||
3 | + CONFIGURATION = 'CONFIGURATION', | ||
4 | +} | ||
5 | + | ||
6 | +export enum AlarmNoticeFieldsNameEnum { | ||
7 | + CONFIGURATION = '配置', | ||
8 | +} | ||
9 | + | ||
10 | +// aws sns | ||
11 | +export enum AwsSnsFieldsEnum { | ||
12 | + TOPIC_ARN_PATTERN = 'topicArnPattern', | ||
13 | + ACCESS_KEY_ID = 'accessKeyId', | ||
14 | + SECRET_ACCESS_KEY = 'secretAccessKey', | ||
15 | + REGION = 'region', | ||
16 | +} | ||
17 | + | ||
18 | +export enum AwsSnsFieldsNameEnum { | ||
19 | + TOPIC_ARN_PATTERN = 'Topic ARN pattern', | ||
20 | + ACCESS_KEY_ID = 'AWS Access Key ID', | ||
21 | + SECRET_ACCESS_KEY = 'AWS Secret Access Key', | ||
22 | + REGION = 'AWS Region', | ||
23 | +} | ||
24 | + | ||
25 | +// Aws sqs | ||
26 | +export enum AwsSqsFieldsEnum { | ||
27 | + QUEUE_TYPE = 'queueType', | ||
28 | + QUEUE_URL_PATTERN = 'queueUrlPattern', | ||
29 | + DELAY_SECONDS = 'delaySeconds', | ||
30 | + MESSAGE_ATTRIBUTES = 'messageAttributes', | ||
31 | + ACCESS_KEY_ID = 'accessKeyId', | ||
32 | + SECRET_ACCESS_KEY = 'secretAccessKey', | ||
33 | + REGION = 'region', | ||
34 | +} | ||
35 | + | ||
36 | +export enum AwsSqsFieldsNameEnum { | ||
37 | + QUEUE_TYPE = 'Queue type', | ||
38 | + QUEUE_URL_PATTERN = 'Queue URL pattern', | ||
39 | + DELAY_SECONDS = 'Delay(seconds)', | ||
40 | + MESSAGE_ATTRIBUTES = 'Message attributes', | ||
41 | + ACCESS_KEY_ID = 'AWS Access Key ID', | ||
42 | + SECRET_ACCESS_KEY = 'AWS Secret Access Key', | ||
43 | + REGION = 'AWS Region', | ||
44 | +} | ||
45 | + | ||
46 | +// Azure iot hub | ||
47 | +export enum AzureIotHubFieldsEnum { | ||
48 | + TOPIC_PATTERN = 'topicPattern', | ||
49 | + HOST = 'host', | ||
50 | + PORT = 'port', | ||
51 | + CONNECT_TIMEOUT_SEC = 'connectTimeoutSec', | ||
52 | + CLIENT_ID = 'clientId', | ||
53 | + CLEAN_SESSION = 'cleanSession', | ||
54 | + SSL = 'ssl', | ||
55 | + CREDENTIALS = 'credentials', | ||
56 | + | ||
57 | + TYPE = 'type', | ||
58 | + SAS_KEY = 'sasKey', | ||
59 | + CA_CERT = 'caCert', | ||
60 | + CA_CERT_FILE_NAME = 'caCertFileName', | ||
61 | + PRIVATE_KEY = 'privateKey', | ||
62 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | ||
63 | + CERT = 'cert', | ||
64 | + CERT_FILE_NAME = 'certFileName', | ||
65 | + PASSWORD = 'password', | ||
66 | +} | ||
67 | + | ||
68 | +export enum AzureIotHubFieldsNameEnum { | ||
69 | + TOPIC_PATTERN = 'Topic', | ||
70 | + HOST = 'Hostname', | ||
71 | + PORT = 'port', | ||
72 | + CONNECT_TIMEOUT_SEC = 'connectTimeoutSec', | ||
73 | + CLIENT_ID = 'Device ID', | ||
74 | + CLEAN_SESSION = 'cleanSession', | ||
75 | + SSL = 'ssl', | ||
76 | + CREDENTIALS = 'credentials', | ||
77 | + | ||
78 | + TYPE = 'Credentials type', | ||
79 | + SAS_KEY = 'sasKey', | ||
80 | + CA_CERT = 'CA certificate file', | ||
81 | + CA_CERT_FILE_NAME = 'caCertFileName', | ||
82 | + PRIVATE_KEY = 'Client private key file', | ||
83 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | ||
84 | + CERT = 'Client certificate file', | ||
85 | + CERT_FILE_NAME = 'certFileName', | ||
86 | + PASSWORD = 'Private key password', | ||
87 | +} | ||
88 | + | ||
89 | +// GCP pubsub | ||
90 | +export enum GcpPubsubFieldsEnum { | ||
91 | + PROJECT_ID = 'projectId', | ||
92 | + TOPIC_NAME = 'topicName', | ||
93 | + SERVICE_ACCOUNT_KEY = 'serviceAccountKey', | ||
94 | + SERVICE_ACCOUNT_KEY_FILE_NAME = 'serviceAccountKeyFileName', | ||
95 | + MESSAGE_ATTRIBUTES = 'messageAttributes', | ||
96 | +} | ||
97 | + | ||
98 | +export enum GcpPubsubFieldsNameEnum { | ||
99 | + PROJECT_ID = 'GCP project ID', | ||
100 | + TOPIC_NAME = 'Topic name', | ||
101 | + SERVICE_ACCOUNT_KEY = 'GCP service account key file', | ||
102 | + SERVICE_ACCOUNT_KEY_FILE_NAME = 'serviceAccountKeyFileName', | ||
103 | + MESSAGE_ATTRIBUTES = 'Message attributes', | ||
104 | +} | ||
105 | + | ||
106 | +// Kafka | ||
107 | +export enum KafkaFieldsEnum { | ||
108 | + TOPIC_PATTERN = 'topicPattern', | ||
109 | + BOOTSTRAP_SERVERS = 'bootstrapServers', | ||
110 | + RETRIES = 'retries', | ||
111 | + BATCH_SIZE = 'batchSize', | ||
112 | + LINGER = 'linger', | ||
113 | + BUFFER_MEMORY = 'bufferMemory', | ||
114 | + ACKS = 'acks', | ||
115 | + KEY_SERIALIZER = 'keySerializer', | ||
116 | + VALUE_SERIALIZER = 'valueSerializer', | ||
117 | + OTHER_PROPERTIES = 'otherProperties', | ||
118 | + ADD_METADATA_KEY_VALUES_AS_KAFKA_HEADERS = 'addMetadataKeyValuesAsKafkaHeaders', | ||
119 | + KAFKA_HEADERS_CHARSET = 'kafkaHeadersCharset', | ||
120 | +} | ||
121 | + | ||
122 | +export enum KafkaFieldsNameEnum { | ||
123 | + TOPIC_PATTERN = 'Topic pattern', | ||
124 | + BOOTSTRAP_SERVERS = 'Bootstrap servers', | ||
125 | + RETRIES = 'Automatically retry times if fails', | ||
126 | + BATCH_SIZE = 'Produces batch size in bytes', | ||
127 | + LINGER = 'Time to buffer locally(ms)', | ||
128 | + BUFFER_MEMORY = 'Client buffer max size in bytes', | ||
129 | + ACKS = 'Number of acknowledgments', | ||
130 | + KEY_SERIALIZER = 'Key serializer', | ||
131 | + VALUE_SERIALIZER = 'Value serializer', | ||
132 | + OTHER_PROPERTIES = 'Other properties', | ||
133 | + ADD_METADATA_KEY_VALUES_AS_KAFKA_HEADERS = 'Add Message metadata key-value pairs to Kafka record headers', | ||
134 | + KAFKA_HEADERS_CHARSET = 'Charset encoding', | ||
135 | +} | ||
136 | + | ||
137 | +// Mqtt | ||
138 | +export enum MqttFieldsEnum { | ||
139 | + TOPIC_PATTERN = 'topicPattern', | ||
140 | + HOST = 'host', | ||
141 | + PORT = 'port', | ||
142 | + CONNECT_TIMEOUT_SEC = 'connectTimeoutSec', | ||
143 | + CLIENT_ID = 'clientId', | ||
144 | + APPEND_CLIENT_ID_SUFFIX = 'appendClientIdSuffix', | ||
145 | + CLEAN_SESSION = 'cleanSession', | ||
146 | + SSL = 'ssl', | ||
147 | + CREDENTIALS = 'credentials', | ||
148 | + | ||
149 | + TYPE = 'type', | ||
150 | + PASSWORD = 'password', | ||
151 | + CA_CERT = 'caCert', | ||
152 | + CA_CERT_FILE_NAME = 'caCertFileName', | ||
153 | + PRIVATE_KEY = 'privateKey', | ||
154 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | ||
155 | + CERT = 'cert', | ||
156 | + CERT_FILE_NAME = 'certFileName', | ||
157 | + USERNAME = 'username', | ||
158 | +} | ||
159 | + | ||
160 | +export enum MqttFieldsNameEnum { | ||
161 | + TOPIC_PATTERN = 'Topic pattern', | ||
162 | + HOST = 'Hose', | ||
163 | + PORT = 'Port', | ||
164 | + CONNECT_TIMEOUT_SEC = 'Connection timeout(sec)', | ||
165 | + CLIENT_ID = 'Client ID', | ||
166 | + APPEND_CLIENT_ID_SUFFIX = 'Add Service ID as suffix to Client ID', | ||
167 | + CLEAN_SESSION = 'Clean session', | ||
168 | + SSL = 'Enable SSL', | ||
169 | + CREDENTIALS = 'credentials', | ||
170 | + | ||
171 | + TYPE = 'Credentials type', | ||
172 | + PASSWORD = 'Password', | ||
173 | + CA_CERT = 'Server CA certificate file', | ||
174 | + CA_CERT_FILE_NAME = 'caCertFileName', | ||
175 | + PRIVATE_KEY = 'Client private key file', | ||
176 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | ||
177 | + CERT = 'Client certificate file', | ||
178 | + CERT_FILE_NAME = 'certFileName', | ||
179 | + USERNAME = 'Username', | ||
180 | +} | ||
181 | + | ||
182 | +// Rabbitmq | ||
183 | +export enum RabbitmqFieldsEnum { | ||
184 | + EXCHANGE_NAME_PATTERN = 'exchangeNamePattern', | ||
185 | + ROUTING_KEY_PATTERN = 'routingKeyPattern', | ||
186 | + MESSAGE_PROPERTIES = 'messageProperties', | ||
187 | + HOST = 'host', | ||
188 | + PORT = 'port', | ||
189 | + VIRTUAL_HOST = 'virtualHost', | ||
190 | + USERNAME = 'username', | ||
191 | + PASSWORD = 'password', | ||
192 | + AUTOMATIC_RECOVERY_ENABLED = 'automaticRecoveryEnabled', | ||
193 | + CONNECTION_TIMEOUT = 'connectionTimeout', | ||
194 | + HANDSHAKE_TIMEOUT = 'handshakeTimeout', | ||
195 | + CLIENT_PROPERTIES = 'clientProperties', | ||
196 | +} | ||
197 | + | ||
198 | +export enum RabbitmqFieldsNameEnum { | ||
199 | + EXCHANGE_NAME_PATTERN = 'Exchange name pattern', | ||
200 | + ROUTING_KEY_PATTERN = 'Routing key pattern', | ||
201 | + MESSAGE_PROPERTIES = 'Message properties', | ||
202 | + HOST = 'Host', | ||
203 | + PORT = 'Port', | ||
204 | + VIRTUAL_HOST = 'Virtual host', | ||
205 | + USERNAME = 'Username', | ||
206 | + PASSWORD = 'Password', | ||
207 | + AUTOMATIC_RECOVERY_ENABLED = 'Automatic recovery', | ||
208 | + CONNECTION_TIMEOUT = 'Connection timeout(ms)', | ||
209 | + HANDSHAKE_TIMEOUT = 'Handshake timeout(ms)', | ||
210 | + CLIENT_PROPERTIES = 'Client properties', | ||
211 | +} | ||
212 | + | ||
213 | +// Rest api call | ||
214 | +export enum RestApiCallFieldsEnum { | ||
215 | + REST_ENDPOINT_URL_PATTERN = 'restEndpointUrlPattern', | ||
216 | + REQUEST_METHOD = 'requestMethod', | ||
217 | + USE_SIMPLE_CLIENT_HTTP_FACTORY = 'useSimpleClientHttpFactory', | ||
218 | + IGNORE_REQUEST_BODY = 'ignoreRequestBody', | ||
219 | + ENABLE_PROXY = 'enableProxy', | ||
220 | + USE_SYSTEM_PROXY_PROPERTIES = 'useSystemProxyProperties', | ||
221 | + PROXY_SCHEME = 'proxyScheme', | ||
222 | + PROXY_HOST = 'proxyHost', | ||
223 | + PROXY_PORT = 'proxyPort', | ||
224 | + PROXY_USER = 'proxyUser', | ||
225 | + PROXY_PASSWORD = 'proxyPassword', | ||
226 | + READ_TIMEOUT_MS = 'readTimeoutMs', | ||
227 | + MAX_PARALLEL_REQUESTS_COUNT = 'maxParallelRequestsCount', | ||
228 | + HEADERS = 'headers', | ||
229 | + USE_REDIS_QUEUE_FOR_MSG_PERSISTENCE = 'useRedisQueueForMsgPersistence', | ||
230 | + TRIM_QUEUE = 'trimQueue', | ||
231 | + MAX_QUEUE_SIZE = 'maxQueueSize', | ||
232 | + CREDENTIALS = 'credentials', | ||
233 | + | ||
234 | + TYPE = 'type', | ||
235 | + PASSWORD = 'password', | ||
236 | + CA_CERT = 'caCert', | ||
237 | + CA_CERT_FILE_NAME = 'caCertFileName', | ||
238 | + PRIVATE_KEY = 'privateKey', | ||
239 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | ||
240 | + CERT = 'cert', | ||
241 | + CERT_FILE_NAME = 'certFileName', | ||
242 | + USERNAME = 'username', | ||
243 | +} | ||
244 | + | ||
245 | +export enum RestApiCallFieldsNameEnum { | ||
246 | + REST_ENDPOINT_URL_PATTERN = 'Endpoint URL pattern', | ||
247 | + REQUEST_METHOD = 'Request method', | ||
248 | + USE_SIMPLE_CLIENT_HTTP_FACTORY = 'Use simple client HTTP factory', | ||
249 | + IGNORE_REQUEST_BODY = 'Without request body', | ||
250 | + ENABLE_PROXY = 'Enable proxy', | ||
251 | + USE_SYSTEM_PROXY_PROPERTIES = 'Use system proxy properties', | ||
252 | + PROXY_SCHEME = 'Proxy scheme', | ||
253 | + PROXY_HOST = 'Proxy host', | ||
254 | + PROXY_PORT = 'Proxy port', | ||
255 | + PROXY_USER = 'Proxy user', | ||
256 | + PROXY_PASSWORD = 'Proxy password', | ||
257 | + READ_TIMEOUT_MS = 'Read timeout in millis', | ||
258 | + MAX_PARALLEL_REQUESTS_COUNT = 'Max number of parallel request', | ||
259 | + HEADERS = 'Header', | ||
260 | + USE_REDIS_QUEUE_FOR_MSG_PERSISTENCE = 'Use redis queue for message persistence', | ||
261 | + TRIM_QUEUE = 'Trim redis queue', | ||
262 | + MAX_QUEUE_SIZE = 'Redis queue max size', | ||
263 | + CREDENTIALS = 'Credentials', | ||
264 | + | ||
265 | + TYPE = 'Credentials type', | ||
266 | + PASSWORD = 'Password', | ||
267 | + CA_CERT = 'Server CA certificate file', | ||
268 | + CA_CERT_FILE_NAME = 'caCertFileName', | ||
269 | + PRIVATE_KEY = 'Client private key file', | ||
270 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | ||
271 | + CERT = 'Client certificate file', | ||
272 | + CERT_FILE_NAME = 'certFileName', | ||
273 | + USERNAME = 'Username', | ||
274 | +} | ||
275 | + | ||
276 | +// send email | ||
277 | +export enum SendEmailFieldsEnum { | ||
278 | + USE_SYSTEM_SMTP_SETTINGS = 'useSystemSmtpSettings', | ||
279 | + SMTP_PROTOCOL = 'smtpProtocol', | ||
280 | + SMTP_HOST = 'smtpHost', | ||
281 | + SMTP_PORT = 'smtpPort', | ||
282 | + TIMEOUT = 'timeout', | ||
283 | + ENABLE_TLS = 'enableTls', | ||
284 | + TLS_VERSION = 'tlsVersion', | ||
285 | + ENABLE_PROXY = 'enableProxy', | ||
286 | + PROXY_HOST = 'proxyHost', | ||
287 | + PROXY_PORT = 'proxyPort', | ||
288 | + PROXY_USER = 'proxyUser', | ||
289 | + PROXY_PASSWORD = 'proxyPassword', | ||
290 | + USERNAME = 'username', | ||
291 | + PASSWORD = 'password', | ||
292 | +} | ||
293 | + | ||
294 | +export enum SendEmailFieldsNameEnum { | ||
295 | + USE_SYSTEM_SMTP_SETTINGS = 'Use system SMTP settings', | ||
296 | + SMTP_PROTOCOL = 'Protocol', | ||
297 | + SMTP_HOST = 'SMTP host', | ||
298 | + SMTP_PORT = 'SMTP port', | ||
299 | + TIMEOUT = 'Timeout ms', | ||
300 | + ENABLE_TLS = 'Enable TLS', | ||
301 | + TLS_VERSION = 'TLS version', | ||
302 | + ENABLE_PROXY = 'Enable proxy', | ||
303 | + PROXY_HOST = 'Proxy host', | ||
304 | + PROXY_PORT = 'Proxy port', | ||
305 | + PROXY_USER = 'Proxy user', | ||
306 | + PROXY_PASSWORD = 'Proxy password', | ||
307 | + USERNAME = 'Username', | ||
308 | + PASSWORD = 'Password', | ||
309 | +} | ||
310 | + | ||
311 | +export enum SendSMSFieldsEnum { | ||
312 | + NUMBERS_TO_TEMPLATE = 'numbersToTemplate', | ||
313 | + SMS_MESSAGE_TEMPLATE = 'smsMessageTemplate', | ||
314 | + USE_SYSTEM_SMS_SETTINGS = 'useSystemSmsSettings', | ||
315 | + SMS_PROVIDER_CONFIGURATION = 'smsProviderConfiguration', | ||
316 | + | ||
317 | + ACCESS_KEY_ID = 'accessKeyId', | ||
318 | + SECRET_ACCESS_KEY = 'secretAccessKey', | ||
319 | + REGION = 'region', | ||
320 | + TYPE = 'type', | ||
321 | + NUMBER_FROM = 'numberFrom', | ||
322 | + ACCOUNT_SID = 'accountSid', | ||
323 | + ACCOUNT_TOKEN = 'accountToken', | ||
324 | +} | ||
325 | + | ||
326 | +export enum SendSMSFieldsNameEnum { | ||
327 | + NUMBERS_TO_TEMPLATE = 'Phone Numbers To Template', | ||
328 | + SMS_MESSAGE_TEMPLATE = 'SMS message Template', | ||
329 | + USE_SYSTEM_SMS_SETTINGS = 'User system SMS provider settings', | ||
330 | + SMS_PROVIDER_CONFIGURATION = 'smsProviderConfiguration', | ||
331 | + | ||
332 | + ACCESS_KEY_ID = 'AWS访问密钥ID', | ||
333 | + SECRET_ACCESS_KEY = 'AWS访问密钥', | ||
334 | + REGION = 'AWS地区', | ||
335 | + TYPE = 'SMS服务商类型', | ||
336 | + NUMBER_FROM = '发送方电话号码', | ||
337 | + ACCOUNT_SID = 'Twilio账户SID', | ||
338 | + ACCOUNT_TOKEN = 'Twilio账户令牌', | ||
339 | +} |
1 | +// Filter Check Alarm Status Fields | ||
2 | +export enum CheckAlarmStatusFieldEnum { | ||
3 | + ALARM_STATUS_LIST = 'alarmStatusList', | ||
4 | +} | ||
5 | + | ||
6 | +export enum CheckAlarmStatusFieldNameEnum { | ||
7 | + ALARM_STATUS_LIST = 'Alarm status filter', | ||
8 | +} | ||
9 | + | ||
10 | +// Filter CHeck Existence Fields | ||
11 | +export enum CheckExistenceFieldsEnum { | ||
12 | + MESSAGE_NAMES = 'messageNames', | ||
13 | + METADATA_NAMES = 'metadataNames', | ||
14 | + CHECK_ALL_KEYS = 'checkAllKeys', | ||
15 | +} | ||
16 | + | ||
17 | +export enum CheckExistenceFieldsNameEnum { | ||
18 | + MESSAGE_NAMES = '消息数据', | ||
19 | + METADATA_NAMES = '消息元数据', | ||
20 | + CHECK_ALL_KEYS = '检查所有选择的键是否都存在', | ||
21 | +} | ||
22 | + | ||
23 | +// Filter Check Relation Fields | ||
24 | +export enum CheckRelationFieldsEnum { | ||
25 | + DIRECTION = 'direction', | ||
26 | + CHECK_FOR_SINGLE_ENTITY = 'checkForSingleEntity', | ||
27 | + ENTITY_TYPE = 'entityType', | ||
28 | + RELEATION_TYPE = 'relationType', | ||
29 | + ENTITY_ID = 'entityId', | ||
30 | +} | ||
31 | + | ||
32 | +export enum CheckRelationFieldsNameEnum { | ||
33 | + DIRECTION = '方向', | ||
34 | + CHECK_FOR_SINGLE_ENTITY = 'Check relation to specific entity', | ||
35 | + ENTITY_TYPE = '类型', | ||
36 | + RELEATION_TYPE = '关联类型', | ||
37 | +} | ||
38 | + | ||
39 | +// Filter Gps geofencing filter | ||
40 | +export enum GpsGeofencingFilterFieldsEnum { | ||
41 | + LATITUDE_KEY_NAME = 'latitudeKeyName', | ||
42 | + LONGITUDE_KEY_NAME = 'longitudeKeyName', | ||
43 | + PERIMETER_TYPE = 'perimeterType', | ||
44 | + FETCH_PERIMETER_INFO_FROM_MESSAGE_METADATA = 'fetchPerimeterInfoFromMessageMetadata', | ||
45 | + PERIMETER_KEY_NAME = 'perimeterKeyName', | ||
46 | + CENTER_LATITUDE = 'centerLatitude', | ||
47 | + CENTER_LONGITUDE = 'centerLongitude', | ||
48 | + RANGE = 'range', | ||
49 | + RANGE_UNIT = 'rangeUnit', | ||
50 | + POLYGONS_DEFINITION = 'polygonsDefinition', | ||
51 | +} | ||
52 | + | ||
53 | +export enum GpsGeofencingFilterFieldsNameEnum { | ||
54 | + LATITUDE_KEY_NAME = 'Latitude Key Name', | ||
55 | + LONGITUDE_KEY_NAME = 'Longitude Key Name', | ||
56 | + PERIMETER_TYPE = 'Perimeter Type', | ||
57 | + FETCH_PERIMETER_INFO_FROM_MESSAGE_METADATA = 'Fetch perimeter information from message metadata', | ||
58 | + CENTER_LATITUDE = 'Center latitude', | ||
59 | + CENTER_LONGITUDE = 'Center longitude', | ||
60 | + RANGE = 'Range', | ||
61 | + RANGE_UNIT = 'Range unit', | ||
62 | + PERIMETER_KEY_NAME = 'Perimeter key name', | ||
63 | + POLYGONS_DEFINITION = 'Polygons definition', | ||
64 | +} | ||
65 | + | ||
66 | +// Filter Message Type | ||
67 | +export enum MessageTypeFieldsEnum { | ||
68 | + MESSAGE_TYPES = 'messageTypes', | ||
69 | +} | ||
70 | + | ||
71 | +export enum MessageTypeFieldsNameEnum { | ||
72 | + MESSAGE_TYPES = 'Message Types Filter', | ||
73 | +} | ||
74 | + | ||
75 | +// Filter Originator Type | ||
76 | +export enum OriginatorTypeFieldsEnum { | ||
77 | + ORIGINATOR_TYPES = 'originatorTypes', | ||
78 | +} | ||
79 | + | ||
80 | +export enum OriginatorTypeFieldsNameEnum { | ||
81 | + ORIGINATOR_TYPES = 'Originator types filter', | ||
82 | +} | ||
83 | + | ||
84 | +// Filter Script | ||
85 | +export enum ScriptFieldsEnum { | ||
86 | + JS_SCRIPT = 'jsScript', | ||
87 | +} | ||
88 | + | ||
89 | +export enum ScriptFieldsNameEnum { | ||
90 | + JS_SCRIPT = 'Filter', | ||
91 | +} | ||
92 | + | ||
93 | +// Filter Switch | ||
94 | +export enum SwitchFieldsEnum { | ||
95 | + JS_SCRIPT = 'jsScript', | ||
96 | +} | ||
97 | + | ||
98 | +export enum SwitchFieldsNameEnum { | ||
99 | + JS_SCRIPT = 'Filter', | ||
100 | +} |
1 | +export enum CheckPointFieldsEnum { | ||
2 | + QUEUE_NAME = 'queueName', | ||
3 | +} | ||
4 | + | ||
5 | +export enum CheckPointFieldsNameEnum { | ||
6 | + QUEUE_NAME = '队列名称', | ||
7 | +} | ||
8 | + | ||
9 | +export enum RuleChainFieldsEnum { | ||
10 | + RULE_CHAIN_ID = 'ruleChainId', | ||
11 | +} | ||
12 | + | ||
13 | +export enum RuleChainFieldsNameEnum { | ||
14 | + RULE_CHAIN_ID = '规则链', | ||
15 | +} |
1 | +// Change originator | ||
2 | +export enum ChangeOriginatorFieldsEnum { | ||
3 | + ORIGINATOR_SOURCE = 'originatorSource', | ||
4 | + RELATIONS_QUERY = 'relationsQuery', | ||
5 | +} | ||
6 | + | ||
7 | +export enum ChangeOriginatorFieldsNameEnum { | ||
8 | + ORIGINATOR_SOURCE = 'Originator source', | ||
9 | + RELATIONS_QUERY = 'Relations Query', | ||
10 | +} | ||
11 | + | ||
12 | +export enum ScriptFieldsEnum { | ||
13 | + JS_SCRIPT = 'jsScript', | ||
14 | +} | ||
15 | + | ||
16 | +export enum ScriptFieldsNameEnum { | ||
17 | + JS_SCRIPT = 'Transform', | ||
18 | +} | ||
19 | + | ||
20 | +export enum ToEmailFieldsEnum { | ||
21 | + FROM_TEMPLATE = 'fromTemplate', | ||
22 | + TO_TEMPLATE = 'toTemplate', | ||
23 | + CC_TEMPLATE = 'ccTemplate', | ||
24 | + BCC_TEMPLATE = 'bccTemplate', | ||
25 | + SUBJECT_TEMPLATE = 'subjectTemplate', | ||
26 | + MAIL_BODY_TYPE = 'mailBodyType', | ||
27 | + IS_HTML_TEMPLATE = 'isHtmlTemplate', | ||
28 | + BODY_TEMPLATE = 'bodyTemplate', | ||
29 | +} | ||
30 | + | ||
31 | +export enum ToEmailFieldsNameEnum { | ||
32 | + FROM_TEMPLATE = 'From Template', | ||
33 | + TO_TEMPLATE = 'To Template', | ||
34 | + CC_TEMPLATE = 'Cc Template', | ||
35 | + BCC_TEMPLATE = 'Bcc Template', | ||
36 | + SUBJECT_TEMPLATE = 'Subject Template', | ||
37 | + MAIL_BODY_TYPE = 'Mail body type', | ||
38 | + IS_HTML_TEMPLATE = 'Dynamic mail body type', | ||
39 | + BODY_TEMPLATE = 'Body Template', | ||
40 | +} |
src/views/rule/designer/enum/index.ts
0 → 100644
1 | +export enum HandleTypeEnum { | ||
2 | + SOURCE = 'source', | ||
3 | + TARGET = 'target', | ||
4 | +} | ||
5 | + | ||
6 | +export enum NodeTypeEnum { | ||
7 | + CUSTOM = 'custom', | ||
8 | +} | ||
9 | + | ||
10 | +export enum EdgeTypeEnum { | ||
11 | + CUSTOM = 'custom', | ||
12 | +} | ||
13 | + | ||
14 | +export enum BasicConnectionModalEnum { | ||
15 | + BASIC = 'BASIC', | ||
16 | + CUSTOM = 'CUSTOM', | ||
17 | +} | ||
18 | + | ||
19 | +export enum MarkerArrowEnum { | ||
20 | + BASIC_ARROW = 'basicArrow', | ||
21 | + BASIC_ARROW_SELECTED = 'basicArrowSelected', | ||
22 | +} | ||
23 | + | ||
24 | +export enum ElementsTypeEnum { | ||
25 | + NODE = 'NODE', | ||
26 | + EDGE = 'EDGE', | ||
27 | +} |
src/views/rule/designer/enum/node.ts
0 → 100644
1 | +import { CommonFields, CommonFieldsName } from './formField/common'; | ||
2 | + | ||
3 | +export enum FetchNodeComFlagTypeENum { | ||
4 | + CONNECTION_MODAL = 'CONNECTION_MODAL', | ||
5 | + CREATE_MODAL = 'CREATE_MODAL', | ||
6 | +} | ||
7 | + | ||
8 | +export enum EdgeBindDataFieldEnum { | ||
9 | + TYPE = 'type', | ||
10 | +} | ||
11 | + | ||
12 | +export enum EdgeBindDataFieldNameEnum { | ||
13 | + TYPE = '链接标签', | ||
14 | +} | ||
15 | + | ||
16 | +export const NodeBindDataFieldEnum = { | ||
17 | + ...CommonFields, | ||
18 | +}; | ||
19 | + | ||
20 | +export const NodeBindDataFieldNameEnum = { | ||
21 | + ...CommonFieldsName, | ||
22 | +}; |
src/views/rule/designer/hook/useAddEdges.ts
0 → 100644
1 | +import type { Connection } from '@vue-flow/core'; | ||
2 | +import { EdgeTypeEnum } from '../enum'; | ||
3 | +import type { EdgeData } from '../types/node'; | ||
4 | +import { buildUUID } from '/@/utils/uuid'; | ||
5 | + | ||
6 | +export function useAddEdges() { | ||
7 | + const getAddedgesParams = (params: Connection, data: string | string[] | any) => { | ||
8 | + return { type: EdgeTypeEnum.CUSTOM, data: { data } as EdgeData, id: buildUUID(), ...params }; | ||
9 | + }; | ||
10 | + | ||
11 | + return { getAddedgesParams }; | ||
12 | +} |
src/views/rule/designer/hook/useAddNodes.ts
0 → 100644
1 | +import { Node } from '@vue-flow/core'; | ||
2 | +import { NodeTypeEnum } from '../enum'; | ||
3 | +import { buildUUID } from '/@/utils/uuid'; | ||
4 | + | ||
5 | +export const useAddNodes = () => { | ||
6 | + const getAddNodesParams = ( | ||
7 | + position: Node['position'], | ||
8 | + data: object, | ||
9 | + options?: Partial<Node> | ||
10 | + ): Node => { | ||
11 | + return { | ||
12 | + id: buildUUID(), | ||
13 | + type: NodeTypeEnum.CUSTOM, | ||
14 | + position, | ||
15 | + data, | ||
16 | + ...options, | ||
17 | + }; | ||
18 | + }; | ||
19 | + | ||
20 | + return { getAddNodesParams }; | ||
21 | +}; |
1 | +import { Component, computed, ref, shallowRef, toRaw, unref } from 'vue'; | ||
2 | +import { fetchConnectionComponent, fetchCreateComponent } from '../packages'; | ||
3 | +import { CreateModalDefineExposeType, AwaitPopupWindowReturnDataType } from '../types'; | ||
4 | +import { EdgeData, NodeData } from '../types/node'; | ||
5 | +import { DataActionModeEnum } from '/@/enums/toolEnum'; | ||
6 | +import { ElementsTypeEnum } from '../enum'; | ||
7 | + | ||
8 | +interface OptionsType { | ||
9 | + mode: DataActionModeEnum; | ||
10 | + type: ElementsTypeEnum; | ||
11 | +} | ||
12 | + | ||
13 | +export interface ElementInfo { | ||
14 | + id: string; | ||
15 | + type: ElementsTypeEnum; | ||
16 | +} | ||
17 | + | ||
18 | +export function useAwaitPopupWindowBindData( | ||
19 | + options: OptionsType = { mode: DataActionModeEnum.CREATE, type: ElementsTypeEnum.NODE } | ||
20 | +) { | ||
21 | + const { type, mode } = options; | ||
22 | + | ||
23 | + const visible = ref(false); | ||
24 | + | ||
25 | + const nodeData = ref<NodeData>(); | ||
26 | + | ||
27 | + const edgeData = ref<EdgeData>(); | ||
28 | + | ||
29 | + const spinning = ref(false); | ||
30 | + | ||
31 | + const resolveFn = ref<(options: AwaitPopupWindowReturnDataType) => void>(); | ||
32 | + | ||
33 | + const createComponentEl = ref<Nullable<CreateModalDefineExposeType>>(); | ||
34 | + | ||
35 | + const shadowComponent = shallowRef<Nullable<Component>>(); | ||
36 | + | ||
37 | + const elementInfo = ref<ElementInfo>(); | ||
38 | + | ||
39 | + const getNodeSetValue = computed(() => { | ||
40 | + return unref(mode) === DataActionModeEnum.CREATE | ||
41 | + ? unref(nodeData)?.config?.configurationDescriptor.nodeDefinition.defaultConfiguration | ||
42 | + : unref(nodeData)?.data?.configuration; | ||
43 | + }); | ||
44 | + | ||
45 | + const getEdgeSetValue = computed(() => { | ||
46 | + return { | ||
47 | + type: | ||
48 | + unref(mode) === DataActionModeEnum.CREATE | ||
49 | + ? unref(nodeData)?.config?.configurationDescriptor?.nodeDefinition.relationTypes | ||
50 | + : unref(edgeData)?.data, | ||
51 | + }; | ||
52 | + }); | ||
53 | + | ||
54 | + const getSetValue = computed(() => | ||
55 | + unref(type) === ElementsTypeEnum.EDGE ? unref(getEdgeSetValue) : unref(getNodeSetValue) | ||
56 | + ); | ||
57 | + | ||
58 | + const getComponentKey = computed(() => unref(nodeData)?.config?.key); | ||
59 | + | ||
60 | + const handleFetchComponent = async (nodeOptions: NodeData, edgeOptions?: EdgeData) => { | ||
61 | + nodeData.value = nodeOptions; | ||
62 | + edgeData.value = edgeOptions; | ||
63 | + | ||
64 | + spinning.value = true; | ||
65 | + shadowComponent.value = null; | ||
66 | + const modules = | ||
67 | + ElementsTypeEnum.NODE === type | ||
68 | + ? await fetchCreateComponent(nodeOptions.config!) | ||
69 | + : await fetchConnectionComponent(nodeOptions.config!); | ||
70 | + | ||
71 | + const component = (await modules?.()) as Record<'default', Component>; | ||
72 | + shadowComponent.value = component?.default; | ||
73 | + spinning.value = false; | ||
74 | + }; | ||
75 | + | ||
76 | + const open = async ( | ||
77 | + nodeData: NodeData, | ||
78 | + edgeData?: EdgeData, | ||
79 | + _elementInfo?: ElementInfo | ||
80 | + ): Promise<AwaitPopupWindowReturnDataType> => { | ||
81 | + elementInfo.value = _elementInfo; | ||
82 | + await handleFetchComponent(nodeData, edgeData); | ||
83 | + return new Promise((_resolve) => { | ||
84 | + visible.value = true; | ||
85 | + resolveFn.value = _resolve; | ||
86 | + }); | ||
87 | + }; | ||
88 | + | ||
89 | + const handleOnMounted = () => { | ||
90 | + unref(createComponentEl)?.setFieldsValue?.(toRaw(unref(getSetValue)), toRaw(unref(nodeData))); | ||
91 | + }; | ||
92 | + | ||
93 | + const validate = async () => { | ||
94 | + return (await unref(createComponentEl)?.validate?.()) || { flag: true }; | ||
95 | + }; | ||
96 | + | ||
97 | + const handleSubmitData = (extraData: Recordable = {}, value: Recordable = {}) => { | ||
98 | + return Object.assign( | ||
99 | + {}, | ||
100 | + extraData, | ||
101 | + unref(type) === ElementsTypeEnum.NODE ? { configuration: toRaw(unref(value)) } : value | ||
102 | + ); | ||
103 | + }; | ||
104 | + | ||
105 | + const handleSubmit = async (extraData: Recordable = {}) => { | ||
106 | + const { flag } = await validate(); | ||
107 | + if (!flag) return; | ||
108 | + const value = await unref(createComponentEl)?.getFieldsValue?.(); | ||
109 | + unref(resolveFn)?.({ | ||
110 | + flag: true, | ||
111 | + data: handleSubmitData(extraData, value), | ||
112 | + } as AwaitPopupWindowReturnDataType); | ||
113 | + visible.value = false; | ||
114 | + }; | ||
115 | + | ||
116 | + const handleCancel = () => { | ||
117 | + unref(resolveFn)?.({ flag: false, data: null } as AwaitPopupWindowReturnDataType); | ||
118 | + visible.value = false; | ||
119 | + }; | ||
120 | + | ||
121 | + return { | ||
122 | + visible, | ||
123 | + nodeData, | ||
124 | + spinning, | ||
125 | + elementInfo, | ||
126 | + shadowComponent, | ||
127 | + createComponentEl, | ||
128 | + getComponentKey, | ||
129 | + open, | ||
130 | + handleOnMounted, | ||
131 | + handleSubmit, | ||
132 | + handleCancel, | ||
133 | + }; | ||
134 | +} |
1 | +import { Ref, toRaw, unref } from 'vue'; | ||
2 | +import { BasicNodeBindData, NodeData } from '../types/node'; | ||
3 | +import { Elements, GraphNode } from '@vue-flow/core'; | ||
4 | +import { RuleChainType } from '../types/ruleNode'; | ||
5 | +import { allComponents } from '../packages'; | ||
6 | +import { RuleNodeTypeEnum } from '../packages/index.type'; | ||
7 | +import { buildUUID } from '/@/utils/uuid'; | ||
8 | +import { isNullOrUnDef } from '/@/utils/is'; | ||
9 | +import { useAddNodes } from './useAddNodes'; | ||
10 | +import { useAddEdges } from './useAddEdges'; | ||
11 | + | ||
12 | +export function useBasicDataTransform() { | ||
13 | + const nodeConfigMap = new Map<string, NodeData>(); | ||
14 | + | ||
15 | + function initNodeConfigMap() { | ||
16 | + for (const key of Object.keys(allComponents)) { | ||
17 | + const category = allComponents[key as RuleNodeTypeEnum]; | ||
18 | + for (const nodeConfig of category.components) { | ||
19 | + const { clazz } = nodeConfig; | ||
20 | + nodeConfigMap.set(clazz, { config: nodeConfig, category: category.category }); | ||
21 | + } | ||
22 | + } | ||
23 | + } | ||
24 | + | ||
25 | + function mergeData(data: NodeData['data'], nodeData: NodeData, node: GraphNode) { | ||
26 | + const { x: layoutX, y: layoutY } = node.computedPosition; | ||
27 | + | ||
28 | + return { | ||
29 | + debugMode: !!data?.debugMode, | ||
30 | + name: data?.name, | ||
31 | + type: nodeData.config?.clazz, | ||
32 | + configuration: toRaw(unref(data?.configuration)), | ||
33 | + additionalInfo: { | ||
34 | + description: data?.description, | ||
35 | + layoutX, | ||
36 | + layoutY, | ||
37 | + }, | ||
38 | + }; | ||
39 | + } | ||
40 | + | ||
41 | + function deconstructionConnection( | ||
42 | + ruleChain: Ref<RuleChainType> | RuleChainType, | ||
43 | + inputNodeId: string | ||
44 | + ) { | ||
45 | + const { connections, nodes, firstNodeIndex } = unref(ruleChain); | ||
46 | + const indexMap = new Map<number, BasicNodeBindData>(); | ||
47 | + const groupByConnections = new Map<string, string[]>(); | ||
48 | + const SOURCE_HANDLE = '__handle-right'; | ||
49 | + const TARGET_HANDLE = '__handle-left'; | ||
50 | + const SEPARATOR = ','; | ||
51 | + const edges: Elements = []; | ||
52 | + const { getAddedgesParams } = useAddEdges(); | ||
53 | + | ||
54 | + nodes.forEach((item, index) => indexMap.set(index, item)); | ||
55 | + | ||
56 | + (connections || []).forEach((item) => { | ||
57 | + const { fromIndex, toIndex, type } = item; | ||
58 | + const key = `${fromIndex}${SEPARATOR}${toIndex}`; | ||
59 | + if (!groupByConnections.has(key)) groupByConnections.set(key, []); | ||
60 | + | ||
61 | + const types = groupByConnections.get(key)!; | ||
62 | + types.push(type); | ||
63 | + }); | ||
64 | + | ||
65 | + for (const [key, types] of Array.from(groupByConnections.entries())) { | ||
66 | + const [fromIndex, toIndex] = key.split(SEPARATOR); | ||
67 | + | ||
68 | + const sourceNode = indexMap.get(Number(fromIndex)); | ||
69 | + const targetNode = indexMap.get(Number(toIndex)); | ||
70 | + const source = sourceNode!.id!.id; | ||
71 | + const target = targetNode!.id!.id; | ||
72 | + const sourceHandle = `${source}${SOURCE_HANDLE}`; | ||
73 | + const targetHandle = `${target}${TARGET_HANDLE}`; | ||
74 | + | ||
75 | + edges.push( | ||
76 | + getAddedgesParams( | ||
77 | + { | ||
78 | + source, | ||
79 | + target, | ||
80 | + sourceHandle, | ||
81 | + targetHandle, | ||
82 | + }, | ||
83 | + { type: types } | ||
84 | + ) | ||
85 | + ); | ||
86 | + } | ||
87 | + | ||
88 | + if (!isNullOrUnDef(firstNodeIndex)) { | ||
89 | + const targetNode = indexMap.get(firstNodeIndex); | ||
90 | + const source = inputNodeId; | ||
91 | + const target = targetNode!.id!.id; | ||
92 | + const sourceHandle = `${source}$${SOURCE_HANDLE}`; | ||
93 | + const targetHandle = `${target}${TARGET_HANDLE}`; | ||
94 | + edges.push( | ||
95 | + getAddedgesParams( | ||
96 | + { | ||
97 | + source, | ||
98 | + target, | ||
99 | + sourceHandle, | ||
100 | + targetHandle, | ||
101 | + }, | ||
102 | + {} | ||
103 | + ) | ||
104 | + ); | ||
105 | + } | ||
106 | + | ||
107 | + return edges; | ||
108 | + } | ||
109 | + | ||
110 | + function genNewNodeByData(node: BasicNodeBindData, config: NodeData) { | ||
111 | + const { additionalInfo, configuration, debugMode, name, id } = node; | ||
112 | + const { layoutX, layoutY, description } = additionalInfo || {}; | ||
113 | + const { getAddNodesParams } = useAddNodes(); | ||
114 | + | ||
115 | + return getAddNodesParams( | ||
116 | + { x: layoutX!, y: layoutY! }, | ||
117 | + { | ||
118 | + ...config, | ||
119 | + data: { | ||
120 | + configuration, | ||
121 | + debugMode, | ||
122 | + description, | ||
123 | + name, | ||
124 | + }, | ||
125 | + }, | ||
126 | + { | ||
127 | + id: id?.id || buildUUID(), | ||
128 | + } | ||
129 | + ); | ||
130 | + } | ||
131 | + | ||
132 | + function deconstructionNode(nodes: RuleChainType['nodes']) { | ||
133 | + const addNodes: Elements = []; | ||
134 | + for (const node of unref(nodes)) { | ||
135 | + const { type } = node; | ||
136 | + if (!type) continue; | ||
137 | + const nodeConfig = nodeConfigMap.get(type); | ||
138 | + | ||
139 | + if (!nodeConfig) { | ||
140 | + throw `No component configuration of type '${type}' was found`; | ||
141 | + } | ||
142 | + | ||
143 | + const newNode = genNewNodeByData(node, nodeConfig); | ||
144 | + | ||
145 | + addNodes.push(newNode); | ||
146 | + } | ||
147 | + return addNodes; | ||
148 | + } | ||
149 | + | ||
150 | + function deconstructionData( | ||
151 | + ruleChain: RuleChainType | Ref<RuleChainType | undefined>, | ||
152 | + inputNodeId: string | ||
153 | + ) { | ||
154 | + if (!ruleChain || !unref(ruleChain)) return; | ||
155 | + ruleChain = toRaw(unref(ruleChain))!; | ||
156 | + | ||
157 | + const nodes = deconstructionNode(ruleChain?.nodes || []); | ||
158 | + | ||
159 | + const edges = deconstructionConnection(ruleChain!, inputNodeId); | ||
160 | + | ||
161 | + return { | ||
162 | + nodes, | ||
163 | + edges, | ||
164 | + }; | ||
165 | + } | ||
166 | + | ||
167 | + initNodeConfigMap(); | ||
168 | + | ||
169 | + return { | ||
170 | + mergeData, | ||
171 | + deconstructionData, | ||
172 | + }; | ||
173 | +} |
1 | +import { EdgeProps, useEdge } from '@vue-flow/core'; | ||
2 | +import { computed, unref } from 'vue'; | ||
3 | +import { MarkerArrowEnum } from '../enum'; | ||
4 | + | ||
5 | +export const useConnectionFocus = (props: EdgeProps) => { | ||
6 | + const { edge } = useEdge(props.id); | ||
7 | + | ||
8 | + const getSelected = computed(() => unref(edge)?.selected); | ||
9 | + | ||
10 | + const getMarkerEnd = computed( | ||
11 | + () => | ||
12 | + `url(#${ | ||
13 | + unref(getSelected) ? MarkerArrowEnum.BASIC_ARROW_SELECTED : MarkerArrowEnum.BASIC_ARROW | ||
14 | + })` | ||
15 | + ); | ||
16 | + | ||
17 | + return { | ||
18 | + getMarkerEnd, | ||
19 | + getSelected, | ||
20 | + }; | ||
21 | +}; |
src/views/rule/designer/hook/useDataTool.ts
0 → 100644
1 | +import { Ref, toRaw, unref } from 'vue'; | ||
2 | +import { NodeData } from '../types/node'; | ||
3 | + | ||
4 | +export function useDataTool() { | ||
5 | + /** | ||
6 | + * @description 通过NodeData获取默认配置信息 | ||
7 | + * @param nodeData | ||
8 | + * @returns | ||
9 | + */ | ||
10 | + function getDefaultConfigurationByNodeData<T = any>(nodeData: Ref<NodeData> | NodeData) { | ||
11 | + nodeData = toRaw(unref(nodeData)); | ||
12 | + | ||
13 | + const { nodeDefinition } = nodeData.config?.configurationDescriptor || {}; | ||
14 | + const { defaultConfiguration } = nodeDefinition || {}; | ||
15 | + | ||
16 | + return { defaultConfiguration: defaultConfiguration as T }; | ||
17 | + } | ||
18 | + | ||
19 | + /** | ||
20 | + * @description 通过NodeData获取节点绑定信息 | ||
21 | + * @param nodeData | ||
22 | + * @returns | ||
23 | + */ | ||
24 | + function getBindDataByNodeData<T = any>(nodeData: Ref<NodeData> | NodeData) { | ||
25 | + nodeData = toRaw(unref(nodeData)); | ||
26 | + | ||
27 | + const data = nodeData.data as T; | ||
28 | + | ||
29 | + return { data }; | ||
30 | + } | ||
31 | + | ||
32 | + return { getDefaultConfigurationByNodeData, getBindDataByNodeData }; | ||
33 | +} |
1 | +import { Ref, toRaw, unref } from 'vue'; | ||
2 | +import type { VueFlowStore } from '@vue-flow/core'; | ||
3 | +import type { FlowElRef } from '../types/flow'; | ||
4 | +import type { CreateNodeModal } from '../src/components/CreateNodeModal'; | ||
5 | +import type { DragTransferData } from '../types/node'; | ||
6 | +import { useAddNodes } from './useAddNodes'; | ||
7 | + | ||
8 | +type EffectSymbol = DataTransfer['dropEffect']; | ||
9 | + | ||
10 | +export const TRANSFER_DATA_KEY = 'NODE_INFO'; | ||
11 | +export const EFFECT_SYMBOL: EffectSymbol = 'move'; | ||
12 | + | ||
13 | +interface UseDragCreateOptionsType { | ||
14 | + el: Ref<Nullable<FlowElRef>>; | ||
15 | + createNodeModalActionType: Ref<Nullable<InstanceType<typeof CreateNodeModal>>>; | ||
16 | + flowActionType: VueFlowStore; | ||
17 | + triggerChange: () => void; | ||
18 | +} | ||
19 | + | ||
20 | +export function useDragCreate(options: UseDragCreateOptionsType) { | ||
21 | + const { el, createNodeModalActionType, flowActionType, triggerChange } = options; | ||
22 | + const { project, addNodes } = flowActionType; | ||
23 | + const { getAddNodesParams } = useAddNodes(); | ||
24 | + | ||
25 | + const handleOnDrop = async (event: DragEvent) => { | ||
26 | + const value = event.dataTransfer?.getData(TRANSFER_DATA_KEY); | ||
27 | + const transferData: DragTransferData = JSON.parse(value || ''); | ||
28 | + const { options: nodeData, offsetX, offsetY } = transferData; | ||
29 | + const { flag, data } = (await unref(createNodeModalActionType)?.open(nodeData)) || {}; | ||
30 | + if (!flag) return; | ||
31 | + | ||
32 | + const flowBounds = unref(el)?.$el.getBoundingClientRect() as DOMRect; | ||
33 | + | ||
34 | + const position = project({ | ||
35 | + x: event.clientX - flowBounds.left - offsetX, | ||
36 | + y: event.clientY - flowBounds.top - offsetY, | ||
37 | + }); | ||
38 | + | ||
39 | + const newNode = getAddNodesParams(position, { ...toRaw(unref(nodeData)), data }); | ||
40 | + addNodes(newNode); | ||
41 | + | ||
42 | + triggerChange(); | ||
43 | + }; | ||
44 | + | ||
45 | + const handleOnDragOver = (event: DragEvent) => { | ||
46 | + event.preventDefault(); | ||
47 | + | ||
48 | + if (event.dataTransfer) event.dataTransfer.dropEffect = EFFECT_SYMBOL; | ||
49 | + }; | ||
50 | + | ||
51 | + const handleOnDragStart = (event: DragEvent, options: object) => { | ||
52 | + if (event.dataTransfer) { | ||
53 | + event.dataTransfer.setData(TRANSFER_DATA_KEY, JSON.stringify(options)); | ||
54 | + event.dataTransfer.effectAllowed = EFFECT_SYMBOL; | ||
55 | + } | ||
56 | + }; | ||
57 | + | ||
58 | + return { | ||
59 | + handleOnDrop, | ||
60 | + handleOnDragOver, | ||
61 | + handleOnDragStart, | ||
62 | + }; | ||
63 | +} |
1 | +import type { Ref } from 'vue'; | ||
2 | +import { inject, provide } from 'vue'; | ||
3 | +import type { VueFlowStore } from '@vue-flow/core'; | ||
4 | +import type { CreateNodeModal } from '../src/components/CreateNodeModal'; | ||
5 | +import type { CreateEdgeModal } from '../src/components/CreateEdgeModal'; | ||
6 | +import { UpdateNodeDrawer } from '../src/components/UpdateNodeDrawer'; | ||
7 | +import { UpdateEdgeDrawer } from '../src/components/UpdateEdgeDrawer'; | ||
8 | + | ||
9 | +const SYMBOL = Symbol('flow-context'); | ||
10 | + | ||
11 | +interface FlowContextOptionsType { | ||
12 | + /** | ||
13 | + * @description 节点 actions | ||
14 | + */ | ||
15 | + createNodeModalActionType: Ref<Nullable<InstanceType<typeof CreateNodeModal>>>; | ||
16 | + | ||
17 | + /** | ||
18 | + * @description 连接线 actions | ||
19 | + */ | ||
20 | + createEdgeModalActionType: Ref<Nullable<InstanceType<typeof CreateEdgeModal>>>; | ||
21 | + | ||
22 | + /** | ||
23 | + * @description 节点更新 actions | ||
24 | + */ | ||
25 | + updateNodeDrawerActionType: Ref<Nullable<InstanceType<typeof UpdateNodeDrawer>>>; | ||
26 | + | ||
27 | + /** | ||
28 | + * @description 连接线更新 actions | ||
29 | + */ | ||
30 | + updateEdgeDrawerActionType: Ref<Nullable<InstanceType<typeof UpdateEdgeDrawer>>>; | ||
31 | + | ||
32 | + /** | ||
33 | + * @description vue flow store | ||
34 | + */ | ||
35 | + flowActionType: VueFlowStore; | ||
36 | + | ||
37 | + /** | ||
38 | + * @description 更新变化 | ||
39 | + */ | ||
40 | + triggerChange: () => void; | ||
41 | +} | ||
42 | + | ||
43 | +export const createFlowContext = (options: FlowContextOptionsType) => { | ||
44 | + provide(SYMBOL, options); | ||
45 | +}; | ||
46 | + | ||
47 | +export const useFlowContext = () => { | ||
48 | + return inject(SYMBOL) as FlowContextOptionsType; | ||
49 | +}; |
1 | +import { useFullscreen } from '@vueuse/core'; | ||
2 | +import type { Ref } from 'vue'; | ||
3 | +import { computed, unref } from 'vue'; | ||
4 | + | ||
5 | +export function useFullScreen(el: Ref<Nullable<HTMLDivElement>>) { | ||
6 | + const { toggle, isFullscreen } = useFullscreen(el); | ||
7 | + | ||
8 | + const getFullScreenIcon = computed(() => | ||
9 | + unref(isFullscreen) ? 'bx:exit-fullscreen' : 'mdi:fullscreen' | ||
10 | + ); | ||
11 | + | ||
12 | + return { | ||
13 | + getFullScreenIcon, | ||
14 | + handleFullScreen: toggle, | ||
15 | + }; | ||
16 | +} |
src/views/rule/designer/hook/useInputNode.ts
0 → 100644
1 | +import { Config as InputConfig } from '../packages/Entry/Input/config'; | ||
2 | +import { useAddNodes } from './useAddNodes'; | ||
3 | + | ||
4 | +export function useInputNode() { | ||
5 | + const getInputNodeConfig = (id?: string) => { | ||
6 | + const { getAddNodesParams } = useAddNodes(); | ||
7 | + | ||
8 | + const newNode = getAddNodesParams( | ||
9 | + { x: 80, y: 50 }, | ||
10 | + { | ||
11 | + ...new InputConfig(), | ||
12 | + data: { | ||
13 | + name: '输入', | ||
14 | + description: '规则链的逻辑输入,将传入消息转发到下一个相关规则节点。', | ||
15 | + }, | ||
16 | + }, | ||
17 | + { id, draggable: false, selectable: false } | ||
18 | + ); | ||
19 | + | ||
20 | + return newNode; | ||
21 | + }; | ||
22 | + | ||
23 | + return { getInputNodeConfig }; | ||
24 | +} |
src/views/rule/designer/hook/useRuleFlow.ts
0 → 100644
1 | +import type { | ||
2 | + Connection, | ||
3 | + EdgeComponent, | ||
4 | + NodeComponent, | ||
5 | + ValidConnectionFunc, | ||
6 | + GraphNode, | ||
7 | +} from '@vue-flow/core'; | ||
8 | +import { ConnectionLineType, SelectionMode, useVueFlow } from '@vue-flow/core'; | ||
9 | +import type { Ref } from 'vue'; | ||
10 | +import { markRaw, toRaw, unref } from 'vue'; | ||
11 | +import { isFunction } from 'lodash-es'; | ||
12 | +import type { CreateNodeModal } from '../src/components/CreateNodeModal'; | ||
13 | +import { EdgeTypeEnum, ElementsTypeEnum, NodeTypeEnum } from '../enum'; | ||
14 | +import { BasicEdge, BasicNode } from '../src/components'; | ||
15 | +import type { EdgeData, NodeData } from '../types/node'; | ||
16 | +import type { CreateEdgeModal } from '../src/components/CreateEdgeModal'; | ||
17 | +import { isInputHandle, isOutputHandle } from '../utils'; | ||
18 | +import { useAddEdges } from './useAddEdges'; | ||
19 | +import { UpdateNodeDrawer } from '../src/components/UpdateNodeDrawer'; | ||
20 | +import { UpdateEdgeDrawer } from '../src/components/UpdateEdgeDrawer'; | ||
21 | +import { isNumber } from '/@/utils/is'; | ||
22 | + | ||
23 | +interface UseRuleFlowOptionsType { | ||
24 | + id: string; | ||
25 | + createNodeModalActionType: Ref<Nullable<InstanceType<typeof CreateNodeModal>>>; | ||
26 | + createEdgeModalActionType: Ref<Nullable<InstanceType<typeof CreateEdgeModal>>>; | ||
27 | + updateNodeDrawerActionType: Ref<Nullable<InstanceType<typeof UpdateNodeDrawer>>>; | ||
28 | + updateEdgeDrawerActionType: Ref<Nullable<InstanceType<typeof UpdateEdgeDrawer>>>; | ||
29 | + triggerChange: () => void; | ||
30 | +} | ||
31 | + | ||
32 | +const validateInputAndOutput: ValidConnectionFunc = (connection: Connection) => { | ||
33 | + const { sourceHandle, targetHandle, source, target } = connection; | ||
34 | + | ||
35 | + return ( | ||
36 | + isOutputHandle(sourceHandle || '') && isInputHandle(targetHandle || '') && source !== target | ||
37 | + ); | ||
38 | +}; | ||
39 | + | ||
40 | +export function useRuleFlow(options: UseRuleFlowOptionsType) { | ||
41 | + const { | ||
42 | + id, | ||
43 | + createEdgeModalActionType, | ||
44 | + updateEdgeDrawerActionType, | ||
45 | + updateNodeDrawerActionType, | ||
46 | + triggerChange, | ||
47 | + } = options; | ||
48 | + | ||
49 | + const flowActionType = useVueFlow({ | ||
50 | + id, | ||
51 | + maxZoom: 1, | ||
52 | + minZoom: 1, | ||
53 | + panOnScroll: true, | ||
54 | + selectionMode: SelectionMode.Partial, | ||
55 | + nodeTypes: { | ||
56 | + [NodeTypeEnum.CUSTOM]: markRaw(BasicNode) as NodeComponent, | ||
57 | + }, | ||
58 | + edgeTypes: { | ||
59 | + [EdgeTypeEnum.CUSTOM]: markRaw(BasicEdge) as EdgeComponent, | ||
60 | + }, | ||
61 | + connectionLineOptions: { | ||
62 | + type: ConnectionLineType.Bezier, | ||
63 | + }, | ||
64 | + defaultViewport: { | ||
65 | + x: 0, | ||
66 | + y: 0, | ||
67 | + }, | ||
68 | + isValidConnection(connection, elements) { | ||
69 | + const validateList = [validateInputAndOutput]; | ||
70 | + const targetData = elements.targetNode.data as NodeData; | ||
71 | + | ||
72 | + if ( | ||
73 | + targetData.category?.validateConnection && | ||
74 | + isFunction(targetData.category.validateConnection) | ||
75 | + ) | ||
76 | + validateList.push(targetData.category?.validateConnection); | ||
77 | + | ||
78 | + if (targetData.config?.validateConnection && isFunction(targetData.config.validateConnection)) | ||
79 | + validateList.push(targetData.config.validateConnection); | ||
80 | + | ||
81 | + if (!validateList.every((item) => item(connection, elements))) return false; | ||
82 | + | ||
83 | + return true; | ||
84 | + }, | ||
85 | + }); | ||
86 | + | ||
87 | + const { | ||
88 | + getEdges, | ||
89 | + addEdges, | ||
90 | + findEdge, | ||
91 | + findNode, | ||
92 | + setViewport, | ||
93 | + removeEdges, | ||
94 | + onConnect, | ||
95 | + onPaneReady, | ||
96 | + onNodeDoubleClick, | ||
97 | + onEdgeDoubleClick, | ||
98 | + onNodeDragStop, | ||
99 | + } = flowActionType; | ||
100 | + | ||
101 | + const { getAddedgesParams } = useAddEdges(); | ||
102 | + | ||
103 | + onConnect(async (params) => { | ||
104 | + const { source } = params; | ||
105 | + const sourceNode = findNode(source); | ||
106 | + const sourceData = sourceNode?.data as NodeData; | ||
107 | + | ||
108 | + let types: string[] = []; | ||
109 | + | ||
110 | + if (sourceData && validateHasLabelConnection(sourceData)) { | ||
111 | + const { flag, data } = (await unref(createEdgeModalActionType)?.open(sourceData)) || {}; | ||
112 | + if (!flag) return; | ||
113 | + types = toRaw(unref(data)); | ||
114 | + } | ||
115 | + | ||
116 | + handleMaxConnectionPoint(sourceNode); | ||
117 | + | ||
118 | + addEdges(getAddedgesParams(params, types)); | ||
119 | + | ||
120 | + triggerChange(); | ||
121 | + }); | ||
122 | + | ||
123 | + onPaneReady(async () => { | ||
124 | + setViewport({ x: 0, y: 0, zoom: 1 }); | ||
125 | + }); | ||
126 | + | ||
127 | + onNodeDoubleClick(async ({ node }) => { | ||
128 | + if ((node.data as NodeData).config?.disableAction) return; | ||
129 | + const { flag, data } = | ||
130 | + (await unref(updateNodeDrawerActionType)?.open( | ||
131 | + toRaw((node as NodeData)?.data as unknown as NodeData), | ||
132 | + void 0, | ||
133 | + { id: node.id, type: ElementsTypeEnum.NODE } | ||
134 | + )) || {}; | ||
135 | + | ||
136 | + if (!flag) return; | ||
137 | + | ||
138 | + const currentNode = findNode(node.id); | ||
139 | + (currentNode!.data as NodeData).data = data; | ||
140 | + }); | ||
141 | + | ||
142 | + onEdgeDoubleClick(async ({ edge }) => { | ||
143 | + if (!validateHasLabelConnection(edge.sourceNode.data)) return; | ||
144 | + | ||
145 | + if ((edge.sourceNode.data as NodeData).config?.disableAction) return; | ||
146 | + | ||
147 | + const { flag, data } = | ||
148 | + (await unref(updateEdgeDrawerActionType)?.open( | ||
149 | + toRaw(unref(edge.sourceNode?.data as unknown as NodeData)), | ||
150 | + toRaw(unref(edge.data as EdgeData)), | ||
151 | + { id: edge.id, type: ElementsTypeEnum.EDGE } | ||
152 | + )) || {}; | ||
153 | + | ||
154 | + if (!flag) return; | ||
155 | + | ||
156 | + const currentEdge = findEdge(edge.id); | ||
157 | + | ||
158 | + (currentEdge!.data as EdgeData).data = toRaw(unref(data)); | ||
159 | + }); | ||
160 | + | ||
161 | + onNodeDragStop(() => { | ||
162 | + triggerChange(); | ||
163 | + }); | ||
164 | + | ||
165 | + /** | ||
166 | + * @description 验证是否有连接label | ||
167 | + * @param sourceData | ||
168 | + * @returns | ||
169 | + */ | ||
170 | + function validateHasLabelConnection(sourceData: NodeData) { | ||
171 | + return !!sourceData?.config?.configurationDescriptor.nodeDefinition?.relationTypes?.length; | ||
172 | + } | ||
173 | + | ||
174 | + function handleMaxConnectionPoint(sourceNode?: GraphNode) { | ||
175 | + if (!sourceNode) return; | ||
176 | + | ||
177 | + const maxConnectionPoint = unref(sourceNode).data?.config?.maxConnectionPoint; | ||
178 | + | ||
179 | + if (!maxConnectionPoint || !isNumber(maxConnectionPoint)) return; | ||
180 | + | ||
181 | + const sourceId = sourceNode.id; | ||
182 | + const connectionPool = unref(getEdges).filter((item) => item.source === sourceId); | ||
183 | + if (connectionPool.length >= maxConnectionPoint && connectionPool[0]) { | ||
184 | + removeEdges(connectionPool[0].id); | ||
185 | + } | ||
186 | + } | ||
187 | + | ||
188 | + return { flowActionType }; | ||
189 | +} |
1 | +import type { VueFlowStore, Getters, Elements } from '@vue-flow/core'; | ||
2 | +import { ComputedRef, computed, ref, unref } from 'vue'; | ||
3 | +import { BasicNodeBindData, EdgeData, NodeData } from '../types/node'; | ||
4 | +import { EntryCategoryComponentEnum } from '../enum/category'; | ||
5 | +import { useBasicDataTransform } from './useBasicDataTransform'; | ||
6 | +import { getRuleChainData, saveRuleChainData } from '/@/api/ruleDesigner'; | ||
7 | +import { ConnectionItemType, RuleChainType } from '../types/ruleNode'; | ||
8 | +import { useInputNode } from './useInputNode'; | ||
9 | +import { buildUUID } from '/@/utils/uuid'; | ||
10 | +import { useRoute } from 'vue-router'; | ||
11 | + | ||
12 | +const ignoreNodeKeys: string[] = [EntryCategoryComponentEnum.INPUT]; | ||
13 | + | ||
14 | +export function useSaveAndRedo() { | ||
15 | + const changeMarker = ref(false); | ||
16 | + | ||
17 | + const loading = ref(false); | ||
18 | + | ||
19 | + const redoDataRef = ref<Elements>([]); | ||
20 | + | ||
21 | + const route = useRoute(); | ||
22 | + | ||
23 | + const getRuleChainId = computed(() => (route.params as Record<'id', string>).id); | ||
24 | + | ||
25 | + const { mergeData, deconstructionData } = useBasicDataTransform(); | ||
26 | + | ||
27 | + const triggerChange = () => { | ||
28 | + changeMarker.value = true; | ||
29 | + }; | ||
30 | + | ||
31 | + const resetChange = () => { | ||
32 | + changeMarker.value = false; | ||
33 | + }; | ||
34 | + | ||
35 | + /** | ||
36 | + * @description 保存连接信息 | ||
37 | + */ | ||
38 | + function getConnections( | ||
39 | + nodesRef: ComputedRef<Getters['getNodes']> | Getters['getNodes'], | ||
40 | + edges: ComputedRef<Getters['getEdges']> | ||
41 | + ) { | ||
42 | + const nodeIndexMap = new Map(); | ||
43 | + | ||
44 | + const connections: ConnectionItemType[] = []; | ||
45 | + | ||
46 | + unref(nodesRef).forEach((item, index) => { | ||
47 | + nodeIndexMap.set(item.id, index); | ||
48 | + }); | ||
49 | + | ||
50 | + for (const item of unref(edges)) { | ||
51 | + const { data, target, source } = item; | ||
52 | + const { data: bindData } = data as EdgeData; | ||
53 | + const { type } = bindData || {}; | ||
54 | + const fromIndex = nodeIndexMap.get(source); | ||
55 | + const toIndex = nodeIndexMap.get(target); | ||
56 | + type?.forEach((key) => { | ||
57 | + connections.push({ fromIndex, toIndex, type: key }); | ||
58 | + }); | ||
59 | + } | ||
60 | + | ||
61 | + return connections; | ||
62 | + } | ||
63 | + | ||
64 | + function getNodes(nodesRef: ComputedRef<Getters['getNodes']> | Getters['getNodes']) { | ||
65 | + const nodes: BasicNodeBindData[] = []; | ||
66 | + | ||
67 | + for (const node of unref(nodesRef)) { | ||
68 | + const nodeData = node.data as NodeData; | ||
69 | + | ||
70 | + if (ignoreNodeKeys.includes(nodeData.config?.key as string)) continue; | ||
71 | + | ||
72 | + const data = nodeData.data; | ||
73 | + | ||
74 | + nodes.push(mergeData(data, nodeData, node)); | ||
75 | + } | ||
76 | + | ||
77 | + return nodes; | ||
78 | + } | ||
79 | + | ||
80 | + function getFirsetNodeIndex( | ||
81 | + nodesRef: ComputedRef<Getters['getNodes']> | Getters['getNodes'], | ||
82 | + edges: ComputedRef<Getters['getEdges']> | ||
83 | + ) { | ||
84 | + const inputNode = unref(edges).find( | ||
85 | + (item) => (item.sourceNode.data as NodeData).config?.key === EntryCategoryComponentEnum.INPUT | ||
86 | + ); | ||
87 | + | ||
88 | + if (inputNode) { | ||
89 | + const targetId = inputNode.target; | ||
90 | + const index = unref(nodesRef).findIndex((item) => item.id === targetId); | ||
91 | + return index; | ||
92 | + } | ||
93 | + } | ||
94 | + | ||
95 | + const handleApplyChange = (flowActionType: VueFlowStore) => { | ||
96 | + if (!unref(changeMarker)) return; | ||
97 | + | ||
98 | + const edgesRef = flowActionType.getEdges; | ||
99 | + | ||
100 | + const extraIgnoreNodeRef = unref(flowActionType.getNodes).filter( | ||
101 | + (item) => !ignoreNodeKeys.includes((item.data as NodeData).config?.key as string) | ||
102 | + ); | ||
103 | + | ||
104 | + const connections = getConnections(extraIgnoreNodeRef, edgesRef); | ||
105 | + | ||
106 | + const nodes = getNodes(extraIgnoreNodeRef); | ||
107 | + | ||
108 | + const firstNodeIndex = getFirsetNodeIndex(extraIgnoreNodeRef, edgesRef); | ||
109 | + | ||
110 | + handleSaveRuleChain(connections, nodes, firstNodeIndex); | ||
111 | + }; | ||
112 | + | ||
113 | + const handleRedoChange = (flowActionType: VueFlowStore) => { | ||
114 | + if (!unref(changeMarker)) return; | ||
115 | + flowActionType.setElements(unref(redoDataRef)); | ||
116 | + resetChange(); | ||
117 | + }; | ||
118 | + | ||
119 | + async function handleSaveRuleChain( | ||
120 | + connections: ConnectionItemType[], | ||
121 | + nodes: BasicNodeBindData[], | ||
122 | + firstNodeIndex?: number | ||
123 | + ) { | ||
124 | + try { | ||
125 | + loading.value = true; | ||
126 | + const data = await saveRuleChainData({ | ||
127 | + connections, | ||
128 | + nodes, | ||
129 | + firstNodeIndex, | ||
130 | + ruleChainId: { | ||
131 | + entityType: 'RULE_CHAIN', | ||
132 | + id: unref(getRuleChainId), | ||
133 | + }, | ||
134 | + }); | ||
135 | + | ||
136 | + parseRuleChain(data); | ||
137 | + | ||
138 | + resetChange(); | ||
139 | + } finally { | ||
140 | + loading.value = false; | ||
141 | + } | ||
142 | + } | ||
143 | + | ||
144 | + async function getCurrentPageMetaData(flowActionType: VueFlowStore) { | ||
145 | + try { | ||
146 | + loading.value = true; | ||
147 | + | ||
148 | + const data = await getRuleChainData(unref(getRuleChainId)); | ||
149 | + | ||
150 | + const elements = parseRuleChain(data); | ||
151 | + | ||
152 | + flowActionType.setElements(elements); | ||
153 | + | ||
154 | + resetChange(); | ||
155 | + } finally { | ||
156 | + loading.value = false; | ||
157 | + } | ||
158 | + } | ||
159 | + | ||
160 | + function parseRuleChain(ruleChain: RuleChainType) { | ||
161 | + const inputId = buildUUID(); | ||
162 | + | ||
163 | + const { getInputNodeConfig } = useInputNode(); | ||
164 | + | ||
165 | + const value = deconstructionData(ruleChain, inputId); | ||
166 | + | ||
167 | + const { nodes = [], edges = [] } = value || {}; | ||
168 | + | ||
169 | + const inputNode = getInputNodeConfig(inputId); | ||
170 | + | ||
171 | + const elements = [inputNode, ...nodes, ...edges]; | ||
172 | + | ||
173 | + redoDataRef.value = elements; | ||
174 | + | ||
175 | + return elements; | ||
176 | + } | ||
177 | + | ||
178 | + return { | ||
179 | + loading, | ||
180 | + changeMarker, | ||
181 | + triggerChange, | ||
182 | + handleApplyChange, | ||
183 | + handleRedoChange, | ||
184 | + getCurrentPageMetaData, | ||
185 | + }; | ||
186 | +} |
src/views/rule/designer/hook/useTextWidth.ts
0 → 100644
1 | +export function useTextWidth(text: string, fontSize: number) { | ||
2 | + const LetterMap = { | ||
3 | + ' ': 0.3329986572265625, | ||
4 | + a: 0.5589996337890625, | ||
5 | + A: 0.6569992065429687, | ||
6 | + b: 0.58599853515625, | ||
7 | + B: 0.6769989013671875, | ||
8 | + c: 0.5469985961914062, | ||
9 | + C: 0.7279998779296875, | ||
10 | + d: 0.58599853515625, | ||
11 | + D: 0.705999755859375, | ||
12 | + e: 0.554998779296875, | ||
13 | + E: 0.63699951171875, | ||
14 | + f: 0.37299957275390627, | ||
15 | + F: 0.5769989013671875, | ||
16 | + g: 0.5909988403320312, | ||
17 | + G: 0.7479995727539063, | ||
18 | + h: 0.555999755859375, | ||
19 | + H: 0.7199996948242188, | ||
20 | + i: 0.255999755859375, | ||
21 | + I: 0.23699951171875, | ||
22 | + j: 0.26699981689453123, | ||
23 | + J: 0.5169998168945312, | ||
24 | + k: 0.5289993286132812, | ||
25 | + K: 0.6899993896484375, | ||
26 | + l: 0.23499908447265624, | ||
27 | + L: 0.5879989624023437, | ||
28 | + m: 0.854998779296875, | ||
29 | + M: 0.8819992065429687, | ||
30 | + n: 0.5589996337890625, | ||
31 | + N: 0.7189987182617188, | ||
32 | + o: 0.58599853515625, | ||
33 | + O: 0.7669998168945312, | ||
34 | + p: 0.58599853515625, | ||
35 | + P: 0.6419998168945312, | ||
36 | + q: 0.58599853515625, | ||
37 | + Q: 0.7669998168945312, | ||
38 | + r: 0.3649993896484375, | ||
39 | + R: 0.6759994506835938, | ||
40 | + s: 0.504998779296875, | ||
41 | + S: 0.6319992065429687, | ||
42 | + t: 0.354998779296875, | ||
43 | + T: 0.6189987182617187, | ||
44 | + u: 0.5599990844726562, | ||
45 | + U: 0.7139999389648437, | ||
46 | + v: 0.48199920654296874, | ||
47 | + V: 0.6389999389648438, | ||
48 | + w: 0.754998779296875, | ||
49 | + W: 0.929998779296875, | ||
50 | + x: 0.5089996337890625, | ||
51 | + X: 0.63699951171875, | ||
52 | + y: 0.4959991455078125, | ||
53 | + Y: 0.66199951171875, | ||
54 | + z: 0.48699951171875, | ||
55 | + Z: 0.6239990234375, | ||
56 | + 0: 0.6, | ||
57 | + 1: 0.40099945068359377, | ||
58 | + 2: 0.6, | ||
59 | + 3: 0.6, | ||
60 | + 4: 0.6, | ||
61 | + 5: 0.6, | ||
62 | + 6: 0.6, | ||
63 | + 7: 0.5469985961914062, | ||
64 | + 8: 0.6, | ||
65 | + 9: 0.6, | ||
66 | + '[': 0.3329986572265625, | ||
67 | + ']': 0.3329986572265625, | ||
68 | + ',': 0.26399993896484375, | ||
69 | + '.': 0.26399993896484375, | ||
70 | + ';': 0.26399993896484375, | ||
71 | + ':': 0.26399993896484375, | ||
72 | + '{': 0.3329986572265625, | ||
73 | + '}': 0.3329986572265625, | ||
74 | + '\\': 0.5, | ||
75 | + '|': 0.19499969482421875, | ||
76 | + '=': 0.604998779296875, | ||
77 | + '+': 0.604998779296875, | ||
78 | + '-': 0.604998779296875, | ||
79 | + _: 0.5, | ||
80 | + '`': 0.3329986572265625, | ||
81 | + ' ~': 0.8329986572265625, | ||
82 | + '!': 0.3329986572265625, | ||
83 | + '@': 0.8579986572265625, | ||
84 | + '#': 0.6, | ||
85 | + $: 0.6, | ||
86 | + '%': 0.9699996948242188, | ||
87 | + '^': 0.517999267578125, | ||
88 | + '&': 0.7259994506835937, | ||
89 | + '*': 0.505999755859375, | ||
90 | + '(': 0.3329986572265625, | ||
91 | + ')': 0.3329986572265625, | ||
92 | + '<': 0.604998779296875, | ||
93 | + '>': 0.604998779296875, | ||
94 | + '/': 0.5, | ||
95 | + '?': 0.53699951171875, | ||
96 | + '"': 0.33699951171875, | ||
97 | + }; | ||
98 | + | ||
99 | + // 计算非中文字符宽度 | ||
100 | + const getLetterWidth = (letter: string, fontSize: number) => fontSize * (LetterMap[letter] || 1); | ||
101 | + | ||
102 | + // 计算文本宽度 | ||
103 | + const getTextWidth = (text: string, fontSize: number) => { | ||
104 | + // 中文匹配正则 | ||
105 | + const pattern = new RegExp('[\u4E00-\u9FA5]+'); | ||
106 | + // 文本宽度 | ||
107 | + const textWidth = text.split('').reduce((pre, curLetter) => { | ||
108 | + // 单个字符宽度 | ||
109 | + const letterWidth = pattern.test(curLetter) ? fontSize : getLetterWidth(curLetter, fontSize); | ||
110 | + return pre + letterWidth; | ||
111 | + }, 0); | ||
112 | + return textWidth; | ||
113 | + }; | ||
114 | + | ||
115 | + return getTextWidth(text, fontSize); | ||
116 | +} |
src/views/rule/designer/index.ts
0 → 100644
1 | +export { default as RuleChainsDesigner } from './index.vue'; |
src/views/rule/designer/index.vue
0 → 100644
1 | +<script setup lang="ts"> | ||
2 | + import { Spin } from 'ant-design-vue'; | ||
3 | + import { Background, BackgroundVariant } from '@vue-flow/background'; | ||
4 | + import { Controls } from '@vue-flow/controls'; | ||
5 | + import { Panel, PanelPosition, VueFlow } from '@vue-flow/core'; | ||
6 | + import { computed, onMounted, Ref, ref, unref } from 'vue'; | ||
7 | + import './style'; | ||
8 | + import { | ||
9 | + BasicConnectionArrow, | ||
10 | + BasicConnectionLine, | ||
11 | + BasicEdge, | ||
12 | + MenuSidebar, | ||
13 | + } from './src/components'; | ||
14 | + import type { FlowElRef } from './types/flow'; | ||
15 | + import { useDragCreate } from './hook/useDragCreate'; | ||
16 | + import { createFlowContext } from './hook/useFlowContext'; | ||
17 | + import { CreateNodeModal } from './src/components/CreateNodeModal'; | ||
18 | + import { useRuleFlow } from './hook/useRuleFlow'; | ||
19 | + import { CreateEdgeModal } from './src/components/CreateEdgeModal'; | ||
20 | + import { useFullScreen } from './hook/useFullScreen'; | ||
21 | + import { useSaveAndRedo } from './hook/useSaveAndRedo'; | ||
22 | + import { Icon } from '/@/components/Icon'; | ||
23 | + import { UpdateNodeDrawer } from './src/components/UpdateNodeDrawer'; | ||
24 | + import { UpdateEdgeDrawer } from './src/components/UpdateEdgeDrawer'; | ||
25 | + | ||
26 | + const getId = Number(Math.random().toString().substring(2)).toString(16); | ||
27 | + | ||
28 | + const rootElRef = ref<Nullable<HTMLDivElement>>(null); | ||
29 | + | ||
30 | + const createNodeModalActionType = ref<Nullable<InstanceType<typeof CreateNodeModal>>>(null); | ||
31 | + | ||
32 | + const createEdgeModalActionType = ref<Nullable<InstanceType<typeof CreateEdgeModal>>>(null); | ||
33 | + | ||
34 | + const updateNodeDrawerActionType = ref<Nullable<InstanceType<typeof UpdateNodeDrawer>>>(null); | ||
35 | + | ||
36 | + const updateEdgeDrawerActionType = ref<Nullable<InstanceType<typeof UpdateEdgeDrawer>>>(null); | ||
37 | + | ||
38 | + const flowElRef = ref<Nullable<FlowElRef>>(null); | ||
39 | + | ||
40 | + const elements = ref([]); | ||
41 | + | ||
42 | + const { | ||
43 | + loading, | ||
44 | + changeMarker, | ||
45 | + getCurrentPageMetaData, | ||
46 | + triggerChange, | ||
47 | + handleApplyChange, | ||
48 | + handleRedoChange, | ||
49 | + } = useSaveAndRedo(); | ||
50 | + | ||
51 | + const { flowActionType } = useRuleFlow({ | ||
52 | + id: getId, | ||
53 | + createNodeModalActionType, | ||
54 | + createEdgeModalActionType, | ||
55 | + updateEdgeDrawerActionType, | ||
56 | + updateNodeDrawerActionType, | ||
57 | + triggerChange, | ||
58 | + }); | ||
59 | + | ||
60 | + const { handleOnDragOver, handleOnDrop } = useDragCreate({ | ||
61 | + el: flowElRef, | ||
62 | + createNodeModalActionType, | ||
63 | + flowActionType, | ||
64 | + triggerChange, | ||
65 | + }); | ||
66 | + | ||
67 | + const { handleFullScreen, getFullScreenIcon } = useFullScreen( | ||
68 | + rootElRef as unknown as Ref<Nullable<HTMLDivElement>> | ||
69 | + ); | ||
70 | + | ||
71 | + const handleGetContainer = () => unref(rootElRef)!; | ||
72 | + | ||
73 | + const getDeleteDisplayState = computed(() => unref(flowActionType.getSelectedElements).length); | ||
74 | + | ||
75 | + const handleDeleteSelectionElements = () => { | ||
76 | + flowActionType.removeEdges(unref(flowActionType.getSelectedEdges)); | ||
77 | + flowActionType.removeNodes(unref(flowActionType.getSelectedNodes)); | ||
78 | + }; | ||
79 | + | ||
80 | + onMounted(() => { | ||
81 | + getCurrentPageMetaData(flowActionType); | ||
82 | + }); | ||
83 | + | ||
84 | + createFlowContext({ | ||
85 | + createEdgeModalActionType, | ||
86 | + createNodeModalActionType, | ||
87 | + updateEdgeDrawerActionType, | ||
88 | + updateNodeDrawerActionType, | ||
89 | + flowActionType, | ||
90 | + triggerChange, | ||
91 | + }); | ||
92 | +</script> | ||
93 | + | ||
94 | +<template> | ||
95 | + <main ref="rootElRef" class="w-full h-full flex relative" @drop="handleOnDrop"> | ||
96 | + <!-- <Sidebar /> --> | ||
97 | + <MenuSidebar /> | ||
98 | + | ||
99 | + <Spin :spinning="loading" wrapperClassName="w-full h-ful rule-chain-designer-loading-container"> | ||
100 | + <VueFlow | ||
101 | + :id="getId" | ||
102 | + ref="flowElRef" | ||
103 | + v-model="elements" | ||
104 | + class="w-full h-full" | ||
105 | + @dragover="handleOnDragOver" | ||
106 | + > | ||
107 | + <template #connection-line="props"> | ||
108 | + <BasicConnectionLine v-bind="props" /> | ||
109 | + </template> | ||
110 | + <template #edge-custom="props"> | ||
111 | + <BasicEdge v-bind="props" /> | ||
112 | + </template> | ||
113 | + | ||
114 | + <BasicConnectionArrow /> | ||
115 | + | ||
116 | + <Background :variant="BackgroundVariant.Lines" :gap="25" pattern-color="#cfcfcf" /> | ||
117 | + | ||
118 | + <Controls :position="PanelPosition.BottomLeft" /> | ||
119 | + | ||
120 | + <Panel position="bottom-right" class="controls"> | ||
121 | + <section class="flex gap-4"> | ||
122 | + <button | ||
123 | + :style="{ transform: `translateY(${getDeleteDisplayState ? 0 : '72px'})` }" | ||
124 | + class="button-box-shadow w-14 h-14 flex justify-center items-center bg-orange-600 rounded-full transition-transform transform" | ||
125 | + @click="handleDeleteSelectionElements" | ||
126 | + > | ||
127 | + <Icon class="!text-3xl !text-light-50" icon="mdi:delete" /> | ||
128 | + </button> | ||
129 | + <button | ||
130 | + class="button-box-shadow w-14 h-14 flex justify-center items-center bg-gray-400 rounded-full opacity-50" | ||
131 | + > | ||
132 | + <Icon class="!text-3xl !text-light-50" icon="carbon:debug" /> | ||
133 | + </button> | ||
134 | + <button | ||
135 | + :class="changeMarker ? '!bg-orange-600 !opacity-100' : 'opacity-50'" | ||
136 | + class="button-box-shadow w-14 h-14 flex justify-center items-center bg-gray-400 rounded-full" | ||
137 | + @click="handleApplyChange(flowActionType)" | ||
138 | + > | ||
139 | + <Icon class="!text-3xl !text-light-50" icon="mdi:tick" /> | ||
140 | + </button> | ||
141 | + <button | ||
142 | + :class="changeMarker ? '!bg-orange-600 !opacity-100' : 'opacity-50'" | ||
143 | + class="button-box-shadow w-14 h-14 flex justify-center items-center bg-gray-400 rounded-full" | ||
144 | + @click="handleRedoChange(flowActionType)" | ||
145 | + > | ||
146 | + <Icon class="!text-3xl !text-light-50" icon="ic:baseline-close" /> | ||
147 | + </button> | ||
148 | + </section> | ||
149 | + </Panel> | ||
150 | + | ||
151 | + <Panel position="top-right"> | ||
152 | + <button | ||
153 | + class="w-10 h-10 bg-gray-300 flex justify-center items-center rounded-full dark:bg-dark-50" | ||
154 | + @click="handleFullScreen" | ||
155 | + > | ||
156 | + <Icon class="!text-2xl dark:text-light-50" :icon="getFullScreenIcon" /> | ||
157 | + </button> | ||
158 | + </Panel> | ||
159 | + </VueFlow> | ||
160 | + </Spin> | ||
161 | + | ||
162 | + <CreateNodeModal ref="createNodeModalActionType" :get-container="handleGetContainer" /> | ||
163 | + <CreateEdgeModal ref="createEdgeModalActionType" :get-container="handleGetContainer" /> | ||
164 | + | ||
165 | + <UpdateEdgeDrawer ref="updateEdgeDrawerActionType" /> | ||
166 | + <UpdateNodeDrawer ref="updateNodeDrawerActionType" /> | ||
167 | + </main> | ||
168 | +</template> | ||
169 | + | ||
170 | +<style scoped> | ||
171 | + .button-box-shadow { | ||
172 | + box-shadow: 0 3px 5px -1px #0003, 0 6px 10px 0 #00000024, 0 1px 18px 0 #0000001f; | ||
173 | + } | ||
174 | +</style> | ||
175 | + | ||
176 | +<style lang="less"> | ||
177 | + .rule-chain-designer-loading-container { | ||
178 | + .ant-spin-container { | ||
179 | + @apply w-full h-full; | ||
180 | + } | ||
181 | + } | ||
182 | +</style> |
1 | +import { cloneDeep } from 'lodash-es'; | ||
2 | +import { PublicNodeItemClass } from '../../../types/node'; | ||
3 | +import type { | ||
4 | + CategoryConfigType, | ||
5 | + CreateComponentType, | ||
6 | + NodeItemConfigType, | ||
7 | +} from '../../../types/node'; | ||
8 | +import { ActionCategoryConfig } from '..'; | ||
9 | +import { AssignToCustomerConfig } from '.'; | ||
10 | + | ||
11 | +export class Config extends PublicNodeItemClass implements CreateComponentType { | ||
12 | + public config: NodeItemConfigType = cloneDeep(AssignToCustomerConfig); | ||
13 | + | ||
14 | + public categoryConfig: CategoryConfigType = cloneDeep(ActionCategoryConfig); | ||
15 | + | ||
16 | + constructor() { | ||
17 | + super(); | ||
18 | + } | ||
19 | +} |
1 | +import { | ||
2 | + AssignToCustomerFieldsEnum, | ||
3 | + AssignToCustomerFieldsNameEnum, | ||
4 | +} from '../../../enum/formField/action'; | ||
5 | +import { FormSchema } from '/@/components/Form'; | ||
6 | + | ||
7 | +export const formSchemas: FormSchema[] = [ | ||
8 | + { | ||
9 | + field: AssignToCustomerFieldsEnum.CUSTOMER_NAME_PATTERN, | ||
10 | + component: 'Input', | ||
11 | + label: AssignToCustomerFieldsNameEnum.CUSTOMER_NAME_PATTERN, | ||
12 | + helpMessage: | ||
13 | + 'Hint: use ${metadataKey} for value from metadata, $[messageKey] for value from message body', | ||
14 | + componentProps: { | ||
15 | + placeholder: `请输入${AssignToCustomerFieldsNameEnum.CUSTOMER_NAME_PATTERN}`, | ||
16 | + }, | ||
17 | + }, | ||
18 | + { | ||
19 | + field: AssignToCustomerFieldsEnum.CREATE_CUSTOMER_IF_NOT_EXISTS, | ||
20 | + component: 'Checkbox', | ||
21 | + label: '', | ||
22 | + renderComponentContent: () => ({ | ||
23 | + default: () => AssignToCustomerFieldsNameEnum.CREATE_CUSTOMER_IF_NOT_EXISTS, | ||
24 | + }), | ||
25 | + }, | ||
26 | + { | ||
27 | + field: AssignToCustomerFieldsEnum.CUSTOMER_CACHE_EXPIRATION, | ||
28 | + component: 'InputNumber', | ||
29 | + label: AssignToCustomerFieldsNameEnum.CUSTOMER_CACHE_EXPIRATION, | ||
30 | + required: true, | ||
31 | + helpMessage: | ||
32 | + 'Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.', | ||
33 | + componentProps: { | ||
34 | + placeholder: `请输入${AssignToCustomerFieldsNameEnum.CUSTOMER_CACHE_EXPIRATION}`, | ||
35 | + min: 0, | ||
36 | + }, | ||
37 | + }, | ||
38 | +]; |
1 | +<script lang="ts" setup> | ||
2 | + import type { CreateModalDefineExposeType } from '../../../types'; | ||
3 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
4 | + import { formSchemas } from './create.config'; | ||
5 | + import { NodeData } from '../../../types/node'; | ||
6 | + | ||
7 | + defineProps<{ | ||
8 | + config: NodeData; | ||
9 | + }>(); | ||
10 | + | ||
11 | + const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | ||
12 | + schemas: formSchemas, | ||
13 | + showActionButtonGroup: false, | ||
14 | + }); | ||
15 | + | ||
16 | + const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | ||
17 | + await validate(); | ||
18 | + const value = getFieldsValue() || {}; | ||
19 | + return value; | ||
20 | + }; | ||
21 | + | ||
22 | + const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | ||
23 | + resetFields(); | ||
24 | + setFieldsValue(value); | ||
25 | + }; | ||
26 | + | ||
27 | + defineExpose({ | ||
28 | + setFieldsValue: setValue, | ||
29 | + getFieldsValue: getValue, | ||
30 | + } as CreateModalDefineExposeType); | ||
31 | +</script> | ||
32 | + | ||
33 | +<template> | ||
34 | + <BasicForm @register="register" /> | ||
35 | +</template> |
1 | +import { ActionCategoryComponentEnum } from '../../../enum/category'; | ||
2 | +import { useCreateNodeKey } from '../../../hook/useCreateNodeKey'; | ||
3 | +import type { NodeItemConfigType } from '../../../types/node'; | ||
4 | +import { RuleNodeTypeEnum } from '../../index.type'; | ||
5 | + | ||
6 | +const keys = useCreateNodeKey(ActionCategoryComponentEnum.ASSIGN_TO_CUSTOMER); | ||
7 | + | ||
8 | +export interface AssignToCustomerDataType { | ||
9 | + someConfiguration?: Recordable; | ||
10 | +} | ||
11 | + | ||
12 | +export const AssignToCustomerConfig: NodeItemConfigType = { | ||
13 | + ...keys, | ||
14 | + clazz: 'org.thingsboard.rule.engine.action.TbAssignToCustomerNode', | ||
15 | + categoryType: RuleNodeTypeEnum.ACTION, | ||
16 | + name: 'assign to customer', | ||
17 | + configurationDescriptor: { | ||
18 | + nodeDefinition: { | ||
19 | + details: | ||
20 | + "Finds target Customer by customer name pattern and then assign Originator Entity to this customer. Will create new Customer if it doesn't exists and 'Create new Customer if not exists' is set to true.", | ||
21 | + description: 'Assign Message Originator Entity to Customer', | ||
22 | + inEnabled: true, | ||
23 | + outEnabled: true, | ||
24 | + relationTypes: ['Success', 'Failure'], | ||
25 | + customRelations: false, | ||
26 | + ruleChainNode: false, | ||
27 | + defaultConfiguration: { | ||
28 | + customerNamePattern: '', | ||
29 | + customerCacheExpiration: 300, | ||
30 | + createCustomerIfNotExists: false, | ||
31 | + }, | ||
32 | + uiResources: ['static/rulenode/rulenode-core-config.js'], | ||
33 | + configDirective: 'tbActionNodeAssignToCustomerConfig', | ||
34 | + icon: 'ic:baseline-add-circle', | ||
35 | + iconUrl: '', | ||
36 | + docUrl: '', | ||
37 | + }, | ||
38 | + }, | ||
39 | +}; |
1 | +import { cloneDeep } from 'lodash-es'; | ||
2 | +import { PublicNodeItemClass } from '../../../types/node'; | ||
3 | +import type { | ||
4 | + CategoryConfigType, | ||
5 | + CreateComponentType, | ||
6 | + NodeItemConfigType, | ||
7 | +} from '../../../types/node'; | ||
8 | +import { ActionCategoryConfig } from '..'; | ||
9 | +import { ClearAlarmConfig } from '.'; | ||
10 | + | ||
11 | +export class Config extends PublicNodeItemClass implements CreateComponentType { | ||
12 | + public config: NodeItemConfigType = cloneDeep(ClearAlarmConfig); | ||
13 | + | ||
14 | + public categoryConfig: CategoryConfigType = cloneDeep(ActionCategoryConfig); | ||
15 | + | ||
16 | + constructor() { | ||
17 | + super(); | ||
18 | + } | ||
19 | +} |
1 | +import { ClearAlarmFieldsEnum, ClearAlarmFieldsNameEnum } from '../../../enum/formField/action'; | ||
2 | +import { JavascriptEditorWithTestModal } from '../../../src/components/JavaScriptFilterModal'; | ||
3 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | ||
4 | + | ||
5 | +useComponentRegister('JavascriptEditorWithTestModal', JavascriptEditorWithTestModal); | ||
6 | + | ||
7 | +export const formSchemas: FormSchema[] = [ | ||
8 | + { | ||
9 | + field: ClearAlarmFieldsEnum.ALARM_DETAILS_BUILD_JS, | ||
10 | + component: 'JavascriptEditorWithTestModal', | ||
11 | + label: ClearAlarmFieldsNameEnum.ALARM_DETAILS_BUILD_JS, | ||
12 | + componentProps: { | ||
13 | + javaScriptEditorProps: { | ||
14 | + functionName: 'Details', | ||
15 | + paramsName: ['msg', 'metadata', 'msgType'], | ||
16 | + }, | ||
17 | + buttonName: 'Test details function', | ||
18 | + }, | ||
19 | + }, | ||
20 | + { | ||
21 | + field: ClearAlarmFieldsEnum.ALARM_TYPE, | ||
22 | + component: 'Input', | ||
23 | + label: ClearAlarmFieldsNameEnum.ALARM_TYPE, | ||
24 | + required: true, | ||
25 | + componentProps: { | ||
26 | + placeholder: `请输入${ClearAlarmFieldsNameEnum.ALARM_TYPE}`, | ||
27 | + }, | ||
28 | + }, | ||
29 | +]; |
1 | +<script lang="ts" setup> | ||
2 | + import type { CreateModalDefineExposeType } from '../../../types'; | ||
3 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
4 | + import { formSchemas } from './create.config'; | ||
5 | + import { NodeData } from '../../../types/node'; | ||
6 | + | ||
7 | + defineProps<{ | ||
8 | + config: NodeData; | ||
9 | + }>(); | ||
10 | + | ||
11 | + const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | ||
12 | + schemas: formSchemas, | ||
13 | + showActionButtonGroup: false, | ||
14 | + }); | ||
15 | + | ||
16 | + const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | ||
17 | + await validate(); | ||
18 | + const value = getFieldsValue() || {}; | ||
19 | + return value; | ||
20 | + }; | ||
21 | + | ||
22 | + const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | ||
23 | + resetFields(); | ||
24 | + setFieldsValue(value); | ||
25 | + }; | ||
26 | + | ||
27 | + defineExpose({ | ||
28 | + setFieldsValue: setValue, | ||
29 | + getFieldsValue: getValue, | ||
30 | + } as CreateModalDefineExposeType); | ||
31 | +</script> | ||
32 | + | ||
33 | +<template> | ||
34 | + <BasicForm @register="register" /> | ||
35 | +</template> |
1 | +import { ActionCategoryComponentEnum } from '../../../enum/category'; | ||
2 | +import { useCreateNodeKey } from '../../../hook/useCreateNodeKey'; | ||
3 | +import type { NodeItemConfigType } from '../../../types/node'; | ||
4 | +import { RuleNodeTypeEnum } from '../../index.type'; | ||
5 | + | ||
6 | +const keys = useCreateNodeKey(ActionCategoryComponentEnum.CLEAR_ALARM); | ||
7 | + | ||
8 | +export interface ClearAlarmDataType { | ||
9 | + someConfiguration?: Recordable; | ||
10 | +} | ||
11 | + | ||
12 | +export const ClearAlarmConfig: NodeItemConfigType = { | ||
13 | + ...keys, | ||
14 | + clazz: 'org.thingsboard.rule.engine.action.TbClearAlarmNode', | ||
15 | + categoryType: RuleNodeTypeEnum.ACTION, | ||
16 | + name: 'clear alarm', | ||
17 | + configurationDescriptor: { | ||
18 | + nodeDefinition: { | ||
19 | + details: | ||
20 | + "Details - JS function that creates JSON object based on incoming message. This object will be added into Alarm.details field.\nNode output:\nIf alarm was not cleared, original message is returned. Otherwise new Message returned with type 'ALARM', Alarm object in 'msg' property and 'metadata' will contains 'isClearedAlarm' property. Message payload can be accessed via <code>msg</code> property. For example <code>'temperature = ' + msg.temperature ;</code>. Message metadata can be accessed via <code>metadata</code> property. For example <code>'name = ' + metadata.customerName;</code>.", | ||
21 | + description: 'Clear Alarm', | ||
22 | + inEnabled: true, | ||
23 | + outEnabled: true, | ||
24 | + relationTypes: ['Cleared', 'False', 'Failure'], | ||
25 | + customRelations: false, | ||
26 | + ruleChainNode: false, | ||
27 | + defaultConfiguration: { | ||
28 | + alarmType: 'General Alarm', | ||
29 | + alarmDetailsBuildJs: | ||
30 | + 'var details = {};\nif (metadata.prevAlarmDetails) {\n details = JSON.parse(metadata.prevAlarmDetails);\n //remove prevAlarmDetails from metadata\n delete metadata.prevAlarmDetails;\n //now metadata is the same as it comes IN this rule node\n}\n\n\nreturn details;', | ||
31 | + }, | ||
32 | + uiResources: ['static/rulenode/rulenode-core-config.js'], | ||
33 | + configDirective: 'tbActionNodeClearAlarmConfig', | ||
34 | + icon: 'material-symbols:notifications-off', | ||
35 | + iconUrl: '', | ||
36 | + docUrl: '', | ||
37 | + }, | ||
38 | + }, | ||
39 | +}; |
1 | +import { cloneDeep } from 'lodash-es'; | ||
2 | +import { PublicNodeItemClass } from '../../../types/node'; | ||
3 | +import type { | ||
4 | + CategoryConfigType, | ||
5 | + CreateComponentType, | ||
6 | + NodeItemConfigType, | ||
7 | +} from '../../../types/node'; | ||
8 | +import { ActionCategoryConfig } from '..'; | ||
9 | +import { CopyToViewConfig } from '.'; | ||
10 | + | ||
11 | +export class Config extends PublicNodeItemClass implements CreateComponentType { | ||
12 | + public config: NodeItemConfigType = cloneDeep(CopyToViewConfig); | ||
13 | + | ||
14 | + public categoryConfig: CategoryConfigType = cloneDeep(ActionCategoryConfig); | ||
15 | + | ||
16 | + constructor() { | ||
17 | + super(); | ||
18 | + } | ||
19 | +} |
1 | +<script lang="ts" setup> | ||
2 | + import type { CreateModalDefineExposeType } from '../../../types'; | ||
3 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
4 | + import { formSchemas } from './create.config'; | ||
5 | + import { NodeData } from '../../../types/node'; | ||
6 | + | ||
7 | + defineProps<{ | ||
8 | + config: NodeData; | ||
9 | + }>(); | ||
10 | + | ||
11 | + const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | ||
12 | + schemas: formSchemas, | ||
13 | + showActionButtonGroup: false, | ||
14 | + }); | ||
15 | + | ||
16 | + const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | ||
17 | + await validate(); | ||
18 | + const value = getFieldsValue() || {}; | ||
19 | + return value; | ||
20 | + }; | ||
21 | + | ||
22 | + const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | ||
23 | + resetFields(); | ||
24 | + setFieldsValue(value); | ||
25 | + }; | ||
26 | + | ||
27 | + defineExpose({ | ||
28 | + setFieldsValue: setValue, | ||
29 | + getFieldsValue: getValue, | ||
30 | + } as CreateModalDefineExposeType); | ||
31 | +</script> | ||
32 | + | ||
33 | +<template> | ||
34 | + <BasicForm @register="register" /> | ||
35 | +</template> |
1 | +import { ActionCategoryComponentEnum } from '../../../enum/category'; | ||
2 | +import { useCreateNodeKey } from '../../../hook/useCreateNodeKey'; | ||
3 | +import type { NodeItemConfigType } from '../../../types/node'; | ||
4 | +import { RuleNodeTypeEnum } from '../../index.type'; | ||
5 | + | ||
6 | +const keys = useCreateNodeKey(ActionCategoryComponentEnum.COPY_TO_VIEW); | ||
7 | + | ||
8 | +export interface CopyToViewDataType { | ||
9 | + someConfiguration?: Recordable; | ||
10 | +} | ||
11 | + | ||
12 | +export const CopyToViewConfig: NodeItemConfigType = { | ||
13 | + ...keys, | ||
14 | + clazz: 'org.thingsboard.rule.engine.action.TbCopyAttributesToEntityViewNode', | ||
15 | + categoryType: RuleNodeTypeEnum.ACTION, | ||
16 | + name: 'copy to view', | ||
17 | + configurationDescriptor: { | ||
18 | + nodeDefinition: { | ||
19 | + details: | ||
20 | + 'Copy attributes from asset/device to related entity view according to entity view configuration. \n Copy will be done only for attributes that are between start and end dates and according to attribute keys configuration. \nChanges message originator to related entity view and produces new messages according to count of updated entity views', | ||
21 | + description: | ||
22 | + 'Copy attributes from asset/device to entity view and changes message originator to related entity view', | ||
23 | + inEnabled: true, | ||
24 | + outEnabled: true, | ||
25 | + relationTypes: ['Success', 'Failure'], | ||
26 | + customRelations: false, | ||
27 | + ruleChainNode: false, | ||
28 | + defaultConfiguration: { | ||
29 | + version: 0, | ||
30 | + }, | ||
31 | + uiResources: ['static/rulenode/rulenode-core-config.js'], | ||
32 | + configDirective: 'tbNodeEmptyConfig', | ||
33 | + icon: 'material-symbols:content-copy', | ||
34 | + iconUrl: '', | ||
35 | + docUrl: '', | ||
36 | + }, | ||
37 | + }, | ||
38 | +}; |
1 | +import { cloneDeep } from 'lodash-es'; | ||
2 | +import { PublicNodeItemClass } from '../../../types/node'; | ||
3 | +import type { | ||
4 | + CategoryConfigType, | ||
5 | + CreateComponentType, | ||
6 | + NodeItemConfigType, | ||
7 | +} from '../../../types/node'; | ||
8 | +import { ActionCategoryConfig } from '..'; | ||
9 | +import { CreateAlarmConfig } from '.'; | ||
10 | + | ||
11 | +export class Config extends PublicNodeItemClass implements CreateComponentType { | ||
12 | + public config: NodeItemConfigType = cloneDeep(CreateAlarmConfig); | ||
13 | + | ||
14 | + public categoryConfig: CategoryConfigType = cloneDeep(ActionCategoryConfig); | ||
15 | + | ||
16 | + constructor() { | ||
17 | + super(); | ||
18 | + } | ||
19 | +} |