threethousanddream před 1 měsícem
rodič
revize
eca991a4e8

+ 1 - 0
src/api/develop.js

@@ -6,5 +6,6 @@ const prefix = config.systemPrefix
 export const list = params => request.get(prefix + "/developerApplyManage/applyPage", {params});
 export const apply = data => request.post(prefix + "/developerApplyManage/review", data);
 export const applyRecord = params => request.get(prefix + "/developerApplyManage/reviewLogList", {params});
+export const getTotal = params => request.get(prefix + "/developerApplyManage/statusCount", {params});
 
 

+ 0 - 388
src/views/backup/list-old.vue

@@ -1,388 +0,0 @@
-<template>
-  <div class="page update_sql">
-    <div class="my-top">
-      <el-form size="default" inline label-width="80px">
-        <el-form-item label="备注名称">
-          <el-input v-model="setting.params.remarkName" style="width: 160px" placeholder="请输入"></el-input>
-        </el-form-item>
-        <el-form-item label="文件名称">
-          <el-input v-model="setting.params.fileName" style="width: 160px" placeholder="请输入"></el-input>
-        </el-form-item>
-        <el-form-item label="恢复状态">
-          <el-select v-model="setting.params.restoreStatus" style="width: 160px">
-            <el-option value="" label="全部"></el-option>
-            <el-option :value="0" label="未恢复"></el-option>
-            <el-option :value="1" label="已恢复"></el-option>
-          </el-select>
-        </el-form-item>
-      </el-form>
-      <el-button size="default" @click="getData">查询</el-button>
-      <el-button size="default" @click="onReset" style="margin-right: 10px;">重置</el-button>
-      <div style="flex: 1"></div>
-      <el-button size="small" @click="setting.remarkShow = true" v-auth="'1823265087981531225'">
-        <SvgIcon icon="selectAll"></SvgIcon>
-        <span style="margin-left: 3px;">全量备份</span>
-      </el-button>
-      <el-button size="small" @click="getSqlList('open')" v-auth="'1823265107757674525'">
-        <SvgIcon icon="backup2" :size="16"></SvgIcon>
-        <span style="margin-left: 3px;">自定义备份</span>
-      </el-button>
-    </div>
-    <div style="height: calc(100% - 95px);overflow-y: auto">
-      <el-table
-        v-loading="setting.tableLoading" :data="setting.sqlData" :header-row-style="{ 'color': '#000', }"
-        fit height="100%"
-      >
-        <el-table-column prop="remarks" label="备注" show-overflow-tooltip></el-table-column>
-        <el-table-column prop="fileName" label="文件名称"></el-table-column>
-        <el-table-column prop="backupTime" label="备份时间"></el-table-column>
-        <el-table-column prop="createUserName" label="操作人"></el-table-column>
-        <el-table-column label="恢复状态">
-          <template v-slot="{row}">
-            <div class="status-box" v-if="row.restoreStatus===0">
-              <div class="point" style="background-color: #ff9b2a"></div>
-              <span>未恢复</span>
-            </div>
-            <div class="status-box" v-if="row.restoreStatus===1">
-              <div class="point" style="background-color: #18b633"></div>
-              <span>已恢复</span>
-            </div>
-          </template>
-        </el-table-column>
-        <el-table-column label="数据来源" width="150">
-          <template v-slot="scope">
-            <span v-if="scope.row.dataSource == 0"> 备份</span>
-            <span v-else>上传</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" width="120px">
-          <template v-slot="scope">
-            <el-button size="small" type="text" @click="downloadBackups(scope.row)"
-                       v-auth="'1823265230537535511'">
-              下载
-            </el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-    </div>
-    <!-- 分页 -->
-    <el-pagination
-      background
-      :current-page.sync="setting.page.current" :page-sizes="[10, 20, 30, 40]" @size-change="handleSizeChange"
-      @current-change="handleCurrentChange" :page-size="setting.page.size"
-      layout="total, sizes, prev, pager, next, jumper" :total="setting.page.total" class="my-page"
-    ></el-pagination>
-    <el-dialog
-      title="自定义备份" v-model="setting.dialogShow" width="800px" :close-on-click-modal="false"
-      :close-on-press-escape="false" class="backup-dialog"
-    >
-      <el-form inline>
-        <el-form-item label="表名称">
-          <el-input v-model="setting.sqlName" placeholder="输入表名称查询" size="small">
-            <template #append>
-              <el-button :icon="Search" @click="getSqlList"/>
-            </template>
-          </el-input>
-        </el-form-item>
-      </el-form>
-      <div style="height:calc(100% - 202px)">
-        <el-table
-          v-loading="setting.loading" :data="setting.tableData" height="100%" style="margin: 10px 0;"
-          @selection-change="handleSelectionChange" size="small"
-        >
-          <el-table-column type="selection" width="55"></el-table-column>
-          <el-table-column prop="tableName" label="表名"></el-table-column>
-          <el-table-column prop="tableComment" label="表备注"></el-table-column>
-          <el-table-column prop="dataMb" label="表大小"></el-table-column>
-          <el-table-column prop="tableRows" label="表行数"></el-table-column>
-        </el-table>
-      </div>
-      <el-form size="small" label-width="70px">
-        <el-form-item label="备份方式" style="margin: 10px 0;">
-          <el-radio-group v-model="setting.backupsForm.backupType">
-            <el-radio :label="1">合并导出</el-radio>
-            <el-radio :label="2">分表导出</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="备注" required>
-          <el-input
-            type="textarea" :rows="3" v-model="setting.backupsForm.remark" maxlength="120" show-word-limit
-          ></el-input>
-        </el-form-item>
-      </el-form>
-      <div class="dialog-btns">
-        <el-button @click="clearVal">取 消</el-button>
-        <el-button
-          :disabled="setting.backupsForm.tableNames == '' || setting.backupsForm.remark == ''" type="primary"
-          @click="handBackups"
-        >
-          确 定
-        </el-button>
-      </div>
-    </el-dialog>
-    <el-dialog append-to-body v-model="setting.remarkShow" width="500px">
-      <template #header>
-        <span style="color: red">*</span>
-        备注
-      </template>
-      <el-input
-        type="textarea" :rows="3" v-model="setting.backupsForm.remark" maxlength="120" show-word-limit
-      ></el-input>
-      <div class="dialog-btns">
-        <el-button @click="setting.remarkShow = false">取 消</el-button>
-        <el-button type="primary" :disabled="setting.backupsForm.remark == ''" @click="backupsAll">确 定</el-button>
-      </div>
-    </el-dialog>
-    <el-dialog
-      title="导入sql" v-model="setting.fileShow" width="70%" top="8vh" :close-on-click-modal="false"
-      :close-on-press-escape="false" class="backup-upload-dialog"
-    >
-      <div style="display: flex;align-items: center;margin-bottom: 10px;">
-        <el-upload
-          accept="zip" action="*" :auto-upload="false" :on-change="addFile"
-          :file-list="setting.fileList" v-auth="'1823265127781281880'"
-        >
-          <el-button type="primary">上传文件</el-button>
-        </el-upload>
-        <div style="margin-left: 20px;color: #777">只能上传zip文件</div>
-      </div>
-      <el-table :data="setting.fileData" :header-row-style="{ 'color': '#000', }" fit max-height="500" :border="true">
-        <el-table-column prop="fileName" label="文件名称"></el-table-column>
-        <el-table-column prop="backupTime" label="上传时间"></el-table-column>
-        <el-table-column prop="remarks" label="备注" show-overflow-tooltip></el-table-column>
-        <el-table-column label="数据来源" width="150">
-          <template v-slot="scope">
-            <span v-if="scope.row.dataSource == 0"> 备份</span>
-            <span v-else>上传</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" width="120px">
-          <template v-slot="scope">
-            <el-button size="small" type="text" @click="downloadBackups(scope.row)"
-                       v-auth="'1823265181954912325'">
-              下载
-            </el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-      <div class="dialog-btns">
-        <el-button @click="setting.fileShow = false">取 消</el-button>
-        <el-button type="primary" @click="setting.fileShow = false" :disabled="!setting.fileData.length">确 定
-        </el-button>
-      </div>
-    </el-dialog>
-    <el-dialog
-      title="执行sql" :show-close="false" v-model="setting.innerVisible"
-      :close-on-click-modal="false" :close-on-press-escape="false" append-to-body
-    >
-      <div style="color: red;"> sql执行中,请勿关闭</div>
-      <div style="margin: 20px 0; text-align: center;">
-        <el-progress type="circle" :percentage="setting.progressNum"></el-progress>
-      </div>
-      <div style="text-align: center;">
-        <i class="el-icon-loading" style="font-size: 30px;"></i>执行中...
-      </div>
-    </el-dialog>
-  </div>
-</template>
-<script setup name="pageBackup">
-import {onMounted} from 'vue';
-import {backupsList, backups, sqlList, upload} from '@/api/backup';
-import {ElLoading, ElMessage,} from 'element-plus'
-import {Search} from "@element-plus/icons-vue";
-const setting = reactive({
-  sqlData: [],
-  date: [],
-  sqlForm: {
-    dataSource: 0, //数据源 0-备份 1-上传
-    fileName: '', //文件名
-    tenantId: '', //租户id
-  },
-  params: {remarkName: '', fileName: '', restoreStatus: ''},
-  page: {current: 1, size: 10, total: 0,},
-  backupsForm: {  //手动备份
-    backupType: 1,  //1:合并导出,2:分表导出
-    tableNames: "", //表名 多个用逗号隔开
-    remark: "",      //备注
-  },
-  sqlName: '', //sql名称
-  dialogShow: false, //弹窗显示
-  remarkShow: false, //弹窗显示
-  fileShow: false, //文件弹窗显示
-  tableData: [], //sql列表
-  sqlTableData: [], //sql列表
-  loading: true,
-  tableLoading: true,
-  fileList: [], //文件列表
-  fileData: [], //上传文件列表
-  isNext: 0, //下一步
-  innerVisible: 0, //下一步
-  progressNum: 0  //进度
-});
-
-onMounted(() => {
-  getData();
-});
-const onReset = () => {
-  setting.params.remarkName = ''
-  setting.params.fileName = ''
-  setting.params.restoreStatus = ''
-  getData()
-}
-const getData = () => {
-  setting.tableLoading = true;
-  let {current, size} = setting.page
-  let data = {current, size}
-  let {remarkName, fileName, restoreStatus} = setting.params
-  if (remarkName) data.remarks = remarkName
-  if (fileName) data.fileName = fileName
-  if (restoreStatus !== '') data.restoreStatus = restoreStatus
-  // 获取备份列表
-  backupsList(data).then(res => {
-    setting.tableLoading = false;
-    setting.sqlData = res.data?.records || [];
-    setting.page.total = res.data.total;
-  }).finally(() => {
-    setting.tableLoading = false;
-  })
-};
-// 全量备份
-const backupsAll = () => {
-  const loading = ElLoading.service({
-    lock: true,
-    text: '数据备份中...',
-    spinner: 'el-icon-loading',
-    background: 'rgba(0, 0, 0, 0.7)',
-  });
-  backups({remark: setting.backupsForm.remark}).then(res => {
-    ElMessage.success('备份成功');
-    setting.remarkShow = false
-    setting.backupsForm.remark = ''
-    loading.close();
-    getData()
-  }).finally(() => {
-    loading.close();
-  })
-};
-// sql列表 getSqlList
-const getSqlList = (val) => {
-  setting.loading = true;
-  if (val == 'open') {
-    setting.dialogShow = true
-    sqlList({tableName: setting.sqlName}).then(res => {
-      setting.loading = false;
-      setting.tableData = res.data;
-      setting.sqlTableData = JSON.parse(JSON.stringify(res.data));
-    })
-  } else {
-    if (setting.sqlName == '') {
-      setting.tableData = setting.sqlTableData
-      setting.loading = false
-    } else {
-      setting.tableData = setting.sqlTableData.filter(item => {
-        return item.tableName.indexOf(setting.sqlName) > -1 || item.tableComment.indexOf(setting.sqlName) > -1
-      })
-      setting.loading = false
-    }
-  }
-};
-// 手动备份 handBackups
-const handBackups = () => {
-  const loading = ElLoading.service({
-    lock: true,
-    text: '数据备份中...',
-    spinner: 'el-icon-loading',
-    background: 'rgba(0, 0, 0, 0.7)',
-  });
-  backups(setting.backupsForm).then(res => {
-    loading.close();
-    ElMessage.success('备份成功');
-    clearVal();
-    getData()
-  }).catch(err => {
-    loading.close();
-    ElMessage.error('备份失败');
-  })
-
-};
-// 下载备份
-const downloadBackups = (row) => {
-  let {filePath, remarks} = row
-  const a = document.createElement("a");
-  a.href = filePath;
-  a.download = remarks || 'download';
-  // a.target = '_blank';
-  document.body.appendChild(a);
-  a.click();
-  document.body.removeChild(a);
-  ElMessage({type: 'success', message: '已开始下载'})
-}
-const handleSelectionChange = (val) => {
-  setting.backupsForm.tableNames = val.map(item => item.tableName).join(',')
-}
-// 关闭弹窗清空内容
-const clearVal = () => {
-  setting.sqlName = '';
-  setting.backupsForm = {
-    backupType: 1,  //1:合并导出,2:分表导出
-    tableNames: "", //表名 多个用逗号隔开
-    remark: "",      //备注
-  }
-  setting.dialogShow = false;
-}
-// 每页条数
-const handleSizeChange = (val) => {
-  setting.page.current = 1;
-  setting.page.size = val;
-  getData();
-}
-// 当前页
-const handleCurrentChange = (val) => {
-  setting.page.current = val;
-  getData();
-}
-// 添加文件
-const addFile = (file, fileList) => {
-  if (file.name.indexOf('.zip') == -1) {
-    ElMessage.error('请上传sql文件');
-    fileList.filter(item => {
-      if (item.name === file.name) {
-        fileList.splice(fileList.indexOf(item), 1)
-      }
-    })
-    return false
-  } else {
-    setting.fileList = fileList
-    uploadFile()
-  }
-}
-// 上传文件
-const uploadFile = () => {
-  const loading = ElLoading.service({
-    lock: true,
-    text: '文件上传中...',
-    spinner: 'el-icon-loading',
-    background: 'rgba(0, 0, 0, 0.7)',
-  });
-  const formData = new FormData();
-  formData.append('file', setting.fileList[0].raw);
-  upload(formData).then(res => {
-    setting.fileList = [];
-    ElMessage.success('上传成功');
-    // }
-    const fileForm = {...setting.sqlForm}
-    // 获取备份列表
-    fileForm.dataSource = 1
-    fileForm.size = 999999
-    fileForm.current = 1
-    backupsList(fileForm).then(res => {
-      setting.fileData = res.data?.records || [];
-    })
-  }).finally(() => {
-    loading.close();
-  })
-}
-</script>
-<style lang="scss">
-@import "./list.scss";
-</style>

