Skip to content

Commit

Permalink
perf(frontend): redis工具箱重构_版本升级 TencentBlueKing#8840
Browse files Browse the repository at this point in the history
  • Loading branch information
3octaves committed Dec 31, 2024
1 parent 0e17e28 commit 04569dd
Show file tree
Hide file tree
Showing 10 changed files with 1,074 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!--
* TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
*
* Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License athttps://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for
* the specific language governing permissions and limitations under the License.
-->

<template>
<Component :is="component" />
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router';

import Page1 from './pages/page1/Index.vue';
import Page2 from './pages/page2/Index.vue';

const route = useRoute();

const comMap = {
ticket: Page1,
success: Page2,
};

const page = ref('');

const component = computed(() => {
if (comMap[page.value as keyof typeof comMap]) {
return comMap[page.value as keyof typeof comMap];
}
return Page1;
});

watch(
route,
() => {
page.value = route.params.page as string;
},
{
immediate: true,
},
);
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,339 @@
<!--
* TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available.
*
* Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License athttps://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for
* the specific language governing permissions and limitations under the License.
-->

<template>
<SmartAction>
<div class="version-upgrade-page">
<BkAlert
closable
theme="info"
:title="t('版本升级:将集群的接入层或存储层,更新到指定版本')" />
<DbForm
ref="form"
class="toolbox-form"
form-type="vertical"
:model="formData"
style="margin-top: 16px">
<EditableTable
ref="editableTable"
class="mt16 mb16"
:model="tableData"
:rules="rules">
<EditableTableRow
v-for="(item, index) in tableData"
:key="index">
<EditClusterWithRelatedClustersColumn
v-model="item.cluster"
:selected="selected"
@batch-edit="handleClusterBatchEdit" />
<EditableTableColumn
:label="t('架构版本')"
:max-width="200"
:min-width="200">
<EditBlock :placeholder="t('输入主机后自动生成')">
{{ item.cluster.cluster_type_name }}
</EditBlock>
</EditableTableColumn>
<NodeTypeColumn
v-model="item.node_type"
:cluster-type="item.cluster.cluster_type"
:disabled="!item.cluster.id"
@batch-edit="(value: string) => handleColumnBatchEdit(value, 'node_type')" />
<CurrentVersionColumn
v-model="item.current_versions"
:cluster-id="item.cluster.id"
:node-type="item.node_type" />
<TargetVersionColumn
v-model="item.target_version"
:cluster-id="item.cluster.id"
:current-versions="item.current_versions"
:node-type="item.node_type"
:table-data="tableData"
@batch-edit="(value: string) => handleColumnBatchEdit(value, 'target_version')" />
<OperationColumn
:create-row-method="createRowData"
:table-data="tableData" />
</EditableTableRow>
</EditableTable>
<TicketRemark v-model="formData.remark" />
</DbForm>
</div>
<template #action>
<BkButton
class="w-88"
:loading="isSubmitting"
theme="primary"
@click="handleSubmit">
{{ t('提交') }}
</BkButton>
<DbPopconfirm
:confirm-handler="handleReset"
:content="t('重置将会清空当前填写的所有内容_请谨慎操作')"
:title="t('确认重置页面')">
<BkButton
class="ml-8 w-88"
:disabled="isSubmitting">
{{ t('重置') }}
</BkButton>
</DbPopconfirm>
</template>
</SmartAction>
</template>

<script setup lang="tsx">
import _ from 'lodash';
import { type ComponentProps } from 'vue-component-type-helpers';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';

import RedisModel from '@services/model/redis/redis';
import { type Redis } from '@services/model/ticket/ticket';
import { findRelatedClustersByClusterIds } from '@services/source/redisToolbox';
import { createTicket } from '@services/source/ticket';

import { useTicketDetail } from '@hooks';

import { ClusterTypes, TicketTypes } from '@common/const';

import EditableTable, {
Block as EditBlock,
Column as EditableTableColumn,
Row as EditableTableRow,
} from '@components/editable-table/Index.vue';

import TicketRemark from '@views/db-manage/common/TicketRemark.vue';
import OperationColumn from '@views/db-manage/common/toolbox-field/operation-column/Index.vue';
import EditClusterWithRelatedClustersColumn from '@views/db-manage/redis/common/toolbox-field/edit-cluster-with-related-clusters/Index.vue';

import CurrentVersionColumn from './components/CurrentVersionColumn.vue';
import NodeTypeColumn from './components/NodeTypeColumn.vue';
import TargetVersionColumn from './components/TargetVersionColumn.vue';

interface IDataRow {
cluster: {
id?: number;
master_domain?: string;
cluster_type?: string;
cluster_type_name?: string;
related_clusters?: {
id: number;
domain: string;
}[];
};
node_type?: string;
current_versions?: string[];
target_version?: string;
}

const createRowData = (values?: Partial<IDataRow>) => ({
cluster: values?.cluster ? values.cluster : ({} as IDataRow['cluster']),
node_type: values?.cluster?.cluster_type === ClusterTypes.REDIS_INSTANCE ? 'Backend' : 'Proxy',
current_versions: values?.current_versions,
target_version: values?.target_version,
});

const createDefaultFormData = () => ({
remark: '',
});

const { t } = useI18n();
const router = useRouter();

