From 14650398d18ad62cdd1a465bd362f528a119f8d0 Mon Sep 17 00:00:00 2001
From: hdm <hdm58@qq.com>
Date: Thu, 5 May 2022 14:33:08 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=95=B0=E6=8D=AE=E5=A4=87?=
 =?UTF-8?q?=E4=BB=BD=E5=92=8C=E8=BF=98=E5=8E=9F=E5=8A=9F=E8=83=BD=E6=A8=A1?=
 =?UTF-8?q?=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/home/controller/Database.php       | 342 +++++++------
 app/home/view/database/backuplist.html | 108 +++-
 app/home/view/database/database.html   |  91 +++-
 app/home/view/log/index.html           |  12 +-
 app/install/data/oa_reset.sql          | 669 +++++++++++++++++++++++++
 extend/backup/Backup.php               | 363 +++++++-------
 6 files changed, 1208 insertions(+), 377 deletions(-)
 create mode 100644 app/install/data/oa_reset.sql

diff --git a/app/home/controller/Database.php b/app/home/controller/Database.php
index 7b6d992..de4577d 100644
--- a/app/home/controller/Database.php
+++ b/app/home/controller/Database.php
@@ -11,171 +11,211 @@ namespace app\home\controller;
 
 use app\base\BaseController;
 use backup\Backup;
+use think\facade\Session;
 use think\facade\Db;
 use think\facade\View;
 
 class Database extends BaseController
 {
-    protected $db = '', $datadir;
-    public function initialize()
+	//数据表列表
+	public function database()
     {
-        parent::initialize();
-        $this->config = array(
-            'path' => './backup/', // 数据库备份路径
-            'part' => 20971520, // 数据库备份卷大小
-            'compress' => 0, // 数据库备份文件是否启用压缩 0不压缩 1 压缩
-            'level' => 9, // 数据库备份文件压缩级别 1普通 4 一般  9最高
-        );
-        $this->db = new Backup($this->config);
-    }
-
-    // 数据列表
-    public function database()
-    {
-        if (request()->isAjax()) {
-            // 数据信息
-            $list = $this->db->dataList();
-            // 计算总大小
-            $total = 0;
-            foreach ($list as $k => $v) {
-                $total += $v['data_length'];
-                $list[$k]['data_size'] = $v['data_length'];
-                $list[$k]['data_length'] = format_bytes($v['data_length']);
+		if (request()->isAjax()) {
+			// 数据信息
+			$db = new Backup();
+			$list = $db->dataList();
+			// 计算总大小
+			$total = 0;
+			foreach ($list as $k => $v) {
+				$total += $v['data_length'];
+				$list[$k]['data_size'] = $v['data_length'];
+				$list[$k]['data_length'] = format_bytes($v['data_length']);
+			}
+			// 提示信息
+			$dataTips = '数据库中共有<strong> ' . count($list) . '</strong> 张表,共计 <strong>' . format_bytes($total) . '</strong>大小。';
+			$data['data'] = $list;
+			return table_assign(0, $dataTips, $data);
+		}
+		return view();
+    }	
+	
+	//备份数据
+	public function backup()
+	{
+		$db= new Backup();
+		if(request()->isPost()){
+			$tables=get_params('tables');           
+			$fileinfo  =$db->getFile();
+			//检查是否有正在执行的任务
+			$lock = "{$fileinfo['filepath']}backup.lock";
+			if(is_file($lock)){
+			    return to_assign(2, '检测到有一个备份任务未完成');
+			} else {
+               //创建锁文件
+               file_put_contents($lock,time());
             }
-            // 提示信息
-            $dataTips = '数据库中共有<strong> ' . count($list) . '</strong> 张表,共计 <strong>' . format_bytes($total) . '</strong>大小。';
-            $data['data'] = $list;
-            return table_assign(0, $dataTips, $data);
-        }
-        return view();
-    }
-
-    // 备份
-    public function backup()
-    {
-        $tables = get_params('id');
-        if (!empty($tables)) {
-            $tables = explode(',', $tables);
-            foreach ($tables as $table) {
-                $this->db->setFile()->backup($table, 0);
+            // 检查备份目录是否可写
+            if(!is_writeable($fileinfo['filepath'])){
+				return to_assign(1, '备份目录不存在或不可写,请检查后重试!');
             }
-            add_log('bak');
-            return to_assign(0, '备份成功!');
-        } else {
-            return to_assign(1, '请选择要备份的表');
-        }
-    }
+ 
+			//缓存锁文件
+			Session::set('lock', $lock);
+			//缓存备份文件信息
+			Session::set('backup_file', $fileinfo['file']);
+			//缓存要备份的表
+			Session::set('backup_tables', $tables);
+			//创建备份文件
+			if(false !== $db->Backup_Init()){
+				return to_assign(0, '初始化成功',['tab'=>['id' => 0, 'start' => 0,'table'=>$tables[0]]]);
+			}else{
+				return to_assign(1, '初始化失败,备份文件创建失败!');
+			}
+		}else if(request()->isGet()){
+			$tables = Session::get('backup_tables');
+			$file=Session::get('backup_file');
+			$id=get_params('id'); 
+			$start=get_params('start');
+			$start= $db->setFile($file)->backup($tables[$id], $start);
+			if(false === $start){
+				return to_assign(1, '备份出错!');
+			}else if(0 === $start){
+				if(isset($tables[++$id])){
+				   return to_assign(0, '备份完成',['tab'=>['id' => $id, 'start' => 0,'table'=>$tables[$id-1]]]);
+				} else { //备份完成,清空缓存
+                   unlink(Session::get('lock'));
+                   Session::delete('backup_tables');
+                   Session::delete('backup_file');
+				   add_log('bak');
+				   return to_assign(0, '备份完成',['tab'=>['start' => 'ok','table'=>$tables[$id-1]]]);
+               }
+           }
+		}else{
+		   return to_assign(1, '参数错误!');
+		}
+	} 
 
-    // 优化
-    public function optimize()
-    {
-        $tables = get_params('id');
-        if (empty($tables)) {
-            return to_assign(0, '请选择要优化的表');
+	//优化表
+	public function optimize($tables= null)
+	{
+        $db= new Backup();
+		//return to_assign(0, $db->optimize($tables));
+        if($db->optimize($tables)){
+			add_log('optimize');
+			return to_assign(0, '数据表优化完成');
+        }else{
+			return to_assign(1, '数据表优化出错请重试');
         }
-        $tables = explode(',', $tables);
-        if ($this->db->optimize($tables)) {
-            add_log('optimize');
-            return to_assign(0, '数据表优化成功!');
-        } else {
-            return to_assign(1, '数据表优化出错请重试');
-        }
-    }
-
-    // 修复
-    public function repair()
-    {
-        $tables = get_params('id');
-        if (empty($tables)) {
-            return to_assign(1, '请选择要修复的表');
-        }
-        $tables = explode(',', $tables);
-        if ($this->db->repair($tables)) {
-            add_log('repair');
-            return to_assign(0, '数据表修复成功');
-        } else {
-            return to_assign(1, '数据表修复出错请重试');
-        }
-    }
-
-    // 还原列表
-    public function backuplist()
-    {
-        // 数据信息
-        $list = $this->db->fileList();
-        $listNew = [];
-        $indx = 0;
+	}
+	
+	//修复表
+	public function repair($tables= null)
+	{
+		$db= new Backup();
+		//return to_assign(0, $db->repair($tables));
+		if($db->repair($tables)){
+			add_log('repair');
+			return to_assign(0, '数据表修复完成');
+		}else{
+			return to_assign(1, '数据表修复出错请重试');
+		}
+	}
+	
+	
+	//备份文件列表
+	public function backuplist()
+	{
+		$db= new Backup();
+		$list = $db->fileList();
+		$fileinfo  =$db->getFile();
+		$lock = "{$fileinfo['filepath']}backup.lock";
+		$lock_time = 0;	
+		if(is_file($lock)){
+			$lock_time = file_get_contents($lock);
+		}
+		$listNew = [];
+		$indx = 0;
         foreach ($list as $k => $v) {
             $listNew[$indx]['time'] = $k;
-            $listNew[$indx]['data'][] = $v;
+            $listNew[$indx]['timespan'] = $v['time'];
+            $listNew[$indx]['data'] = $v;
             $indx++;
-            // $listNew[$k]['list'] = $list[$k];
         }
         $list = $listNew;
         array_multisort(array_column($list, 'time'), SORT_DESC, $list);
-        return view('', ['list' => $list]);
-    }
-
-    // 执行还原数据库操作
-    public function import(int $id)
-    {
-        $list = $this->db->getFile('timeverif', $id);
-        $this->db->setFile($list)->import(1);
-        add_log('reduction');
-        return to_assign(0, '还原成功!');
-    }
-
-    // 下载
-    public function downfile(string $name)
-    {
-        $file_name = $name; //得到文件名
-        header("Content-type:text/html;charset=utf-8");
-        $file_name = iconv("utf-8", "gb2312", $file_name); // 转换编码
-        $file_sub_path = $this->config['path']; //确保文件在这个路径下面,换成你文件所在的路径
-        $file_path = $file_sub_path . $file_name;
-        # 将反斜杠 替换成正斜杠
-        $file_path = str_replace('\\', '/', $file_path);
-        if (!file_exists($file_path)) {
-            $this->error($file_path);exit; //如果提示这个错误,很可能你的路径不对,可以打印$file_sub_path查看
-        }
-        $fp = fopen($file_path, "r"); // 以可读的方式打开这个文件
-        # 如果出现图片无法打开,可以在这个位置添加函数
-        ob_clean(); # 清空擦掉,输出缓冲区。
-        $file_size = filesize($file_path);
-        //下载文件需要用到的头
-        Header("Content-type: application/octet-stream");
-        Header("Accept-Ranges: bytes");
-        Header("Accept-Length:" . $file_size);
-        Header("Content-Disposition: attachment; filename = " . $file_name);
-        $buffer = 1024000;
-        $file_count = 0;
-        while (!feof($fp) && $file_count < $file_size) {
-            $file_con = fread($fp, $buffer);
-            $file_count += $buffer;
-            echo $file_con;
-        }
-        fclose($fp); //关闭这个打开的文件
-    }
-
-    // 删除sql文件
-    public function del(string $id)
-    {
-        if (request()->isAjax()) {
-            if (strpos($id, ',') !== false) {
-                $idArr = explode(',', $id);
-                foreach ($idArr as $k => $v) {
-                    $this->db->delFile($v);
+		return view('',['list'=>$list,'lock_time' => $lock_time]);
+	}
+	
+	//数据还原
+	public function import($time = 0, $part = null, $start = null)
+	{
+		$db= new Backup();
+		$time =(int)$time;
+		if(is_numeric($time) && is_null($part) && is_null($start)){
+			$list  = $db->getFile('timeverif',$time);
+			if(is_array($list)){
+				Session::set('backup_list', $list);
+				return to_assign(0, '初始化完成',array('part' => 1, 'start' => 0,'time' => $time));
+			}else{
+				return to_assign(1, '备份文件可能已经损坏,请检查');
+			}
+		}else if(is_numeric($part) && is_numeric($start)){ 
+            $list=Session::get('backup_list');
+			$part =(int)$part;
+			$start =(int)$start;
+            $start= $db->setFile($list)->import($start,$time,$part);               
+            if(false===$start){
+				return to_assign(1, '还原数据出错,请重试');
+            }elseif(0 === $start){
+                if(isset($list[++$part])){
+                    $data = array('part' => $part, 'start' => 0,'time' => $time);
+					return to_assign(0, "正在还原...卷{$part},请勿关闭当前页面",$data);
+                } else {
+                    Session::delete('backup_list');
+					return to_assign(0, '还原数据成功');
                 }
-                add_log('delete');
-                return to_assign(0, "删除成功");
-            }
-            if ($this->db->delFile($id)) {
-                add_log('delete');
-                return to_assign(0, "删除成功");
-            } else {
-                return to_assign(1, "备份文件删除失败,请检查文件权限");
-            }
-        }
-    }
-
-}
+            }else{
+                $data = array('part' => $part, 'start' => $start[0],'time' => $time);
+                if($start[1]){
+                    $rate = floor(100 * ($start[0] / $start[1]));
+					return to_assign(0, "正在还原...卷{$part} ({$rate}%),请勿关闭当前页面",$data);
+                } else {
+                    $data['gz'] = 1;
+                    return to_assign(0, "正在还原...卷{$part},请勿关闭当前页面",$data);
+                }
+                return to_assign(0, "正在还原...卷{$part},请勿关闭当前页面");                   
+            }             
+		}else{
+		   return to_assign(1, "参数错误");
+		}       
+	}
+	/**
+    * 删除备份文件
+    */
+	public function del($time = 0,$lock=0){
+		$db= new Backup();
+		if($lock==1){
+			$fileinfo  =$db->getFile();
+			$lock = "{$fileinfo['filepath']}backup.lock";
+			if(is_file($lock)){
+				$time = file_get_contents($lock);
+				unlink($lock);
+			}
+		}	
+		if($db->delFile((int)$time)){
+			add_log('delete');
+			return to_assign(0, '删除成功');
+		}else{
+			return to_assign(0, '删除失败,请检查权限');
+		}
+	}
+    /**
+    * 下载备份文件
+    */
+	public function downfile($time = 0,$part=0){
+		$db= new Backup();
+		add_log('down');
+		$db->downloadFile((int)$time,$part-1);
+	}
+	
+}
\ No newline at end of file
diff --git a/app/home/view/database/backuplist.html b/app/home/view/database/backuplist.html
index 92598b7..08b08d0 100644
--- a/app/home/view/database/backuplist.html
+++ b/app/home/view/database/backuplist.html
@@ -5,10 +5,10 @@
 	<table cellspacing="0" cellpadding="0" border="0" class="layui-table">
 		<tr style="background-color: #f5f5f5; text-align: center;">
 			<th style=" text-align: center; font-weight: 800;"><span>文件名称</span></th>
-			<th style=" text-align: center; font-weight: 800;"><span>分卷</span></th>
-			<th style=" text-align: center; font-weight: 800;"><span>文件大小</span></th>
 			<th style=" text-align: center; font-weight: 800;"><span>文件格式</span></th>
 			<th style=" text-align: center; font-weight: 800;"><span>分隔符</span></th>
+			<th style=" text-align: center; font-weight: 800;"><span>文件总大小</span></th>
+			<th style=" text-align: center; font-weight: 800;"><span>分卷总数</span></th>
 			<th style=" text-align: center; font-weight: 800; width:222px"><span>操作</span></th>
 		</tr>			
 		{empty name="list"}
@@ -18,26 +18,32 @@
 		{/empty}
 			{volist name="list" id="vo" key="k"}
 			<tr style="background-color: #fafafa;">
-				<td colspan="6"><strong>备份时间:{$vo.time}</strong></td>
-			</tr>
-			{volist name="vo.data" id="voo"}
-			<tr>
-				<td>
-					{:date("Ymd",$voo.time)}{$voo.compress}{:date("His",$voo.time)}{$voo.compress}{$voo.part}.sql
-				</td>				
-				<td align="center"><span>{$voo.part}</span></td>
-				<td align="center"><span>{:format_bytes($voo.size)}</span></td>
+				<td><strong>备份时间:{$vo.time}</strong>{if $vo.timespan == $lock_time}<span style="color:red; margin-left:20px;">该备份不是完整备份,请删除重新备份</span>{/if}</td>
 				<td align="center"><span>.sql</span></td>
-				<td align="center"><span>{$voo.compress}</span></td>
-				<td align="center" data-id='{$voo.time}'>
-					<div class="layui-btn-group" data-id='{$voo.time}'>
+				<td align="center"><span>{$vo.data.compress}</span></td>
+				<td align="center"><span>{:format_bytes($vo.data.size)}</span></td>
+				<td align="center"><span>{$vo.data.part}</span></td>
+				<td align="center">
+					<div class="layui-btn-group" data-time='{$vo.timespan}'>
+						{if $vo.timespan == $lock_time}
+						<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="reset">清除不完整的备份</a>
+						{else/}
 						<a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="import">数据还原</a>
-						<a class="layui-btn layui-btn-xs" href='/home/database/downfile?name={:date("Ymd",$voo.time)}{$voo.compress}{:date("His",$voo.time)}{$voo.compress}{$voo.part}.sql'>备份下载</a>
 						<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">备份删除</a>
+						{/if}
 					</div>
 				</td>
 			</tr>
-			{/volist}
+			{for start="0" end="$vo.data.part" step="1"}
+			<tr>
+				<td colspan="5">
+					{:date("Ymd",$vo.timespan)}{$vo.data.compress}{:date("His",$vo.timespan)}{$vo.data.compress}{$i+1}.sql
+				</td>
+				<td align="center">
+					<a class="layui-btn layui-btn-xs" href='/home/database/downfile?time={$vo.data.time}&part={$i+1}'>下载备份(分卷{$i+1})</a>				
+				</td>
+			</tr>
+			{/for}
 			{/volist}
 	</table>
 </div>
@@ -49,43 +55,93 @@
 {block name="script"}
 <script>
 	function init(layui) {
-		var table = layui.table,
-			form = layui.form;
+		function importData(data){
+			if(data.code==0){
+				console.log(data.msg);
+				layer.closeAll();
+				layer.msg(data.msg,{time: 200000});
+				if($.isPlainObject(data.data)){
+					$.ajax({
+						url: "/home/database/import",
+						type:'get',
+						data:{"part" : data.data.part, "start" : data.data.start,time:data.data.time},
+						success: function (res) {
+							importData(res);
+						}
+					})					 
+				}else {
+					layer.msg(data.msg);
+					window.onbeforeunload = function(){ return null; }
+				}
+			} else {
+				layer.msg(data.msg);
+			}
+		}	
 		//监听行工具事件
 		$('[lay-event="import"]').on('click',function(){
-			var id=$(this).parent().data('id');
+			var time=$(this).parent().data('time');
 			layer.confirm('确认要还原该备份吗?', {
 					icon: 3,
 					title: '提示'
 				}, function (index) {
+				    layer.msg("数据还原中...",{time: 200000});				
 					$.ajax({
-						url: "/home/database/import?id="+id,
+						url: "/home/database/import?time="+time,
+						type:'get',
 						success: function (res) {
-							layer.msg(res.msg);
+							importData(res);
 						}
 					})
-					layer.close(index);
-				});
+				window.onbeforeunload = function(){ return "正在还原数据库,请不要关闭!" }
+				layer.close(index);
+			});
+			return false;
 		})
 
 		$('[lay-event="del"]').on('click',function(){
-			var id=$(this).parent().data('id');
+			var time=$(this).parent().data('time');
 			layer.confirm('确认要删除该备份吗?', {
 					icon: 3,
 					title: '提示'
 				}, function (index) {
 					$.ajax({
 						url: "/home/database/del",
-						data: {'id':id},
+						data: {'time':time},
 						success: function (res) {
 							layer.msg(res.msg);
 							if (res.code == 0) {
-								location.reload();
+								setTimeout(function(){
+									location.reload();
+								},2000)
 							}
 						}
 					})
 					layer.close(index);
 				});
+			return false;
+		})
+		
+		$('[lay-event="reset"]').on('click',function(){
+			var time=$(this).parent().data('time');
+			layer.confirm('确认要清除该备份吗?', {
+					icon: 3,
+					title: '提示'
+				}, function (index) {
+					$.ajax({
+						url: "/home/database/del",
+						data: {'time':time,'lock':1},
+						success: function (res) {
+							layer.msg(res.msg);
+							if (res.code == 0) {
+								setTimeout(function(){
+									location.reload();
+								},2000)
+							}
+						}
+					})
+					layer.close(index);
+				});
+			return false;
 		})
 	}
 </script>