+ 337 - 153
src/views/backup/list.vue

@@ -1,204 +1,388 @@
 <template>
-  <div class="page page-develop">
-    <div class="header">
-      <div class="item" :class="{active:state.active===0}" @click="onTypeChange(0)">
-        全部({{ state.totals.total }})
-      </div>
-      <div class="item" :class="{active:state.active===1}" @click="onTypeChange(1)">
-        待审核({{ state.totals.apply }})
-      </div>
-      <div class="item" :class="{active:state.active===3}" @click="onTypeChange(3)">
-        未通过({{ state.totals.fail }})
-      </div>
-      <div class="item" :class="{active:state.active===2}" @click="onTypeChange(2)">
-        通过({{ state.totals.path }})
-      </div>
-    </div>
+  <div class="page update_sql">
     <div class="my-top">
-      <el-form class="inline-form" label-width="90px" inline size="default">
-        <el-form-item label="申请人">
-          <UserSelect ignore-tenant v-model="state.userId"></UserSelect>
+      <el-form size="default" inline label-width="80px">
+        <el-form-item label="备注名称">
+          <el-input v-model="setting.params.remarkName" style="width: 160px" placeholder="请输入"></el-input>
+        </el-form-item>
+        <el-form-item label="文件名称">
+          <el-input v-model="setting.params.fileName" style="width: 160px" placeholder="请输入"></el-input>
+        </el-form-item>
+        <el-form-item label="恢复状态">
+          <el-select v-model="setting.params.restoreStatus" style="width: 160px">
+            <el-option value="" label="全部"></el-option>
+            <el-option :value="0" label="未恢复"></el-option>
+            <el-option :value="1" label="已恢复"></el-option>
+          </el-select>
         </el-form-item>
       </el-form>
