Commit a37da656 authored by 智勇's avatar 智勇

db 同步

parent ac17fb0f
...@@ -23,3 +23,35 @@ export function deleteConfig(query) { ...@@ -23,3 +23,35 @@ export function deleteConfig(query) {
params: query params: query
}) })
} }
export function getNamespace(query) {
return request({
url: '/dbsync/get_name_space',
method: 'get',
params: query
})
}
export function getDBName(query) {
return request({
url: '/dbsync/get_dbs',
method: 'get',
params: query
})
}
export function dbSync(data) {
return request({
url: '/dbsync/db_sync',
method: 'post',
data
})
}
export function dbSyncQuery(data) {
return request({
url: '/dbsync/db_sync_query',
method: 'post',
data
})
}
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1552358833449" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5768" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 438.857143q135.428571 0 253.142857-24.571429t185.714286-72.571428v97.142857q0 39.428571-58.857143 73.142857t-160 53.428571-220 19.714286-220-19.714286T132 512 73.142857 438.857143V341.714286q68 48 185.714286 72.571428t253.142857 24.571429z m0 438.857143q135.428571 0 253.142857-24.571429t185.714286-72.571428v97.142857q0 39.428571-58.857143 73.142857t-160 53.428571-220 19.714286-220-19.714286-160-53.428571-58.857143-73.142857v-97.142857q68 48 185.714286 72.571428t253.142857 24.571429z m0-219.428572q135.428571 0 253.142857-24.571428t185.714286-72.571429v97.142857q0 39.428571-58.857143 73.142857t-160 53.428572-220 19.714286-220-19.714286-160-53.428572-58.857143-73.142857V561.142857q68 48 185.714286 72.571429t253.142857 24.571428zM512 0q118.857143 0 220 19.714286t160 53.428571 58.857143 73.142857v73.142857q0 39.428571-58.857143 73.142858t-160 53.428571T512 365.714286t-220-19.714286T132 292.571429 73.142857 219.428571V146.285714q0-39.428571 58.857143-73.142857t160-53.428571T512 0z" p-id="5769"></path></svg>
\ No newline at end of file
...@@ -126,6 +126,20 @@ export default new Router({ ...@@ -126,6 +126,20 @@ export default new Router({
}) })
export const asyncRouterMap = [ export const asyncRouterMap = [
{
path: '/dbsync',
component: Layout,
redirect: 'noredirect',
children: [
{
path: '',
component: () => import('@/views/dbconfig/sync/index'),
name: 'DB同步',
meta: { title: '执行DB同步', icon: 'database' }
}
]
},
{ {
path: '/dbconfig', path: '/dbconfig',
component: Layout, component: Layout,
...@@ -152,6 +166,35 @@ export const asyncRouterMap = [ ...@@ -152,6 +166,35 @@ export const asyncRouterMap = [
} }
] ]
}, },
{
path: '/proconfig',
component: Layout,
redirect: 'noredirect',
children: [
{
path: '',
component: () => import('@/views/proconfig/index'),
name: 'proconfig',
meta: { title: '项目配置文件管理', icon: 'documentation' }
}
]
},
{
path: '/testdata',
component: Layout,
redirect: 'noredirect',
children: [
{
path: '',
component: () => import('@/views/testdata/index'),
name: 'testdata',
meta: { title: '数据生成器', icon: 'people' }
}
]
},
{ {
path: '/pipeline', path: '/pipeline',
component: Layout, component: Layout,
...@@ -221,34 +264,6 @@ export const asyncRouterMap = [ ...@@ -221,34 +264,6 @@ export const asyncRouterMap = [
] ]
}, },
{
path: '/proconfig',
component: Layout,
redirect: 'noredirect',
children: [
{
path: '',
component: () => import('@/views/proconfig/index'),
name: 'proconfig',
meta: { title: '配置文件管理', icon: 'documentation' }
}
]
},
{
path: '/testdata',
component: Layout,
redirect: 'noredirect',
children: [
{
path: '',
component: () => import('@/views/testdata/index'),
name: 'testdata',
meta: { title: '数据生成器', icon: 'people' }
}
]
},
/** When your routing table is too long, you can split it into small modules**/ /** When your routing table is too long, you can split it into small modules**/
componentsRouter, componentsRouter,
chartsRouter, chartsRouter,
...@@ -301,162 +316,163 @@ export const asyncRouterMap = [ ...@@ -301,162 +316,163 @@ export const asyncRouterMap = [
] ]
}, },
{ // {
path: '/error', // path: '/error',
component: Layout, // component: Layout,
redirect: 'noredirect', // redirect: 'noredirect',
name: 'ErrorPages', // name: 'ErrorPages',
meta: { // meta: {
title: 'errorPages', // title: 'errorPages',
icon: '404' // icon: '404'
}, // },
children: [ // children: [
{ // {
path: '401', // path: '401',
component: () => import('@/views/errorPage/401'), // component: () => import('@/views/errorPage/401'),
name: 'Page401', // name: 'Page401',
meta: { title: 'page401', noCache: true } // meta: { title: 'page401', noCache: true }
}, // },
{ // {
path: '404', // path: '404',
component: () => import('@/views/errorPage/404'), // component: () => import('@/views/errorPage/404'),
name: 'Page404', // name: 'Page404',
meta: { title: 'page404', noCache: true } // meta: { title: 'page404', noCache: true }
} // }
] // ]
}, // },
{ // {
path: '/error-log', // path: '/error-log',
component: Layout, // component: Layout,
redirect: 'noredirect', // redirect: 'noredirect',
children: [ // children: [
{ // {
path: 'log', // path: 'log',
component: () => import('@/views/errorLog/index'), // component: () => import('@/views/errorLog/index'),
name: 'ErrorLog', // name: 'ErrorLog',
meta: { title: 'errorLog', icon: 'bug' } // meta: { title: 'errorLog', icon: 'bug' }
} // }
] // ]
}, // },
{ // {
path: '/excel', // path: '/excel',
component: Layout, // component: Layout,
redirect: '/excel/export-excel', // redirect: '/excel/export-excel',
name: 'Excel', // name: 'Excel',
meta: { // meta: {
title: 'excel', // title: 'excel',
icon: 'excel' // icon: 'excel'
}, // },
children: [ // children: [
{ // {
path: 'export-excel', // path: 'export-excel',
component: () => import('@/views/excel/exportExcel'), // component: () => import('@/views/excel/exportExcel'),
name: 'ExportExcel', // name: 'ExportExcel',
meta: { title: 'exportExcel' } // meta: { title: 'exportExcel' }
}, // },
{ // {
path: 'export-selected-excel', // path: 'export-selected-excel',
component: () => import('@/views/excel/selectExcel'), // component: () => import('@/views/excel/selectExcel'),
name: 'SelectExcel', // name: 'SelectExcel',
meta: { title: 'selectExcel' } // meta: { title: 'selectExcel' }
}, // },
{ // {
path: 'upload-excel', // path: 'upload-excel',
component: () => import('@/views/excel/uploadExcel'), // component: () => import('@/views/excel/uploadExcel'),
name: 'UploadExcel', // name: 'UploadExcel',
meta: { title: 'uploadExcel' } // meta: { title: 'uploadExcel' }
} // }
] // ]
}, // },
{ // {
path: '/zip', // path: '/zip',
component: Layout, // component: Layout,
redirect: '/zip/download', // redirect: '/zip/download',
alwaysShow: true, // alwaysShow: true,
meta: { title: 'zip', icon: 'zip' }, // meta: { title: 'zip', icon: 'zip' },
children: [ // children: [
{ // {
path: 'download', // path: 'download',
component: () => import('@/views/zip/index'), // component: () => import('@/views/zip/index'),
name: 'ExportZip', // name: 'ExportZip',
meta: { title: 'exportZip' } // meta: { title: 'exportZip' }
} // }
] // ]
}, // },
{ // {
path: '/pdf', // path: '/pdf',
component: Layout, // component: Layout,
redirect: '/pdf/index', // redirect: '/pdf/index',
children: [ // children: [
{ // {
path: 'index', // path: 'index',
component: () => import('@/views/pdf/index'), // component: () => import('@/views/pdf/index'),
name: 'PDF', // name: 'PDF',
meta: { title: 'pdf', icon: 'pdf' } // meta: { title: 'pdf', icon: 'pdf' }
} // }
] // ]
}, // },
{
path: '/pdf/download',
component: () => import('@/views/pdf/download'),
hidden: true
},
{ // {
path: '/theme', // path: '/pdf/download',
component: Layout, // component: () => import('@/views/pdf/download'),
redirect: 'noredirect', // hidden: true
children: [ // },
{
path: 'index',
component: () => import('@/views/theme/index'),
name: 'Theme',
meta: { title: 'theme', icon: 'theme' }
}
]
},
{ // {
path: '/clipboard', // path: '/theme',
component: Layout, // component: Layout,
redirect: 'noredirect', // redirect: 'noredirect',
children: [ // children: [
{ // {
path: 'index', // path: 'index',
component: () => import('@/views/clipboard/index'), // component: () => import('@/views/theme/index'),
name: 'ClipboardDemo', // name: 'Theme',
meta: { title: 'clipboardDemo', icon: 'clipboard' } // meta: { title: 'theme', icon: 'theme' }
} // }
] // ]
}, // },
{ // {
path: '/i18n', // path: '/clipboard',
component: Layout, // component: Layout,
children: [ // redirect: 'noredirect',
{ // children: [
path: 'index', // {
component: () => import('@/views/i18n-demo/index'), // path: 'index',
name: 'I18n', // component: () => import('@/views/clipboard/index'),
meta: { title: 'i18n', icon: 'international' } // name: 'ClipboardDemo',
} // meta: { title: 'clipboardDemo', icon: 'clipboard' }
] // }
}, // ]
// },
{ // {
path: 'external-link', // path: '/i18n',
component: Layout, // component: Layout,
children: [ // children: [
{ // {
path: 'https://github.com/PanJiaChen/vue-element-admin', // path: 'index',
meta: { title: 'externalLink', icon: 'link' } // component: () => import('@/views/i18n-demo/index'),
} // name: 'I18n',
] // meta: { title: 'i18n', icon: 'international' }
}, // }
// ]
// },
// {
// path: 'external-link',
// component: Layout,
// children: [
// {
// path: 'https://github.com/PanJiaChen/vue-element-admin',
// meta: { title: 'externalLink', icon: 'link' }
// }
// ]
// },
{ path: '*', redirect: '/404', hidden: true } { path: '*', redirect: '/404', hidden: true }
] ]
...@@ -161,15 +161,23 @@ export default { ...@@ -161,15 +161,23 @@ export default {
createData() { createData() {
this.$refs['dataForm'].validate((valid) => { this.$refs['dataForm'].validate((valid) => {
if (valid) { if (valid) {
saveConfig(this.temp).then(() => { saveConfig(this.temp).then((res) => {
this.dialogFormVisible = false if (res.data.code !== '0000') {
this.$notify({ this.$notify({
title: '成功', message: `${res.data.msg}`,
message: '保存成功', type: 'error',
type: 'success', duration: 2000
duration: 2000 })
}) } else {
this.getConfig() this.dialogFormVisible = false
this.$notify({
title: '成功',
message: '保存成功',
type: 'success',
duration: 2000
})
this.getConfig()
}
}) })
} }
}) })
......
<template>
<div >
<div class="app-container" style="width:1000px; margin:0 auto;">
<el-form ref="dataForm" :inline="true" :rules="rules" :model="temp" label-width="150px" style="margin-bottom:15px">
<el-form-item label="Namespace" prop="namespace">
<el-select :disabled="disableBool" v-model="temp.namespace" style="width:310px" placeholder="要同步数据库的环境">
<el-option v-for="item in namespaces" :value="item" :label="item" :key="item" />
</el-select>
</el-form-item>
<el-form-item label="数据库名称" prop="dbname">
<el-select :disabled="disableBool" v-model="temp.dbname" placeholder="要同步表结构及配置数据的数据库名称" style="width:310px">
<el-option v-for="item in dbnames" :value="item" :label="item" :key="item" />
</el-select>
</el-form-item>
</el-form>
<el-form :inline="true" :model="temp" label-width="150px">
<el-form-item label="保留业务数据">
<el-switch :disabled="disableBool" v-model="temp.not_delete_business_data" style="margin-right:280px" />
<span 是否保留当前已经存在的测试数据/>
</el-form-item>
<el-form-item label="使用备份数据">
<el-switch :disabled="disableBool" v-model="temp.use_cache"/>
</el-form-item>
</el-form>
<div style="margin-left:420px">
<el-button :disabled="disableBool" type="primary" @click="sync()">{{ $t('table.confirm') }}</el-button>
<el-button :disabled="disableBool" @click="resetTemp()">{{ $t('table.cancel') }}</el-button>
</div >
</div >
<div style="padding:10px 20px 0px">
<!-- <div v-if="desc" style="padding:10px 20px 0px"> -->
<textarea v-if="desc" v-model="desc" style="min-height:600px;background-color:black;width:-webkit-fill-available;color:white"/>
</div>
</div>
</template>
<script>
import { getNamespace, getDBName, dbSync, dbSyncQuery } from '@/api/dbconfig'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
import JsonEditor from '@/components/JsonEditor'
export default {
name: 'DBSync',
components: { Pagination, JsonEditor },
filters: {
},
data() {
return {
dialogFormVisible: false,
dialogDeleteVisible: false,
dialogStatus: '',
rules: {
dbname: [{ required: true, message: '请输入', trigger: 'change' }],
namespace: [{ required: true, message: '请输入', trigger: 'change' }]
},
configs: [],
namespace: undefined,
namespaces: [],
dbname: undefined,
dbnames: [],
temp: {
not_delete_business_data: true,
use_cache: true
},
desc: '',
location: '',
time: undefined,
disableBool: false
}
},
computed: {
},
watch: {
},
created() {
this.getNamespace()
this.getDBName()
},
methods: {
getNamespace() {
getNamespace().then(res => {
this.namespaces = res.data.data.map(item => item.name)
})
},
getDBName() {
getDBName().then(res => {
this.dbnames = res.data.data.map(item => item.dbname)
this.dbnames.unshift('all(no_mall)')
})
},
resetTemp() {
this.temp = {
namespace: '',
dbname: '',
not_delete_business_data: false,
use_cache: false
}
},
syncQuery(location) {
dbSyncQuery({ location }).then(res => {
res = res.data.data
if (this.timer > 300) {
this.$notify({
title: '超时',
message: '同步超时!',
type: 'error',
duration: 2000
})
return true
}
if (res.status === 'complete') {
this.desc = new Date().toLocaleTimeString() + ' 完成同步: ' + res.msg.result + '; ID: ' + res.msg.number + '\n\n\n' + res.log.body
this.disableBool = false
this.$notify({
title: '成功',
message: '完成同步!',
type: 'success',
duration: 2000
})
return true
}
this.timer = this.timer + 3
this.desc = new Date().toLocaleTimeString() + ` 测试环境 ${this.temp.namespace} 正在同步 ${this.temp.dbname} 数据库,已等待 ${this.timer}s...\n\n\n` + res.log.body
setTimeout(() => {
this.syncQuery(location)
}, 3000)
})
},
sync() {
console.log(1, this)
this.$refs['dataForm'].validate((valid) => {
if (valid) {
dbSync(this.temp).then((res) => {
this.dialogFormVisible = false
this.location = res.data.data.location
this.$notify({
message: '正在同步',
type: 'success',
duration: 2000
})
this.desc = ''
this.timer = 0
this.disableBool = true
this.syncQuery(this.location)
})
}
})
}
}
}
</script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment