Commit 594b8ae08c35ddd3c7a1a4396d8f84f5c74ccdf4
Merge branch 'fix/tenant-config-add-config' into 'main_dev'
fix: 租户配置添加独立规则链的配置 See merge request yunteng/thingskit-front!1450
Showing
5 changed files
with
684 additions
and
27 deletions
1 | +<template> | |
2 | + <BasicForm @register="registerForm"> | |
3 | + <template #nameSlot="{ model }"> | |
4 | + <Input | |
5 | + :disabled="model.disabled" | |
6 | + v-model:value="model.name" | |
7 | + @change="handleNameChange" | |
8 | + placeholder="请输入" | |
9 | + /> | |
10 | + </template> | |
11 | + </BasicForm> | |
12 | + | |
13 | + <CollapseContainer | |
14 | + title="提交设置" | |
15 | + style="box-shadow: 0 3px 1px -2px #0003, 0 2px 2px #00000024, 0 1px 5px #0000001f" | |
16 | + > | |
17 | + <BasicForm @register="registerSubmitStrategyForm" /> | |
18 | + </CollapseContainer> | |
19 | + | |
20 | + <CollapseContainer | |
21 | + title="重试处理设置" | |
22 | + class="my-2 retry" | |
23 | + style="box-shadow: 0 3px 1px -2px #0003, 0 2px 2px #00000024, 0 1px 5px #0000001f" | |
24 | + > | |
25 | + <BasicForm @register="registerProcessingStrategyForm" /> | |
26 | + </CollapseContainer> | |
27 | + <CollapseContainer | |
28 | + title="轮询设置" | |
29 | + style="box-shadow: 0 3px 1px -2px #0003, 0 2px 2px #00000024, 0 1px 5px #0000001f" | |
30 | + > | |
31 | + <BasicForm @register="registerPollingSettingsForm" /> | |
32 | + </CollapseContainer> | |
33 | +</template> | |
34 | + | |
35 | +<script lang="ts" setup> | |
36 | + import { BasicForm, useForm } from '/@/components/Form'; | |
37 | + import { Input } from 'ant-design-vue'; | |
38 | + import { | |
39 | + formSchema, | |
40 | + submitStrategySchema, | |
41 | + processingStrategySchema, | |
42 | + pollingSettingsSchema, | |
43 | + } from './config'; | |
44 | + import { CollapseContainer } from '/@/components/Container/index'; | |
45 | + | |
46 | + // const props = defineProps({ | |
47 | + // record: { type: Object }, | |
48 | + // }); | |
49 | + | |
50 | + const emit = defineEmits(['handleNameChange']); | |
51 | + | |
52 | + const [registerForm, { validate, getFieldsValue, setFieldsValue }] = useForm({ | |
53 | + schemas: formSchema, | |
54 | + showActionButtonGroup: false, | |
55 | + }); | |
56 | + | |
57 | + const [ | |
58 | + registerSubmitStrategyForm, | |
59 | + { | |
60 | + validate: validateSubmitStrategy, | |
61 | + getFieldsValue: getFieldsValueSubmitStrategy, | |
62 | + setFieldsValue: setFieldsValueSubmitStrategy, | |
63 | + }, | |
64 | + ] = useForm({ | |
65 | + schemas: submitStrategySchema, | |
66 | + showActionButtonGroup: false, | |
67 | + baseColProps: { span: 12 }, | |
68 | + wrapperCol: { span: 18 }, | |
69 | + }); | |
70 | + const [ | |
71 | + registerProcessingStrategyForm, | |
72 | + { | |
73 | + validate: validateProcessingStrategy, | |
74 | + setFieldsValue: setFieldsValueProcessingStrategy, | |
75 | + getFieldsValue: getFieldsValueProcessingStrategy, | |
76 | + }, | |
77 | + ] = useForm({ | |
78 | + schemas: processingStrategySchema, | |
79 | + showActionButtonGroup: false, | |
80 | + // baseColProps: { span: 12 }, | |
81 | + // wrapperCol: { span: 18 }, | |
82 | + }); | |
83 | + const [ | |
84 | + registerPollingSettingsForm, | |
85 | + { | |
86 | + validate: validatePollingSettings, | |
87 | + getFieldsValue: getFieldsValuePollingSettings, | |
88 | + setFieldsValue: setFieldsValuePollingSettings, | |
89 | + }, | |
90 | + ] = useForm({ | |
91 | + schemas: pollingSettingsSchema, | |
92 | + showActionButtonGroup: false, | |
93 | + // baseColProps: { span: 12 }, | |
94 | + // wrapperCol: { span: 18 }, | |
95 | + }); | |
96 | + | |
97 | + const validateAll = async () => { | |
98 | + await validate(); | |
99 | + await validateSubmitStrategy(); | |
100 | + await validateProcessingStrategy(); | |
101 | + await validatePollingSettings(); | |
102 | + }; | |
103 | + | |
104 | + const getAllFieldsValue = () => { | |
105 | + const { name, description, customProperties, nameOnly, topic } = getFieldsValue() || {}; | |
106 | + const additionalInfo = { description, customProperties }; | |
107 | + const processingStrategy = getFieldsValueProcessingStrategy(); | |
108 | + const submitStrategy = getFieldsValueSubmitStrategy(); | |
109 | + const values = getFieldsValuePollingSettings(); | |
110 | + const valuesInfo = { | |
111 | + name, | |
112 | + nameOnly, | |
113 | + additionalInfo, | |
114 | + processingStrategy, | |
115 | + submitStrategy, | |
116 | + topic, | |
117 | + ...values, | |
118 | + }; | |
119 | + return valuesInfo; | |
120 | + }; | |
121 | + | |
122 | + const setAllFieldsValue = (record: any) => { | |
123 | + // disabled 只是用来禁用名称输入 Main HighPriority SequentialByOriginator 默认是禁用 编辑的时候全部也是禁用 | |
124 | + const { name, additionalInfo, processingStrategy, disabled, submitStrategy, topic, ...values } = | |
125 | + record || {}; | |
126 | + setFieldsValue({ name, ...additionalInfo, disabled, topic }); | |
127 | + setFieldsValueSubmitStrategy(submitStrategy); | |
128 | + setFieldsValueProcessingStrategy(processingStrategy); | |
129 | + setFieldsValuePollingSettings({ ...values }); | |
130 | + }; | |
131 | + | |
132 | + const handleNameChange = ({ target }) => { | |
133 | + emit('handleNameChange', target?.value); | |
134 | + }; | |
135 | + | |
136 | + defineExpose({ getAllFieldsValue, setAllFieldsValue, setFieldsValue, validateAll }); | |
137 | +</script> | |
138 | + | |
139 | +<style lang="less" scoped> | |
140 | + :deep(.ant-input-number) { | |
141 | + width: 95% !important; | |
142 | + } | |
143 | + | |
144 | + :deep(.ant-select) { | |
145 | + width: 95% !important; | |
146 | + } | |
147 | + | |
148 | + .retry { | |
149 | + :deep(.ant-select) { | |
150 | + width: 97.5% !important; | |
151 | + } | |
152 | + } | |
153 | +</style> | ... | ... |
src/views/tenant/config/components/config.ts
0 → 100644
1 | +import { FormSchema } from '/@/components/Form'; | |
2 | + | |
3 | +const PolicyTypeEnum = { | |
4 | + SEQUENTIAL_BY_ORIGINATOR: 'SEQUENTIAL_BY_ORIGINATOR', | |
5 | + SEQUENTIAL_BY_TENANT: 'SEQUENTIAL_BY_TENANT', | |
6 | + SEQUENTIAL: 'SEQUENTIAL', | |
7 | + BURST: 'BURST', | |
8 | + BATCH: 'BATCH', | |
9 | +}; | |
10 | +const PolicyTypeLabelEnum = { | |
11 | + SEQUENTIAL_BY_ORIGINATOR: '按发起者顺序处理', | |
12 | + SEQUENTIAL_BY_TENANT: '按租户顺序处理', | |
13 | + SEQUENTIAL: '顺序处理', | |
14 | + BURST: '突发处理', | |
15 | + BATCH: '批量处理', | |
16 | +}; | |
17 | + | |
18 | +const ProcessTypeEnum = { | |
19 | + RETRY_FAILED_AND_TIMED_OUT: 'RETRY_FAILED_AND_TIMED_OUT', | |
20 | + SKIP_ALL_FAILURES: 'SKIP_ALL_FAILURES', | |
21 | + SKIP_ALL_FAILURES_AND_TIMED_OUT: 'SKIP_ALL_FAILURES_AND_TIMED_OUT', | |
22 | + RETRY_ALL: 'RETRY_ALL', | |
23 | + RETRY_FAILED: 'RETRY_FAILED', | |
24 | + RETRY_TIMED_OUT: 'RETRY_TIMED_OUT', | |
25 | +}; | |
26 | + | |
27 | +const ProcessTypeLabelEnum = { | |
28 | + RETRY_FAILED_AND_TIMED_OUT: '失败与超时重试', | |
29 | + SKIP_ALL_FAILURES: '跳过所有失败', | |
30 | + SKIP_ALL_FAILURES_AND_TIMED_OUT: '跳过所有失败和超时', | |
31 | + RETRY_ALL: '全部重试', | |
32 | + RETRY_FAILED: '失败重试', | |
33 | + RETRY_TIMED_OUT: '超时重试', | |
34 | +}; | |
35 | + | |
36 | +export const formSchema: FormSchema[] = [ | |
37 | + { | |
38 | + field: 'name', | |
39 | + label: '名称', | |
40 | + component: 'Input', | |
41 | + required: true, | |
42 | + rules: [ | |
43 | + { | |
44 | + pattern: /^[A-Za-z0-9._-]*$/, | |
45 | + message: "不能包含ASCII字母数字以外的字符, '.', '_' 和 '-'等", | |
46 | + }, | |
47 | + { | |
48 | + required: true, | |
49 | + }, | |
50 | + ], | |
51 | + slot: 'nameSlot', | |
52 | + }, | |
53 | + { | |
54 | + field: 'disabled', | |
55 | + label: '', | |
56 | + component: 'Checkbox', | |
57 | + ifShow: false, | |
58 | + }, | |
59 | + { | |
60 | + // 用于判断名称是否是唯一的 | |
61 | + field: 'nameOnly', | |
62 | + label: '', | |
63 | + defaultValue: true, | |
64 | + component: 'Checkbox', | |
65 | + ifShow: false, | |
66 | + }, | |
67 | + { | |
68 | + field: 'topic', | |
69 | + label: '', | |
70 | + component: 'Input', | |
71 | + ifShow: false, | |
72 | + }, | |
73 | + { | |
74 | + field: 'customProperties', | |
75 | + label: '自定义属性', | |
76 | + component: 'Input', | |
77 | + helpMessage: [ | |
78 | + '自定义队列(主题)创建属性,例如:retention.ms:604800000;retention.bytes:1048576000', | |
79 | + ], | |
80 | + }, | |
81 | + { | |
82 | + field: 'description', | |
83 | + label: '说明', | |
84 | + component: 'InputTextArea', | |
85 | + helpMessage: ['此文本将显示在队列说明中,而不是所选策略中'], | |
86 | + }, | |
87 | +]; | |
88 | + | |
89 | +export const submitStrategySchema: FormSchema[] = [ | |
90 | + { | |
91 | + field: 'type', | |
92 | + label: '策略类型', | |
93 | + component: 'Select', | |
94 | + helpMessage: [ | |
95 | + '按发起者顺序处理:在确认设备A的前一条消息之前,不会提交设备A的新消息', | |
96 | + '按租户顺序处理:在确认租户A的前一条消息之前,不会提交租户A的新消息', | |
97 | + '顺序处理:在确认前一条消息之前,不会提交新消息', | |
98 | + '突发处理:所有消息都按到达顺序提交到规则链', | |
99 | + '批量处理:在确认前一批消息之前,不会提交新批', | |
100 | + ], | |
101 | + defaultValue: PolicyTypeEnum.BURST, | |
102 | + componentProps: { | |
103 | + options: Object.keys(PolicyTypeLabelEnum).map((item) => ({ | |
104 | + label: PolicyTypeLabelEnum[item], | |
105 | + value: PolicyTypeEnum[item], | |
106 | + })), | |
107 | + }, | |
108 | + }, | |
109 | + { | |
110 | + field: 'batchSize', | |
111 | + label: '批量处理大小', | |
112 | + required: true, | |
113 | + component: 'InputNumber', | |
114 | + ifShow: ({ model }) => model.type === PolicyTypeEnum.BATCH, | |
115 | + }, | |
116 | +]; | |
117 | + | |
118 | +export const processingStrategySchema: FormSchema[] = [ | |
119 | + { | |
120 | + field: 'type', | |
121 | + label: '处理类型', | |
122 | + component: 'Select', | |
123 | + colProps: { span: 24 }, | |
124 | + required: true, | |
125 | + componentProps: { | |
126 | + options: Object.keys(ProcessTypeLabelEnum).map((item) => ({ | |
127 | + label: ProcessTypeLabelEnum[item], | |
128 | + value: ProcessTypeEnum[item], | |
129 | + })), | |
130 | + }, | |
131 | + helpMessage: [ | |
132 | + '失败与超时重试:重试处理包重所有失败和超时的消息', | |
133 | + '跳过所有失败:忽略所有失败', | |
134 | + '跳过所有失败和超时:忽略所有失败和超时', | |
135 | + '全部重试:重试处理包中的所有消息', | |
136 | + '失败重试:重试处理包重的所有失败消息', | |
137 | + '超时重试:重试处理包中的所有超时消息', | |
138 | + ], | |
139 | + defaultValue: ProcessTypeEnum.SKIP_ALL_FAILURES, | |
140 | + }, | |
141 | + { | |
142 | + field: 'retries', | |
143 | + label: '重试次数(0-无限制)', | |
144 | + required: true, | |
145 | + component: 'InputNumber', | |
146 | + colProps: { span: 12 }, | |
147 | + }, | |
148 | + | |
149 | + { | |
150 | + field: 'failurePercentage', | |
151 | + label: '跳过重试的失败消息百分比', | |
152 | + required: true, | |
153 | + component: 'InputNumber', | |
154 | + colProps: { span: 12 }, | |
155 | + }, | |
156 | + { | |
157 | + field: 'pauseBetweenRetries', | |
158 | + label: '重试间隔(秒)', | |
159 | + required: true, | |
160 | + component: 'InputNumber', | |
161 | + colProps: { span: 12 }, | |
162 | + }, | |
163 | + { | |
164 | + field: 'maxPauseBetweenRetries', | |
165 | + label: '最大重试间隔(秒)', | |
166 | + required: true, | |
167 | + component: 'InputNumber', | |
168 | + colProps: { span: 12 }, | |
169 | + }, | |
170 | +]; | |
171 | + | |
172 | +export const pollingSettingsSchema: FormSchema[] = [ | |
173 | + { | |
174 | + field: 'pollInterval', | |
175 | + label: '轮询间隔', | |
176 | + required: true, | |
177 | + colProps: { span: 12 }, | |
178 | + component: 'InputNumber', | |
179 | + }, | |
180 | + { | |
181 | + field: 'partitions', | |
182 | + label: '分区', | |
183 | + required: true, | |
184 | + colProps: { span: 12 }, | |
185 | + component: 'InputNumber', | |
186 | + }, | |
187 | + { | |
188 | + field: 'consumerPerPartition', | |
189 | + label: '每个分区消费者单独轮询消息', | |
190 | + required: true, | |
191 | + colProps: { span: 12 }, | |
192 | + component: 'Checkbox', | |
193 | + }, | |
194 | + { | |
195 | + field: 'packProcessingTimeout', | |
196 | + label: '处理超时(毫秒)', | |
197 | + required: true, | |
198 | + colProps: { span: 12 }, | |
199 | + component: 'InputNumber', | |
200 | + }, | |
201 | +]; | ... | ... |
... | ... | @@ -55,29 +55,42 @@ export const formSchema: FormSchema[] = [ |
55 | 55 | placeholder: '请输入名称', |
56 | 56 | }, |
57 | 57 | }, |
58 | + // { | |
59 | + // field: 'isolatedTbRuleEngine', | |
60 | + // label: '', | |
61 | + // component: 'Checkbox', | |
62 | + // ifShow: false, | |
63 | + // renderComponentContent: () => { | |
64 | + // return h('span', {}, [ | |
65 | + // h('span', {}, '隔离板芯容器中的加工'), | |
66 | + // h('span', { style: { color: 'grey' } }, '(每个独立租户需要单独的微服务)'), | |
67 | + // ]); | |
68 | + // }, | |
69 | + // }, | |
70 | + // { | |
71 | + // field: 'isolatedTbCore', | |
72 | + // label: '', | |
73 | + // component: 'Checkbox', | |
74 | + // ifShow: false, | |
75 | + // renderComponentContent: () => { | |
76 | + // return h('span', {}, [ | |
77 | + // h('span', {}, '在独立的规则引擎中处理'), | |
78 | + // h('span', { style: { color: 'grey' } }, '(每个独立租户需要单独的微服务)'), | |
79 | + // ]); | |
80 | + // }, | |
81 | + // }, | |
58 | 82 | { |
59 | 83 | field: 'isolatedTbRuleEngine', |
60 | 84 | label: '', |
61 | 85 | component: 'Checkbox', |
62 | - ifShow: false, | |
86 | + // ifShow: false, | |
63 | 87 | renderComponentContent: () => { |
64 | 88 | return h('span', {}, [ |
65 | - h('span', {}, '隔离板芯容器中的加工'), | |
66 | - h('span', { style: { color: 'grey' } }, '(每个独立租户需要单独的微服务)'), | |
67 | - ]); | |
68 | - }, | |
69 | - }, | |
70 | - { | |
71 | - field: 'isolatedTbCore', | |
72 | - label: '', | |
73 | - component: 'Checkbox', | |
74 | - ifShow: false, | |
75 | - renderComponentContent: () => { | |
76 | - return h('span', {}, [ | |
77 | - h('span', {}, '在独立的规则引擎中处理'), | |
78 | - h('span', { style: { color: 'grey' } }, '(每个独立租户需要单独的微服务)'), | |
89 | + h('span', {}, '使用独立的规则引擎服务'), | |
90 | + h('span', { style: { color: 'grey' } }, '每个独立租户需要单独的规则引擎微服务'), | |
79 | 91 | ]); |
80 | 92 | }, |
93 | + slot: 'isolatedTbRuleEngine', | |
81 | 94 | }, |
82 | 95 | { |
83 | 96 | field: 'description', | ... | ... |
... | ... | @@ -19,7 +19,12 @@ |
19 | 19 | |
20 | 20 | const speedData = ref<{ value: string | number; second: string | number; uuid?: string }[]>([]); |
21 | 21 | const handleSuccess = (values) => { |
22 | - if (values.length) speedData.value = values; | |
22 | + if (!values?.length) { | |
23 | + speedData.value = []; | |
24 | + emit('update:value', []); | |
25 | + return; | |
26 | + } | |
27 | + speedData.value = values; | |
23 | 28 | const items = values.map((item) => `${item.value}:${item.second}`).join(','); |
24 | 29 | emit('update:value', items); |
25 | 30 | }; | ... | ... |
... | ... | @@ -9,8 +9,50 @@ |
9 | 9 | width="700px" |
10 | 10 | @ok="handleSubmit" |
11 | 11 | > |
12 | - <BasicForm @register="registerForm" /> | |
12 | + <BasicForm @register="registerForm"> | |
13 | + <template #isolatedTbRuleEngine="{ model }"> | |
14 | + <div class="flex items-center"> | |
15 | + <Checkbox v-model:checked="model.isolatedTbRuleEngine" @change="handleCheckbox" /> | |
16 | + <span>使用独立的规则引擎服务</span> | |
17 | + <span style="color: grey">(每个独立租户需要单独的规则引擎微服务)</span> | |
18 | + </div> | |
19 | + </template> | |
20 | + </BasicForm> | |
13 | 21 | <!-- <CpnsTenantSet ref="getChildData" :parentData="parentSetData" /> --> |
22 | + | |
23 | + <CollapseContainer | |
24 | + title="队列" | |
25 | + :defaultExpand="true" | |
26 | + v-if="isolatedTbRuleEngine" | |
27 | + class="mb-2" | |
28 | + > | |
29 | + <CollapseContainer | |
30 | + v-for="(item, index) in queueConfiguration" | |
31 | + :key="item.id" | |
32 | + :title="item.name" | |
33 | + :defaultExpand="true" | |
34 | + class="my-4" | |
35 | + style="box-shadow: 0 3px 1px -2px #0003, 0 2px 2px #00000024, 0 1px 5px #0000001f" | |
36 | + > | |
37 | + <template #action v-if="item.name !== 'Main'"> | |
38 | + <Tooltip title="删除"> | |
39 | + <Icon | |
40 | + class="ml-2 cursor-pointer" | |
41 | + icon="fluent:delete-off-20-regular" | |
42 | + size="20" | |
43 | + @click="handleDeleteTenant(index)" | |
44 | + /> | |
45 | + </Tooltip> | |
46 | + </template> | |
47 | + <TenantConfig | |
48 | + ref="getTenantConfig" | |
49 | + :record="item" | |
50 | + @handleNameChange="(name) => handleNameChange(index, name)" | |
51 | + /> | |
52 | + </CollapseContainer> | |
53 | + | |
54 | + <Button @click="handleCreateQueue" type="primary" class="my-3">添加队列</Button> | |
55 | + </CollapseContainer> | |
14 | 56 | <CollapseContainer title="实体 (0-无限制)" :defaultExpand="false"> |
15 | 57 | <Entity ref="getEntity" /> |
16 | 58 | </CollapseContainer> |
... | ... | @@ -36,7 +78,15 @@ |
36 | 78 | </div> |
37 | 79 | </template> |
38 | 80 | <script lang="ts"> |
39 | - import { defineComponent, ref, computed, unref, getCurrentInstance, reactive } from 'vue'; | |
81 | + import { | |
82 | + defineComponent, | |
83 | + ref, | |
84 | + computed, | |
85 | + unref, | |
86 | + getCurrentInstance, | |
87 | + reactive, | |
88 | + nextTick, | |
89 | + } from 'vue'; | |
40 | 90 | import { BasicForm, useForm } from '/@/components/Form'; |
41 | 91 | import { formSchema } from './config'; |
42 | 92 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
... | ... | @@ -51,6 +101,9 @@ |
51 | 101 | import { saveTenantProfileApi } from '/@/api/tenant/tenantApi'; |
52 | 102 | import { useMessage } from '/@/hooks/web/useMessage'; |
53 | 103 | import { CollapseContainer } from '/@/components/Container/index'; |
104 | + import { Checkbox, Tooltip, Button } from 'ant-design-vue'; | |
105 | + import TenantConfig from './components/TenantConfig.vue'; | |
106 | + import { buildUUID } from '/@/utils/uuid'; | |
54 | 107 | |
55 | 108 | export default defineComponent({ |
56 | 109 | name: 'ConfigDrawer', |
... | ... | @@ -66,6 +119,10 @@ |
66 | 119 | Ota, |
67 | 120 | Speed, |
68 | 121 | Entity, |
122 | + Checkbox, | |
123 | + Tooltip, | |
124 | + Button, | |
125 | + TenantConfig, | |
69 | 126 | }, |
70 | 127 | emits: ['success', 'register'], |
71 | 128 | setup(_, { emit }) { |
... | ... | @@ -84,15 +141,177 @@ |
84 | 141 | const getOta = ref(null); |
85 | 142 | const getWs = ref(null); |
86 | 143 | const getSpeed = ref(null); |
144 | + const getTenantConfig = ref(null); | |
87 | 145 | |
88 | 146 | const editGetId: any = ref(''); |
89 | 147 | const isDefault = ref(false); |
90 | 148 | const createTime = ref<string>(''); |
149 | + | |
150 | + // 独立规则引擎默认的三项Main不能删除其他能删除 | |
151 | + const defaultQueueConfiguration = () => { | |
152 | + return [ | |
153 | + { | |
154 | + name: 'Main', | |
155 | + topic: 'tb_rule_engine.main', | |
156 | + pollInterval: 2000, | |
157 | + partitions: 1, | |
158 | + consumerPerPartition: false, | |
159 | + packProcessingTimeout: 10000, | |
160 | + submitStrategy: { | |
161 | + type: 'BURST', | |
162 | + batchSize: 1000, | |
163 | + }, | |
164 | + processingStrategy: { | |
165 | + type: 'SKIP_ALL_FAILURES', | |
166 | + retries: 3, | |
167 | + failurePercentage: 0, | |
168 | + pauseBetweenRetries: 3, | |
169 | + maxPauseBetweenRetries: 3, | |
170 | + }, | |
171 | + id: buildUUID(), | |
172 | + disabled: true, | |
173 | + nameOnly: true, | |
174 | + additionalInfo: { | |
175 | + description: '', | |
176 | + customProperties: '', | |
177 | + }, | |
178 | + }, | |
179 | + { | |
180 | + name: 'HighPriority', | |
181 | + topic: 'tb_rule_engine.hp', | |
182 | + pollInterval: 2000, | |
183 | + partitions: 1, | |
184 | + consumerPerPartition: false, | |
185 | + packProcessingTimeout: 10000, | |
186 | + submitStrategy: { | |
187 | + type: 'BURST', | |
188 | + batchSize: 100, | |
189 | + }, | |
190 | + processingStrategy: { | |
191 | + type: 'RETRY_FAILED_AND_TIMED_OUT', | |
192 | + retries: 0, | |
193 | + failurePercentage: 0, | |
194 | + pauseBetweenRetries: 5, | |
195 | + maxPauseBetweenRetries: 5, | |
196 | + }, | |
197 | + id: buildUUID(), | |
198 | + disabled: true, | |
199 | + nameOnly: true, | |
200 | + additionalInfo: { | |
201 | + description: '', | |
202 | + customProperties: '', | |
203 | + }, | |
204 | + }, | |
205 | + { | |
206 | + name: 'SequentialByOriginator', | |
207 | + topic: 'tb_rule_engine.sq', | |
208 | + pollInterval: 2000, | |
209 | + partitions: 1, | |
210 | + consumerPerPartition: false, | |
211 | + packProcessingTimeout: 10000, | |
212 | + submitStrategy: { | |
213 | + type: 'SEQUENTIAL_BY_ORIGINATOR', | |
214 | + batchSize: 100, | |
215 | + }, | |
216 | + processingStrategy: { | |
217 | + type: 'RETRY_FAILED_AND_TIMED_OUT', | |
218 | + retries: 3, | |
219 | + failurePercentage: 0, | |
220 | + pauseBetweenRetries: 5, | |
221 | + maxPauseBetweenRetries: 5, | |
222 | + }, | |
223 | + id: buildUUID(), | |
224 | + disabled: true, | |
225 | + nameOnly: true, | |
226 | + additionalInfo: { | |
227 | + description: '', | |
228 | + customProperties: '', | |
229 | + }, | |
230 | + }, | |
231 | + ]; | |
232 | + }; | |
233 | + const queueConfiguration = ref<any>([]); | |
234 | + | |
91 | 235 | const [registerForm, { validate, resetFields, setFieldsValue, updateSchema }] = useForm({ |
92 | 236 | schemas: formSchema, |
93 | 237 | showActionButtonGroup: false, |
94 | 238 | }); |
95 | 239 | |
240 | + // 判断是否启用独立规则引擎 | |
241 | + const isolatedTbRuleEngine = ref<boolean>(false); | |
242 | + const handleCheckbox = (checkedValue) => { | |
243 | + const { | |
244 | + target: { checked }, | |
245 | + } = checkedValue || {}; | |
246 | + isolatedTbRuleEngine.value = checked; | |
247 | + if (checked && !unref(isUpdate)) { | |
248 | + queueConfiguration.value = defaultQueueConfiguration(); | |
249 | + nextTick(() => { | |
250 | + unref(queueConfiguration).forEach((item, index) => { | |
251 | + proxy.$refs.getTenantConfig[index]?.setAllFieldsValue(item); | |
252 | + }); | |
253 | + }); | |
254 | + } | |
255 | + }; | |
256 | + | |
257 | + // 删除队列 | |
258 | + const handleDeleteTenant = (index: number) => { | |
259 | + queueConfiguration.value.splice(index, 1); | |
260 | + }; | |
261 | + | |
262 | + const handleNameChange = async (index: number, name: string) => { | |
263 | + const isRepeat = unref(queueConfiguration).every((item) => item.name !== name); | |
264 | + nextTick(() => { | |
265 | + queueConfiguration.value[index].name = name; | |
266 | + }); | |
267 | + if (!isRepeat) { | |
268 | + createMessage.warning('队列名称必须唯一。'); | |
269 | + proxy.$refs.getTenantConfig[index]?.setFieldsValue({ | |
270 | + nameOnly: false, | |
271 | + topic: 'tb_rule_engine.' + name, | |
272 | + }); | |
273 | + return; | |
274 | + } | |
275 | + proxy.$refs.getTenantConfig[index]?.setFieldsValue({ | |
276 | + nameOnly: true, | |
277 | + topic: 'tb_rule_engine.' + name, | |
278 | + }); | |
279 | + }; | |
280 | + | |
281 | + const handleCreateQueue = () => { | |
282 | + const values = { | |
283 | + name: '', | |
284 | + pollInterval: 2000, | |
285 | + partitions: 1, | |
286 | + consumerPerPartition: false, | |
287 | + packProcessingTimeout: 10000, | |
288 | + submitStrategy: { | |
289 | + type: 'BURST', | |
290 | + batchSize: 1000, | |
291 | + }, | |
292 | + processingStrategy: { | |
293 | + type: 'SKIP_ALL_FAILURES', | |
294 | + retries: 3, | |
295 | + failurePercentage: 0, | |
296 | + pauseBetweenRetries: 3, | |
297 | + maxPauseBetweenRetries: 3, | |
298 | + }, | |
299 | + disabled: false, | |
300 | + id: buildUUID(), | |
301 | + nameOnly: true, | |
302 | + additionalInfo: { | |
303 | + description: '', | |
304 | + customProperties: '', | |
305 | + }, | |
306 | + }; | |
307 | + queueConfiguration.value.push(values); | |
308 | + nextTick(() => { | |
309 | + proxy.$refs.getTenantConfig[unref(queueConfiguration).length - 1]?.setAllFieldsValue( | |
310 | + values | |
311 | + ); | |
312 | + }); | |
313 | + }; | |
314 | + | |
96 | 315 | const funcResetFields = () => { |
97 | 316 | proxy.$refs.getEntity.funcResetFields(); |
98 | 317 | proxy.$refs.getRuleEngine.funcResetFields(); |
... | ... | @@ -128,6 +347,28 @@ |
128 | 347 | await setFieldsValue({ |
129 | 348 | ...data.record, |
130 | 349 | }); |
350 | + const { isolatedTbRuleEngine: dataIsolatedTbRuleEngine } = data.record || {}; | |
351 | + isolatedTbRuleEngine.value = dataIsolatedTbRuleEngine; | |
352 | + | |
353 | + const oldQueueConfiguration = data.record.profileData.queueConfiguration; | |
354 | + //独立规则引擎服务赋值 | |
355 | + if (dataIsolatedTbRuleEngine && oldQueueConfiguration?.length) { | |
356 | + queueConfiguration.value = | |
357 | + oldQueueConfiguration.map((item) => { | |
358 | + return { | |
359 | + ...item, | |
360 | + id: buildUUID(), | |
361 | + disabled: true, | |
362 | + nameOnly: true, | |
363 | + }; | |
364 | + }) || defaultQueueConfiguration(); | |
365 | + nextTick(() => { | |
366 | + unref(queueConfiguration).forEach((item, index) => { | |
367 | + proxy.$refs.getTenantConfig[index]?.setAllFieldsValue(item); | |
368 | + }); | |
369 | + }); | |
370 | + } | |
371 | + | |
131 | 372 | createTime.value = data.record.createdTime; |
132 | 373 | updateStatusSchema(true); |
133 | 374 | } |
... | ... | @@ -142,12 +383,12 @@ |
142 | 383 | disabled: status, |
143 | 384 | }, |
144 | 385 | }, |
145 | - { | |
146 | - field: 'isolatedTbCore', | |
147 | - componentProps: { | |
148 | - disabled: status, | |
149 | - }, | |
150 | - }, | |
386 | + // { | |
387 | + // field: 'isolatedTbRuleEngine', | |
388 | + // componentProps: { | |
389 | + // disabled: status, | |
390 | + // }, | |
391 | + // }, | |
151 | 392 | ]); |
152 | 393 | }; |
153 | 394 | |
... | ... | @@ -205,15 +446,52 @@ |
205 | 446 | try { |
206 | 447 | if (!unref(isUpdate)) { |
207 | 448 | await getAllFieldsFunc(); |
208 | - // return; | |
209 | - await saveTenantProfileApi({ ...postAllData, isolatedTbRuleEngine: null }); | |
449 | + const getTenantConfigRefs = proxy.$refs.getTenantConfig; | |
450 | + const queueConfigValues: any = []; | |
451 | + for (let i = 0; i < getTenantConfigRefs?.length; i++) { | |
452 | + await proxy.$refs.getTenantConfig[i].validateAll(); | |
453 | + const values = proxy.$refs.getTenantConfig[i].getAllFieldsValue(); | |
454 | + queueConfigValues.push({ ...values, nameOnly: undefined }); | |
455 | + const { nameOnly } = values || {}; | |
456 | + if (!nameOnly) { | |
457 | + createMessage.success('队列名称必须唯一。'); | |
458 | + return false; | |
459 | + } | |
460 | + } | |
461 | + const { | |
462 | + profileData: { configuration }, | |
463 | + } = postAllData || {}; | |
464 | + await saveTenantProfileApi({ | |
465 | + ...postAllData, | |
466 | + profileData: { configuration, queueConfiguration: queueConfigValues }, | |
467 | + }); | |
210 | 468 | createMessage.success('租户配置新增成功'); |
469 | + | |
211 | 470 | closeDrawer(); |
212 | 471 | emit('success'); |
213 | 472 | resetFields(); |
214 | 473 | } else { |
215 | 474 | await getAllFieldsFunc(true); |
216 | - await saveTenantProfileApi({ ...postAllData, isolatedTbRuleEngine: null }); | |
475 | + const getTenantConfigRefs = proxy.$refs.getTenantConfig; | |
476 | + // proxy.$refs.getTenantConfig[index].getAllFieldsValue(); | |
477 | + const queueConfigValues: any = []; | |
478 | + for (let i = 0; i < getTenantConfigRefs?.length; i++) { | |
479 | + await proxy.$refs.getTenantConfig[i].validateAll(); | |
480 | + const values = proxy.$refs.getTenantConfig[i].getAllFieldsValue(); | |
481 | + queueConfigValues.push({ ...values, nameOnly: undefined }); | |
482 | + const { nameOnly } = values || {}; | |
483 | + if (!nameOnly) { | |
484 | + createMessage.warning('队列名称必须唯一。'); | |
485 | + return false; | |
486 | + } | |
487 | + } | |
488 | + const { | |
489 | + profileData: { configuration }, | |
490 | + } = postAllData || {}; | |
491 | + await saveTenantProfileApi({ | |
492 | + ...postAllData, | |
493 | + profileData: { configuration, queueConfiguration: queueConfigValues }, | |
494 | + }); | |
217 | 495 | createMessage.success('租户配置编辑成功'); |
218 | 496 | closeDrawer(); |
219 | 497 | emit('success'); |
... | ... | @@ -239,6 +517,13 @@ |
239 | 517 | getOta, |
240 | 518 | getWs, |
241 | 519 | getSpeed, |
520 | + handleCheckbox, | |
521 | + isolatedTbRuleEngine, | |
522 | + handleDeleteTenant, | |
523 | + queueConfiguration, | |
524 | + getTenantConfig, | |
525 | + handleNameChange, | |
526 | + handleCreateQueue, | |
242 | 527 | }; |
243 | 528 | }, |
244 | 529 | }); | ... | ... |