|
@@ -0,0 +1,247 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <div style="margin: 10px">
|
|
|
+ <el-select v-model="databaseName" @change="changeSearch" filterable allow-create default-first-option clearable>
|
|
|
+ <el-option v-for="(item, index) in databaseOptions" :key="index" :label="item" :value="item" />
|
|
|
+ </el-select>
|
|
|
+ <el-button style="margin-left: 20px" size="mini" type="primary" @click="addLog">新增备份</el-button>
|
|
|
+ <el-button style="margin-left: 20px" size="mini" type="" @click="clickSearch">刷新</el-button>
|
|
|
+ <span style="color: red; font-size: 12px;margin-left: 20px">注意:1、该功能只能在正式环境中使用,其他环境会出现问题;2、存储地址默认是/opt/v70/api/upload,因为映射的关系,在物理机上/mnt/ncs/upload可以找到备份文件;3、因为异步的关系,操作完成需要手动刷新数据。</span>
|
|
|
+ </div>
|
|
|
+ <div class="table-wrapper" style="padding-bottom: 10px;padding-left: 10px">
|
|
|
+ <el-table :data="tableData.data" id="myTableId" stripe border style="width: 100%" ref="refTable" height="520">
|
|
|
+<!-- <el-table-column type="selection" width="55"></el-table-column>-->
|
|
|
+ <el-table-column prop="database_name" min-width="100" label="数据库" align="center" />
|
|
|
+<!-- <el-table-column prop="container_name" label="容器名称" min-width="100" align="center" />-->
|
|
|
+ <el-table-column prop="backups_path" label="备份地址" min-width="130" align="center" />
|
|
|
+ <el-table-column prop="backups_name" label="文件名" min-width="130" align="center" />
|
|
|
+ <el-table-column prop="operation" label="操作次数" width="100" align="center" />
|
|
|
+ <el-table-column prop="recovery_time" label="恢复时间" width="170" align="center" :formatter="fortDate"/>
|
|
|
+ <el-table-column prop="create_time" label="备份时间" width="170" align="center" :formatter="fortDate" />
|
|
|
+ <el-table-column prop="state" label="状态" width="100" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-tag v-if="scope.row.status === 0" type="success" disable-transitions>正常</el-tag>
|
|
|
+ <el-tag v-if="scope.row.status === 1" type="danger" disable-transitions>文件不存在</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column style="text-align: left;" label="操作" width="120" fixed="right">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button v-if="scope.row.status === 0" type="success" size="mini" @click="handlerEdit(scope.row)">
|
|
|
+ 还原
|
|
|
+ </el-button>
|
|
|
+ <el-button v-else type="info" size="mini" @click="handlerDel(scope.row.id)">
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <el-pagination
|
|
|
+ v-if="tableData"
|
|
|
+ slot="pagination"
|
|
|
+ @size-change="handlePageSizeChange"
|
|
|
+ @current-change="handlePageCurrentChange"
|
|
|
+ :current-page="tableData.page_no"
|
|
|
+ :page-sizes="[20, 50, 100, 500]"
|
|
|
+ :page-size="tableData.page_size"
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
+ :total="tableData.data_total">
|
|
|
+ </el-pagination>
|
|
|
+ </div>
|
|
|
+ <el-dialog title="新增备份" :visible.sync="fromDialog" width="700px" :close-on-click-modal="false" :close-on-press-escape="false">
|
|
|
+ <el-form :model="myForm" ref="myForm" :rules="formRules" label-width="140px">
|
|
|
+ <el-form-item label="数据库" prop="database_name">
|
|
|
+ <el-select v-model="myForm.database_name" filterable allow-create default-first-option placeholder="请选择或输入数据库">
|
|
|
+ <el-option v-for="(item, index) in databaseOptions" :key="index" :label="item" :value="item"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+<!-- <el-form-item label="是否装在docker">-->
|
|
|
+<!-- <el-radio-group v-model="myForm.bool_docker">-->
|
|
|
+<!-- <el-radio :label="false">没有</el-radio>-->
|
|
|
+<!-- <el-radio :label="true">装在</el-radio>-->
|
|
|
+<!-- </el-radio-group>-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- <el-form-item v-if="myForm.bool_docker" label="容器名称" prop="container_name">-->
|
|
|
+<!-- <el-input v-model="myForm.container_name" placeholder="默认mysql" />-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+ <el-form-item label="备份地址" prop="backups_path">
|
|
|
+ <el-input v-model="myForm.backups_path" placeholder="请输入备份地址" clearable />
|
|
|
+ </el-form-item>
|
|
|
+<!-- <el-form-item label="mysql服务器地址">-->
|
|
|
+<!-- <el-input v-model="myForm.mysql_ip" placeholder="mysql服务器地址" />-->
|
|
|
+<!-- <el-link type="primary" @click="myForm.mysql_ip = serverIP">填入服务器地址</el-link>-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="fromDialog = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="handleConfirm">确 定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { unix2Date } from '@/utils/Foundation'
|
|
|
+import * as API_MysqlBackups from '@/api/mysql_backups'
|
|
|
+export default {
|
|
|
+ name: 'index',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ tableData: [],
|
|
|
+ /** 列表参数 */
|
|
|
+ params: {
|
|
|
+ page_size: 20,
|
|
|
+ page_no: 1,
|
|
|
+ sort: 'create_time',
|
|
|
+ dir: 'desc'
|
|
|
+ },
|
|
|
+ /** ag-grid参数 **/
|
|
|
+ pageData: [],
|
|
|
+ loading: false,
|
|
|
+ fromDialog: false,
|
|
|
+ myForm: {
|
|
|
+ database_name: 'wdkl_ncs',
|
|
|
+ container_name: 'mysql',
|
|
|
+ mysql_ip: '',
|
|
|
+ backups_path: '/opt/v70/api/upload',
|
|
|
+ bool_docker: false
|
|
|
+ },
|
|
|
+ formRules: {
|
|
|
+ database_name: [{ required: true, message: '请选择或输入数据库', trigger: 'change' }],
|
|
|
+ container_name: [{ required: true, message: '请输入容器名称', trigger: 'blur' }],
|
|
|
+ backups_path: [{ required: true, message: '请输入文件存储地址', trigger: 'blur' }],
|
|
|
+ mysql_ip: [{ required: true, message: '请输入mysql服务器地址', trigger: 'blur' }]
|
|
|
+ },
|
|
|
+ databaseOptions:['wdkl_ncs', 'wdkl_nfc', 'kea'],
|
|
|
+ databaseName: '',
|
|
|
+ localIP: '',
|
|
|
+ serverIP: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.localIP = window.location.hostname
|
|
|
+ this.serverIP = this.API_GetIP()
|
|
|
+ this.GET_List()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ /** 分页大小发生改变 */
|
|
|
+ handlePageSizeChange(size) {
|
|
|
+ this.params.page_size = size
|
|
|
+ this.GET_List()
|
|
|
+ },
|
|
|
+ /** 分页页数发生改变 */
|
|
|
+ handlePageCurrentChange(page) {
|
|
|
+ this.params.page_no = page
|
|
|
+ this.GET_List()
|
|
|
+ },
|
|
|
+ GET_List() {
|
|
|
+ API_MysqlBackups.getList(this.params).then(res => {
|
|
|
+ this.tableData = res
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /** 点击搜索按钮 **/
|
|
|
+ clickSearch() {
|
|
|
+ this.params.page_no = 1
|
|
|
+ this.GET_List()
|
|
|
+ },
|
|
|
+ /** 点击每页显示数量 **/
|
|
|
+ fortDate(row, column, cellValue, index) {
|
|
|
+ if (!cellValue) return '暂无'
|
|
|
+ return unix2Date(cellValue * 1000)
|
|
|
+ },
|
|
|
+ handlerEdit(row) {
|
|
|
+ console.log('还原....',row)
|
|
|
+ this.$confirm('您确定要恢复还原吗?', '警告', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ // if (row.mysql_ip === this.API_GetIP()) {
|
|
|
+ const _this = this
|
|
|
+ API_MysqlBackups.rollback(row.id).then(res => {
|
|
|
+ _this.$message.info(res.message)
|
|
|
+ if (!res.success) {
|
|
|
+ _this.GET_List()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // } else {
|
|
|
+ // this.$message({
|
|
|
+ // type: 'warning',
|
|
|
+ // message: '该备份文件为存储在' + row.mysql_ip + '机器上,其他环境不能还原'
|
|
|
+ // })
|
|
|
+ // }
|
|
|
+ }).catch(() => {
|
|
|
+ console.log('取消删除')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /** 单条数据删除处理 */
|
|
|
+ handlerDel(ids) {
|
|
|
+ this.$confirm('删除操作后数据不可复原,您确定要删除此数据?', '警告', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ API_MysqlBackups.remove(ids).then(
|
|
|
+ response => {
|
|
|
+ this.GET_List()
|
|
|
+ this.$message({
|
|
|
+ type: 'success',
|
|
|
+ message: '删除成功!'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ )
|
|
|
+ }).catch(() => {
|
|
|
+ console.log('取消删除')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleConfirm() {
|
|
|
+ const _this = this
|
|
|
+ this.$refs['myForm'].validate((valid, error) => {
|
|
|
+ if (valid) {
|
|
|
+ const params = _this.MixinClone(_this.myForm)
|
|
|
+ // 新增
|
|
|
+ API_MysqlBackups.mysqlBackups(params).then(res => {
|
|
|
+ _this.fromDialog = false
|
|
|
+ _this.$message.info(res.message)
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.$message.error('表单填写有误,请检查!')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ API_GetIP() {
|
|
|
+ const regex = /\/\/([\d.]+):\d+/
|
|
|
+ const matches = regex.exec(domain.serverUrl)
|
|
|
+ if (matches !== null) {
|
|
|
+ console.log(matches[1]) // 输出192.168.1.199
|
|
|
+ return matches[1]
|
|
|
+ } else {
|
|
|
+ if (domain.serverUrl.indexOf('localhost') > -1) {
|
|
|
+ return 'localhost'
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ changeSearch() {
|
|
|
+ if (this.databaseName) {
|
|
|
+ this.params.fixedCondition = " database_name='" +this.databaseName + "'"
|
|
|
+ } else {
|
|
|
+ this.params.fixedCondition = ' 1=1 '
|
|
|
+ }
|
|
|
+ this.params.page_no = 1
|
|
|
+ this.GET_List()
|
|
|
+ },
|
|
|
+ addLog() {
|
|
|
+ // if (this.localIP !== this.serverIP) {
|
|
|
+ // this.$message.error('浏览器地址与请求服务器地址不一致!')
|
|
|
+ // return
|
|
|
+ // }
|
|
|
+ this.fromDialog = true
|
|
|
+ },
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+
|
|
|
+</style>
|