diff --git a/app/home/view/database/database.html b/app/home/view/database/database.html
index c32c6ea..98697be 100644
--- a/app/home/view/database/database.html
+++ b/app/home/view/database/database.html
@@ -2,18 +2,19 @@
 <!-- 主体 -->
 {block name="body"}
 <div class="body-table">
-	<table class="layui-hide" id="test" lay-filter="test"></table>
+	<table class="layui-hide" id="backup" lay-filter="test"></table>
 </div>
 <script type="text/html" id="toolbarDemo">
 	<div class="layui-btn-group">
-		<span class="layui-btn layui-btn-sm layui-btn-normal" lay-event="backup">数据备份</span><span class="layui-btn layui-btn-sm" lay-event="optimize">数据优化</span><span class="layui-btn layui-btn-danger layui-btn-sm" lay-event="repair">数据修复</span>
+		<span class="layui-btn layui-btn-sm layui-btn-normal" lay-event="backup">数据备份</span><span class="layui-btn layui-btn-sm" lay-event="optimize">数据表优化</span><span class="layui-btn layui-btn-danger layui-btn-sm" lay-event="repair">数据表修复</span>
   	</div>
 	<span id="dataTips" style="font-size:12px; margin-left:10px"></span>  
 </script>
-
 {/block}
 <!-- /主体 -->
 
+
+<script>
 <!-- 脚本 -->
 {block name="script"}
 <script>
