Commit 594b8ae08c35ddd3c7a1a4396d8f84f5c74ccdf4

Authored by xp.Huang
2 parents 4205799d 176b0a5e

Merge branch 'fix/tenant-config-add-config' into 'main_dev'

fix: 租户配置添加独立规则链的配置

See merge request yunteng/thingskit-front!1450
  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>
... ...
  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 });
... ...