You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
373 lines
10 KiB
373 lines
10 KiB
<!--
|
|
@ 作者: 秦东
|
|
@ 时间: 2023-11-13 10:44:48
|
|
@ 备注: Redis数据迁移
|
|
-->
|
|
<script lang='ts' setup>
|
|
import { Eleme } from '@element-plus/icons-vue'
|
|
import { redisConfing,redisKeysNumber } from '@/api/system/redis/types'
|
|
import { testRedisLink,moveOldRedisToNewRedis } from '@/api/system/redis/api'
|
|
const svg = `
|
|
<path class="path" d="
|
|
M 30 15
|
|
L 28 17
|
|
M 25.61 25.61
|
|
A 15 15, 0, 0, 1, 15 30
|
|
A 15 15, 0, 1, 1, 27.99 7.5
|
|
L 15 15
|
|
" style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
|
|
`
|
|
const originConfig = reactive<redisConfing>({
|
|
ip:"127.0.0.1",
|
|
port:6379,
|
|
pwd:"",
|
|
state:0
|
|
})
|
|
const targetConfig = reactive<redisConfing>({
|
|
ip:"127.0.0.1",
|
|
port:6379,
|
|
pwd:"",
|
|
state:0
|
|
})
|
|
const originTestLoad = ref(false); //测试源
|
|
const originTextType = ref<string>("info")
|
|
const originDbNumber = ref<number>(0)
|
|
const originCheckList = ref<number[]>([])
|
|
const originKeyList = reactive<redisKeysNumber[]>([])
|
|
//进行源Redis连接测试
|
|
const originTestLink = () =>{
|
|
originTestLoad.value=true
|
|
originConfig.port = originConfig.port*1
|
|
originConfig.state = originConfig.state*1
|
|
testRedisLink(originConfig)
|
|
.then((data:any)=>{
|
|
if(data.data.isTrue){
|
|
if(data.data.isTrue == 1){
|
|
originConfig.state = 1
|
|
originTextType.value = "success"
|
|
}else{
|
|
originConfig.state = 2
|
|
originTextType.value = "danger"
|
|
}
|
|
}else{
|
|
originConfig.state = 2
|
|
}
|
|
if(data.data.dbNumber){
|
|
originDbNumber.value = data.data.dbNumber
|
|
}
|
|
originKeyList.splice(0,originKeyList.length);
|
|
if(data.data.redisList && data.data.redisList.length > 0){
|
|
data.data.redisList.forEach((item:any)=>{
|
|
originKeyList.push({
|
|
dbName: item.dbName,
|
|
dbNumber: item.dbNumber
|
|
})
|
|
})
|
|
}
|
|
// console.log("进行源Redis连接测试",originConfig,originKeyList)
|
|
})
|
|
.finally(()=>{
|
|
originTestLoad.value=false
|
|
})
|
|
}
|
|
const targetTestLoad = ref(false); //测试目标
|
|
const targetTextType = ref<string>("info")
|
|
const targetDbNumber = ref<number>(1)
|
|
const targetKeyList = reactive<redisKeysNumber[]>([])
|
|
//进行目标Redis连接测试
|
|
const targetTestLink = () =>{
|
|
targetTestLoad.value=true
|
|
targetConfig.port = targetConfig.port*1
|
|
targetConfig.state = targetConfig.state*1
|
|
testRedisLink(targetConfig)
|
|
.then((data:any)=>{
|
|
if(data.data.isTrue){
|
|
if(data.data.isTrue == 1){
|
|
targetConfig.state = 1
|
|
targetTextType.value = "success"
|
|
}else{
|
|
targetConfig.state = 2
|
|
targetTextType.value = "danger"
|
|
}
|
|
}else{
|
|
targetConfig.state = 2
|
|
}
|
|
// targetDbNumber.value = new Array
|
|
if(data.data.dbNumber){
|
|
targetDbNumber.value = data.data.dbNumber
|
|
}
|
|
targetKeyList.splice(0,targetKeyList.length);
|
|
if(data.data.redisList && data.data.redisList.length > 0){
|
|
data.data.redisList.forEach((item:any)=>{
|
|
targetKeyList.push({
|
|
dbName: item.dbName,
|
|
dbNumber: item.dbNumber
|
|
})
|
|
})
|
|
}
|
|
|
|
})
|
|
.finally(()=>{
|
|
targetTestLoad.value=false
|
|
})
|
|
}
|
|
//迁移
|
|
const migrateLoad = ref(false)
|
|
const logList = ref<any[]>([])
|
|
const migrateRedisInfo = () =>{
|
|
migrateLoad.value = true
|
|
if(originConfig.state != 1){
|
|
migrateLoad.value = false;
|
|
ElMessageBox({
|
|
title: '温馨提示!',
|
|
// message: "您未进行源Redis连通性测试!为确保迁移正常进行,请先测试一下是否可以连通!",
|
|
message:h('p', null, [
|
|
h('span', null, '您未进行'),
|
|
h('span', { style: 'color: #ff0000' }, '源Redis连通性测试!'),
|
|
h('span', null, '为确保迁移正常进行,请先测试一下'),
|
|
h('span', { style: 'color: #ff0000' }, '是否可以连通!'),
|
|
])
|
|
})
|
|
return
|
|
}
|
|
if(targetConfig.state != 1){
|
|
migrateLoad.value = false;
|
|
ElMessageBox({
|
|
title: '温馨提示!',
|
|
// message: "您未进行目标Redis连通性测试!为确保迁移正常进行,请先测试一下是否可以连通!",
|
|
message:h('p', null, [
|
|
h('span', null, '您未进行'),
|
|
h('span', { style: 'color: #ff0000' }, '目标Redis连通性测试!'),
|
|
h('span', null, '为确保迁移正常进行,请先测试一下'),
|
|
h('span', { style: 'color: #ff0000' }, '是否可以连通!'),
|
|
])
|
|
})
|
|
return
|
|
}
|
|
if(targetConfig.ip == originConfig.ip && targetConfig.port == originConfig.port){
|
|
migrateLoad.value = false;
|
|
ElMessageBox({
|
|
title: '温馨提示!',
|
|
// message: "您未进行目标Redis连通性测试!为确保迁移正常进行,请先测试一下是否可以连通!",
|
|
message:h('p', null, [
|
|
h('span', { style: 'color: #ff0000' }, '源Redis与目标Redis相同!'),
|
|
h('span', null, '不能进行迁移!'),
|
|
])
|
|
})
|
|
return
|
|
}
|
|
let sendInfo = {
|
|
originRedis:originConfig, //源
|
|
targetRedis:targetConfig, //目标
|
|
dblist:originCheckList.value //选择库
|
|
}
|
|
moveOldRedisToNewRedis(sendInfo)
|
|
.then((data)=>{
|
|
console.log("进行源Redis连接测试",data)
|
|
logList.value = data.data
|
|
})
|
|
.finally(()=>{
|
|
migrateLoad.value = false;
|
|
})
|
|
|
|
|
|
}
|
|
</script>
|
|
<template>
|
|
<div class="app-main body_cont">
|
|
<table border="1" class="table_body">
|
|
<tr>
|
|
<td rowspan="4" width="10%" align="center">源Redsi</td>
|
|
<td width="35%">
|
|
<table border="0">
|
|
<tr>
|
|
<td width="60">IP地址</td>
|
|
<td><el-input v-model="originConfig.ip" clearable placeholder="请输入Redis源IP"></el-input></td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
<td rowspan="4" colspan="2" width="10%" align="center">
|
|
<el-button :loading-icon="Eleme" :loading="migrateLoad" type="primary" style="width:100%" @click="migrateRedisInfo">迁移</el-button>
|
|
</td>
|
|
|
|
<td width="35%">
|
|
<table border="0">
|
|
<tr>
|
|
<td width="60">IP地址</td>
|
|
<td><el-input v-model="targetConfig.ip" clearable placeholder="请输入Redis源IP"></el-input></td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
<td rowspan="4" width="10%" align="center">目标Redis</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<table border="0">
|
|
<tr>
|
|
<td width="60">端口</td>
|
|
<td><el-input v-model="originConfig.port" type="number" clearable placeholder="请输入Redis源IP"></el-input></td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
|
|
|
|
<td>
|
|
<table border="0">
|
|
<tr>
|
|
<td width="60">端口</td>
|
|
<td><el-input v-model="targetConfig.port" type="number" clearable placeholder="请输入Redis源IP"></el-input></td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<table border="0">
|
|
<tr>
|
|
<td width="60">密码</td>
|
|
<td><el-input v-model="originConfig.pwd" type="password" show-password clearable placeholder="请输入Redis源IP"></el-input></td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
|
|
|
|
<td>
|
|
<table border="0">
|
|
<tr>
|
|
<td width="60">密码</td>
|
|
<td><el-input v-model="targetConfig.pwd" type="password" show-password clearable placeholder="请输入Redis源IP"></el-input></td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<table border="0">
|
|
<tr>
|
|
<td width="50">
|
|
<el-button :loading-icon="Eleme" :loading="originTestLoad" type="primary" @click="originTestLink">测试链接</el-button>
|
|
</td>
|
|
<td align="right">
|
|
<el-text class="mx-1" :type="originTextType">
|
|
<i v-if="originConfig.state == 1" class="fa fa-check"></i>
|
|
<i v-else-if="originConfig.state == 2" class="fa fa-close"></i>
|
|
<span v-else>未测试</span>
|
|
</el-text>
|
|
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
<td>
|
|
<table border="0">
|
|
<tr>
|
|
<td align="left">
|
|
<el-text class="mx-1" :type="targetTextType">
|
|
<i v-if="targetConfig.state == 1" class="fa fa-check"></i>
|
|
<i v-else-if="targetConfig.state == 2" class="fa fa-close"></i>
|
|
<span v-else>未测试</span>
|
|
</el-text>
|
|
</td>
|
|
<td width="50">
|
|
<el-button :loading-icon="Eleme" :loading="targetTestLoad" type="primary" @click="targetTestLink">测试链接</el-button>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td valign="top" align="center">数据库列表</td>
|
|
<td valign="top" colspan="2" class="min_td_height" width="40%" style="table-layout:fixed">
|
|
|
|
<el-checkbox-group v-model="originCheckList">
|
|
<el-row :gutter="10">
|
|
<el-col v-for="(item,index) in originKeyList" :key="index" :span="6" class="row_col_body">
|
|
<el-checkbox :label="item.dbName" border size="small">DB{{item.dbName}}(Keys:{{item.dbNumber}})</el-checkbox>
|
|
</el-col>
|
|
</el-row>
|
|
</el-checkbox-group>
|
|
|
|
</td>
|
|
<td valign="top" colspan="2" class="min_td_height" width="40%" style="table-layout:fixed">
|
|
|
|
<el-row :gutter="10">
|
|
<el-col v-for="(item,index) in targetKeyList" :key="index" :span="6" class="row_col_body">
|
|
<el-button size="small">DB{{item.dbName}}(Keys:{{item.dbNumber}})</el-button>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
</td>
|
|
<td valign="top" align="center">数据库列表</td>
|
|
</tr>
|
|
<tr>
|
|
<td valign="top" align="center">处理结果</td>
|
|
<td colspan="5" valign="top">
|
|
<div
|
|
v-loading="migrateLoad"
|
|
element-loading-text="Loading..."
|
|
:element-loading-spinner="svg"
|
|
element-loading-svg-view-box="-10, -10, 50, 50"
|
|
element-loading-background="rgba(122, 122, 122, 0.8)"
|
|
class="chuli_jieguo"
|
|
>
|
|
<div v-for="(item,index) in logList" :key="index" class="text_width">
|
|
<el-text type="warning" >开始迁移Rdis:{{ item.dbName }}库</el-text>
|
|
<el-text v-for="(logCont,lgindex) in item.msgList" :key="lgindex" :type="logCont.state==1?'success':'warning'" >{{ logCont.keys }}:{{ logCont.msg }}</el-text>
|
|
<el-text type="primary" >Rdis:{{ item.dbName }}库迁移完成</el-text>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</template>
|
|
<style lang='scss' scoped>
|
|
.body_cont{
|
|
padding:20px;
|
|
}
|
|
.table_body{
|
|
background-color: #FFFFFF;
|
|
width:100%;
|
|
border-collapse: collapse;
|
|
/*
|
|
* 设置边框
|
|
*/
|
|
td,th {
|
|
border: 1px solid black;
|
|
padding: 5px;
|
|
table{
|
|
width:100%;
|
|
td,th{
|
|
border: 0px solid black;
|
|
padding: 0px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.left_border{
|
|
border-left: 1px solid black;
|
|
}
|
|
.min_td_height{
|
|
height:150px;
|
|
}
|
|
.chuli_jieguo{
|
|
height: calc(100vh - 480px);
|
|
overflow: hidden;
|
|
overflow-y: auto;
|
|
}
|
|
.checkbox_group{
|
|
max-width:300px;
|
|
}
|
|
.row_col_body{
|
|
margin-top:10px;
|
|
}
|
|
.text_width{
|
|
border-bottom: 1px solid #EEEEEE;
|
|
padding:5px 0;
|
|
span {
|
|
display: block;
|
|
width: 100%;
|
|
margin-top: 5px;
|
|
}
|
|
}
|
|
</style>
|
|
|