Skip to content

Commit

Permalink
feat(frontend): 工具箱重构_库表备份、全库备份 #8076
Browse files Browse the repository at this point in the history
# Reviewed, transaction id: 29118
  • Loading branch information
JustaCattt committed Jan 13, 2025
1 parent 55aa24b commit cf8fff8
Show file tree
Hide file tree
Showing 17 changed files with 1,350 additions and 60 deletions.
4 changes: 1 addition & 3 deletions dbm-ui/frontend/src/locales/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -4022,10 +4022,8 @@
"从资源池选择": "从资源池选择",
"还差n台_请先勾选足够的IP": "还差 {n} 台,请先勾选足够的 IP",
"已选够n台": "已选够 {n} 台",
"从资源池选择": "从资源池选择",
"还差n台_请先勾选足够的IP": "还差 {n} 台,请先勾选足够的 IP",
"已选够n台": "已选够 {n} 台",
"原DB名": "原 DB 名",
"DB已存在": "DB 已存在",
"DB不存在": "DB 不存在",
"这行勿动!新增翻译请在上一行添加!": ""
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,28 +83,45 @@
trigger: 'change',
},
{
validator: async (value: string) => {
if (!_.some(value, (item) => !/[*%]/.test(item))) {
validator: (value: string) => {
if (!props.checkExist) {
return true;
}
const data = await checkClusterDatabase({
const clearDbList = _.filter(value, (item) => !/[*%]/.test(item));
if (clearDbList.length < 1) {
return true;
}
return checkClusterDatabase({
infos: [
{
cluster_id: props.clusterId,
db_names: [value],
},
],
});
const isExist = Boolean(data[0]?.check_info[value]);
if (isExist && props.checkExist) {
return t('DB已存在');
}).then((data) => (data.length > 0 ? data[0].check_info[value] : false));
},
message: t('DB不存在'),
trigger: 'blur',
},
{
validator: (value: string) => {
if (!props.checkNotExist) {
return true;
}
if (!isExist && props.checkNotExist) {
return t('DB不存在');
const clearDbList = _.filter(value, (item) => !/[*%]/.test(item));
if (clearDbList.length < 1) {
return true;
}
return true;
return checkClusterDatabase({
infos: [
{
cluster_id: props.clusterId,
db_names: [value],
},
],
}).then((data) => (data.length > 0 ? !data[0].check_info[value] : true));
},
message: '',
message: t('DB已存在'),
trigger: 'blur',
},
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
<!--
* 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>
<Column
:append-rules="rules"
:field="field"
:label="label"
:min-width="minWidth"
:required="required">
<template #headAppend>
<BatchEditColumn
v-model="showBatchEdit"
:title="label"
type="taginput"
@change="handleBatchEditChange">
<span
v-bk-tooltips="t('统一设置:将该列统一设置为相同的值')"
class="batch-edit-btn"
@click="handleBatchEditShow">
<DbIcon type="bulk-edit" />
</span>
</BatchEditColumn>
</template>
<div
ref="rootRef"
style="flex: 1"
@click="handleShowTips">
<TagInput
v-model="modelValue"
allow-auto-match
allow-create
has-delete-icon
:placeholder="t('请输入DB 名称,支持通配符“%”,含通配符的仅支持单个')" />
</div>
</Column>
<div style="display: none">
<div
ref="popRef"
style="font-size: 12px; line-height: 24px; color: #63656e">
<div class="db-table-tag-tip">
<div style="font-weight: 700">{{ t('库表输入说明') }}:</div>
<div>
<div class="circle-dot"></div>
<span>{{ t('不允许输入系统库和特殊库,如mysql、sys 等') }}</span>
</div>
<div>
<div class="circle-dot"></div>
<span>{{ t('DB名、表名不允许为空,忽略DB名、忽略表名不允许为 *') }}</span>
</div>
<div>
<div class="circle-dot"></div>
<span>{{ t('支持 %(指代任意长度字符串), ?(指代单个字符串), *(指代全部)三个通配符') }}</span>
</div>
<div>
<div class="circle-dot"></div>
<span>{{ t('单元格可同时输入多个对象,使用换行,空格或;,|分隔,按 Enter 或失焦完成内容输入') }}</span>
</div>
<div>
<div class="circle-dot"></div>
<span>{{ t('% ? 不能独立使用, * 只能单独使用') }}</span>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import _ from 'lodash';
import tippy, { type Instance, type SingleTarget } from 'tippy.js';
import { useI18n } from 'vue-i18n';

import { checkClusterDatabase } from '@services/source/dbbase';

import { Column, TagInput } from '@components/editable-table/Index.vue';

import BatchEditColumn from '@views/db-manage/common/batch-edit-column/Index.vue';

interface Props {
field: string;
label: string;
clusterId: number;
minWidth?: number;
required?: boolean;
checkExist?: boolean;
checkNotExist?: boolean;
allowAsterisk?: boolean;
rules?: {
validator: (value: string[]) => boolean;
message: string;
trigger: string;
}[];
}

const props = withDefaults(defineProps<Props>(), {
minWidth: 200,
required: false,
checkExist: false,
checkNotExist: false,
allowAsterisk: false,
rules: () => [],
});

const modelValue = defineModel<string[]>({
required: true,
});

const { t } = useI18n();

let tippyIns: Instance | undefined;

const rootRef = ref();
const popRef = ref();
const showBatchEdit = ref(false);

const rules = computed(() => {
if (props.rules && props.rules.length > 0) {
return props.rules;
}

const systemDbNames = ['mysql', 'db_infobase', 'information_schema', 'performance_schema', 'sys', 'infodba_schema'];

return [
{
validator: (value: string[]) => _.every(value, (item) => /^(?!stage_truncate)(?!.*dba_rollback$).*/.test(item)),
message: t('不能以stage_truncate开头或dba_rollback结尾'),
trigger: 'change',
},
{
validator: (value: string[]) => _.every(value, (item) => /^[-_a-zA-Z0-9*?%]{0,35}$/.test(item)),
message: t('库表名支持数字、字母、中划线、下划线,最大35字符'),
trigger: 'change',
},
{
validator: (value: string[]) => _.every(value, (item) => !systemDbNames.includes(item)),
message: t('不允许输入系统库和特殊库'),
trigger: 'change',
},
{
validator: (value: string[]) => {
if (props.allowAsterisk) {
return true;
}

return _.every(value, (item) => item !== '*');
},
message: t('不允许为 *'),
trigger: 'change',
},
{
validator: (value: string[]) => {
if (!props.checkExist) {
return true;
}
if (!props.clusterId) {
return false;
}
// % 通配符不需要校验存在
if (/%$/.test(value[0]) || value[0] === '*') {
return true;
}
const clearDbList = _.filter(value, (item) => !/[*%]/.test(item));
if (clearDbList.length < 1) {
return true;
}
return checkClusterDatabase({
bk_biz_id: window.PROJECT_CONFIG.BIZ_ID,
cluster_id: props.clusterId,
db_list: value,
}).then((data) => {
const existDbList = Object.keys(data).reduce<string[]>((result, dbName) => {
if (data[dbName]) {
result.push(dbName);
}
return result;
}, []);
if (existDbList.length > 0) {
return t('n 已存在', { n: existDbList.join('、') });
}

return true;
});
},
message: t('DB 已存在'),
trigger: 'change',
},
{
validator: (value: string[]) => {
if (!props.checkNotExist) {
return true;
}
if (!props.clusterId) {
return false;
}
const clearDbList = _.filter(value, (item) => !/[*%]/.test(item));
if (clearDbList.length < 1) {
return true;
}
return checkClusterDatabase({
bk_biz_id: window.PROJECT_CONFIG.BIZ_ID,
cluster_id: props.clusterId,
db_list: value,
}).then((data) => {
const notExistDbList = Object.keys(data).reduce<string[]>((result, dbName) => {
if (!data[dbName]) {
result.push(dbName);
}
return result;
}, []);
if (notExistDbList.length > 0) {
return t('n 不存在', { n: notExistDbList.join('、') });
}

return true;
});
},
message: t('DB 不存在'),
trigger: 'change',
},
];
});

const handleBatchEditShow = () => {
showBatchEdit.value = true;
};

const handleBatchEditChange = (value: string[]) => {
modelValue.value = value;
};

const handleShowTips = () => {
tippyIns?.show();
};

onMounted(() => {
nextTick(() => {
if (rootRef.value) {
tippyIns = tippy(rootRef.value as SingleTarget, {
content: popRef.value,
placement: 'top',
appendTo: () => document.body,
theme: 'light',
maxWidth: 'none',
trigger: 'manual',
interactive: true,
arrow: true,
offset: [0, 18],
zIndex: 9998,
hideOnClick: true,
});
}
});
});

onBeforeUnmount(() => {
if (tippyIns) {
tippyIns.hide();
tippyIns.unmount();
tippyIns.destroy();
tippyIns = undefined;
}
});
</script>
<style lang="less" scoped>
.batch-edit-btn {
font-size: 14px;
color: #3a84ff;
cursor: pointer;
}

.db-table-tag-tip {
display: flex;
padding: 3px 7px;
line-height: 24px;
flex-direction: column;

div {
display: flex;
align-items: center;

.circle-dot {
display: inline-block;
width: 4px;
height: 4px;
margin-right: 6px;
background-color: #63656e;
border-radius: 50%;
}
}
}
</style>
Loading

0 comments on commit cf8fff8

Please sign in to comment.