Skip to content

Commit 17aaa4b

Browse files
committed
perf(frontend): redis工具箱重构_安装Module #8840
1 parent 22913cb commit 17aaa4b

File tree

8 files changed

+453
-9
lines changed

8 files changed

+453
-9
lines changed

dbm-ui/frontend/src/services/model/ticket/details/redis/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export * from './dataStructure';
1111
export * from './dataStructureTaskDelete';
1212
export * from './destroy';
1313
export * from './insApply';
14+
export * from './installModule';
1415
export * from './instanceDestroy';
1516
export * from './instanceProxyClose';
1617
export * from './instanceProxyOpen';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { DetailBase, DetailClusters } from '../common';
2+
3+
export interface InstallModule extends DetailBase {
4+
clusters: DetailClusters;
5+
bk_cloud_id: number;
6+
infos: {
7+
cluster_id: number;
8+
db_version: string;
9+
load_modules: string[];
10+
}[];
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!--
2+
* TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
3+
*
4+
* Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
5+
*
6+
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License athttps://opensource.org/licenses/MIT
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
10+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for
11+
* the specific language governing permissions and limitations under the License.
12+
-->
13+
14+
<template>
15+
<Component :is="components[page]" />
16+
</template>
17+
<script setup lang="ts">
18+
import { useRoute } from 'vue-router';
19+
20+
import Page2 from '@views/db-manage/common/create-ticket-success/Index.vue';
21+
22+
import Page1 from './create/Index.vue';
23+
24+
const route = useRoute();
25+
26+
const components = {
27+
create: Page1,
28+
success: Page2,
29+
};
30+
31+
const page = computed(() => (route.params.page as keyof typeof components) || 'create');
32+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
<!--
2+
* TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
3+
*
4+
* Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
5+
*
6+
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License athttps://opensource.org/licenses/MIT
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
10+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for
11+
* the specific language governing permissions and limitations under the License.
12+
-->
13+
14+
<template>
15+
<SmartAction>
16+
<div class="install-module">
17+
<BkAlert
18+
closable
19+
theme="info"
20+
:title="t('为集群安装扩展 Module,仅 RedisCluster、Redis 主从 支持安装 Module。')" />
21+
<DbForm
22+
ref="form"
23+
class="toolbox-form mt-16"
24+
form-type="vertical"
25+
:model="formData">
26+
<EditableTable
27+
ref="editableTable"
28+
class="mt16 mb16"
29+
:model="formData.tableData"
30+
:rules="rules">
31+
<EditableRow
32+
v-for="(item, index) in formData.tableData"
33+
:key="index">
34+
<ClusterColumn
35+
v-model="item.cluster"
36+
:cluster-types="[ClusterTypes.REDIS]"
37+
field="cluster.master_domain"
38+
:label="t('目标集群')"
39+
:selected="selected"
40+
:tab-list-config="tabListConfig"
41+
@batch-edit="handleClusterBatchEdit" />
42+
<EditableColumn
43+
:label="t('架构版本')"
44+
:width="200">
45+
<EditableBlock :placeholder="t('选择集群后自动生成')">
46+
{{ item.cluster.cluster_type_name }}
47+
</EditableBlock>
48+
</EditableColumn>
49+
<EditableColumn
50+
:label="t('版本')"
51+
:width="200">
52+
<EditableBlock :placeholder="t('选择集群后自动生成')">
53+
{{ item.cluster.major_version }}
54+
</EditableBlock>
55+
</EditableColumn>
56+
<ModuleSelectColumn
57+
v-model="item.load_modules"
58+
:params="{
59+
clusterId: item.cluster.id,
60+
version: item.cluster.major_version,
61+
}">
62+
</ModuleSelectColumn>
63+
<OperationColumn
64+
:create-row-method="createRowData"
65+
:table-data="formData.tableData" />
66+
</EditableRow>
67+
</EditableTable>
68+
<TicketPayload v-model="formData" />
69+
</DbForm>
70+
</div>
71+
<template #action>
72+
<BkButton
73+
class="w-88"
74+
:loading="isSubmitting"
75+
theme="primary"
76+
@click="handleSubmit">
77+
{{ t('提交') }}
78+
</BkButton>
79+
<DbPopconfirm
80+
:confirm-handler="handleReset"
81+
:content="t('重置将会清空当前填写的所有内容_请谨慎操作')"
82+
:title="t('确认重置页面')">
83+
<BkButton
84+
class="ml-8 w-88"
85+
:disabled="isSubmitting">
86+
{{ t('重置') }}
87+
</BkButton>
88+
</DbPopconfirm>
89+
</template>
90+
</SmartAction>
91+
</template>
92+
93+
<script setup lang="ts">
94+
import type { ComponentProps } from 'vue-component-type-helpers';
95+
import { useI18n } from 'vue-i18n';
96+
97+
import RedisModel from '@services/model/redis/redis';
98+
import { RepairAndVerifyFrequencyModes, RepairAndVerifyModes } from '@services/model/redis/redis-dst-history-job';
99+
import { type Redis } from '@services/model/ticket/ticket';
100+
import { getRedisList } from '@services/source/redis';
101+
102+
import { useCreateTicket, useTicketDetail } from '@hooks';
103+
104+
import { ClusterTypes, TicketTypes } from '@common/const';
105+
106+
import { type TabItem } from '@components/cluster-selector/Index.vue';
107+
108+
import TicketPayload, {
109+
createTickePayload,
110+
} from '@views/db-manage/common/toolbox-field/form-item/ticket-payload/Index.vue';
111+
import ClusterColumn from '@views/db-manage/redis/common/toolbox-field/cluster-column/Index.vue';
112+
113+
import { messageError } from '@utils';
114+
115+
import ModuleSelectColumn from './components/ModuleSelectColumn.vue';
116+
117+
interface IDataRow {
118+
cluster: {
119+
id: number;
120+
master_domain: string;
121+
bk_cloud_id: number;
122+
cluster_type: string;
123+
cluster_type_name: string;
124+
major_version: string;
125+
};
126+
load_modules: string[];
127+
}
128+
129+
const createRowData = (values = {} as Partial<IDataRow>) => ({
130+
cluster: Object.assign(
131+
{
132+
id: 0,
133+
master_domain: '',
134+
bk_cloud_id: 0,
135+
cluster_type: '',
136+
cluster_type_name: '',
137+
major_version: '',
138+
},
139+
values.cluster,
140+
),
141+
load_modules: values?.load_modules || [],
142+
});
143+
144+
const createDefaultFormData = () => ({
145+
tableData: [createRowData()],
146+
data_check_repair_setting_type: RepairAndVerifyModes.DATA_CHECK_AND_REPAIR,
147+
data_check_repair_setting_execution_frequency: RepairAndVerifyFrequencyModes.ONCE_AFTER_REPLICATION,
148+
...createTickePayload(),
149+
});
150+
151+
const { t } = useI18n();
152+
153+
// 单据克隆
154+
useTicketDetail<Redis.InstallModule>(TicketTypes.REDIS_CLUSTER_LOAD_MODULES, {
155+
onSuccess(ticketDetail) {
156+
const { details, remark } = ticketDetail;
157+
const { infos, clusters } = details;
158+
Object.assign(formData, {
159+
tableData: infos.map((infoItem) =>
160+
createRowData({
161+
cluster: {
162+
master_domain: clusters[infoItem.cluster_id].immute_domain,
163+
} as IDataRow['cluster'],
164+
load_modules: infoItem.load_modules,
165+
}),
166+
),
167+
remark,
168+
});
169+
},
170+
});
171+
172+
const { run: createTicketRun, loading: isSubmitting } = useCreateTicket<{
173+
bk_cloud_id: number;
174+
infos: {
175+
cluster_id: number;
176+
db_version: string;
177+
load_modules: string[];
178+
}[];
179+
}>(TicketTypes.REDIS_CLUSTER_LOAD_MODULES);
180+
181+
const editableTableRef = useTemplateRef('editableTable');
182+
183+
const formData = reactive(createDefaultFormData());
184+
185+
const rules = {
186+
'cluster.master_domain': [
187+
{
188+
validator: (value: string) => {
189+
if (value) {
190+
const nonEmptyIdList = formData.tableData.filter((row) => row.cluster.master_domain === value);
191+
return nonEmptyIdList.length === 1;
192+
}
193+
return true;
194+
},
195+
trigger: 'change',
196+
message: t('目标集群重复'),
197+
},
198+
],
199+
};
200+
201+
const tabListConfig = {
202+
[ClusterTypes.REDIS]: {
203+
getResourceList: (params: ServiceParameters<typeof getRedisList>) =>
204+
getRedisList({
205+
cluster_type: [ClusterTypes.PREDIXY_REDIS_CLUSTER, ClusterTypes.REDIS_INSTANCE].join(','),
206+
...params,
207+
}),
208+
},
209+
} as unknown as Record<string, TabItem>;
210+
211+
const selected = computed(() => {
212+
const selectedClusters: ComponentProps<typeof ClusterColumn>['selected'] = {
213+
[ClusterTypes.REDIS]: [],
214+
};
215+
formData.tableData.forEach((tableRow) => {
216+
const { id, master_domain: masterDomain } = tableRow.cluster;
217+
if (id && masterDomain) {
218+
selectedClusters[ClusterTypes.REDIS].push({
219+
id,
220+
master_domain: masterDomain,
221+
});
222+
}
223+
});
224+
return selectedClusters;
225+
});
226+
227+
const clusterMemo = computed(() =>
228+
Object.fromEntries(
229+
Object.values(selected.value).flatMap((clusters) =>
230+
clusters.filter((cluster) => cluster.master_domain).map((cluster) => [cluster.master_domain, true]),
231+
),
232+
),
233+
);
234+
235+
const handleClusterBatchEdit = (clusterList: RedisModel[]) => {
236+
const newList: IDataRow[] = [];
237+
clusterList.forEach((item) => {
238+
if (!clusterMemo.value[item.master_domain]) {
239+
const domain = item.master_domain;
240+
if (!clusterMemo.value[domain]) {
241+
newList.push(
242+
createRowData({
243+
cluster: {
244+
id: item.id,
245+
master_domain: item.master_domain,
246+
bk_cloud_id: item.bk_cloud_id,
247+
cluster_type: item.cluster_type,
248+
cluster_type_name: item.cluster_type_name,
249+
major_version: item.major_version,
250+
},
251+
}),
252+
);
253+
}
254+
}
255+
});
256+
formData.tableData = [...(formData.tableData[0].cluster.id ? formData.tableData : []), ...newList];
257+
window.changeConfirm = true;
258+
};
259+
260+
const handleSubmit = async () => {
261+
const validateResult = await editableTableRef.value!.validate();
262+
if (validateResult) {
263+
const isSameCloud = formData.tableData.every(
264+
(item) => item.cluster.bk_cloud_id === formData.tableData[0].cluster.bk_cloud_id,
265+
);
266+
if (!isSameCloud) {
267+
messageError(t('仅允许同一管控区域的集群一起安装module'));
268+
return;
269+
}
270+
createTicketRun({
271+
details: {
272+
bk_cloud_id: formData.tableData[0].cluster.bk_cloud_id,
273+
infos: formData.tableData.map((tableItem) => ({
274+
cluster_id: tableItem.cluster.id,
275+
db_version: tableItem.cluster.major_version,
276+
load_modules: tableItem.load_modules,
277+
})),
278+
},
279+
remark: formData.remark,
280+
});
281+
}
282+
};
283+
284+
// 重置
285+
const handleReset = () => {
286+
Object.assign(formData, createDefaultFormData());
287+
window.changeConfirm = false;
288+
};
289+
</script>
290+
291+
<style lang="less" scoped>
292+
.install-module {
293+
padding-bottom: 20px;
294+
}
295+
</style>

0 commit comments

Comments
 (0)