-      <el-button @click="getData" size="default" :loading="state.dataLoading">查询</el-button>
-      <el-button @click="onReset" size="default" :loading="state.dataLoading">重置</el-button>
+      <el-button size="default" @click="getData">查询</el-button>
+      <el-button size="default" @click="onReset" style="margin-right: 10px;">重置</el-button>
       <div style="flex: 1"></div>
-      <el-button type="primary" @click="applyBatch" size="default">
-        <SvgIcon icon="batch" style="margin-right: 3px;"></SvgIcon>
-        批量审核
+      <el-button size="small" @click="setting.remarkShow = true" v-auth="'1823265087981531225'">
+        <SvgIcon icon="selectAll"></SvgIcon>
+        <span style="margin-left: 3px;">全量备份</span>
+      </el-button>
+      <el-button size="small" @click="getSqlList('open')" v-auth="'1823265107757674525'">
+        <SvgIcon icon="backup2" :size="16"></SvgIcon>
+        <span style="margin-left: 3px;">自定义备份</span>
       </el-button>
     </div>
-    <div class="table-box">
-      <el-table :data="state.list" size="default" :header-row-style="{color:'#161616'}" height="100%">
-        <el-table-column label="" width="60px">
-          <template v-slot="{row}">
-            <el-checkbox v-model="row.select"></el-checkbox>
-          </template>
-        </el-table-column>
-        <el-table-column label="所属用户" prop="tenantName"></el-table-column>
-        <el-table-column label="申请人" prop="userNickName"></el-table-column>
-        <el-table-column label="申请人账号" prop="userId"></el-table-column>
-        <el-table-column label="申请时间" prop="createTime"></el-table-column>
-        <el-table-column label="认证信息" prop="userAccount"></el-table-column>
-        <el-table-column label="审核状态">
+    <div style="height: calc(100% - 95px);overflow-y: auto">
+      <el-table
+        v-loading="setting.tableLoading" :data="setting.sqlData" :header-row-style="{ 'color': '#000', }"
+        fit height="100%"
+      >
+        <el-table-column prop="remarks" label="备注" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="fileName" label="文件名称"></el-table-column>
+        <el-table-column prop="backupTime" label="备份时间"></el-table-column>
+        <el-table-column prop="createUserName" label="操作人"></el-table-column>
+        <el-table-column label="恢复状态">
           <template v-slot="{row}">