useTicketDetail<Redis.VersionUpdateOnline>(TicketTypes.REDIS_VERSION_UPDATE_ONLINE, {
onSuccess(ticketDetail) {
const { details, remark } = ticketDetail;
const { infos, clusters } = details;
tableData.value = infos.map((infoItem) => ({
cluster: {
master_domain: clusters[infoItem.cluster_ids[0]].immute_domain,
},
node_type: infoItem.node_type,
current_versions: infoItem.current_versions,
target_version: infoItem.target_version,
}));
Object.assign(formData, {
remark,
});
},
});

const formRef = useTemplateRef('form');
const editableTableRef = useTemplateRef('editableTable');

const rules = {
'cluster.master_domain': [
{
validator: (value: string) => {
if (value) {
const domainList = tableData.value
.flatMap((tableRow) => [
tableRow.cluster.master_domain || '',
...(tableRow.cluster.related_clusters || []).map((relatedItem) => relatedItem.domain),
])
.filter((domainItem) => domainItem);
return domainList.filter((domain) => domain === value).length === 1;
}
return true;
},
trigger: 'change',
message: t('目标集群重复'),
},
],
};

const isSubmitting = ref(false);
const tableData = ref<IDataRow[]>([createRowData()]);
const formData = reactive(createDefaultFormData());

const selected = computed(() => {
const selectedClusters: ComponentProps<typeof EditClusterWithRelatedClustersColumn>['selected'] = {
[ClusterTypes.REDIS]: [],
};
tableData.value.forEach((tableRow) => {
const { id, master_domain: masterDomain } = tableRow.cluster;
if (id && masterDomain) {
selectedClusters[ClusterTypes.REDIS].push({
id,
master_domain: masterDomain,
});
}
});
return selectedClusters;
});

const clusterMemo = computed(() =>
Object.fromEntries(
Object.values(selected.value).flatMap((clusters) =>
clusters.filter((cluster) => cluster.master_domain).map((cluster) => [cluster.master_domain, true]),
),
),
);

const handleClusterBatchEdit = async (clusterList: RedisModel[]) => {
const newList: IDataRow[] = [];
const clusterIdList = clusterList.reduce<number[]>((prevList, listItem) => {
prevList.push(listItem.id);
return prevList;
}, []);
const relatedClusterResult = await findRelatedClustersByClusterIds({
cluster_ids: clusterIdList,
});
const relatedClusterMap = relatedClusterResult.reduce<Record<string, string[]>>(
(prev, item) =>
Object.assign(prev, {
[item.cluster_info.master_domain]: item.related_clusters.map((item) => item.master_domain),
}),
{},
);
const relatedClusterSet = new Set<string>();
clusterList.forEach((item) => {
if (!clusterMemo.value[item.master_domain]) {
const domain = item.master_domain;
if (!clusterMemo.value[domain] && !relatedClusterSet.has(domain)) {
newList.push(
createRowData({
cluster: {
id: item.id,
master_domain: item.master_domain,
cluster_type: item.cluster_type,
cluster_type_name: item.cluster_type_name,
},
}),
);
relatedClusterMap[domain].forEach((mapItem) => relatedClusterSet.add(mapItem));
}
if (clusterMemo.value[domain]) {
relatedClusterMap[domain].forEach((mapItem) => relatedClusterSet.add(mapItem));
}
}
});
tableData.value = [...(_.isEmpty(tableData.value[0].cluster) ? tableData.value : []), ...newList];
window.changeConfirm = true;
};

const handleColumnBatchEdit = (value: string, field: keyof Pick<IDataRow, 'node_type' | 'target_version'>) => {
tableData.value.forEach((item) => {
Object.assign(item, { [field]: value });
});
window.changeConfirm = true;
};

// 点击提交按钮
const handleSubmit = async () => {
isSubmitting.value = true;
try {
isSubmitting.value = true;
await formRef.value!.validate();
const validateResult = await editableTableRef.value!.validate();
if (validateResult) {
const params = {
bk_biz_id: window.PROJECT_CONFIG.BIZ_ID,
remark: formData.remark,
ticket_type: TicketTypes.REDIS_VERSION_UPDATE_ONLINE,
details: {
infos: tableData.value.map((tableItem) => ({
cluster_ids: [
tableItem.cluster.id,
...tableItem.cluster.related_clusters!.map((relatedClusterItem) => relatedClusterItem.id),
],
node_type: tableItem.node_type,
current_versions: tableItem.current_versions,
target_version: tableItem.target_version,
})),
},
};
await createTicket(params).then((data) => {
window.changeConfirm = false;
router.push({
name: TicketTypes.REDIS_VERSION_UPDATE_ONLINE,
params: {
page: 'success',
},
query: {
ticketId: data.id,
},
});
});
}
} finally {
isSubmitting.value = false;
}
};

const handleReset = () => {
Object.assign(formData, createDefaultFormData());
tableData.value = [createRowData()];
window.changeConfirm = false;
};
</script>

<style lang="less" scoped>
.version-upgrade-page {
padding-bottom: 20px;

.page-action-box {
display: flex;
align-items: center;
margin-top: 16px;

.safe-action {
margin-left: auto;

.safe-action-text {
padding-bottom: 2px;
border-bottom: 1px dashed #979ba5;
}
}
}
}
</style>
Loading

0 comments on commit 04569dd

Please sign in to comment.