Explorar o código

增加数据备份计划模块口,增加数据备份日志模块,增加操作日志查询模块

chenwen hai 1 ano
pai
achega
077d515367

+ 32 - 0
src/api/dbBackup.js

@@ -0,0 +1,32 @@
+import request from '../utils/request';
+
+const api={}
+
+api.load=(sort)=>{
+	return request({
+	    url: '/backup/schedule/get',
+	    method: 'post',
+		data:  {sort}
+	});
+}
+
+api.save=(data)=>{
+	let url='/backup/schedule/add'
+	if(data.scheduleId){
+		url='/backup/schedule/update'
+	}
+	return request({
+	    url: url,
+	    method: 'post',
+		data:  data
+	});
+}
+
+api.getBackupTarget=()=>{
+	return request({
+	    url: '/backup/schedule/tabdic/load',
+	    method: 'get'
+	});
+}
+
+export  default api

+ 135 - 0
src/pages/sys/DbBackupLog.vue

@@ -0,0 +1,135 @@
+<template>
+	<div class="qpage">
+		<el-form :inline="true" :model="queryForm" class="query-form-inline"  label-width="auto">
+		  <el-form-item label="备份对象">
+		    <el-select v-model="queryForm.tabsort" clearable>
+				<el-option v-for="(item,index) in backupTargets" :key="index" :label="item.name" :value="item.sort"/>
+			</el-select>
+		  </el-form-item>
+		  
+		  <el-form-item label="操作时间">
+		    <el-date-picker
+		            v-model="queryForm.dataTime"
+		            type="daterange"
+		            start-placeholder="开始时间"
+		            end-placeholder="截止时间"
+		            :unlink-panels="true"
+		    		   value-format="YYYY-MM-DD"
+		  						  
+		          />
+		  </el-form-item>
+		  
+		  <el-form-item>
+		    <el-button type="primary" :loading="isQuerying" @click="queryHandle">检索</el-button>
+		  </el-form-item>
+		</el-form>
+		
+		<div class="qpage-body">
+			<CrudTable 
+			ref="crudTable"
+			page-info-opts="total, prev, pager, next,sizes"
+			url="/backup/log/query"
+			:pageSize="20"
+			>
+			  
+				<template #tabColumns={indexGenerate}>
+					  <el-table-column type="index" :index="indexGenerate" label="序号" width="60" align="center"/>
+					  <el-table-column prop="deviceName" label="备份任务" width="160" />
+					  <el-table-column prop="startTIme" label="开始时间" width="160" />
+					  <el-table-column prop="endTime" label="结束时间" width="160" />
+					  <el-table-column prop="operator" label="备份人" width="120" />
+					  <el-table-column prop="status" label="状态" width="120" />
+					  <el-table-column prop="note" label="备注" width="120" />
+					  
+				</template>
+				
+			</CrudTable>
+		</div>
+		
+		
+		
+	</div>
+</template>
+
+<script setup>
+	import {reactive,ref,onMounted,toRaw} from 'vue'
+	import CrudTable from "../../components/crudtable/CrudTable.vue"
+	import {ElMessageBox,ElMessage} from 'element-plus'
+	import api from "../../api/dbBackup.js"
+	
+	const crudTable=ref(null)
+	
+	const isQuerying=ref(false)
+	
+	
+	
+	const queryForm = reactive({
+	  tabsort: null,
+	  dataTime:null
+	})
+	
+	const backupTargets=ref([])
+	
+	const queryHandle=()=>{
+		isQuerying.value=true
+		let formdata=toRaw(queryForm)
+		let [startTime,endTime]=formdata.dataTime||[]
+		formdata['startTime']=startTime
+		formdata['endTime']=endTime
+		crudTable.value.query(formdata).then(resp=>{
+			isQuerying.value=false
+		})
+		
+	}
+	
+	onMounted(()=>{
+		load()
+	})
+	
+	const load=()=>{
+		api.getBackupTarget().then(resp=>{
+			if(resp.code!=0){
+				ElMessage.error(resp.msg || '加载数据失败')
+			}
+			else{
+				backupTargets.value=respProcess(resp.data)
+			}
+		}).catch(err=>{
+			console.log(err)
+			ElMessage.error('加载数据出错')
+		})
+	}
+	
+	const respProcess=(datas)=>{
+		let sortary=[],sortidx={}
+		datas.forEach(data=>{
+			if(!sortidx[data.tagCode]){
+				sortary.push({sort:data.tagCode,name:data.tagName})
+				sortidx[data.tagCode]=true
+			}
+		})
+		let defaultBack={sort:'glb',name:'全部表结构'}
+		return [defaultBack,...sortary]
+	}
+	
+
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+</script>
+
+<style scoped>
+	@import url('../../assets/css/qpage.css');
+	
+	.edit-form-item{
+		width:260px;
+	}
+</style>