-            <div class="status-box" v-if="row.status===3">
-              <div class="point" style="background-color: #bfbfbf"></div>
-              <span>未通过</span>
+            <div class="status-box" v-if="row.restoreStatus===0">
+              <div class="point" style="background-color: #ff9b2a"></div>
+              <span>未恢复</span>
             </div>
-            <div class="status-box" v-if="row.status===2">
+            <div class="status-box" v-if="row.restoreStatus===1">
               <div class="point" style="background-color: #18b633"></div>
-              <span>通过</span>
-            </div>
-            <div class="status-box" v-if="row.status===1">
-              <div class="point" style="background-color: #eb5a10"></div>
-              <span>待审核</span>
+              <span>已恢复</span>
             </div>
           </template>
         </el-table-column>
-        <el-table-column label="操作" align="center" width="160px">
-          <template v-slot="{row}">
-            <el-button type="text" @click="onApply(row)">审核</el-button>
-            <el-button type="text" @click="onShowRecord(row)">审核详情</el-button>
+        <el-table-column label="数据来源" width="150">
+          <template v-slot="scope">
+            <span v-if="scope.row.dataSource == 0"> 备份</span>
+            <span v-else>上传</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="120px">
+          <template v-slot="scope">
+            <el-button size="small" type="text" @click="downloadBackups(scope.row)"
+                       v-auth="'1823265230537535511'">
+              下载
+            </el-button>
           </template>
         </el-table-column>
       </el-table>
     </div>
+    <!-- 分页 -->
     <el-pagination
-      :current-page.sync="state.page.current" :page-size="state.page.size" :page-sizes="[10, 20, 30, 40]"
-      :total="state.page.total" @current-change="getData"
-      background layout="total, sizes, prev, pager, next, jumper" @size-change="onSizeChange" class="my-page"
+      background
+      :current-page.sync="setting.page.current" :page-sizes="[10, 20, 30, 40]" @size-change="handleSizeChange"
+      @current-change="handleCurrentChange" :page-size="setting.page.size"
+      layout="total, sizes, prev, pager, next, jumper" :total="setting.page.total" class="my-page"
     ></el-pagination>
-    <el-dialog v-model="state.showAudit" append-to-body width="500px" title="审核">
-      <el-form label-width="70px">
-        <el-form-item label="是否通过">
-          <el-radio-group v-model="state.auditForm.pass">
-            <el-radio :label="true">通过</el-radio>
-            <el-radio :label="false">驳回</el-radio>
+    <el-dialog
+      title="自定义备份" v-model="setting.dialogShow" width="800px" :close-on-click-modal="false"
+      :close-on-press-escape="false" class="backup-dialog"
+    >
+      <el-form inline>
+        <el-form-item label="表名称">
+          <el-input v-model="setting.sqlName" placeholder="输入表名称查询" size="small">
+            <template #append>
+              <el-button :icon="Search" @click="getSqlList"/>
+            </template>
+          </el-input>
+        </el-form-item>
+      </el-form>
+      <div style="height:calc(100% - 202px)">
+        <el-table
+          v-loading="setting.loading" :data="setting.tableData" height="100%" style="margin: 10px 0;"
+          @selection-change="handleSelectionChange" size="small"
+        >
+          <el-table-column type="selection" width="55"></el-table-column>
+          <el-table-column prop="tableName" label="表名"></el-table-column>
+          <el-table-column prop="tableComment" label="表备注"></el-table-column>
+          <el-table-column prop="dataMb" label="表大小"></el-table-column>
+          <el-table-column prop="tableRows" label="表行数"></el-table-column>
+        </el-table>
+      </div>
+      <el-form size="small" label-width="70px">
+        <el-form-item label="备份方式" style="margin: 10px 0;">
+          <el-radio-group v-model="setting.backupsForm.backupType">
+            <el-radio :label="1">合并导出</el-radio>
+            <el-radio :label="2">分表导出</el-radio>
           </el-radio-group>
         </el-form-item>