@@ -22,7 +23,7 @@
 			form = layui.form;
 
 		var tableIns = table.render({
-			elem: '#test',
+			elem: '#backup',
 			title: '数据备份',
 			toolbar: '#toolbarDemo',
 			url: "/home/database/database", //数据接口
@@ -34,7 +35,16 @@
 						field: 'name',
 						title: '数据表',
 						width: 220
-					}, {
+					},
+					{
+						field: 'status',
+						title: '状态',
+						width: 120,
+						templet:function(d){
+							return '<span id="table_'+d.name+'">-</span>';
+						}
+					},
+					{
 						field: 'engine',
 						title: '存储引擎',
 						align: 'center',
@@ -75,22 +85,42 @@
 			}
 		});
 
+     	//递归备份表
+      	function backup(tab,status,table){
+			layer.closeAll();
+			layer.msg("备份中...,请勿关闭本页面",{time: 200000});
+       		$.get("/home/database/backup", tab, function(data){
+	          	// console.log(data)
+				if(data.code==0){
+	            	showmsg(data.data.tab.table, data.msg);
+	             	if(data.data.tab.start=='ok'){
+						layer.msg('备份完成');
+	                    window.onbeforeunload = function(){ return null }
+	                    return;
+	                } 
+	                backup(data.data.tab, tab.id != data.data.tab.id);
+	            } else {
+					layer.msg('立即备份');
+	            }
+       		}, "json"); 
+      	}
+
+	    //修改备份状态
+	    function showmsg(table, msg){
+			console.log(table);
+	    	$("#table_"+table).addClass('span-color-2').html(msg);
+	    }
 		//监听行工具事件
 		table.on('toolbar(test)', function (obj) {
 			var checkData = table.checkStatus(obj.config.id).data;
 			var len = checkData.length;
-			var ids='';
+			var tables=[];
 			if(len==0){
 				layer.msg('请先选择表');
 				return false;
 			}
 			for(var i=0;i<len;i++){
-				if(i==0){
-					ids+=checkData[i].name;
-				}
-				else{
-					ids+=','+checkData[i].name;
-				}			   
+				tables.push(checkData[i].name);		   
 			}
 			if (obj.event === 'backup') {
 				layer.confirm('确认要备份选中的'+len+'个数据表吗?', {
@@ -99,11 +129,30 @@
 				}, function (index) {
 					$.ajax({
 						url: "/home/database/backup",
-						data: {'id':ids},
+						type:'post',
+						data: {'tables':tables},
 						success: function (res) {
-							layer.msg(res.msg);
 							if (res.code == 0) {
-								location.reload();
+								layer.msg( "开始备份,请不要关闭本页面!");
+               					window.onbeforeunload = function(){ return "正在备份数据库,请不要关闭!" }
+								backup(res.data.tab);
+							}
+							if (res.code == 2) {
+								layer.confirm('检测到有一个备份任务未完成,请先清除未完成的备份', {
+									icon: 3,
+									title: '提示'
+								}, function (index) {
+									$.ajax({
+										url: "/home/database/del",
+										data: {'lock':1},
+										success: function (res) {
+											layer.msg(res.msg);
+										}
+									})							
+								})
+							}
+							else{
+								layer.msg(res.msg);
 							}
 						}
 					})
@@ -116,11 +165,13 @@
 				}, function (index) {
 					$.ajax({
 						url: "/home/database/optimize",
-						data: {'id':ids},
+						data: {'tables':tables},
 						success: function (res) {
 							layer.msg(res.msg);
 							if (res.code == 0) {
-								location.reload();
+								setTimeout(function(){
+									location.reload();
+								},2000)								
 							}
 						}
 					})
@@ -133,11 +184,13 @@
 				}, function (index) {
 					$.ajax({
 						url: "/home/database/repair",
-						data: {'id':ids},
+						data: {'tables':tables},
 						success: function (res) {
 							layer.msg(res.msg);
 							if (res.code == 0) {
-								location.reload();
+								setTimeout(function(){
+									location.reload();
+								},2000)
 							}
 						}
 					})
diff --git a/app/home/view/log/index.html b/app/home/view/log/index.html
index 205917f..4e56aa0 100644
--- a/app/home/view/log/index.html
+++ b/app/home/view/log/index.html
@@ -4,7 +4,7 @@
 <div class="body-table">
 	<form class="layui-form layui-form-bar">
 		<div class="layui-input-inline" style="width:300px;">
-			<input type="text" name="keywords" placeholder="昵称/操作节点名称/操作数据ID" class="layui-input" autocomplete="off" />
+			<input type="text" name="keywords" placeholder="昵称/操作数据id/操作描述" class="layui-input" autocomplete="off" />
 		</div>
 		<div class="layui-input-inline">
 			<select name="action">
@@ -49,18 +49,14 @@
 						width: 80
 					}, {
 						field: 'content',
-						title: '操作描述',
-						width: 348
+						title: '操作描述'
 					}, {
 						field: 'param_id',
 						title: '操作数据ID',
 						align: 'center',
 						width: 100
-					}, {
-						field: 'param',
-						title: '操作数据'
-					}, {
-						field: 'name',
+					},{
+						field: 'nickname',
 						title: '操作用户',
 						align: 'center',
 						width: 100
diff --git a/app/install/data/oa_reset.sql b/app/install/data/oa_reset.sql
new file mode 100644
index 0000000..34c73f7
--- /dev/null
+++ b/app/install/data/oa_reset.sql
@@ -0,0 +1,669 @@
+-- ----------------------------
+-- Table structure for oa_admin_group
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_admin_group`;
+CREATE TABLE `oa_admin_group`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL DEFAULT '',
+  `status` int(1) NOT NULL DEFAULT 1,
+  `rules` varchar(1000) NULL DEFAULT '' COMMENT '用户组拥有的规则id, 多个规则\",\"隔开',
+  `desc` text NULL COMMENT '备注',
+  `create_time` int(11) NOT NULL DEFAULT 0,
+  `update_time` int(11) NOT NULL DEFAULT 0,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE INDEX `id`(`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '员工权限分组表';
+
+-- ----------------------------
+-- Records of cms_admin_group
+-- ----------------------------
+INSERT INTO `oa_admin_group` VALUES (1, '超级员工权限', 1, '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141',  '超级员工权限,拥有系统的最高权限,不可修改', 0, 0);
+INSERT INTO `oa_admin_group` VALUES (2, '人事总监权限', 1, '2,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,3,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,4,78,79,80,81,82,83,84,85,86,87,5,88,89,90,91,6,92,93,94,95,96,7,97,99,100,101,98,8,102,104,105,106,103,107,109,110,111,112,108,113,114,115,116,117,9,118,119,120,122,123,124,125,127,128,129,131,132,133,134', '人力资源部门领导的最高管理权限', 0, 0);
+
+-- ----------------------------
+-- Table structure for oa_admin_module
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_admin_module`;
+CREATE TABLE `oa_admin_module`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL DEFAULT '' COMMENT '模块名称',
+  `name` varchar(255) NOT NULL DEFAULT '' COMMENT '模块标识唯一,字母',
+  `icon` varchar(255) NOT NULL DEFAULT '' COMMENT '图标',
+  `status` int(1) NOT NULL DEFAULT 1 COMMENT '状态,0禁用,1正常',
+  `type` int(1) NOT NULL DEFAULT 2 COMMENT '模块类型,2普通模块,1系统模块',
+  `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '功能模块表';
+
+-- ----------------------------
+-- Records of oa_admin_module
+-- ----------------------------
+INSERT INTO `oa_admin_module` VALUES (1, '系统模块', 'HOME', '', 1, 1, 1639562910, 0);
+INSERT INTO `oa_admin_module` VALUES (2, '用户模块', 'USER', '', 1, 1, 1639562910, 0);
+INSERT INTO `oa_admin_module` VALUES (3, '消息模块', 'MSG', '', 1, 1, 1639562910, 0);
+INSERT INTO `oa_admin_module` VALUES (4, '公告模块', 'NOTE', '', 1, 1, 1639562910, 0);
+INSERT INTO `oa_admin_module` VALUES (5, '知识模块', 'KQ', '', 1, 1, 1639562910, 0);
+INSERT INTO `oa_admin_module` VALUES (6, 'OA模块', 'OA', '', 1, 1, 1639562910, 0);
+INSERT INTO `oa_admin_module` VALUES (7, '财务模块', 'CF', '', 1, 1, 1639562910, 0);
+INSERT INTO `oa_admin_module` VALUES (8, '统计模块', 'BI', '', 1, 1, 1639562910, 0);
+
+
+-- ----------------------------
+-- Table structure for oa_admin_rule
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_admin_rule`;
+CREATE TABLE `oa_admin_rule`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `pid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '父id',
+  `src` varchar(255) NOT NULL DEFAULT '' COMMENT 'url链接',
+  `title` varchar(255) NOT NULL DEFAULT '' COMMENT '名称',
+  `name` varchar(255) NOT NULL DEFAULT '' COMMENT '日志操作名称',
+  `module` varchar(255) NOT NULL DEFAULT '' COMMENT '所属模块',
+  `icon` varchar(255) NOT NULL DEFAULT '' COMMENT '图标',
+  `menu` int(1) NOT NULL DEFAULT 0 COMMENT '是否是菜单,1是,2不是',
+  `sort` int(11) NOT NULL DEFAULT 1 COMMENT '越小越靠前',
+  `status` int(1) NOT NULL DEFAULT 1 COMMENT '状态,0禁用,1正常',
+  `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '菜单及权限表';
+
+
+-- ----------------------------
+-- Records of oa_admin_rule
+-- ----------------------------
+INSERT INTO `oa_admin_rule` VALUES (1, 0, '', '系统管理', '系统管理', 'HOME', 'icon-jichupeizhi', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (2, 0, '', '基础数据', '基础数据', 'HOME', 'icon-hetongshezhi', 1, 2, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (3, 0, '', '员工管理', '员工管理', 'USER', 'icon-renshishezhi', 1, 3, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (4, 0, '', '消息通知', '消息通知', 'MSG', 'icon-xiaoxishezhi', 1, 4, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (5, 0, '', '企业公告', '企业公告', 'NOTE', 'icon-zhaoshengbaobiao', 1, 5, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (6, 0, '', '知识文章', '知识文章', 'KQ', 'icon-kecheng', 1, 6, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (7, 0, '', '办公审批', '办公审批', 'OA', 'icon-shenpishezhi', 1, 7, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (8, 0, '', '日常办公', '日常办公', 'OA', 'icon-kaoshijihua', 1, 8, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (9, 0, '', '财务管理', '财务管理', 'CF', 'icon-yuangongtidian', 1, 9, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (10, 0, '', '商业智能', '商业智能', 'BI', 'icon-jiaoxuetongji', 1, 10, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (11, 1, 'home/conf/index', '系统配置', '系统配置', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (12, 11, 'home/conf/add', '新建/编辑', '配置项', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (13, 11, 'home/conf/delete', '删除', '配置项', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (14, 11, 'home/conf/edit', '编辑', '配置详情', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (15, 1, 'home/module/index', '功能模块', '功能模块', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (16, 15, 'home/module/add', '新建/编辑', '功能模块', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (17, 15, 'home/module/disable', '禁用/启用', '功能模块', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (18, 1, 'home/rule/index', '功能节点', '功能节点', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (19, 18, 'home/rule/add', '新建/编辑', '功能节点', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (20, 18, 'home/rule/delete', '删除', '功能节点', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (21, 1, 'home/role/index', '权限角色', '权限角色', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (22, 21, 'home/role/add', '新建/编辑', '权限角色', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (23, 21, 'home/role/delete', '删除', '权限角色', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (24, 1, 'home/log/index', '操作日志', '操作日志', 'HOME', '', 1, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (25, 1, 'home/database/database', '备份数据', '备份数据', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (26, 25, 'home/database/backup', '备份数据表', '备份数据', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (27, 25, 'home/database/optimize', '优化数据表', '优化数据表', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (28, 25, 'home/database/repair', '修复数据表', '修复数据表', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (29, 1, 'home/database/backuplist', '还原数据', '还原数据', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (30, 29, 'home/database/import', '还原数据表', '还原数据', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (31, 29, 'home/database/downfile', '下载备份数据', '下载备份数据', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (32, 29, 'home/database/del', '删除备份数据', '删除备份数据', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (33, 2, 'home/cate/flow_type', '审批类型', '审批类型', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (34, 33, 'home/cate/flow_type_add', '新建/编辑', '审批类型', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (35, 33, 'home/cate/flow_type_check', '设置', '审批类型', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (36, 2, 'home/flow/index', '审批流程', '审批流程', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (37, 36, 'home/flow/add', '新建/编辑', '审批流程', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (38, 36, 'home/flow/delete', '删除', '审批流程', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (39, 36, 'home/flow/check', '设置', '审批流程', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (40, 2, 'home/cate/expense_cate', '报销类型', '报销类型', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (41, 40, 'home/cate/expense_cate_add', '新建/编辑', '报销类型', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (42, 40, 'home/cate/expense_cate_check', '设置', '报销类型', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (43, 2, 'home/cate/cost_cate', '费用类型', '费用类型', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (44, 43, 'home/cate/cost_cate_add', '新建/编辑', '费用类型', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (45, 43, 'home/cate/cost_cate_check', '设置', '费用类型', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (46, 2, 'home/cate/seal_cate', '印章类型', '印章类型', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (47, 46, 'home/cate/seal_cate_add', '新建/编辑', '印章类型', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (48, 46, 'home/cate/seal_cate_check', '设置', '印章类型', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (49, 2, 'home/cate/car_cate', '车辆类型', '车辆类型', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (50, 49, 'home/cate/car_cate_add', '新建/编辑', '车辆类型', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (51, 49, 'home/cate/car_cate_check', '设置', '车辆类型', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (52, 2, 'home/cate/subject', '发票主体', '发票主体', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (53, 52, 'home/cate/subject_add', '新建/编辑', '发票主体', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (54, 52, 'home/cate/subject_check', '设置', '发票主体', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (55, 2, 'home/cate/note_cate', '公告类型', '公告类型', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (56, 55, 'home/cate/note_cate_add', '新建/编辑', '公告类型', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (57, 55, 'home/cate/note_cate_delete', '删除', '公告类型', 'HOME', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (58, 2, 'home/cate/article_cate', '知识类型', '知识类型', 'HOME', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (59, 58, 'home/cate/article_cate_add', '新建/编辑', '知识类型', 'HOME', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (60, 58, 'home/cate/article_cate_delete', '删除', '知识类型', 'HOME', '', 2, 1, 1, 0, 0);
+
+
+INSERT INTO `oa_admin_rule` VALUES (61, 3, 'user/department/index', '部门架构', '部门', 'USER', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (62, 61, 'user/department/add', '新建/编辑', '部门', 'USER', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (63, 61, 'user/department/delete', '删除', '部门', 'USER', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (64, 3, 'user/position/index', '岗位职称', '岗位职称', 'USER', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (65, 64, 'user/position/add', '新建/编辑', '岗位职称', 'USER', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (66, 64, 'user/position/delete', '删除', '岗位职称', 'USER', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (67, 64, 'user/position/view', '查看', '岗位职称', 'USER', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (68, 3, 'user/user/index', '企业员工', '员工', 'USER', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (69, 68, 'user/user/add', '新建/编辑', '员工', 'USER', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (70, 68, 'user/user/view', '查看', '员工信息', 'USER', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (71, 68, 'user/user/set', '设置', '员工状态', 'USER', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (72, 68, 'user/user/reset_psw', '重设密码', '员工密码', 'USER', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (73, 3, 'user/personal/change', '人事调动', '人事调动', 'USER', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (74, 73, 'user/personal/change_add', '新建/编辑', '人事调动', 'USER', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (75, 3, 'user/personal/leave', '离职档案', '离职档案', 'USER', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (76, 75, 'user/personal/leave_add', '新建/编辑', '离职档案', 'USER', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (77, 75, 'user/personal/leave_delete', '删除', '离职档案', 'USER', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (78, 4, 'message/index/inbox', '收件箱', '收件箱', 'MSG', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (79, 78, 'message/index/add', '新建/编辑', '消息', 'MSG', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (80, 78, 'message/index/send', '发送', '消息', 'MSG', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (81, 78, 'message/index/save', '保存', '消息到草稿', 'MSG', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (82, 78, 'message/index/reply', '回复', '消息', 'MSG', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (83, 78, 'message/index/read', '查看', '消息', 'MSG', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (84, 78, 'message/index/check', '设置', '消息状态', 'MSG', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (85, 4, 'message/index/sendbox', '发件箱', '发件箱', 'MSG', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (86, 4, 'message/index/draft', '草稿箱', '草稿箱', 'MSG', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (87, 4, 'message/index/rubbish', '垃圾箱', '垃圾箱', 'MSG', '', 1, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (88, 5, 'note/index/index', '公告列表', '公告', 'NOTE', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (89, 88, 'note/index/add', '新建/编辑', '公告', 'NOTE', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (90, 88, 'note/index/delete', '删除', '公告', 'NOTE', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (91, 88, 'note/index/view', '查看', '公告', 'NOTE', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (92, 6, 'article/index/index', '共享知识', '知识文章', 'KQ', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (93, 6, 'article/index/list', '个人知识', '知识文章', 'KQ', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (94, 93, 'article/index/add', '新建/编辑', '知识文章', 'KQ', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (95, 93, 'article/index/delete', '删除', '知识文章', 'KQ', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (96, 93, 'article/index/view', '查看', '知识文章', 'KQ', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (97, 7, 'oa/approve/index', '我发起的审批', '办公审批', 'OA', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (98, 7, 'oa/approve/list', '待我处理的审批', '办公审批', 'OA', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (99, 97, 'oa/approve/add', '新建/编辑', '办公审批', 'OA', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (100, 97, 'oa/approve/view', '查看', '办公审批', 'OA', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (101, 97, 'oa/approve/check', '审核', '办公审批', 'OA', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (102, 8, 'oa/plan/calendar', '日程日历', '日程安排', 'OA', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (103, 8, 'oa/plan/index', '日程安排', '日程安排', 'OA', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (104, 102, 'oa/plan/add', '新建/编辑', '日程安排', 'OA', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (105, 102, 'oa/plan/delete', '删除', '日程安排', 'OA', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (106, 102, 'oa/plan/detail', '查看', '日程安排', 'OA', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (107, 8, 'oa/schedule/calendar', '工作日历', '工作日历', 'OA', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (108, 8, 'oa/schedule/index', '工作记录', '工作记录', 'OA', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (109, 107, 'oa/schedule/add', '新建/编辑', '工作记录', 'OA', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (110, 107, 'oa/schedule/delete', '删除', '工作记录', 'OA', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (111, 107, 'oa/schedule/detail', '查看', '工作记录', 'OA', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (112, 107, 'oa/schedule/update_labor_time', '更改工时', '工时', 'OA', '', 0, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (113, 8, 'oa/work/index', '工作汇报', '工作汇报', 'OA', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (114, 113, 'oa/work/add', '新建/编辑', '工作汇报', 'OA', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (115, 113, 'oa/work/send', '发送', '工作汇报', 'OA', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (116, 113, 'oa/work/read', '查看', '工作汇报', 'OA', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (117, 113, 'oa/work/delete', '删除', '工作汇报', 'OA', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (118, 9, '', '报销管理', '报销', 'CF', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (119, 118, 'finance/expense/index', '我申请的报销', '报销', 'CF', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (120, 118, 'finance/expense/list', '我负责的报销', '报销', 'CF', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (121, 118, 'finance/expense/checkedlist', '报销打款', '报销', 'CF', '', 1, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (122, 118, 'finance/expense/add', '新建/编辑', '报销', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (123, 118, 'finance/expense/delete', '删除', '报销', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (124, 118, 'finance/expense/view', '查看', '报销', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (125, 118, 'finance/expense/check', '审核', '报销', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (126, 118, 'finance/expense/topay', '打款', '报销', 'CF', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (127, 9, '', '发票管理', '发票', 'CF', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (128, 127, 'finance/invoice/index', '我申请的发票', '发票', 'CF', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (129, 127, 'finance/invoice/list', '我负责的发票', '发票', 'CF', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (130, 127, 'finance/invoice/checkedlist', '发票开具', '发票', 'CF', '', 1, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (131, 127, 'finance/invoice/add', '新建/编辑', '发票', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (132, 127, 'finance/invoice/delete', '删除', '发票', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (133, 127, 'finance/invoice/view', '查看', '发票', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (134, 127, 'finance/invoice/check', '审核', '发票', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (135, 127, 'finance/invoice/open', '开具', '发票', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (136, 127, 'finance/invoice/tovoid', '作废', '发票', 'CF', '', 2, 1, 1, 0, 0);
+
+INSERT INTO `oa_admin_rule` VALUES (137, 9, 'finance/income/index', '到账管理', '到账记录', 'CF', '', 1, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (138, 137, 'finance/income/add', '新建/编辑', '到账记录', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (139, 137, 'finance/income/view', '查看', '到账记录', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (140, 137, 'finance/income/delete', '删除', '到账记录', 'CF', '', 2, 1, 1, 0, 0);
+INSERT INTO `oa_admin_rule` VALUES (141, 10, 'business/analysis/index', '智能分析', '智能分析', 'BI', '', 1, 1, 1, 0, 0);
+
+
+-- ----------------------------
+-- Table structure for oa_article_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_article_cate`;
+CREATE TABLE `oa_article_cate`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `pid` int(11) NOT NULL DEFAULT 0 COMMENT '父类ID',
+  `sort` int(5) NOT NULL DEFAULT 0 COMMENT '排序',
+  `title` varchar(255) NOT NULL DEFAULT '' COMMENT '分类标题',
+  `desc` varchar(1000) NULL DEFAULT '' COMMENT '描述',
+  `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '添加时间',
+  `update_time` int(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '知识文章分类表';
+
+-- ----------------------------
+-- Records of oa_article_cate
+-- ----------------------------
+INSERT INTO `oa_article_cate` VALUES (1, 0, 0, '办公技巧', '', 1637984651, 0);
+INSERT INTO `oa_article_cate` VALUES (2, 0, 0, '行业技能', '', 1637984739, 0);
+
+-- ----------------------------
+-- Table structure for oa_article_keywords
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_article_keywords`;
+CREATE TABLE `oa_article_keywords`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `aid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '知识文章ID',
+  `keywords_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '关联关键字id',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `aid`(`aid`) USING BTREE,
+  INDEX `inid`(`keywords_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '知识文章关联表';
+
+-- ----------------------------
+-- Records of oa_article_keywords
+-- ----------------------------
+INSERT INTO `oa_article_keywords` VALUES (1, 1, 1, 1, 1638093082);
+INSERT INTO `oa_article_keywords` VALUES (2, 2, 2, 1, 1638093082);
+INSERT INTO `oa_article_keywords` VALUES (3, 3, 3, 3, 1638093082);
+INSERT INTO `oa_article_keywords` VALUES (4, 4, 4, 4, 1638093082);
+
+-- ----------------------------
+-- Table structure for oa_config
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_config`;
+CREATE TABLE `oa_config`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL DEFAULT '' COMMENT '配置名称',
+  `name` varchar(255) NOT NULL DEFAULT '' COMMENT '配置标识',
+  `content` text NULL COMMENT '配置内容',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COMMENT = '系统配置表';
+
+-- ----------------------------
+-- Records of oa_config
+-- ----------------------------
+INSERT INTO `oa_config` VALUES (1, '网站配置', 'web', 'a:13:{s:2:\"id\";s:1:\"1\";s:11:\"admin_title\";s:8:\"勾股OA\";s:5:\"title\";s:8:\"勾股OA\";s:4:\"logo\";s:52:\"/storage/202111/fc507cc8332d5ef49d9425185e4a9697.jpg\";s:4:\"file\";s:0:\"\";s:6:\"domain\";s:23:\"https://oa.gougucms.com\";s:3:\"icp\";s:23:\"粤ICP备1xxxxxx11号-1\";s:8:\"keywords\";s:8:\"勾股OA\";s:5:\"beian\";s:29:\"粤公网安备1xxxxxx11号-1\";s:4:\"desc\";s:479:\"勾股办公是一款基于ThinkPHP6 + Layui + MySql打造的,简单实用的开源免费的企业办公系统框架。系统集成了系统设置、人事管理模块、消息管理模块、日常办公、财务管理等基础模块。系统简约,易于功能扩展,方便二次开发,让开发者更专注于业务深度需求的开发,帮助开发者简单高效降低二次开发成本,通过二次开发之后可以用来做CRM,ERP,业务管理等系统。 \";s:4:\"code\";s:0:\"\";s:9:\"copyright\";s:36:\"© 2022 gougucms.com GPL-2.0 license\";s:7:\"version\";s:6:\"1.0.22\";}', 1, 1612514630, 1638010154);
+INSERT INTO `oa_config` VALUES (2, '邮箱配置', 'email', 'a:8:{s:2:\"id\";s:1:\"2\";s:4:\"smtp\";s:11:\"smtp.qq.com\";s:9:\"smtp_port\";s:3:\"465\";s:9:\"smtp_user\";s:15:\"gougucms@qq.com\";s:8:\"smtp_pwd\";s:6:\"123456\";s:4:\"from\";s:24:\"勾股CMS系统管理员\";s:5:\"email\";s:18:\"admin@gougucms.com\";s:8:\"template\";s:485:\"<p>勾股办公是一款基于ThinkPHP6 + Layui + MySql打造的,简单实用的开源免费的企业办公系统框架。系统集成了系统设置、人事管理模块、消息管理模块、日常办公、财务管理等基础模块。系统简约,易于功能扩展,方便二次开发,让开发者更专注于业务深度需求的开发,帮助开发者简单高效降低二次开发成本,通过二次开发之后可以用来做CRM,ERP,业务管理等系统。</p>\";}', 1, 1612521657, 1637075205);
+INSERT INTO `oa_config` VALUES (3, 'Api Token配置', 'token', 'a:5:{s:2:\"id\";s:1:\"3\";s:3:\"iss\";s:15:\"oa.gougucms.com\";s:3:\"aud\";s:7:\"gouguoa\";s:7:\"secrect\";s:7:\"GOUGUOA\";s:7:\"exptime\";s:4:\"3600\";}', 1, 1627313142, 1638010233);
+INSERT INTO `oa_config` VALUES (4, '其他配置', 'other', 'a:3:{s:2:\"id\";s:1:\"5\";s:6:\"author\";s:15:\"勾股工作室\";s:7:\"version\";s:13:\"v1.2021.07.28\";}', 1, 1613725791, 1635953640);
+
+-- ----------------------------
+-- Table structure for oa_department
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_department`;
+CREATE TABLE `oa_department`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '部门名称',
+  `pid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '上级部门id',
+  `leader_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '部门负责人ID',
+  `phone` varchar(60) NOT NULL DEFAULT '' COMMENT '部门联系电话',
+  `remark` varchar(1000) NULL DEFAULT '' COMMENT '备注',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '部门组织';
+
+-- ----------------------------
+-- Records of oa_department
+-- ----------------------------
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (1, '董事会', 0, 0, '13688888888');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (2, '人事部', 1, 0, '13688888889');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (3, '财务部', 1, 0, '13688888898');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (4, '市场部', 1, 0, '13688888978');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (5, '销售部', 1, 0, '13688889868');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (6, '技术部', 1, 0, '13688898858');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (7, '客服部', 1, 0, '13688988848');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (8, '销售一部', 5, 0, '13688998838');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (9, '销售二部', 5, 0, '13688999828');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (10, '销售三部', 5, 0, '13688999918');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (11, '产品部', 6, 0, '13688888886');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (12, '设计部', 6, 0, '13688888876');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (13, '研发部', 6, 0, '13688888666');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (14, '客服一部', 7, 0, '13688888865');
+INSERT INTO `oa_department`(`id`, `title`, `pid`, `leader_id`, `phone`) VALUES (15, '客服二部', 7, 0, '13688888855');
+
+-- ----------------------------
+-- Table structure for oa_department_change
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_department_change`;
+CREATE TABLE `oa_department_change`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户ID',
+  `from_did` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '原部门id',
+  `to_did` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '调到部门id',
+  `remark` varchar(1000) NULL DEFAULT '' COMMENT '备注',
+  `admin_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `move_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '调到时间',
+  `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '人事调动部门记录表';
+
+-- ----------------------------
+-- Table structure for oa_personal_quit
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_personal_quit`;
+CREATE TABLE `oa_personal_quit`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户ID',
+  `remark` varchar(1000) NULL DEFAULT '' COMMENT '备注',
+  `admin_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人',
+  `lead_admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '部门负责人',
+  `connect_uids` varchar(100) NOT NULL DEFAULT '' COMMENT '交接人',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `quit_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '离职时间',
+  `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '人事离职记录表';
+
+-- ----------------------------
+-- Table structure for oa_flow_type
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_flow_type`;
+CREATE TABLE `oa_flow_type`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `type` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '1假勤,2行政,3财务,4人事,5其他',
+  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '审批名称',
+  `name` varchar(100) NOT NULL DEFAULT '' COMMENT '审批标识',
+  `icon` varchar(255) NOT NULL DEFAULT '' COMMENT '图标',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '审批类型';
+
+-- ----------------------------
+-- Records of oa_flow_type
+-- ----------------------------
+INSERT INTO `oa_flow_type` VALUES (1, 1, '请假', 'qingjia', 'icon-kechengziyuanguanli', 1, 1639896302, 0);
+INSERT INTO `oa_flow_type` VALUES (2, 1, '出差', 'chuchai', 'icon-jiaoshiguanli', 1, 1641802838, 0);
+INSERT INTO `oa_flow_type` VALUES (3, 1, '外出', 'waichu', 'icon-tuiguangguanli', 1, 1641802858, 0);
+INSERT INTO `oa_flow_type` VALUES (4, 1, '加班', 'jiaban', 'icon-xueshengchengji', 1, 1641802892, 0);
+INSERT INTO `oa_flow_type` VALUES (5, 2, '会议室预定', 'huiyishi', 'icon-kehuguanli', 1, 1641802939, 0);
+INSERT INTO `oa_flow_type` VALUES (6, 2, '公文流转', 'gongwen', 'icon-jiaoxuejihua', 1, 1641802976, 0);
+INSERT INTO `oa_flow_type` VALUES (7, 2, '物品维修', 'weixiu', 'icon-chuangjianxitong', 1, 1641803005, 0);
+INSERT INTO `oa_flow_type` VALUES (8, 2, '用章', 'yongzhang', 'icon-shenpishezhi', 1, 1641804126, 0);
+INSERT INTO `oa_flow_type` VALUES (9, 2, '用车', 'yongche', 'icon-dongtaiguanli', 1, 1641804283, 0);
+INSERT INTO `oa_flow_type` VALUES (10, 2, '用车归还', 'yongcheguihai', 'icon-kaoheguanli', 1, 1641804411, 0);
+INSERT INTO `oa_flow_type` VALUES (11, 3, '借款申请', 'jiekuan', 'icon-zhangbuguanli', 1, 1641804537, 0);
+INSERT INTO `oa_flow_type` VALUES (12, 3, '付款申请', 'fukuan', 'icon-gongziguanli', 1, 1641804601, 0);
+INSERT INTO `oa_flow_type` VALUES (13, 3, '奖励申请', 'jiangli', 'icon-hetongguanli', 1, 1641804711, 0);
+INSERT INTO `oa_flow_type` VALUES (14, 3, '采购', 'caigou', 'icon-xiaoshoupin', 1, 1641804917, 0);
+INSERT INTO `oa_flow_type` VALUES (15, 3, '活动经费', 'huodong', 'icon-wangxiaoshezhi1', 1, 1641805110, 0);
+INSERT INTO `oa_flow_type` VALUES (16, 4, '入职', 'ruzhi', 'icon-xueshengdaoru', 1, 1641893853, 0);
+INSERT INTO `oa_flow_type` VALUES (17, 4, '转正', 'zhuanzheng', 'icon-xueshengyidong', 1, 1641893926, 0);
+INSERT INTO `oa_flow_type` VALUES (18, 4, '离职', 'lizhi', 'icon-banjiguanli', 1, 1641894048, 0);
+INSERT INTO `oa_flow_type` VALUES (19, 4, '招聘需求', 'zhaopin', 'icon-zhaopinguanli', 1, 1641894080, 0);
+INSERT INTO `oa_flow_type` VALUES (20, 6, '报销', 'baoxiao', 'icon-jizhang', 1, 1641804488, 0);
+INSERT INTO `oa_flow_type` VALUES (21, 7, '发票', 'fapiao', 'icon-fuwuliebiao', 1, 1642904833, 0);
+
+-- ----------------------------
+-- Table structure for oa_flow
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_flow`;
+CREATE TABLE `oa_flow`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(50) NOT NULL COMMENT '审批流名称',
+  `check_type` tinyint(4) NOT NULL COMMENT '1固定审批,2授权审批人',
+  `type` tinyint(4) NOT NULL COMMENT '应用模块,1假勤,2行政,3财务,4人事,5其他,6报销,7发票',
+  `flow_cate` tinyint(11) NOT NULL DEFAULT 0 COMMENT '应用审批类型id',
+  `department_ids` varchar(500) NOT NULL DEFAULT '' COMMENT '应用部门ID(0为全部)1,2,3',
+  `user_ids` varchar(500) NOT NULL DEFAULT '' COMMENT '员工ID',
+  `remark` varchar(500) NOT NULL DEFAULT '' COMMENT '流程说明',
+  `flow_list` varchar(1000) NULL DEFAULT '' COMMENT '流程数据序列化',
+  `admin_id` int(11) NOT NULL COMMENT '创建人ID',
+  `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+  `status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '状态 1启用,0禁用',
+  `delete_time` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
+  `delete_user_id` int(11) NOT NULL DEFAULT 0 COMMENT '删除人ID',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '审批流程表';
+
+-- ----------------------------
+-- Records of oa_flow
+-- ----------------------------
+INSERT INTO `oa_flow` VALUES (1, '请假审批', 2, 1, 1, '', '', '请假审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644401970, 1644402071, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (2, '出差审批', 2, 1, 2, '', '', '请假审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402054, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (3, '外出审批', 2, 1, 3, '', '', '外出审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402116, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (4, '加班申请审批', 2, 1, 4, '', '', '加班申请审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402147, 1644456735, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (5, '会议室预定审批', 2, 2, 5, '', '', '会议室预定审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402193, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (6, '公文流转审批', 2, 2, 6, '', '', '公文流转审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402386, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (7, '物品维修审批', 2, 2, 7, '', '', '物品维修审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402473, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (8, '用章审批', 2, 2, 8, '', '', '用章审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402499, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (9, '用车审批', 2, 2, 9, '', '', '用车审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402525, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (10, '用车归还审批', 2, 2, 10, '', '', '用车归还审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402549, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (11, '借款申请审批', 2, 3, 11, '', '', '借款申请审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402611, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (12, '付款申请审批', 2, 3, 12, '', '', '付款申请审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402679, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (13, '奖励申请审批', 2, 3, 13, '', '', '奖励申请审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402705, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (14, '采购申请审批', 2, 3, 14, '', '', '采购申请审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402739, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (15, '活动经费审批', 2, 3, 15, '', '', '活动经费审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402762, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (16, '入职申请审批', 2, 4, 16, '', '', '入职申请审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402791, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (17, '转正申请审批', 2, 4, 17, '', '', '转正申请审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402812, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (18, '离职申请审批', 2, 4, 18, '', '', '离职申请审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402834, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (19, '招聘需求审批', 2, 4, 19, '', '', '招聘需求审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644402855, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (20, '报销审批', 2, 6, 20, '', '', '报销审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644490024, 0, 1, 0, 0);
+INSERT INTO `oa_flow` VALUES (21, '发票审批', 2, 7, 21, '', '', '报销审批流程', 'a:1:{i:0;a:2:{s:9:\"flow_type\";s:1:\"1\";s:9:\"flow_uids\";s:0:\"\";}}', 1, 1644490053, 0, 1, 0, 0);
+
+-- ----------------------------
+-- Table structure for oa_cost_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_cost_cate`;
+CREATE TABLE `oa_cost_cate`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '费用类型名称',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '费用类型';
+
+-- ----------------------------
+-- Records of oa_cost_cate
+-- ----------------------------
+INSERT INTO `oa_cost_cate` VALUES (1, '差旅费', 1, 1639898199, 0);
+INSERT INTO `oa_cost_cate` VALUES (2, '办公费', 1, 1639898434, 0);
+INSERT INTO `oa_cost_cate` VALUES (3, '招待费', 1, 1639898564, 0);
+INSERT INTO `oa_cost_cate` VALUES (4, '交通费', 1, 1639898564, 0);
+INSERT INTO `oa_cost_cate` VALUES (5, '通讯费', 1, 1639898564, 0);
+INSERT INTO `oa_cost_cate` VALUES (6, '采购付款', 1, 1639898564, 0);
+INSERT INTO `oa_cost_cate` VALUES (7, '其他', 1, 1639898564, 0);
+
+
+-- ----------------------------
+-- Table structure for oa_seal_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_seal_cate`;
+CREATE TABLE `oa_seal_cate`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '印章类型名称',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '印章类型';
+
+-- ----------------------------
+-- Records of oa_seal_cate
+-- ----------------------------
+INSERT INTO `oa_seal_cate` VALUES (1, '公章', 1, 1639899124, 0);
+INSERT INTO `oa_seal_cate` VALUES (2, '合同章', 1, 1639899140, 0);
+INSERT INTO `oa_seal_cate` VALUES (3, '法人章', 1, 1639899148, 0);
+INSERT INTO `oa_seal_cate` VALUES (4, '其他', 1, 1639899158, 0);
+
+-- ----------------------------
+-- Table structure for oa_car_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_car_cate`;
+CREATE TABLE `oa_car_cate`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '车辆名称',
+  `name` varchar(100) NOT NULL DEFAULT '' COMMENT '车辆号码',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '用车类型';
+
+-- ----------------------------
+-- Records of oa_car_cate
+-- ----------------------------
+INSERT INTO `oa_car_cate` VALUES (1, '宝马X5', '粤A55555', 1, 1639900555, 0);
+INSERT INTO `oa_car_cate` VALUES (2, '哈弗H6', '粤A66666', 1, 1639900666, 0);
+INSERT INTO `oa_car_cate` VALUES (3, '奥迪Q8', '粤A88888', 1, 1639900888, 0);
+
+-- ----------------------------
+-- Table structure for oa_expense_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_expense_cate`;
+CREATE TABLE `oa_expense_cate`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '报销类型名称',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '报销类型';
+
+-- ----------------------------
+-- Records of oa_expense_cate
+-- ----------------------------
+INSERT INTO `oa_expense_cate` VALUES (1, '交通费', 1, 1637987189, 0);
+INSERT INTO `oa_expense_cate` VALUES (2, '住宿费', 1, 1637987199, 0);
+INSERT INTO `oa_expense_cate` VALUES (3, '餐补费', 1, 1638088518, 0);
+INSERT INTO `oa_expense_cate` VALUES (4, '招待费', 1, 1637987199, 0);
+INSERT INTO `oa_expense_cate` VALUES (5, '汽油费', 1, 1637987199, 0);
+INSERT INTO `oa_expense_cate` VALUES (6, '其他费', 1, 1637987199, 0);
+
+-- ----------------------------
+-- Table structure for oa_invoice_subject
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_invoice_subject`;
+CREATE TABLE `oa_invoice_subject`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '主体名称',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '发票主体名称';
+
+-- ----------------------------
+-- Records of oa_invoice_subject
+-- ----------------------------
+INSERT INTO `oa_invoice_subject` VALUES (1, '勾股信息科技有限公司', 1, 1638006751, 0);
+
+-- ----------------------------
+-- Table structure for oa_keywords
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_keywords`;
+CREATE TABLE `oa_keywords`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL DEFAULT '' COMMENT '关键字名称',
+  `sort` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '关键字表';
+
+-- ----------------------------
+-- Records of oa_keywords
+-- ----------------------------
+INSERT INTO `oa_keywords` VALUES (1, '勾股OA', 1, 1, 1638006730, 0);
+INSERT INTO `oa_keywords` VALUES (2, '勾股CMS', 1, 1, 1638006730, 0);
+INSERT INTO `oa_keywords` VALUES (3, '勾股BLOG', 1, 1, 1638006730, 0);
+INSERT INTO `oa_keywords` VALUES (3, '勾股DEV', 1, 1, 1638006730, 0);
+
+-- ----------------------------
+-- Table structure for oa_note_cate
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_note_cate`;
+CREATE TABLE `oa_note_cate`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `pid` int(11) NOT NULL DEFAULT 0 COMMENT '父类ID',
+  `sort` int(5) NOT NULL DEFAULT 0 COMMENT '排序',
+  `title` varchar(50) NOT NULL DEFAULT '' COMMENT '标题',
+  `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '添加时间',
+  `update_time` int(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '公告分类';
+
+-- ----------------------------
+-- Records of oa_note_cate
+-- ----------------------------
+INSERT INTO `oa_note_cate` VALUES (1, 0, 1, '普通公告', 1637984265, 1637984299);
+INSERT INTO `oa_note_cate` VALUES (2, 0, 2, '紧急公告', 1637984283, 1637984310);
+
+-- ----------------------------
+-- Table structure for oa_position
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_position`;
+CREATE TABLE `oa_position`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '岗位名称',
+  `work_price` int(10) NOT NULL DEFAULT 0 COMMENT '工时单价',
+  `remark` varchar(1000) NULL DEFAULT '' COMMENT '备注',
+  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
+  `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '岗位职称';
+
+-- ----------------------------
+-- Records of oa_position
+-- ----------------------------
+INSERT INTO `oa_position` VALUES (1, '超级岗位', 1000, '超级岗位,不能轻易修改权限', 1, 0, 0);
+INSERT INTO `oa_position` VALUES (2, '人事总监', 1000, '人事部的最大领导', 1, 0, 0);
+
+-- ----------------------------
+-- Table structure for oa_position_group
+-- ----------------------------
+DROP TABLE IF EXISTS `oa_position_group`;
+CREATE TABLE `oa_position_group`  (
+  `pid` int(11) UNSIGNED NULL DEFAULT NULL COMMENT '岗位id',
+  `group_id` int(11) NULL DEFAULT NULL COMMENT '权限id',
+  `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
+  `update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
+  UNIQUE INDEX `pid_group_id`(`pid`, `group_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '权限分组和岗位的关联表';
+
+-- ----------------------------
+-- Records of oa_position_group
+-- ----------------------------
+INSERT INTO `oa_position_group` VALUES (1, 1, 1635755739, 0);
+INSERT INTO `oa_position_group` VALUES (2, 2, 1638007427, 0);
\ No newline at end of file
diff --git a/extend/backup/Backup.php b/extend/backup/Backup.php
index 81d2f4c..144eefa 100644
--- a/extend/backup/Backup.php
+++ b/extend/backup/Backup.php
@@ -1,118 +1,139 @@
 <?php
 declare (strict_types = 1);
 namespace backup;
-use think\facade\Db;
 use think\facade\Config;
 class Backup
 {
-    /**
-     * 文件指针
-     * @var resource
-     */
     private $fp;
-    
     /**
      * 备份文件信息 part - 卷号,name - 文件名
      * @var array
      */
     private $file;
-
     /**
      * 当前打开文件大小
      * @var integer
      */
     private $size = 0;
+
     /**
      * 数据库配置
      * @var integer
      */
-    private $dbconfig=array();
-
+    private $dbconfig = array();
     /**
      * 备份配置
      * @var integer
      */
-    private $config=array(
-        'path'     => './backup/',//数据库备份路径
-        'part'     => 20971520,//数据库备份卷大小
-        'compress' => 0,//数据库备份文件是否启用压缩 0不压缩 1 压缩
-        'level'    => 9 //数据库备份文件压缩级别 1普通 4 一般  9最高
+    private $config = array(
+		//数据库备份路径
+        'path' => './backup/',
+		//数据库备份卷大小,默认10MB
+        'part' => 10485760,
+        //数据库备份文件是否启用压缩 0不压缩 1 压缩
+        'compress' => 0,
+        //数压缩级别
+        'level' => 9,
     );
     /**
      * 数据库备份构造方法
      * @param array  $file   备份或还原的文件信息
      * @param array  $config 备份配置信息
      */
-    public function __construct($config=[]){
+    public function __construct($config = [])
+    {
         $this->config = array_merge($this->config, $config);
         //初始化文件名
         $this->setFile();
         //初始化数据库连接参数
         $this->setDbConn();
         //检查文件是否可写
-        if(!$this->checkPath($this->config['path'])){
-            throw new \Exception("The current directory is not writable");
+        if (!$this->checkPath($this->config['path'])) {
+            throw new \think\Exception("The current directory is not writable");
         }
     }
-
+    /**
+     * 设置脚本运行超时时间
+     * 0表示不限制,支持连贯操作
+     */
+    public function setTimeout($time=null)
+    {
+        if (!is_null($time)) {
+           set_time_limit($time)||ini_set("max_execution_time", $time);
+        }
+        return $this;
+    }
     /**
      * 设置数据库连接必备参数
      * @param array  $dbconfig   数据库连接配置信息
-     * @return object 
+     * @return object
      */
-    public function setDbConn($dbconfig=[])
+    public function setDbConn($dbconfig = [])
     {
         if (empty($dbconfig)) {
-            $this->dbconfig = Config::get('database'); 
-        }else{
-            $this->dbconfig=$dbconfig;
+            $this->dbconfig = Config::get('database');
+        } else {
+            $this->dbconfig = $dbconfig;
         }
         return $this;
     }
     /**
      * 设置备份文件名
-     * @param String  $file  文件名字
-     * @return object 
+     * @param Array  $file  文件名字
+     * @return object
      */
-    public function setFile($file=null)
+    public function setFile($file = null)
     {
-        if(is_null($file)){
-            $this->file=['name'=>date('Ymd-His'),'part'=>1];
-        }else{
-            if(!array_key_exists("name",$file) && !array_key_exists("part",$file)){
-                $this->file=$file['1'];
-            }else{
-                $this->file=$file;
+        if (is_null($file)) {
+            $this->file = ['name' => date('Ymd-His'), 'part' => 1];
+        } else {
+            if (!array_key_exists("name", $file) && !array_key_exists("part", $file)) {
+                $this->file = $file['1'];
+            } else {
+                $this->file = $file;
             }
-           
         }
         return $this;
     }
     //数据类连接
     public static function connect()
     {
-       return  Db::connect();
+        return \think\facade\Db::connect();
+    }
+    //数据库表列表
+    public function dataList($table = null,$type=1)
+    {
+        $db = self::connect();
+        if (is_null($table)) {
+            $list = $db->query("SHOW TABLE STATUS");
+        } else {
+            if ($type) {
+                $list = $db->query("SHOW FULL COLUMNS FROM {$table}");
+            }else{
+                 $list = $db->query("show columns from {$table}");
+            }
+        }
+        return array_map('array_change_key_case', $list);
+        //$list;
     }
-
     //数据库备份文件列表
     public function fileList()
     {
-       if(!is_dir($this->config['path'])){
-        mkdir($this->config['path'], 0755, true);
-       }
-       $path = realpath($this->config['path']);
-       $flag = \FilesystemIterator::KEY_AS_FILENAME;
-       $glob = new \FilesystemIterator($path,  $flag);
-       $list = array();
-       foreach ($glob as $name => $file) {
-            if(preg_match('/^\d{8,8}-\d{6,6}-\d+\.sql(?:\.gz)?$/', $name)){
+        if (!is_dir($this->config['path'])) {
+            mkdir($this->config['path'], 0755, true);
+        }
+        $path = realpath($this->config['path']);
+        $flag = \FilesystemIterator::KEY_AS_FILENAME;
+        $glob = new \FilesystemIterator($path, $flag);
+        $list = array();
+        foreach ($glob as $name => $file) {
+            if (preg_match('/^\\d{8,8}-\\d{6,6}-\\d+\\.sql(?:\\.gz)?$/', $name)) {
+                $name1= $name;
                 $name = sscanf($name, '%4s%2s%2s-%2s%2s%2s-%d');
-
                 $date = "{$name[0]}-{$name[1]}-{$name[2]}";
                 $time = "{$name[3]}:{$name[4]}:{$name[5]}";
                 $part = $name[6];
-
-                if(isset($list["{$date} {$time}"])){
+                if (isset($list["{$date} {$time}"])) {
                     $info = $list["{$date} {$time}"];
                     $info['part'] = max($info['part'], $part);
                     $info['size'] = $info['size'] + $file->getSize();
@@ -120,104 +141,121 @@ class Backup
                     $info['part'] = $part;
                     $info['size'] = $file->getSize();
                 }
-                $extension        = strtoupper(pathinfo($file->getFilename(), PATHINFO_EXTENSION));
-                $info['compress'] = ($extension === 'SQL') ? '-' : $extension;
-                $info['time']     = strtotime("{$date} {$time}");
-
+                $extension = strtoupper(pathinfo($file->getFilename(), PATHINFO_EXTENSION));
+                $info['name']=$name1;
+                $info['compress'] = $extension === 'SQL' ? '-' : $extension;
+                $info['time'] = strtotime("{$date} {$time}");
                 $list["{$date} {$time}"] = $info;
             }
         }
-
-       return $list;
+        return $list;
     }
-    public function getFile($type='',$time=0)
-    {          //
-        if(!is_numeric($time) ){
-            throw new \Exception("{$time} Illegal data type");
+    public function getFile($type = '', $time = 0)
+    {
+        //
+        if (!is_numeric($time)) {
+            throw new \think\Exception("{$time} Illegal data type");
         }
-        switch ($type)
-        {
+        switch ($type) {
             case 'time':
-				$time = intval($time);
-                $name  = date('Ymd-His', $time) . '-*.sql*';
-                $path  = realpath($this->config['path']) . DIRECTORY_SEPARATOR . $name;
+                $name = date('Ymd-His', $time) . '-*.sql*';
+                $path = realpath($this->config['path']) . DIRECTORY_SEPARATOR . $name;
                 return glob($path);
                 break;
             case 'timeverif':
-				$time = intval($time);
-                $name  = date('Ymd-His', $time) . '-*.sql*';
-                $path  = realpath($this->config['path']) . DIRECTORY_SEPARATOR . $name;
+                $name = date('Ymd-His', $time) . '-*.sql*';
+                $path = realpath($this->config['path']) . DIRECTORY_SEPARATOR . $name;
                 $files = glob($path);
-                $list  = array();
-                foreach($files as $name){
+                $list = array();
+                foreach ($files as $name) {
                     $basename = basename($name);
-                    $match    = sscanf($basename, '%4s%2s%2s-%2s%2s%2s-%d');
-                    $gz       = preg_match('/^\d{8,8}-\d{6,6}-\d+\.sql.gz$/', $basename);
+                    $match = sscanf($basename, '%4s%2s%2s-%2s%2s%2s-%d');
+                    $gz = preg_match('/^\\d{8,8}-\\d{6,6}-\\d+\\.sql.gz$/', $basename);
                     $list[$match[6]] = array($match[6], $name, $gz);
                 }
                 $last = end($list);
-                if(count($list) === $last[0]){
+                if (count($list) === $last[0]) {
                     return $list;
                 } else {
-                    throw new \Exception("File {$files['0']} may be damaged, please check again");
+                    throw new \think\Exception("File {$files['0']} may be damaged, please check again");
                 }
-               
                 break;
             case 'pathname':
                 return "{$this->config['path']}{$this->file['name']}-{$this->file['part']}.sql";
-                break; 
+                break;
             case 'filename':
                 return "{$this->file['name']}-{$this->file['part']}.sql";
-                break; 
+                break;
             case 'filepath':
                 return $this->config['path'];
                 break;
             default:
-                $arr=array(
-                    'pathname'=>"{$this->config['path']}{$this->file['name']}-{$this->file['part']}.sql",
-                    'filename'=>"{$this->file['name']}-{$this->file['part']}.sql",
-                    'filepath'=>$this->config['path'],
-                    'file'=>$this->file
-                );
-            return $arr;
+                $arr = array('pathname' => "{$this->config['path']}{$this->file['name']}-{$this->file['part']}.sql", 'filename' => "{$this->file['name']}-{$this->file['part']}.sql", 'filepath' => $this->config['path'], 'file' => $this->file);
+                return $arr;
         }
     }
-
     //删除备份文件
     public function delFile($time)
     {
-        if($time){
-            $file=$this->getFile('time',$time);
-            array_map("unlink", $this->getFile('time',$time));
-            if(count( $this->getFile('time',$time) )){
-                throw new \Exception("File {$path} deleted failed");
+        if ($time) {
+            $file = $this->getFile('time', $time);
+            array_map("unlink", $this->getFile('time', $time));
+            if (count($this->getFile('time', $time))) {
+                throw new \think\Exception("File {$path} deleted failed");
             } else {
-               return $time;
+                return $time;
             }
         } else {
-            throw new \Exception("{$time} Time parameter is incorrect");
+            throw new \think\Exception("{$time} Time parameter is incorrect");
         }
     }
-    public function import($start){
+    /**
+     * 下载备份
+     * @param string $time
+     * @param integer $part
+     * @return array|mixed|string
+     */
+    public function downloadFile($time, $part = 0)
+    {
+        $file = $this->getFile('time', $time);
+        $fileName = $file[$part];
+        if (file_exists($fileName)) {
+            ob_end_clean();
+            header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
+            header('Content-Description: File Transfer');
+            header('Content-Type: application/octet-stream');
+            header('Content-Length: ' . filesize($fileName));
+            header('Content-Disposition: attachment; filename=' . basename($fileName));
+            readfile($fileName);
+        } else {
+            throw new \think\Exception("{$time} File is abnormal");
+        }
+    }
+    public function import($start,$time,$part)
+    {
         //还原数据
-        $db =  self::connect();
-
-        if($this->config['compress']){
-            $gz   = gzopen($this->file[1], 'r');
+        $db = self::connect();
+        //$this->file=$this->getFile('time',$time);
+		$file = $this->getFile('time', $time);
+        $fileName = $file[$part-1];
+        if (!file_exists($fileName)) {
+			return false;
+		}
+        if ($this->config['compress']) {
+            $gz = gzopen($fileName, 'r');
             $size = 0;
         } else {
-            $size = filesize($this->file[1]);
-            $gz   = fopen($this->file[1], 'r');
+            $size = filesize($fileName);
+            $gz = fopen($fileName, 'r');
         }
-
-        $sql  = '';
-        if($start){
+        $sql = '';
+        if ($start) {
             $this->config['compress'] ? gzseek($gz, $start) : fseek($gz, $start);
         }
-        for($i = 0; $i < 1000; $i++){
-            $sql .= $this->config['compress'] ? gzgets($gz) : fgets($gz); 
-            if(preg_match('/.*;$/', trim($sql))){
-                if(false !== $db->execute($sql)){
+        for ($i = 0; $i < 1000; $i++) {
+            $sql .= $this->config['compress'] ? gzgets($gz) : fgets($gz);
+            if (preg_match('/.*;$/', trim($sql))) {
+                if (false !== $db->execute($sql)) {
                     $start += strlen($sql);
                 } else {
                     return false;
@@ -227,95 +265,71 @@ class Backup
                 return 0;
             }
         }
-
         return array($start, $size);
     }
-
-
-    //数据库表列表
-    public function dataList($table=null)
-    {
-        $db = self::connect();
-        
-        if(is_null($table)){
-            $list = $db->query("SHOW TABLE STATUS");
-        }else{
-            $list = $db->query("show columns from {$table}");
-        }
-        return  array_map('array_change_key_case', $list);//$list;
-    }
     /**
      * 写入初始数据
      * @return boolean true - 写入成功,false - 写入失败
      */
-    public function Backup_Init(){
-        $sql  = "-- -----------------------------\n";
+    public function Backup_Init()
+    {
+        $sql = "-- -----------------------------\n";
         $sql .= "-- Think MySQL Data Transfer \n";
         $sql .= "-- \n";
-        $sql .= "-- Host     : " .$this->dbconfig['hostname']. "\n";
-        $sql .= "-- Port     : " .$this->dbconfig['hostport']. "\n";
-        $sql .= "-- Database : " .$this->dbconfig['database']. "\n";
         $sql .= "-- \n";
         $sql .= "-- Part : #{$this->file['part']}\n";
         $sql .= "-- Date : " . date("Y-m-d H:i:s") . "\n";
         $sql .= "-- -----------------------------\n\n";
         $sql .= "SET FOREIGN_KEY_CHECKS = 0;\n\n";
-        return  $this->write($sql);
+        return $this->write($sql);
     }
-
     /**
      * 备份表结构
      * @param  string  $table 表名
      * @param  integer $start 起始行数
      * @return boolean        false - 备份失败
      */
-    public function backup($table, $start){
-
+    public function backup($table, $start)
+    {
         $db = self::connect();
         // 备份表结构
-        if(0 == $start){
+        if (0 == $start) {
             $result = $db->query("SHOW CREATE TABLE `{$table}`");
-            $sql  = "\n";
+            $sql = "\n";
             $sql .= "-- -----------------------------\n";
             $sql .= "-- Table structure for `{$table}`\n";
             $sql .= "-- -----------------------------\n";
             $sql .= "DROP TABLE IF EXISTS `{$table}`;\n";
-
             $sql .= trim($result[0]['Create Table']) . ";\n\n";
-
-            if(false === $this->write($sql)){
+            if (false === $this->write($sql)) {
                 return false;
             }
         }
-
         //数据总数
         $result = $db->query("SELECT COUNT(*) AS count FROM `{$table}`");
-       
-        $count  = $result['0']['count'];
-            
+        $count = $result['0']['count'];
         //备份表数据
-        if($count){
+        if ($count) {
             //写入数据注释
-            if(0 == $start){
-                $sql  = "-- -----------------------------\n";
+            if (0 == $start) {
+                $sql = "-- -----------------------------\n";
                 $sql .= "-- Records of `{$table}`\n";
                 $sql .= "-- -----------------------------\n";
                 $this->write($sql);
             }
-
             //备份数据记录
             $result = $db->query("SELECT * FROM `{$table}` LIMIT {$start}, 1000");
             foreach ($result as $row) {
                 $row = array_map('addslashes', $row);
-                $sql = "INSERT INTO `{$table}` VALUES ('" . str_replace(array("\r","\n"),array('\r','\n'),implode("', '", $row)) . "');\n";
-                if(false === $this->write($sql)){
+                $sql = "INSERT INTO `{$table}` VALUES ('" . str_replace(array("\r", "\n"), array('\\r', '\\n'), implode("', '", $row)) . "');\n";
+                if (false === $this->write($sql)) {
                     return false;
                 }
             }
-
             //还有更多数据
-            if($count > $start + 1000){
-                return array($start + 1000, $count);
+            if ($count > $start + 1000) {
+                //return array($start + 1000, $count);
+                return $this->backup($table, $start + 1000);
             }
         }
         //备份下一表
@@ -324,81 +338,84 @@ class Backup
     /**
      * 优化表
      * @param  String $tables 表名
-     * @return String $tables  
+     * @return String $tables
      */
-    public function optimize($tables = null){
-        if($tables) {
+    public function optimize($tables = null)
+    {
+        if ($tables) {
             $db = self::connect();
-            if(is_array($tables)){
+            if (is_array($tables)) {
                 $tables = implode('`,`', $tables);
                 $list = $db->query("OPTIMIZE TABLE `{$tables}`");
             } else {
                 $list = $db->query("OPTIMIZE TABLE `{$tables}`");
             }
-            if($list){
+            if ($list) {
                 return $tables;
             } else {
-                throw new \Exception("data sheet'{$tables}'Repair mistakes please try again!");
+                throw new \think\Exception("data sheet'{$tables}'Repair mistakes please try again!");
             }
         } else {
-            throw new \Exception("Please specify the table to be repaired!");
+            throw new \think\Exception("Please specify the table to be repaired!");
         }
     }
     /**
      * 修复表
      * @param  String $tables 表名
-     * @return String $tables  
+     * @return String $tables
      */
-    public function repair($tables = null){
-        if($tables) {
+    public function repair($tables = null)
+    {
+        if ($tables) {
             $db = self::connect();
-            if(is_array($tables)){
+            if (is_array($tables)) {
                 $tables = implode('`,`', $tables);
                 $list = $db->query("REPAIR TABLE `{$tables}`");
             } else {
-                $list =  $db->query("REPAIR TABLE `{$tables}`");
+                $list = $db->query("REPAIR TABLE `{$tables}`");
             }
-            if($list){
+            if ($list) {
                 return $list;
             } else {
-                throw new \Exception("data sheet'{$tables}'Repair mistakes please try again!");
+                throw new \think\Exception("data sheet'{$tables}'Repair mistakes please try again!");
             }
         } else {
-            throw new \Exception("Please specify the table to be repaired!");
+            throw new \think\Exception("Please specify the table to be repaired!");
         }
     }
-
     /**
      * 写入SQL语句
      * @param  string $sql 要写入的SQL语句
      * @return boolean     true - 写入成功,false - 写入失败!
      */
-    private function write($sql){
+    private function write($sql)
+    {
         $size = strlen($sql);
         //由于压缩原因,无法计算出压缩后的长度,这里假设压缩率为50%,
         //一般情况压缩率都会高于50%;
         $size = $this->config['compress'] ? $size / 2 : $size;
-        $this->open($size); 
+        $this->open($size);
         return $this->config['compress'] ? @gzwrite($this->fp, $sql) : @fwrite($this->fp, $sql);
     }
     /**
      * 打开一个卷,用于写入数据
      * @param  integer $size 写入数据的大小
      */
-    private function open($size){
-        if($this->fp){
+    private function open($size)
+    {
+        if ($this->fp) {
             $this->size += $size;
-            if($this->size > $this->config['part']){
+            if ($this->size > $this->config['part']) {
                 $this->config['compress'] ? @gzclose($this->fp) : @fclose($this->fp);
                 $this->fp = null;
                 $this->file['part']++;
                 session('backup_file', $this->file);
-                $this->create();
+                $this->Backup_Init();
             }
         } else {
             $backuppath = $this->config['path'];
-            $filename   = "{$backuppath}{$this->file['name']}-{$this->file['part']}.sql";
-            if($this->config['compress']){
+            $filename = "{$backuppath}{$this->file['name']}-{$this->file['part']}.sql";
+            if ($this->config['compress']) {
                 $filename = "{$filename}.gz";
                 $this->fp = @gzopen($filename, "a{$this->config['level']}");
             } else {
@@ -426,10 +443,10 @@ class Backup
     /**
      * 析构方法,用于关闭文件资源
      */
-    public function __destruct(){
+    public function __destruct()
+    {
         if($this->fp){
             $this->config['compress'] ? @gzclose($this->fp) : @fclose($this->fp);
-        }        
+        }
     }
-
 }