+ 204 - 0
src/pages/sys/DbBackupSchedule.vue

@@ -0,0 +1,204 @@
+<template>
+	<div class="page-container">
+		<el-form :model="formModel" label-width="120px">
+		<el-card class="backup-left">
+			<el-collapse v-model="activeNames">
+				    <el-collapse-item  v-for="(sort,index) in backupTargets" :key="index" :name="sort.sort" >
+						<template  #title>
+							<el-checkbox v-model="formModel.targetSort" :label="sort.name+'('+sort.tabs.length+')'"  :true-label="sort.sort" false-label="" @click.stop="" @change="selectBackupTarget"/>
+						</template>
+						<div v-for="(tab,index2) in sort.tabs" :key="index2">{{tab.itemName}}【{{tab.itemCode}}】</div>
+					</el-collapse-item>
+					
+					
+				</el-collapse>
+			</el-card>
+			
+			<el-card class="backup-right">
+				<div v-show="formModel.targetSort!='glb'">
+					<el-form-item label="备份对象">
+						{{formModel?.sortName}}
+					</el-form-item>
+					<el-form-item label="备份模式">
+						{{formModel?.backupMode=='full'?'全量':'增量'}}
+					</el-form-item>
+					
+					<el-form-item label="重复模式">
+						<label>每天</label>
+						<!-- <el-checkbox v-model="formModel.repeatMode" label="每天"/>
+						<el-checkbox v-model="formModel.repeatMode" label="每周"/>
+						<el-checkbox v-model="formModel.repeatMode" label="每月"/> -->
+						
+					</el-form-item>
+					
+					<el-form-item label="备份时间">
+						<el-time-picker v-model="formModel.backupTime" placeholder="选择备份时点"  format="HH:mm" value-format="HH:mm"/>
+					</el-form-item>
+					<el-form-item label="状态">
+						<el-switch v-model="formModel.disableIf" active-text="启用" inactive-text="禁用" :active-value="false" :inactive-value="true"/>
+					</el-form-item>
+					<el-form-item label=" ">
+						<el-button type="primary" @click="save">应用</el-button>
+					</el-form-item>
+				</div>
+					
+				<div v-show="formModel.targetSort=='glb'">
+					<el-form-item label="备份对象">
+						{{formModel?.sortName}}
+					</el-form-item>
+					<el-form-item label="备份内容">
+						表结构
+					</el-form-item>
+					<el-form-item label=" ">
+						<el-button type="primary">开始手动备份</el-button>
+					</el-form-item>
+				</div>	
+				
+			</el-card>
+		</el-form>
+	</div>
+</template>
+
+<script setup>
+	import {ref,reactive,toRaw,onMounted } from 'vue'
+	import api from "../../api/dbBackup.js"
+	import {ElMessageBox,ElMessage} from 'element-plus'
+	
+	const activeNames=ref(['gather'])
+	
+	const formModel=reactive({
+		scheduleId:null,
+		backupMode:null,
+		repeatMode:null,
+		backupTime:'',
+		targetSort:null,
+		sortName:null,
+		disableIf:false,
+		backupCorn:null,
+		backupCon:null
+	})
+	
+	const backupTargets=ref([])
+	
+	const selectTarget=reactive({})
+	
+	onMounted(()=>{
+		api.getBackupTarget().then(resp=>{
+			if(resp.code!=0){
+				ElMessage.error(resp.msg || '加载数据失败')
+			}
+			else{
+				backupTargets.value=respProcess(resp.data)
+			}
+		}).catch(err=>{
+			console.log(err)
+			ElMessage.error('加载数据出错')
+		})
+	})
+	
+	const respProcess=(datas)=>{
+		let sortary=[],sortidx={}
+		datas.forEach(data=>{
+			if(sortidx[data.tagCode]==null){
+				sortary.push({sort:data.tagCode,name:data.tagName,tabs:[]})
+				sortidx[data.tagCode]=sortary.length-1
+			}
+			sortary[sortidx[data.tagCode]]['tabs'].push(data)
+		})
+		let defaultBack={sort:'glb',name:'全部表结构',tabs:[{itemName:'全部表结构',itemCode:'all table'}]}
+		return [defaultBack,...sortary]
+	}
+	
+	//选择分类进行备份设置
+	const selectBackupTarget=(val)=>{
+		//console.log(val)
+		if(val.length==0){
+			return
+		}
+		let selsort=toRaw(backupTargets.value).filter(itm=>itm.sort==val)
+		//console.log(selsort[0])
+		let {sort:targetSort,name:sortName}=selsort[0]
+		let backupMode=targetSort=='gather'?'increase':'full'
+		let backupCon=targetSort=='glb'?'onlyCreate':'onlyData'
+		Object.assign(formModel,{targetSort,sortName,backupMode,backupCon,disableIf:false,backupTime:null})
+		
+		load(targetSort)
+	}
+	
+	const load=(sort)=>{
+		api.load(sort).then(resp=>{
+			if(resp.code!=0){
+				ElMessage.error(resp.msg || '加载数据失败')
+				return
+			}
+			if(resp.data){
+				formModel.scheduleId=resp.data.scheduleId
+				formModel.backupTime=resp.data.backupTime
+				formModel.disableIf=resp.data.disableIf
+			}
+			
+		}).catch(err=>{
+			console.log(err)
+			ElMessage.error('加载数据出错')
+		})
+	}
+	
+	const save=()=>{
+		api.save(toRaw(formModel)).then(resp=>{
+			if(resp.code==0){
+				ElMessage.success('操作成功')
+				load(formModel.targetSort)
+			}
+			else{
+				ElMessage.error(resp.msg || '操作失败')
+			}
+		}).catch(err=>{
+			console.log(err)
+			ElMessage.error('操作出错')
+		})
+	}
+</script>
+
+<style scoped>
+	.page-container{
+		padding:5px 10px;
+		height: 100%;
+		box-sizing: border-box;
+	}
+	
+	.el-form{
+		display: flex;
+		flex-flow: row nowrap;
+		height: 100%;
+		box-sizing: border-box;
+	}
+	
+	.backup-left{
+		width:500px;
+	}
+	
+	.backup-left:deep(.el-card__body){
+		height: 100%;
+		overflow-y: auto;
+		box-sizing: border-box;
+	}
+	
+	.backup-left:deep(.el-collapse-item__content){
+		padding-left:15px;
+	}
+	
+	.backup-left:deep(.el-checkbox__label){
+		font-size:16px;
+		font-weight: bold;
+	}
+	
+	.backup-right{
+		flex:1;
+		margin-left:5px;
+	}
+	
+	.el-collapse-item div{
+		font-size: 14px;
+	}
+	
+</style>