-        <el-form-item label="备注" required v-if="!state.auditForm.pass">
-          <el-input type="textarea" :rows="3" placeholder="请输入备注" v-model="state.auditForm.reason"></el-input>
+        <el-form-item label="备注" required>
+          <el-input
+            type="textarea" :rows="3" v-model="setting.backupsForm.remark" maxlength="120" show-word-limit
+          ></el-input>
         </el-form-item>
       </el-form>
       <div class="dialog-btns">
-        <el-button @click="state.showAudit=false" size="default">取消</el-button>
-        <el-button @click="onAuditConfirm" type="primary" size="default" :loading="state.saveAuditLoading">确定
+        <el-button @click="clearVal">取 消</el-button>
+        <el-button
+          :disabled="setting.backupsForm.tableNames == '' || setting.backupsForm.remark == ''" type="primary"
+          @click="handBackups"
+        >
+          确 定
         </el-button>
       </div>
     </el-dialog>
-    <el-dialog v-model="state.showAuditRecord" append-to-body width="600px" title="审核详情">
-      <el-table :data="state.auditRecord" max-height="500px">
-        <el-table-column label="时间" prop="createTime" width="160px"></el-table-column>
-        <el-table-column label="操作人" prop="createUserName"></el-table-column>
-        <el-table-column label="审核状态">
-          <template v-slot="{row}">
-            <div class="status-box" v-if="row.status===2">
-              <div class="point" style="background-color: #bfbfbf"></div>
-              <span>未通过</span>
-            </div>
-            <div class="status-box" v-if="row.status===1">
-              <div class="point" style="background-color: #18b633"></div>
-              <span>通过</span>
-            </div>
-            <div class="status-box" v-if="row.status===0">
-              <div class="point" style="background-color: #eb5a10"></div>
-              <span>待审核</span>
-            </div>
+    <el-dialog append-to-body v-model="setting.remarkShow" width="500px">
+      <template #header>
+        <span style="color: red">*</span>
+        备注
+      </template>
+      <el-input
+        type="textarea" :rows="3" v-model="setting.backupsForm.remark" maxlength="120" show-word-limit
+      ></el-input>
+      <div class="dialog-btns">
+        <el-button @click="setting.remarkShow = false">取 消</el-button>
+        <el-button type="primary" :disabled="setting.backupsForm.remark == ''" @click="backupsAll">确 定</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog
+      title="导入sql" v-model="setting.fileShow" width="70%" top="8vh" :close-on-click-modal="false"
+      :close-on-press-escape="false" class="backup-upload-dialog"
+    >
+      <div style="display: flex;align-items: center;margin-bottom: 10px;">
+        <el-upload
+          accept="zip" action="*" :auto-upload="false" :on-change="addFile"
+          :file-list="setting.fileList" v-auth="'1823265127781281880'"
+        >
+          <el-button type="primary">上传文件</el-button>
+        </el-upload>
+        <div style="margin-left: 20px;color: #777">只能上传zip文件</div>
+      </div>
+      <el-table :data="setting.fileData" :header-row-style="{ 'color': '#000', }" fit max-height="500" :border="true">
+        <el-table-column prop="fileName" label="文件名称"></el-table-column>
+        <el-table-column prop="backupTime" label="上传时间"></el-table-column>
+        <el-table-column prop="remarks" label="备注" show-overflow-tooltip></el-table-column>
+        <el-table-column label="数据来源" width="150">
+          <template v-slot="scope">
+            <span v-if="scope.row.dataSource == 0"> 备份</span>
+            <span v-else>上传</span>
           </template>
         </el-table-column>
-        <el-table-column label="备注">
-          <template v-slot="{row}">
-            <span>{{ row.remark }}</span>
+        <el-table-column label="操作" width="120px">
+          <template v-slot="scope">
+            <el-button size="small" type="text" @click="downloadBackups(scope.row)"
+                       v-auth="'1823265181954912325'">
+              下载
+            </el-button>
           </template>
         </el-table-column>
       </el-table>
       <div class="dialog-btns">
-        <el-button @click="state.showAuditRecord=false" type="primary" size="default">确定</el-button>
+        <el-button @click="setting.fileShow = false">取 消</el-button>
+        <el-button type="primary" @click="setting.fileShow = false" :disabled="!setting.fileData.length">确 定
+        </el-button>
+      </div>
+    </el-dialog>
+    <el-dialog
+      title="执行sql" :show-close="false" v-model="setting.innerVisible"
+      :close-on-click-modal="false" :close-on-press-escape="false" append-to-body
+    >
+      <div style="color: red;"> sql执行中,请勿关闭</div>
+      <div style="margin: 20px 0; text-align: center;">
+        <el-progress type="circle" :percentage="setting.progressNum"></el-progress>
+      </div>
+      <div style="text-align: center;">
+        <i class="el-icon-loading" style="font-size: 30px;"></i>执行中...
       </div>
     </el-dialog>
   </div>
 </template>
-<script setup>
-import {list, apply, applyRecord} from '@/api/develop'
-import UserSelect from "/@/components/UserSelect/index.vue";
-import SvgIcon from "/@/components/svgIcon/index.vue";
-import {ElMessage} from "element-plus";
-let state = reactive({
-  totals: {total: 0, apply: 0, fail: 0, path: 0,},
-  active: 0,
-  page: {total: 0, current: 1, size: 10},
-  list: [],
-  userId: '',
-  dataLoading: false,
-  showAudit: false,
-  auditForm: {},
-  saveAuditLoading: false,
-  showAuditRecord: false,
-  auditRecord: [],
-})
+<script setup name="pageBackup">
+import {onMounted} from 'vue';
+import {backupsList, backups, sqlList, upload} from '@/api/backup';
+import {ElLoading, ElMessage,} from 'element-plus'
+import {Search} from "@element-plus/icons-vue";
+const setting = reactive({
+  sqlData: [],
+  date: [],
+  sqlForm: {
+    dataSource: 0, //数据源 0-备份 1-上传
+    fileName: '', //文件名
+    tenantId: '', //租户id
+  },
+  params: {remarkName: '', fileName: '', restoreStatus: ''},
+  page: {current: 1, size: 10, total: 0,},
+  backupsForm: {  //手动备份
+    backupType: 1,  //1:合并导出,2:分表导出
+    tableNames: "", //表名 多个用逗号隔开
+    remark: "",      //备注
+  },
+  sqlName: '', //sql名称
+  dialogShow: false, //弹窗显示
+  remarkShow: false, //弹窗显示
+  fileShow: false, //文件弹窗显示
+  tableData: [], //sql列表
+  sqlTableData: [], //sql列表
+  loading: true,
+  tableLoading: true,
+  fileList: [], //文件列表
+  fileData: [], //上传文件列表
+  isNext: 0, //下一步
+  innerVisible: 0, //下一步
+  progressNum: 0  //进度
+});
+
 onMounted(() => {
+  getData();
+});
+const onReset = () => {
+  setting.params.remarkName = ''
+  setting.params.fileName = ''
+  setting.params.restoreStatus = ''
   getData()
-})
-const applyBatch = () => {
+}
+const getData = () => {
+  setting.tableLoading = true;
+  let {current, size} = setting.page
+  let data = {current, size}
+  let {remarkName, fileName, restoreStatus} = setting.params
+  if (remarkName) data.remarks = remarkName
+  if (fileName) data.fileName = fileName
+  if (restoreStatus !== '') data.restoreStatus = restoreStatus
+  // 获取备份列表
+  backupsList(data).then(res => {
+    setting.tableLoading = false;
+    setting.sqlData = res.data?.records || [];
+    setting.page.total = res.data.total;
+  }).finally(() => {
+    setting.tableLoading = false;
+  })
+};
+// 全量备份
+const backupsAll = () => {
+  const loading = ElLoading.service({
+    lock: true,
+    text: '数据备份中...',
+    spinner: 'el-icon-loading',
+    background: 'rgba(0, 0, 0, 0.7)',
+  });
+  backups({remark: setting.backupsForm.remark}).then(res => {
+    ElMessage.success('备份成功');
+    setting.remarkShow = false
+    setting.backupsForm.remark = ''
+    loading.close();
+    getData()
+  }).finally(() => {
+    loading.close();
+  })
+};
+// sql列表 getSqlList
+const getSqlList = (val) => {
+  setting.loading = true;
+  if (val == 'open') {
+    setting.dialogShow = true
+    sqlList({tableName: setting.sqlName}).then(res => {
+      setting.loading = false;
+      setting.tableData = res.data;
+      setting.sqlTableData = JSON.parse(JSON.stringify(res.data));
+    })
+  } else {
+    if (setting.sqlName == '') {
+      setting.tableData = setting.sqlTableData
+      setting.loading = false
+    } else {
+      setting.tableData = setting.sqlTableData.filter(item => {
+        return item.tableName.indexOf(setting.sqlName) > -1 || item.tableComment.indexOf(setting.sqlName) > -1
+      })
+      setting.loading = false
+    }
+  }
+};
+// 手动备份 handBackups
+const handBackups = () => {
+  const loading = ElLoading.service({
+    lock: true,
+    text: '数据备份中...',
+    spinner: 'el-icon-loading',
+    background: 'rgba(0, 0, 0, 0.7)',
+  });
+  backups(setting.backupsForm).then(res => {
+    loading.close();
+    ElMessage.success('备份成功');
+    clearVal();
+    getData()
+  }).catch(err => {
+    loading.close();
+    ElMessage.error('备份失败');
+  })
 
+};
+// 下载备份
+const downloadBackups = (row) => {
+  let {filePath, remarks} = row
+  const a = document.createElement("a");
+  a.href = filePath;
+  a.download = remarks || 'download';
+  // a.target = '_blank';
+  document.body.appendChild(a);
+  a.click();
+  document.body.removeChild(a);
+  ElMessage({type: 'success', message: '已开始下载'})
 }