+ 86 - 0
src/pages/sys/OperationLog.vue

@@ -0,0 +1,86 @@
+<template>
+<div class="qpage">
+	<el-form :inline="true" :model="queryForm" class="query-form-inline">
+	   <el-form-item label="操作人">
+	     <el-input v-model="queryForm.usName" placeholder="请输入姓名关键字" clearable style="width:160px;"/>
+	   </el-form-item>
+	   
+	   <el-form-item label="操作时间">
+	     <el-date-picker
+	             v-model="queryForm.dataTime"
+	             type="daterange"
+	             start-placeholder="开始时间"
+	             end-placeholder="截止时间"
+	             :unlink-panels="true"
+	     		   value-format="YYYY-MM-DD"
+	   						  
+	           />
+	   </el-form-item>
+	   
+	   <el-form-item>
+	     <el-button type="primary" :loading="isQuerying" @click="queryHandle">检索</el-button>
+	   </el-form-item>
+	</el-form>
+	 
+	<div class="qpage-body">
+		<CrudTable
+		ref="crudTable"
+		page-info-opts="total, prev, pager, next,sizes"
+		url="/log/query"
+		:pageSize="20"
+		>
+		  
+		  <template #tabColumns>
+			  <el-table-column fixed type="index" label="序号" width="60" align="center"/>
+			  <el-table-column fixed prop="operatorName" label="操作人" width="100" />
+			  <el-table-column prop="operateTime" label="操作时间" width="160" />
+			  <el-table-column prop="fromIp" label="来源IP" width="150" />
+			  <el-table-column prop="operateDesc" label="操作内容" width="500" />
+			
+			  
+		  </template>			
+		</CrudTable> 
+		
+	</div>
+	 
+	
+ </div>
+  
+</template>
+
+<script  setup>
+	import {reactive,ref,toRaw} from 'vue'
+	import {ElMessageBox,ElMessage} from 'element-plus'
+	import CrudTable from "../../components/crudtable/CrudTable.vue"
+	const crudTable=ref(null)
+	
+	const isQuerying=ref(false)
+	
+	
+	const queryForm = reactive({
+		usName: null,
+		dataTime:null
+	})
+	
+	const queryHandle=()=>{
+		isQuerying.value=true
+		let formdata=toRaw(queryForm)
+		let [startTime,endTime]=formdata.dataTime||[]
+		formdata['startTime']=startTime
+		formdata['endTime']=endTime
+		crudTable.value.query(formdata).then(resp=>{
+			isQuerying.value=false
+		})
+		
+	}
+	
+	
+	
+	
+	
+</script>
+
+<style scoped>
+	@import url('../../assets/css/qpage.css');
+	
+</style>