-const onApply = row => {
-  state.auditForm = {id: row.id, pass: true, reason: '',}
-  state.showAudit = true
+const handleSelectionChange = (val) => {
+  setting.backupsForm.tableNames = val.map(item => item.tableName).join(',')
 }
-const onAuditConfirm = () => {
-  if (state.saveAuditLoading) return
-  if (!state.auditForm.pass && !state.auditForm.reason) {
-    return ElMessage({type: 'error', message: '请填写备注'})
+// 关闭弹窗清空内容
+const clearVal = () => {
+  setting.sqlName = '';
+  setting.backupsForm = {
+    backupType: 1,  //1:合并导出,2:分表导出
+    tableNames: "", //表名 多个用逗号隔开
+    remark: "",      //备注
   }
-  state.saveAuditLoading = true
-  apply({...state.auditForm}).then(res => {
-    ElMessage({type: 'success', message: '已提交'})
-    state.showAudit = false
-    getData()
-  }).finally(() => state.saveAuditLoading = false)
+  setting.dialogShow = false;
 }
-const onShowRecord = row => {
-  state.auditRecord = []
-  applyRecord({id: row.id}).then(res => {
-    state.auditRecord = res.data || []
-    state.showAuditRecord = true
-  })
+// 每页条数
+const handleSizeChange = (val) => {
+  setting.page.current = 1;
+  setting.page.size = val;
+  getData();
 }
-const onTypeChange = type => {
-  state.active = type
-  getData()
+// 当前页
+const handleCurrentChange = (val) => {
+  setting.page.current = val;
+  getData();
 }
-const getData = () => {
-  if (state.dataLoading) return
-  let {current, size} = state.page
-  let params = {current, size}
-  if (state.active) params.status = state.active
-  if (state.userId) params.userId = state.userId
-  state.dataLoading = true
-  list(params).then(res => {
-    let {records, total} = res.data
-    state.page.total = total
-    records.forEach(i => i.select = false)
-    state.list = records
+// 添加文件
+const addFile = (file, fileList) => {
+  if (file.name.indexOf('.zip') == -1) {
+    ElMessage.error('请上传sql文件');
+    fileList.filter(item => {
+      if (item.name === file.name) {
+        fileList.splice(fileList.indexOf(item), 1)
+      }
+    })
+    return false
+  } else {
+    setting.fileList = fileList
+    uploadFile()
+  }
+}
+// 上传文件
+const uploadFile = () => {
+  const loading = ElLoading.service({
+    lock: true,
+    text: '文件上传中...',
+    spinner: 'el-icon-loading',
+    background: 'rgba(0, 0, 0, 0.7)',
+  });
+  const formData = new FormData();
+  formData.append('file', setting.fileList[0].raw);
+  upload(formData).then(res => {
+    setting.fileList = [];
+    ElMessage.success('上传成功');
+    // }
+    const fileForm = {...setting.sqlForm}
+    // 获取备份列表
+    fileForm.dataSource = 1
+    fileForm.size = 999999
+    fileForm.current = 1
+    backupsList(fileForm).then(res => {
+      setting.fileData = res.data?.records || [];
+    })
   }).finally(() => {
-    state.dataLoading = false
+    loading.close();
   })
 }
-const onReset = () => {
-  state.page.current = 1
-  state.page.size = 10
-  state.userId = ''
-  state.active = 0
-  getData()
-}
-const onSizeChange = size => {
-  state.page.size = size
-  state.page.current = 1
-  getData()
-}
 </script>
 <style lang="scss">
-@import "./develop.scss";
-</style>
+@import "./list.scss";
+</style>

src/views/backup/develop.scss → src/views/system/develop.scss


+ 218 - 0
src/views/system/develop.vue

@@ -0,0 +1,218 @@
+<template>
+  <div class="page page-develop">
+    <div class="header">
+      <div class="item" :class="{active:state.active===0}" @click="onTypeChange(0)">
+        全部({{ state.totals.total }})
+      </div>
+      <div class="item" :class="{active:state.active===1}" @click="onTypeChange(1)">
+        待审核({{ state.totals.apply }})
+      </div>
+      <div class="item" :class="{active:state.active===3}" @click="onTypeChange(3)">
+        未通过({{ state.totals.fail }})
+      </div>
+      <div class="item" :class="{active:state.active===2}" @click="onTypeChange(2)">
+        通过({{ state.totals.path }})
+      </div>
+    </div>
+    <div class="my-top">
+      <el-form class="inline-form" label-width="90px" inline size="default">
+        <el-form-item label="申请人">
+          <UserSelect ignore-tenant v-model="state.userId"></UserSelect>
+        </el-form-item>
+      </el-form>
+      <el-button @click="getData" size="default" :loading="state.dataLoading">查询</el-button>
+      <el-button @click="onReset" size="default" :loading="state.dataLoading">重置</el-button>
+      <div style="flex: 1"></div>
+      <el-button type="primary" @click="onApplyBatch" size="default">
+        <SvgIcon icon="batch" style="margin-right: 3px;"></SvgIcon>
+        批量审核
+      </el-button>
+    </div>
+    <div class="table-box">
+      <el-table :data="state.list" size="default" :header-row-style="{color:'#161616'}" height="100%">
+        <el-table-column label="" width="60px">
+          <template v-slot="{row}">
+            <el-checkbox v-model="row.select"></el-checkbox>
+          </template>
+        </el-table-column>
+        <el-table-column label="所属用户" prop="tenantName"></el-table-column>
+        <el-table-column label="申请人" prop="userNickName"></el-table-column>
+        <el-table-column label="申请人账号" prop="userId"></el-table-column>
+        <el-table-column label="申请时间" prop="createTime"></el-table-column>
+        <el-table-column label="认证信息" prop="userAccount"></el-table-column>
+        <el-table-column label="审核状态">
+          <template v-slot="{row}">
+            <div class="status-box" v-if="row.status===3">
+              <div class="point" style="background-color: #bfbfbf"></div>
+              <span>未通过</span>
+            </div>
+            <div class="status-box" v-if="row.status===2">
+              <div class="point" style="background-color: #18b633"></div>
+              <span>通过</span>
+            </div>
+            <div class="status-box" v-if="row.status===1">
+              <div class="point" style="background-color: #eb5a10"></div>
+              <span>待审核</span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" width="160px">
+          <template v-slot="{row}">
+            <el-button type="text" @click="onApply(row)">审核</el-button>
+            <el-button type="text" @click="onShowRecord(row)">审核详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <el-pagination
+      :current-page.sync="state.page.current" :page-size="state.page.size" :page-sizes="[10, 20, 30, 40]"
+      :total="state.page.total" @current-change="getData"
+      background layout="total, sizes, prev, pager, next, jumper" @size-change="onSizeChange" class="my-page"
+    ></el-pagination>
+    <el-dialog v-model="state.showAudit" append-to-body width="500px" title="审核">
+      <el-form label-width="70px">
+        <el-form-item label="是否通过">
+          <el-radio-group v-model="state.auditForm.pass">
+            <el-radio :label="true">通过</el-radio>
+            <el-radio :label="false">驳回</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="备注" required v-if="!state.auditForm.pass">
+          <el-input type="textarea" :rows="3" placeholder="请输入备注" v-model="state.auditForm.reason"></el-input>
+        </el-form-item>
+      </el-form>
+      <div class="dialog-btns">
+        <el-button @click="state.showAudit=false" size="default">取消</el-button>
+        <el-button @click="onAuditConfirm" type="primary" size="default" :loading="state.saveAuditLoading">确定
+        </el-button>
+      </div>
+    </el-dialog>
+    <el-dialog v-model="state.showAuditRecord" append-to-body width="600px" title="审核详情">
+      <el-table :data="state.auditRecord" max-height="500px">
+        <el-table-column label="时间" prop="createTime" width="160px"></el-table-column>
+        <el-table-column label="操作人" prop="createUserName"></el-table-column>
+        <el-table-column label="审核状态">
+          <template v-slot="{row}">
+            <div class="status-box" v-if="row.status===3">
+              <div class="point" style="background-color: #bfbfbf"></div>
+              <span>未通过</span>
+            </div>
+            <div class="status-box" v-if="row.status===2">
+              <div class="point" style="background-color: #18b633"></div>
+              <span>通过</span>
+            </div>
+            <div class="status-box" v-if="row.status===1">
+              <div class="point" style="background-color: #eb5a10"></div>
+              <span>待审核</span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="备注">
+          <template v-slot="{row}">
+            <span>{{ row.remark }}</span>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="dialog-btns">
+        <el-button @click="state.showAuditRecord=false" type="primary" size="default">确定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import {list, apply, applyRecord, getTotal} from '/@/api/develop'
+import UserSelect from "/src/components/UserSelect/index.vue";
+import SvgIcon from "/src/components/svgIcon/index.vue";
+import {ElMessage} from "element-plus";
+let state = reactive({
+  totals: {total: 0, apply: 0, fail: 0, path: 0,},
+  active: 0,
+  page: {total: 0, current: 1, size: 10},
+  list: [],
+  userId: '',
+  dataLoading: false,
+  showAudit: false,
+  auditForm: {},
+  saveAuditLoading: false,
+  showAuditRecord: false,
+  auditRecord: [],
+  batchFlag: false,
+})
+onMounted(() => {
+  getData()
+})
+const onApplyBatch = () => {
+  state.batchFlag = true
+  state.auditForm = {id: '', pass: true, reason: '',}
+  state.showAudit = true
+}
+const onApply = row => {
+  state.batchFlag = false
+  state.auditForm = {id: row.id, pass: true, reason: '',}
+  state.showAudit = true
+}
+const onAuditConfirm = () => {
+  if (state.saveAuditLoading) return
+  if (!state.auditForm.pass && !state.auditForm.reason) {
+    return ElMessage({type: 'error', message: '请填写备注'})
+  }
+  state.saveAuditLoading = true
+  let data = {pass: state.auditForm.pass, reason: state.auditForm.reason,}
+  if (state.batchFlag) {
+    data.ids = state.list.filter(i => i.select).map(i => i.id)
+  } else {
+    data.ids = [state.auditForm.id]
+  }
+  apply(data).then(res => {
+    ElMessage({type: 'success', message: '已提交'})
+    state.showAudit = false
+    getData()
+  }).finally(() => state.saveAuditLoading = false)
+}
+const onShowRecord = row => {
+  state.auditRecord = []
+  applyRecord({id: row.id}).then(res => {
+    state.auditRecord = res.data || []
+    state.showAuditRecord = true
+  })
+}
+const onTypeChange = type => {
+  state.active = type
+  getData()
+}
+const getData = () => {
+  if (state.dataLoading) return
+  let {current, size} = state.page
+  let params = {current, size}
+  if (state.active) params.status = state.active
+  if (state.userId) params.userId = state.userId
+  state.dataLoading = true
+  list(params).then(res => {
+    let {records, total} = res.data
+    state.page.total = total
+    records.forEach(i => i.select = false)
+    state.list = records
+  }).finally(() => {
+    state.dataLoading = false
+  })
+  getTotal().then(res => {
+    let {all, notReview, reject, reviewed} = res.data
+    state.totals = {total: all, apply: notReview, fail: reject, path: reviewed,}
+  })
+}
+const onReset = () => {
+  state.page.current = 1
+  state.page.size = 10
+  state.userId = ''
+  state.active = 0
+  getData()
+}
+const onSizeChange = size => {
+  state.page.size = size
+  state.page.current = 1
+  getData()
+}
+</script>
+<style lang="scss">
+@import "develop";
+</style>