From b192a0151fa540596e10ec67f41e2fd3a39c77a3 Mon Sep 17 00:00:00 2001 From: JaguarJack Date: Wed, 29 Apr 2020 17:37:45 +0800 Subject: [PATCH] recover --- catch/index/controller/Index.php | 22 + catch/index/module.json | 13 + catch/index/route.php | 5 + catch/login/LoginLogEvent.php | 82 + catch/login/controller/Index.php | 63 + catch/login/module.json | 13 + catch/login/request/LoginRequest.php | 26 + catch/login/route.php | 4 + catch/permissions/Auth.php | 110 ++ catch/permissions/AuthTokenMiddleware.php | 34 + catch/permissions/OperateLogEvent.php | 31 + catch/permissions/PermissionsMiddleware.php | 132 ++ catch/permissions/controller/Department.php | 68 + catch/permissions/controller/Job.php | 80 + catch/permissions/controller/Permission.php | 124 ++ catch/permissions/controller/Role.php | 148 ++ catch/permissions/controller/User.php | 229 +++ .../migrations/20191128114204_users.php | 45 + .../migrations/20191208125722_roles.php | 42 + .../migrations/20191208125726_permissions.php | 48 + .../20191208131107_user_has_roles.php | 36 + .../20191208131115_role_has_permissions.php | 36 + .../migrations/20200108143438_department.php | 45 + .../migrations/20200108143506_job.php | 43 + .../20200112003534_user_relate_job.php | 36 + .../20200112031437_role_has_departments.php | 36 + .../20200409023815_change_permissions.php | 41 + .../20200422080926_permissions_add_column.php | 38 + .../database/seeds/DepartmentsSeed.php | 39 + .../database/seeds/PermissionSeed.php | 1454 +++++++++++++++++ .../permissions/database/seeds/UsersSeed.php | 24 + catch/permissions/model/Department.php | 43 + .../permissions/model/HasDepartmentsTrait.php | 57 + catch/permissions/model/HasJobsTrait.php | 58 + .../permissions/model/HasPermissionsTrait.php | 76 + catch/permissions/model/HasRolesTrait.php | 58 + catch/permissions/model/Job.php | 36 + catch/permissions/model/Permissions.php | 103 ++ catch/permissions/model/Roles.php | 90 + catch/permissions/model/Users.php | 85 + .../model/search/DepartmentSearch.php | 15 + catch/permissions/model/search/JobsSearch.php | 20 + .../model/search/PermissionsSearch.php | 31 + .../permissions/model/search/RolesSearch.php | 16 + catch/permissions/model/search/UserSearch.php | 25 + catch/permissions/module.json | 11 + catch/permissions/request/CreateRequest.php | 24 + catch/permissions/request/UpdateRequest.php | 23 + catch/permissions/route.php | 21 + catch/system/controller/Attachments.php | 31 + catch/system/controller/Config.php | 65 + catch/system/controller/DataDictionary.php | 106 ++ catch/system/controller/Generate.php | 28 + catch/system/controller/LoginLog.php | 35 + catch/system/controller/OperateLog.php | 34 + catch/system/controller/Upload.php | 57 + .../migrations/20191212110921_login_log.php | 40 + .../migrations/20191212110930_operate_log.php | 42 + .../migrations/20200125133249_attachments.php | 44 + .../migrations/20200417083602_config.php | 44 + catch/system/database/seeds/ConfigSeed.php | 36 + catch/system/model/Attachments.php | 45 + catch/system/model/Config.php | 210 +++ catch/system/model/LoginLog.php | 21 + catch/system/model/OperateLog.php | 40 + catch/system/module.json | 11 + catch/system/route.php | 28 + 67 files changed, 4856 insertions(+) create mode 100644 catch/index/controller/Index.php create mode 100644 catch/index/module.json create mode 100644 catch/index/route.php create mode 100644 catch/login/LoginLogEvent.php create mode 100644 catch/login/controller/Index.php create mode 100644 catch/login/module.json create mode 100644 catch/login/request/LoginRequest.php create mode 100644 catch/login/route.php create mode 100644 catch/permissions/Auth.php create mode 100644 catch/permissions/AuthTokenMiddleware.php create mode 100644 catch/permissions/OperateLogEvent.php create mode 100644 catch/permissions/PermissionsMiddleware.php create mode 100644 catch/permissions/controller/Department.php create mode 100644 catch/permissions/controller/Job.php create mode 100644 catch/permissions/controller/Permission.php create mode 100644 catch/permissions/controller/Role.php create mode 100644 catch/permissions/controller/User.php create mode 100644 catch/permissions/database/migrations/20191128114204_users.php create mode 100644 catch/permissions/database/migrations/20191208125722_roles.php create mode 100644 catch/permissions/database/migrations/20191208125726_permissions.php create mode 100644 catch/permissions/database/migrations/20191208131107_user_has_roles.php create mode 100644 catch/permissions/database/migrations/20191208131115_role_has_permissions.php create mode 100644 catch/permissions/database/migrations/20200108143438_department.php create mode 100644 catch/permissions/database/migrations/20200108143506_job.php create mode 100644 catch/permissions/database/migrations/20200112003534_user_relate_job.php create mode 100644 catch/permissions/database/migrations/20200112031437_role_has_departments.php create mode 100644 catch/permissions/database/migrations/20200409023815_change_permissions.php create mode 100644 catch/permissions/database/migrations/20200422080926_permissions_add_column.php create mode 100644 catch/permissions/database/seeds/DepartmentsSeed.php create mode 100644 catch/permissions/database/seeds/PermissionSeed.php create mode 100644 catch/permissions/database/seeds/UsersSeed.php create mode 100644 catch/permissions/model/Department.php create mode 100644 catch/permissions/model/HasDepartmentsTrait.php create mode 100644 catch/permissions/model/HasJobsTrait.php create mode 100644 catch/permissions/model/HasPermissionsTrait.php create mode 100644 catch/permissions/model/HasRolesTrait.php create mode 100644 catch/permissions/model/Job.php create mode 100644 catch/permissions/model/Permissions.php create mode 100644 catch/permissions/model/Roles.php create mode 100644 catch/permissions/model/Users.php create mode 100644 catch/permissions/model/search/DepartmentSearch.php create mode 100644 catch/permissions/model/search/JobsSearch.php create mode 100644 catch/permissions/model/search/PermissionsSearch.php create mode 100644 catch/permissions/model/search/RolesSearch.php create mode 100644 catch/permissions/model/search/UserSearch.php create mode 100644 catch/permissions/module.json create mode 100644 catch/permissions/request/CreateRequest.php create mode 100644 catch/permissions/request/UpdateRequest.php create mode 100644 catch/permissions/route.php create mode 100644 catch/system/controller/Attachments.php create mode 100644 catch/system/controller/Config.php create mode 100644 catch/system/controller/DataDictionary.php create mode 100644 catch/system/controller/Generate.php create mode 100644 catch/system/controller/LoginLog.php create mode 100644 catch/system/controller/OperateLog.php create mode 100644 catch/system/controller/Upload.php create mode 100644 catch/system/database/migrations/20191212110921_login_log.php create mode 100644 catch/system/database/migrations/20191212110930_operate_log.php create mode 100644 catch/system/database/migrations/20200125133249_attachments.php create mode 100644 catch/system/database/migrations/20200417083602_config.php create mode 100644 catch/system/database/seeds/ConfigSeed.php create mode 100644 catch/system/model/Attachments.php create mode 100644 catch/system/model/Config.php create mode 100644 catch/system/model/LoginLog.php create mode 100644 catch/system/model/OperateLog.php create mode 100644 catch/system/module.json create mode 100644 catch/system/route.php diff --git a/catch/index/controller/Index.php b/catch/index/controller/Index.php new file mode 100644 index 0000000..b64da43 --- /dev/null +++ b/catch/index/controller/Index.php @@ -0,0 +1,22 @@ +fetch([ + 'mysql_version' => $mysqlVersion['0']['version'], + ]); + } +} diff --git a/catch/index/module.json b/catch/index/module.json new file mode 100644 index 0000000..35b94da --- /dev/null +++ b/catch/index/module.json @@ -0,0 +1,13 @@ +{ + "name": "首页管理", + "alias": "index", + "description": "", + "keywords": [], + "order": 0, + "services": [ + "catchAdmin\\index\\IndexService" + ], + "aliases": {}, + "files": [], + "requires": [] +} \ No newline at end of file diff --git a/catch/index/route.php b/catch/index/route.php new file mode 100644 index 0000000..3f0cdef --- /dev/null +++ b/catch/index/route.php @@ -0,0 +1,5 @@ +get('/', '\catchAdmin\index\controller\Index@index'); +$router->get('theme', '\catchAdmin\index\controller\Index@theme'); +$router->get('dashboard', '\catchAdmin\index\controller\Index@dashboard'); diff --git a/catch/login/LoginLogEvent.php b/catch/login/LoginLogEvent.php new file mode 100644 index 0000000..77dea50 --- /dev/null +++ b/catch/login/LoginLogEvent.php @@ -0,0 +1,82 @@ +header('user-agent'); + + $username = Users::where('email', $params['email'])->value('username'); + + app(LoginLog::class)->storeBy([ + 'login_name' => $username ? : $params['email'], + 'login_ip' => request()->ip(), + 'browser' => $this->getBrowser($agent), + 'os' => $this->getOs($agent), + 'login_at' => time(), + 'status' => $params['success'] ? 1 : 2, + ]); + } + + /** + * + * @time 2019年12月12日 + * @param $agent + * @return string + */ + private function getOs($agent): string + { + if (false !== stripos($agent, 'win') && preg_match('/nt 6.1/i', $agent)) { + return 'Windows 7'; + } + if (false !== stripos($agent, 'win') && preg_match('/nt 6.2/i', $agent)) { + return 'Windows 8'; + } + if(false !== stripos($agent, 'win') && preg_match('/nt 10.0/i', $agent)) { + return 'Windows 10';#添加win10判断 + } + if (false !== stripos($agent, 'win') && preg_match('/nt 5.1/i', $agent)) { + return 'Windows XP'; + } + if (false !== stripos($agent, 'linux')) { + return 'Linux'; + } + if (false !== stripos($agent, 'mac')) { + return 'mac'; + } + + return '未知'; + } + + /** + * + * @time 2019年12月12日 + * @param $agent + * @return string + */ + private function getBrowser($agent): string + { + if (false !== stripos($agent, "MSIE")) { + return 'MSIE'; + } + if (false !== stripos($agent, "Firefox")) { + return 'Firefox'; + } + if (false !== stripos($agent, "Chrome")) { + return 'Chrome'; + } + if (false !== stripos($agent, "Safari")) { + return 'Safari'; + } + if (false !== stripos($agent, "Opera")) { + return 'Opera'; + } + + return '未知'; + } +} diff --git a/catch/login/controller/Index.php b/catch/login/controller/Index.php new file mode 100644 index 0000000..1b18a91 --- /dev/null +++ b/catch/login/controller/Index.php @@ -0,0 +1,63 @@ +param(); + + $token = $auth->attempt($params); + + $user = $auth->user(); + + if ($user->status == Users::DISABLE) { + throw new LoginFailedException('该用户已被禁用'); + } + + // 记录用户登录 + $user->last_login_ip = request()->ip(); + $user->last_login_time = time(); + $user->save(); + + // 登录事件 + $params['success'] = $token; + + event('loginLog', $params); + + return $token ? CatchResponse::success([ + 'token' => $token, + ], '登录成功') : CatchResponse::success('', '登录失败'); + } + + /** + * 登出 + * + * @time 2019年11月28日 + * @param CatchAuth $auth + * @return \think\response\Json + */ + public function logout(CatchAuth $auth): \think\response\Json + { + if ($auth->logout()) { + return CatchResponse::success(); + } + + return CatchResponse::fail('登出失败'); + } +} diff --git a/catch/login/module.json b/catch/login/module.json new file mode 100644 index 0000000..1456ed4 --- /dev/null +++ b/catch/login/module.json @@ -0,0 +1,13 @@ +{ + "name": "登陆", + "alias": "login", + "description": "", + "keywords": [], + "order": 1, + "services": [ + "catchAdmin\\login\\LoginService" + ], + "aliases": {}, + "files": [], + "requires": [] +} \ No newline at end of file diff --git a/catch/login/request/LoginRequest.php b/catch/login/request/LoginRequest.php new file mode 100644 index 0000000..b392a8e --- /dev/null +++ b/catch/login/request/LoginRequest.php @@ -0,0 +1,26 @@ + 'email', + 'password|密码' => 'require', + // 'captcha|验证码' => 'require|captcha' + ]; + } + + protected function message(): array + { + // TODO: Implement message() method. + return []; + + } +} diff --git a/catch/login/route.php b/catch/login/route.php new file mode 100644 index 0000000..90b3847 --- /dev/null +++ b/catch/login/route.php @@ -0,0 +1,4 @@ +post('login', '\catchAdmin\login\controller\Index@login'); + diff --git a/catch/permissions/Auth.php b/catch/permissions/Auth.php new file mode 100644 index 0000000..e51e02d --- /dev/null +++ b/catch/permissions/Auth.php @@ -0,0 +1,110 @@ +find(); + + if (!$user) { + throw new LoginFailedException('登陆失败, 请检查用户名和密码'); + } + + if (!password_verify($params['password'], $user->password)) { + throw new LoginFailedException('登陆失败, 请检查用户名和密码'); + } + + + + // Session::set(self::getLoginUserKey(), $user); + + return JWTAuth::builder([self::USER_ID => $user->id]); + } + + /** + * 退出登陆 + * + * @time 2019年11月28日 + * @return bool + */ + public static function logout(): bool + { + Session::delete(self::getLoginUserKey()); + + return true; + } + + /** + * + * @time 2019年12月15日 + * @return mixed + */ + public static function user() + { + return Users::where('id', JWTAuth::auth()[self::USER_ID]) + ->field(['id', 'username', 'status'])->find(); + } + + public static function getUserInfo() + { + $user = self::user(); + + $roles = $user->getRoles(); + + $user->permissions = Permissions::whereIn('id', $user->getPermissionsBy()) + ->field(['permission_name as title', 'route', 'icon']) + ->select(); + + $user->roles = $roles; + + return $user; + } + + /** + * + * @time 2019年12月15日 + * @return string + */ + protected static function getLoginUserKey(): string + { + // return md5(self::USER_KEY); + } + + /** + * + * @time 2019年12月15日 + * @param $mark + * @param $module + * @return bool + */ + public static function hasPermissions($mark, $module): bool + { + $user = self::user(); + + $permissionIds = $user->getPermissionsBy($user->id); + + $permissionId = Permissions::where('module', $module) + ->where('permission_mark', $mark)->value('id'); + + return in_array($permissionId, $permissionIds); + } +} diff --git a/catch/permissions/AuthTokenMiddleware.php b/catch/permissions/AuthTokenMiddleware.php new file mode 100644 index 0000000..16ad861 --- /dev/null +++ b/catch/permissions/AuthTokenMiddleware.php @@ -0,0 +1,34 @@ +parent_id)->value('permission_name'); + + $requestParams = request()->param(); + + app(OperateLog::class)->storeBy([ + 'creator_id' => $params['creator_id'], + 'module' => $parentPermission ? : '', + 'method' => request()->method(), + 'operate' => $permission->permission_name, + 'route' => $permission->permission_mark, + 'params' => !empty($requestParams) ? json_encode($requestParams, JSON_UNESCAPED_UNICODE) : '', + 'created_at' => time(), + 'ip' => request()->ip(), + ]); + } +} diff --git a/catch/permissions/PermissionsMiddleware.php b/catch/permissions/PermissionsMiddleware.php new file mode 100644 index 0000000..7e25446 --- /dev/null +++ b/catch/permissions/PermissionsMiddleware.php @@ -0,0 +1,132 @@ +rule()->getName(); + + if (!$rule) { + return $next($request); + } + // 模块忽略 + [$module, $controller, $action] = $this->parseRule($rule); + // toad + if (in_array($module, $this->ignoreModule())) { + return $next($request); + } + // 用户未登录 + $user = $request->user(); + if (!$user) { + throw new PermissionForbiddenException('Login is invalid', Code::LOST_LOGIN); + } + //dd($this->parseRule($rule)); + $permission = $this->getPermission($module, $controller, $action); + // 记录操作 + $this->operateEvent($request->user()->id, $permission); + // 超级管理员 + if ($request->user()->id === config('catch.permissions.super_admin_id')) { + return $next($request); + } + // Get 请求 + if ($request->isGet() && config('catch.permissions.is_allow_get')) { + return $next($request); + } + + if (!$permission || !in_array($permission->id, Cache::get(CatchCacheKeys::USER_PERMISSIONS . $user->id))) { + throw new PermissionForbiddenException(); + } + + return $next($request); + } + + /** + * 解析规则 + * + * @time 2020年04月16日 + * @param $rule + * @return array + */ + protected function parseRule($rule) + { + [$controller, $action] = explode(Str::contains($rule, '@') ? '@' : '/', $rule); + + $controller = explode('\\', $controller); + + $controllerName = strtolower(array_pop($controller)); + + array_pop($controller); + + $module = array_pop($controller); + + return [$module, $controllerName, $action]; + } + + + /** + * + * @time 2019年12月14日 + * @param $module + * @param $controllerName + * @param $action + * @param $request + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return array|bool|\think\Model|null + */ + protected function getPermission($module, $controllerName, $action) + { + $permissionMark = sprintf('%s@%s', $controllerName, $action); + + return Permissions::where('module', $module)->where('permission_mark', $permissionMark)->find(); + } + + /** + * 忽略模块 + * + * @time 2020年04月16日 + * @return array + */ + protected function ignoreModule() + { + return ['login']; + } + + /** + * 操作日志 + * + * @time 2020年04月16日 + * @param $creatorId + * @param $permission + * @return void + */ + protected function operateEvent($creatorId, $permission) + { + // 操作日志 + $permission && event('operateLog', [ + 'creator_id' => $creatorId, + 'permission' => $permission, + ]); + } +} diff --git a/catch/permissions/controller/Department.php b/catch/permissions/controller/Department.php new file mode 100644 index 0000000..036cefa --- /dev/null +++ b/catch/permissions/controller/Department.php @@ -0,0 +1,68 @@ +department = $department; + } + + /** + * 列表 + * + * @time 2020年01月09日 + * @param CatchRequest $request + * @return \think\response\Json + * @throws \think\db\exception\DbException + */ + public function index(): \think\response\Json + { + return CatchResponse::success(Tree::done($this->department->getList())); + } + + /** + * 保存 + * + * @time 2020年01月09日 + * @param CatchRequest $request + * @return \think\response\Json + */ + public function save(CatchRequest $request): \think\response\Json + { + return CatchResponse::success($this->department->storeBy($request->post())); + } + + /** + * 更新 + * + * @time 2020年01月09日 + * @param $id + * @param CatchRequest $request + * @return \think\response\Json + */ + public function update($id, CatchRequest $request): \think\response\Json + { + return CatchResponse::success($this->department->updateBy($id, $request->post())); + } + + /** + * 删除 + * + * @time 2020年01月09日 + * @param $id + * @return \think\response\Json + */ + public function delete($id): \think\response\Json + { + return CatchResponse::success($this->department->deleteBy($id)); + } +} diff --git a/catch/permissions/controller/Job.php b/catch/permissions/controller/Job.php new file mode 100644 index 0000000..4ef8e2c --- /dev/null +++ b/catch/permissions/controller/Job.php @@ -0,0 +1,80 @@ +job = $job; + } + + /** + * 列表 + * + * @time 2020年01月09日 + * @param CatchRequest $request + * @return \think\response\Json + * @throws \think\db\exception\DbException + */ + public function index(): \think\response\Json + { + return CatchResponse::paginate($this->job->getList()); + } + + /** + * 保存 + * + * @time 2020年01月09日 + * @param CatchRequest $request + * @return \think\response\Json + */ + public function save(CatchRequest $request): \think\response\Json + { + return CatchResponse::success($this->job->storeBy($request->post())); + } + + /** + * 更新 + * + * @time 2020年01月09日 + * @param $id + * @param CatchRequest $request + * @return \think\response\Json + */ + public function update($id, CatchRequest $request): \think\response\Json + { + return CatchResponse::success($this->job->updateBy($id, $request->post())); + } + + /** + * 删除 + * + * @time 2020年01月09日 + * @param $id + * @return \think\response\Json + */ + public function delete($id): \think\response\Json + { + return CatchResponse::success($this->job->deleteBy($id)); + } + +/** + * 获取所有 + * + * @return \think\response\Json + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getAll() + { + return CatchResponse::success($this->job->field(['id', 'job_name'])->select()); + } +} diff --git a/catch/permissions/controller/Permission.php b/catch/permissions/controller/Permission.php new file mode 100644 index 0000000..da1530e --- /dev/null +++ b/catch/permissions/controller/Permission.php @@ -0,0 +1,124 @@ +permissions = $permissions; + } + + /** + * + * @time 2019年12月11日 + * @param Request $request + * @return Json + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\db\exception\DataNotFoundException + */ + public function index(Request $request): Json + { + // 获取菜单类型 + $menuList = $this->permissions->getList(true); + + // 获取按钮类型并且重新排列 + $buttonList = []; + $this->permissions + ->whereIn('parent_id', array_unique($menuList->column('id'))) + ->where('type', Permissions::BTN_TYPE) + ->select()->each(function ($item) use (&$buttonList){ + $buttonList[$item['parent_id']][] = $item->toArray(); + }); + + // 子节点的 key + $children = $request->param('actionList') ?? 'children'; + // 返回树结构 + return CatchResponse::success(Tree::done($menuList->each(function (&$item) use ($buttonList, $children){ + $item[$children] = $buttonList[$item['id']] ?? []; + })->toArray())); + } + + /** + * + * @time 2019年12月11日 + * @param Request $request + * @return Json + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\db\exception\DataNotFoundException + */ + public function save(Request $request): Json + { + $params = $request->param(); + + // 如果是子分类 自动写入父类模块 + $parentId = $params['parent_id'] ?? 0; + if ($parentId) { + $parent = $this->permissions->findBy($parentId); + $params['module'] = $parent->module; + } + + return CatchResponse::success($this->permissions->storeBy($params)); + } + + /** + * + * @time 2019年12月11日 + * @param $id + * @param Request $request + * @return Json + */ + public function update($id, Request $request): Json + { + $permission = $this->permissions->findBy($id); + + $params = array_merge($request->param(), [ + 'parent_id' => $permission->parent_id, + 'level' => $permission->level + ]); + + // 如果是父分类需要更新所有子分类的模块 + if (!$permission->parent_id) { + $this->permissions->updateBy($permission->parent_id, [ + 'module' => $permission->module, + ], 'parent_id'); + } + + return CatchResponse::success($this->permissions->updateBy($id, $params)); + } + + /** + * + * @time 2019年12月11日 + * @param $id + * @throws FailedException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return Json + */ + public function delete($id): Json + { + if ($this->permissions->where('parent_id', $id)->find()) { + throw new FailedException('存在子菜单,无法删除'); + } + + $this->permissions->findBy($id)->roles()->detach(); + + return CatchResponse::success($this->permissions->deleteBy($id)); + } +} + + diff --git a/catch/permissions/controller/Role.php b/catch/permissions/controller/Role.php new file mode 100644 index 0000000..3213626 --- /dev/null +++ b/catch/permissions/controller/Role.php @@ -0,0 +1,148 @@ +role = $role; + } + + /** + * + * @time 2019年12月09日 + * @param Request $request + * @return string + */ + public function index() + { + return CatchResponse::success(Tree::done($this->role->getList())); + } + + /** + * + * @time 2019年12月11日 + * @param Request $request + * @return Json + * @throws \think\db\exception\DbException + */ + public function save(Request $request) + { + $this->role->storeBy($request->param()); + + $permissions = $request->param('permissions'); + if (!empty($permissions)) { + $this->role->attach(array_unique($permissions)); + } + if (!empty($request->param('departments'))) { + $this->role->attachDepartments($request->param('departments')); + } + // 添加角色 + return CatchResponse::success(); + } + + public function read($id) + { + $role = $this->role->findBy($id); + $role->permissions = $role->getPermissions(); + $role->departments = $role->getDepartments(); + return CatchResponse::success($role); + } + + /** + * + * @time 2019年12月11日 + * @param $id + * @param Request $request + * @return Json + * @throws \think\db\exception\DbException + */ + public function update($id, Request $request): Json + { + $this->role->updateBy($id, $request->param()); + $role = $this->role->findBy($id); + $role->detach(); + + $permissions = $request->param('permissions'); + if (!empty($permissions)) { + $this->role->attach(array_unique($permissions)); + } + + if (!empty($request->param('departments'))) { + $role->detachDepartments(); + $role->attachDepartments($request->param('departments')); + } + return CatchResponse::success(); + } + + /** + * + * @time 2019年12月11日 + * @param $id + * @throws FailedException + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return Json + */ + public function delete($id): Json + { + if ($this->role->where('parent_id', $id)->find()) { + throw new FailedException('存在子角色,无法删除'); + } + $role = $this->role->findBy($id); + // 删除权限 + $role->detach(); + // 删除部门关联 + $role->detachDepartments(); + // 删除用户关联 + $role->users()->detach(); + // 删除 + $this->role->deleteBy($id); + + return CatchResponse::success(); + } + + /** + * + * @time 2019年12月11日 + * @param Request $request + * @param \catchAdmin\permissions\model\Permissions $permission + * @return Json + */ + public function getPermissions(Request $request, \catchAdmin\permissions\model\Permissions $permission): Json + { + $parentRoleHasPermissionIds = []; + if ($request->param('parent_id')) { + $permissions = $this->role->findBy($request->param('parent_id'))->getPermissions(); + foreach ($permissions as $_permission) { + $parentRoleHasPermissionIds[] = $_permission->pivot->permission_id; + } + } + + $permissions = Tree::done(Permissions::whereIn('id', $parentRoleHasPermissionIds)->select()->toArray()); + + $permissionIds = []; + if ($request->param('role_id')) { + $roleHasPermissions = $this->role->findBy($request->param('role_id'))->getPermissions(); + foreach ($roleHasPermissions as $_permission) { + $permissionIds[] = $_permission->pivot->permission_id; + } + } + + return CatchResponse::success([ + 'permissions' => $permissions, + 'hasPermissions' => $permissionIds, + ]); + } +} diff --git a/catch/permissions/controller/User.php b/catch/permissions/controller/User.php new file mode 100644 index 0000000..5300ffc --- /dev/null +++ b/catch/permissions/controller/User.php @@ -0,0 +1,229 @@ +user = $user; + } + + /** + * + * @time 2020年04月24日 + * @param Request $request + * @throws \think\db\exception\DbException + * @return \think\response\Json + */ + public function index(Request $request) + { + return CatchResponse::paginate($this->user->getList($request->param())); + } + + /** + * 获取用户信息 + * + * @time 2020年01月07日 + * @param CatchAuth $auth + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return \think\response\Json + */ + public function info(CatchAuth $auth) + { + $user = $auth->user(); + + $roles = $user->getRoles(); + + $permissionIds = $user->getPermissionsBy($user->id); + // 缓存用户权限 + Cache::set(CatchCacheKeys::USER_PERMISSIONS . $user->id, $permissionIds); + + $user->permissions = Permissions::getCurrentUserPermissions($permissionIds); + + $user->roles = $roles; + + // 用户数据权限 + // $user->data_range = Roles::getDepartmentUserIdsBy($roles); + + return CatchResponse::success($user); + } + + /** + * + * @time 2019年12月06日 + * @throws \Exception + * @return string + */ + public function create() + {} + + /** + * + * @param CreateRequest $request + * @time 2019年12月06日 + * @return \think\response\Json + */ + public function save(CreateRequest $request) + { + $this->user->storeBy($request->post()); + + $this->user->attach($request->param('roles')); + + $this->user->attachJobs($request->param('jobs')); + + return CatchResponse::success('', '添加成功'); + } + + /** + * + * @time 2019年12月04日 + * @param $id + * @return \think\response\Json + */ + public function read($id) + { + $user = $this->user->findBy($id); + $user->roles = $user->getRoles(); + $user->jobs = $user->getJobs(); + return CatchResponse::success($user); + } + + /** + * @param $id + * @return string + * @throws \Exception + */ + public function edit($id){} + /** + * + * @time 2019年12月04日 + * @param $id + * @param UpdateRequest $request + * @return \think\response\Json + */ + public function update($id, UpdateRequest $request) + { + $this->user->updateBy($id, $request->post()); + + $user = $this->user->findBy($id); + + $user->detach(); + $user->detachJobs(); + + if (!empty($request->param('roles'))) { + $user->attach($request->param('roles')); + } + if (!empty($request->param('jobs'))) { + $user->attachJobs($request->param('jobs')); + } + return CatchResponse::success(); + } + + /** + * + * @time 2019年12月04日 + * @param $id + * @return \think\response\Json + */ + public function delete($id) + { + $ids = Utils::stringToArrayBy($id); + + foreach ($ids as $_id) { + $user = $this->user->findBy($_id); + // 删除角色 + $user->detach(); + // 删除岗位 + $user->detachJobs(); + + $this->user->deleteBy($_id); + } + + return CatchResponse::success(); + } + + /** + * + * @time 2019年12月07日 + * @param $id + * @return \think\response\Json + */ + public function switchStatus($id): \think\response\Json + { + $ids = Utils::stringToArrayBy($id); + + foreach ($ids as $_id) { + + $user = $this->user->findBy($_id); + + $this->user->updateBy($_id, [ + 'status' => $user->status == Users::ENABLE ? Users::DISABLE : Users::ENABLE, + ]); + } + + return CatchResponse::success([], '操作成功'); + } + + /** + * + * @time 2019年12月07日 + * @param $id + * @return \think\response\Json + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\db\exception\DataNotFoundException + */ + public function recover($id): \think\response\Json + { + $trashedUser = $this->user->findBy($id, ['*'], true); + + if ($this->user->where('email', $trashedUser->email)->find()) { + return CatchResponse::fail(sprintf('该恢复用户的邮箱 [%s] 已被占用', $trashedUser->email)); + } + + return CatchResponse::success($this->user->recover($id)); + } + + /** + * + * @time 2019年12月11日 + * @param Request $request + * @param Roles $roles + * @return \think\response\Json + */ + public function getRoles(Request $request, Roles $roles): \think\response\Json + { + $roles = Tree::done($roles->getList()); + + $roleIds = []; + if ($request->param('uid')) { + $userHasRoles = $this->user->findBy($request->param('uid'))->getRoles(); + foreach ($userHasRoles as $role) { + $roleIds[] = $role->pivot->role_id; + } + } + + return CatchResponse::success([ + 'roles' => $roles, + 'hasRoles' => $roleIds, + ]); + } +} diff --git a/catch/permissions/database/migrations/20191128114204_users.php b/catch/permissions/database/migrations/20191128114204_users.php new file mode 100644 index 0000000..ba6a2a6 --- /dev/null +++ b/catch/permissions/database/migrations/20191128114204_users.php @@ -0,0 +1,45 @@ +table('users',array('engine'=>'Innodb', 'comment' => '用户表', 'signed' => false)); + $table->addColumn('username', 'string',array('limit' => 15,'default'=>'','comment'=>'用户名')) + ->addColumn('password', 'string',array('limit' => 255,'comment'=>'用户密码')) + ->addColumn('email', 'string',array('limit' => 100, 'comment'=>'邮箱 登录')) + ->addColumn('creator_id', 'integer',['default' => 0, 'comment'=>'创建人ID']) + ->addColumn('department_id', 'integer',['default' => 0, 'comment'=>'部门ID']) + ->addColumn('status', 'boolean',array('limit' => 1,'default'=> 1,'comment'=>'用户状态 1 正常 2 禁用')) + ->addColumn('last_login_ip', 'string',array('limit' => 50,'default'=>0,'comment'=>'最后登录IP')) + ->addColumn('last_login_time', 'integer',array('default'=>0,'comment'=>'最后登录时间', 'signed' => false)) + ->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false )) + ->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false)) + ->addColumn('deleted_at', 'integer', array('default'=>0,'comment'=>'删除状态,0未删除 >0 已删除', 'signed' => false)) + ->create(); + } +} diff --git a/catch/permissions/database/migrations/20191208125722_roles.php b/catch/permissions/database/migrations/20191208125722_roles.php new file mode 100644 index 0000000..15b6d81 --- /dev/null +++ b/catch/permissions/database/migrations/20191208125722_roles.php @@ -0,0 +1,42 @@ +table('roles',['engine'=>'Innodb', 'comment' => '角色表', 'signed' => false]); + $table->addColumn('role_name', 'string',['limit' => 15,'default'=>'','comment'=>'角色名']) + ->addColumn('parent_id', 'integer',['default'=>0,'comment'=>'父级ID', 'signed' => false]) + ->addColumn('description', 'string',['default'=> '','comment'=>'角色备注']) + ->addColumn('data_range', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 0,'comment'=>'1 全部数据 2 自定义数据 3 仅本人数据 4 部门数据 5 部门及以下数据']) + ->addColumn('creator_id', 'integer',['default' => 0, 'comment'=>'创建人ID']) + ->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false )) + ->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false)) + ->addColumn('deleted_at', 'integer', array('default'=>0,'comment'=>'删除状态,0未删除 >0 已删除', 'signed' => false)) + ->create(); + } +} diff --git a/catch/permissions/database/migrations/20191208125726_permissions.php b/catch/permissions/database/migrations/20191208125726_permissions.php new file mode 100644 index 0000000..596f778 --- /dev/null +++ b/catch/permissions/database/migrations/20191208125726_permissions.php @@ -0,0 +1,48 @@ +table('permissions',['engine'=>'Innodb', 'comment' => '菜单表', 'signed' => false]); + $table->addColumn('permission_name', 'string',['limit' => 15,'default'=>'','comment'=>'菜单名称']) + ->addColumn('parent_id', 'integer',['default'=>0,'comment'=>'父级ID', 'signed' => false]) + ->addColumn('route', 'string', ['default' => '', 'comment' => '路由', 'limit' => 50]) + ->addColumn('icon', 'string', ['default' => '', 'comment' => '菜单图标', 'limit' => 50]) + ->addColumn('module', 'string', ['default' => '', 'comment' => '模块', 'limit' => 20]) + ->addColumn('creator_id', 'integer',['default' => 0, 'comment'=>'创建人ID']) + ->addColumn('method', 'string', ['default' => 'get', 'comment' => '路由请求方法', 'limit' => 15]) + ->addColumn('permission_mark', 'string', ['null' => false, 'comment' => '权限标识', 'limit' => 50]) + ->addColumn('type', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 1,'comment'=>'1 菜单 2 按钮']) + ->addColumn('sort', 'integer',['default'=> 0,'comment'=>'排序字段']) + ->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false )) + ->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false)) + ->addColumn('deleted_at', 'integer', array('default'=>0,'comment'=>'删除状态,null 未删除 timestamp 已删除', 'signed' => false)) + ->create(); + + } +} diff --git a/catch/permissions/database/migrations/20191208131107_user_has_roles.php b/catch/permissions/database/migrations/20191208131107_user_has_roles.php new file mode 100644 index 0000000..55d8450 --- /dev/null +++ b/catch/permissions/database/migrations/20191208131107_user_has_roles.php @@ -0,0 +1,36 @@ +table('user_has_roles',['engine'=>'Innodb', 'comment' => '用户角色表', 'signed' => false]); + $table->addColumn('uid', 'integer',['comment'=>'用户ID', 'signed' => false]) + ->addColumn('role_id', 'integer', ['comment'=>'角色ID', 'signed' => false]) + ->create(); + } +} diff --git a/catch/permissions/database/migrations/20191208131115_role_has_permissions.php b/catch/permissions/database/migrations/20191208131115_role_has_permissions.php new file mode 100644 index 0000000..c31c58b --- /dev/null +++ b/catch/permissions/database/migrations/20191208131115_role_has_permissions.php @@ -0,0 +1,36 @@ +table('role_has_permissions',['engine'=>'Innodb', 'comment' => '角色权限表', 'signed' => false]); + $table->addColumn('role_id', 'integer',['comment'=>'角色ID', 'signed' => false]) + ->addColumn('permission_id', 'integer', ['comment'=>'权限ID', 'signed' => false]) + ->create(); + } +} diff --git a/catch/permissions/database/migrations/20200108143438_department.php b/catch/permissions/database/migrations/20200108143438_department.php new file mode 100644 index 0000000..2584d1b --- /dev/null +++ b/catch/permissions/database/migrations/20200108143438_department.php @@ -0,0 +1,45 @@ +table('departments',['engine'=>'Innodb', 'comment' => '部门表', 'signed' => false]); + $table->addColumn('department_name', 'string',['limit' => 15,'default'=>'','comment'=>'部门名称']) + ->addColumn('parent_id', 'integer',['default'=>0,'comment'=>'父级ID', 'signed' => false]) + ->addColumn('principal', 'string', ['default' => '', 'comment' => '负责人', 'limit' => 20]) + ->addColumn('mobile', 'string', ['default' => '', 'comment' => '联系电话', 'limit' => 20]) + ->addColumn('email', 'string', ['default' => '', 'comment' => '联系又想', 'limit' => 100]) + ->addColumn('creator_id', 'integer',['default' => 0, 'comment'=>'创建人ID']) + ->addColumn('status', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 1,'comment'=>'1 正常 2 停用']) + ->addColumn('sort', 'integer',['default'=> 0,'comment'=>'排序字段']) + ->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false )) + ->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false)) + ->addColumn('deleted_at', 'integer', array('default'=>0,'comment'=>'删除状态,null 未删除 timestamp 已删除', 'signed' => false)) + ->create(); + } +} diff --git a/catch/permissions/database/migrations/20200108143506_job.php b/catch/permissions/database/migrations/20200108143506_job.php new file mode 100644 index 0000000..7307fe3 --- /dev/null +++ b/catch/permissions/database/migrations/20200108143506_job.php @@ -0,0 +1,43 @@ +table('jobs',['engine'=>'Innodb', 'comment' => '岗位表', 'signed' => false]); + $table->addColumn('job_name', 'string',['limit' => 15,'default'=>'','comment'=>'岗位名称']) + ->addColumn('coding', 'string', ['default' => '', 'comment' => '编码', 'limit' => 50]) + ->addColumn('creator_id', 'integer',['default' => 0, 'comment'=>'创建人ID']) + ->addColumn('status', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 1,'comment'=>'1 正常 2 停用']) + ->addColumn('sort', 'integer',['default'=> 0,'comment'=>'排序字段']) + ->addColumn('description', 'string', ['default' => '', 'comment' => '描述', 'limit' => 255]) + ->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'创建时间', 'signed' => false )) + ->addColumn('updated_at', 'integer', array('default'=>0,'comment'=>'更新时间', 'signed' => false)) + ->addColumn('deleted_at', 'integer', array('default'=>0,'comment'=>'删除状态,null 未删除 timestamp 已删除', 'signed' => false)) + ->create(); + } +} diff --git a/catch/permissions/database/migrations/20200112003534_user_relate_job.php b/catch/permissions/database/migrations/20200112003534_user_relate_job.php new file mode 100644 index 0000000..581903a --- /dev/null +++ b/catch/permissions/database/migrations/20200112003534_user_relate_job.php @@ -0,0 +1,36 @@ +table('user_has_jobs',['engine'=>'Innodb', 'comment' => '用户角色表', 'signed' => false]); + $table->addColumn('uid', 'integer',['comment'=>'用户ID', 'signed' => false]) + ->addColumn('job_id', 'integer', ['comment'=>'岗位ID', 'signed' => false]) + ->create(); + } +} diff --git a/catch/permissions/database/migrations/20200112031437_role_has_departments.php b/catch/permissions/database/migrations/20200112031437_role_has_departments.php new file mode 100644 index 0000000..a569c02 --- /dev/null +++ b/catch/permissions/database/migrations/20200112031437_role_has_departments.php @@ -0,0 +1,36 @@ +table('role_has_departments',['engine'=>'Innodb', 'comment' => '角色部门表', 'signed' => false]); + $table->addColumn('role_id', 'integer',['comment'=>'角色ID', 'signed' => false]) + ->addColumn('department_id', 'integer', ['comment'=>'部门ID', 'signed' => false]) + ->create(); + } +} diff --git a/catch/permissions/database/migrations/20200409023815_change_permissions.php b/catch/permissions/database/migrations/20200409023815_change_permissions.php new file mode 100644 index 0000000..f2d1c0a --- /dev/null +++ b/catch/permissions/database/migrations/20200409023815_change_permissions.php @@ -0,0 +1,41 @@ +hasTable('permissions')) { + $table = $this->table('permissions'); + + $table->addColumn('component', 'string', ['default' => '', 'comment' => '组件名称', 'limit' => '255', 'after' => 'permission_mark']) + ->addColumn('redirect', 'string', ['default' => '', 'comment' => '跳转地址', 'limit' => '255', 'after' => 'component']) + ->addColumn('hide_children_in_menu', 'integer', ['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY, 'default' => 1, 'comment' => '1 显示 2隐藏', 'after' => 'redirect']) + ->addColumn('keepalive', 'integer', ['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY, 'default' => 1, 'comment' => '1 缓存 2 不存在 ', 'after' => 'hide_children_in_menu']) + ->update(); + } + } +} diff --git a/catch/permissions/database/migrations/20200422080926_permissions_add_column.php b/catch/permissions/database/migrations/20200422080926_permissions_add_column.php new file mode 100644 index 0000000..4fe8cda --- /dev/null +++ b/catch/permissions/database/migrations/20200422080926_permissions_add_column.php @@ -0,0 +1,38 @@ +hasTable('permissions')) { + $table = $this->table('permissions'); + + $table->addColumn('level', 'string', ['default' => '', 'comment' => '层级', 'limit' => '50', 'after' => 'parent_id']) + ->update(); + } + } +} diff --git a/catch/permissions/database/seeds/DepartmentsSeed.php b/catch/permissions/database/seeds/DepartmentsSeed.php new file mode 100644 index 0000000..7ae2fb0 --- /dev/null +++ b/catch/permissions/database/seeds/DepartmentsSeed.php @@ -0,0 +1,39 @@ + 1, + 'department_name' => '总部', + 'parent_id' => 0, + ], + [ + 'id' => 2, + 'department_name' => '北京总部', + 'parent_id' => 1, + ], + [ + 'id' => 3, + 'department_name' => '南京总部', + 'parent_id' => 1, + ], + ]; + + foreach ($data as $item) { + \catchAdmin\permissions\model\Department::create($item); + } + } +} diff --git a/catch/permissions/database/seeds/PermissionSeed.php b/catch/permissions/database/seeds/PermissionSeed.php new file mode 100644 index 0000000..1d336e2 --- /dev/null +++ b/catch/permissions/database/seeds/PermissionSeed.php @@ -0,0 +1,1454 @@ +roles(); + $this->createPermissions(); + } + + protected function roles() + { + \catchAdmin\permissions\model\Roles::create([ + 'role_name' => '超级管理员', + 'description' => 'super user', + 'creator_id' => 1, + ]); + + \think\facade\Db::name( 'user_has_roles')->insert([ + 'role_id' => 1, + 'uid' => 1, + ]); + } + + + protected function createPermissions() + { + \catcher\Utils::importTreeData($this->getPermissions(), 'permissions', 'parent_id'); + } + + + + protected function getPermissions() + { + return array( + 0 => + array( + 'id' => 1, + 'permission_name' => 'Dashboard', + 'parent_id' => 0, + 'level' => '', + 'route' => '/dashboard', + 'icon' => 'home', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'index@dashboard', + 'component' => 'routeView', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 1000, + 'created_at' => 1587461227, + 'updated_at' => 1587622113, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 2, + 'permission_name' => '主页', + 'parent_id' => 1, + 'level' => '1', + 'route' => '/dashboard/workplace', + 'icon' => '', + 'module' => 'index', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'index@index', + 'component' => 'workplace', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 1, + 'created_at' => 1587461326, + 'updated_at' => 1587547886, + 'deleted_at' => 0, + ), + ), + ), + 1 => + array( + 'id' => 3, + 'permission_name' => '权限管理', + 'parent_id' => 0, + 'level' => '', + 'route' => '/permissions', + 'icon' => 'appstore', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'permission@index', + 'component' => 'pageView', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 100, + 'created_at' => 1587461455, + 'updated_at' => 1587622113, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 4, + 'permission_name' => '用户管理', + 'parent_id' => 3, + 'level' => '3', + 'route' => '/permissions/users', + 'icon' => 'user', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'user@index', + 'component' => 'users', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 10, + 'created_at' => 1587461597, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 5, + 'permission_name' => '列表', + 'parent_id' => 4, + 'level' => '3-4', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'user@index', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587461647, + 'updated_at' => 1587548455, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 6, + 'permission_name' => '创建', + 'parent_id' => 4, + 'level' => '3-4', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'user@create', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587461696, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 2 => + array( + 'id' => 7, + 'permission_name' => '保存', + 'parent_id' => 4, + 'level' => '3-4', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'user@save', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587461721, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 3 => + array( + 'id' => 8, + 'permission_name' => '查看', + 'parent_id' => 4, + 'level' => '3-4', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'user@edit', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587461742, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 4 => + array( + 'id' => 9, + 'permission_name' => '更新', + 'parent_id' => 4, + 'level' => '3-4', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'user@update', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587461762, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 5 => + array( + 'id' => 10, + 'permission_name' => '删除', + 'parent_id' => 4, + 'level' => '3-4', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'user@delete', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587461841, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 6 => + array( + 'id' => 11, + 'permission_name' => '禁用', + 'parent_id' => 4, + 'level' => '3-4', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'user@switchStatus', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587461876, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 7 => + array( + 'id' => 12, + 'permission_name' => '恢复', + 'parent_id' => 4, + 'level' => '3-4', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'user@recover', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587461901, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + ), + ), + 1 => + array( + 'id' => 13, + 'permission_name' => '角色管理', + 'parent_id' => 3, + 'level' => '3', + 'route' => '/permissions/roles', + 'icon' => 'usergroup-add', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'role@index', + 'component' => 'roles', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 9, + 'created_at' => 1587461939, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 14, + 'permission_name' => '列表', + 'parent_id' => 13, + 'level' => '3-13', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'role@list', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587461984, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 15, + 'permission_name' => '创建', + 'parent_id' => 13, + 'level' => '3-13', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'role@create', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462007, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 2 => + array( + 'id' => 16, + 'permission_name' => '保存', + 'parent_id' => 13, + 'level' => '3-13', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'role@save', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462021, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 3 => + array( + 'id' => 17, + 'permission_name' => '查看', + 'parent_id' => 13, + 'level' => '3-13', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'role@edit', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462040, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 4 => + array( + 'id' => 18, + 'permission_name' => '更新', + 'parent_id' => 13, + 'level' => '3-13', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'role@update', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462058, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 5 => + array( + 'id' => 19, + 'permission_name' => '删除', + 'parent_id' => 13, + 'level' => '3-13', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'role@delete', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462070, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 6 => + array( + 'id' => 20, + 'permission_name' => '权限获取', + 'parent_id' => 13, + 'level' => '3-13', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'role@getPermissions', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462094, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + ), + ), + 2 => + array( + 'id' => 21, + 'permission_name' => '菜单管理', + 'parent_id' => 3, + 'level' => '3', + 'route' => '/permissions/rules', + 'icon' => 'build', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'permission@index', + 'component' => 'rules', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 8, + 'created_at' => 1587462147, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 22, + 'permission_name' => '列表', + 'parent_id' => 21, + 'level' => '3-21', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'permission@index', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462205, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 23, + 'permission_name' => '创建', + 'parent_id' => 21, + 'level' => '3-21', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'permission@create', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462232, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 2 => + array( + 'id' => 24, + 'permission_name' => '保存', + 'parent_id' => 21, + 'level' => '3-21', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'permission@save', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462250, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 3 => + array( + 'id' => 25, + 'permission_name' => '查看', + 'parent_id' => 21, + 'level' => '3-21', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'permission@edit', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462273, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 4 => + array( + 'id' => 26, + 'permission_name' => '更新', + 'parent_id' => 21, + 'level' => '3-21', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'permission@update', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462284, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 5 => + array( + 'id' => 27, + 'permission_name' => '删除', + 'parent_id' => 21, + 'level' => '3-21', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'permission@delete', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462296, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + ), + ), + 3 => + array( + 'id' => 29, + 'permission_name' => '部门管理', + 'parent_id' => 3, + 'level' => '3', + 'route' => '/permissions/departments', + 'icon' => 'desktop', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'departments', + 'component' => 'departments', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 7, + 'created_at' => 1587462488, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 30, + 'permission_name' => '列表', + 'parent_id' => 29, + 'level' => '3-29', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'department@index', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462529, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 31, + 'permission_name' => '保存', + 'parent_id' => 29, + 'level' => '3-29', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'department@save', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462548, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 2 => + array( + 'id' => 32, + 'permission_name' => '更新', + 'parent_id' => 29, + 'level' => '3-29', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'department@update', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462579, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 3 => + array( + 'id' => 33, + 'permission_name' => '删除', + 'parent_id' => 29, + 'level' => '3-29', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'department@delete', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462592, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + ), + ), + 4 => + array( + 'id' => 34, + 'permission_name' => '岗位管理', + 'parent_id' => 3, + 'level' => '3', + 'route' => '/permissions/jobs', + 'icon' => 'skin', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'jobs', + 'component' => 'jobs', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 1, + 'created_at' => 1587462707, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 35, + 'permission_name' => '列表', + 'parent_id' => 34, + 'level' => '3-34', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'job@index', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462757, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 36, + 'permission_name' => '保存', + 'parent_id' => 34, + 'level' => '3-34', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'job@save', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462774, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 2 => + array( + 'id' => 37, + 'permission_name' => '更新', + 'parent_id' => 34, + 'level' => '3-34', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'job@update', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462785, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 3 => + array( + 'id' => 38, + 'permission_name' => '删除', + 'parent_id' => 34, + 'level' => '3-34', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'job@delete', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462794, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 4 => + array( + 'id' => 39, + 'permission_name' => '获取全部', + 'parent_id' => 34, + 'level' => '3-34', + 'route' => '', + 'icon' => '', + 'module' => 'permissions', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'job@getAll', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587462818, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + ), + ), + ), + ), + 2 => + array( + 'id' => 28, + 'permission_name' => '系统管理', + 'parent_id' => 0, + 'level' => '', + 'route' => '/system', + 'icon' => 'bar-chart', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'system', + 'component' => 'pageView', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 2, + 'type' => 1, + 'sort' => 1, + 'created_at' => 1587462349, + 'updated_at' => 1587622113, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 40, + 'permission_name' => '数据字典', + 'parent_id' => 28, + 'level' => '28', + 'route' => '/system/database', + 'icon' => 'hdd', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'datadictory', + 'component' => 'database', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 8, + 'created_at' => 1587463087, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 41, + 'permission_name' => '查看', + 'parent_id' => 40, + 'level' => '28-40', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'datadictionary@view', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587463113, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 42, + 'permission_name' => '列表', + 'parent_id' => 40, + 'level' => '28-40', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'datadictionary@tables', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 10, + 'created_at' => 1587463173, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 2 => + array( + 'id' => 43, + 'permission_name' => '优化', + 'parent_id' => 40, + 'level' => '28-40', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'datadictionary@optimize', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587463201, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 3 => + array( + 'id' => 44, + 'permission_name' => '备份', + 'parent_id' => 40, + 'level' => '28-40', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'optimize@backup', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587463217, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + ), + ), + 1 => + array( + 'id' => 45, + 'permission_name' => '附件管理', + 'parent_id' => 28, + 'level' => '28', + 'route' => '/attactments', + 'icon' => 'folder-open', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'attactments', + 'component' => 'attachment', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 10, + 'created_at' => 1587463302, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 46, + 'permission_name' => '列表', + 'parent_id' => 45, + 'level' => '28-45', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'attachments@index', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587463335, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 47, + 'permission_name' => '删除', + 'parent_id' => 45, + 'level' => '28-45', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'attachments@delete', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587463355, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 2 => + array( + 'id' => 48, + 'permission_name' => '上传图片', + 'parent_id' => 45, + 'level' => '28-45', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'upload@image', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587466919, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 3 => + array( + 'id' => 49, + 'permission_name' => '上传文件', + 'parent_id' => 45, + 'level' => '28-45', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'upload@file', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587466939, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + ), + ), + 2 => + array( + 'id' => 50, + 'permission_name' => '配置管理', + 'parent_id' => 28, + 'level' => '28', + 'route' => '/system/config', + 'icon' => 'setting', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'config', + 'component' => 'config', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 9, + 'created_at' => 1587466991, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 51, + 'permission_name' => '获取父级配置', + 'parent_id' => 50, + 'level' => '28-50', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'config@parent', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587467036, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 52, + 'permission_name' => '存储', + 'parent_id' => 50, + 'level' => '28-50', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'config@save', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587467052, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 2 => + array( + 'id' => 53, + 'permission_name' => '获取', + 'parent_id' => 50, + 'level' => '28-50', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'config@read', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587467062, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + ), + ), + 3 => + array( + 'id' => 54, + 'permission_name' => '登陆日志', + 'parent_id' => 28, + 'level' => '28', + 'route' => '/system/log/operate', + 'icon' => 'export', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'loginLog', + 'component' => 'loginLog', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 5, + 'created_at' => 1587467150, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 56, + 'permission_name' => '列表', + 'parent_id' => 54, + 'level' => '28-54', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'loginlog@list', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587467206, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 57, + 'permission_name' => '清空', + 'parent_id' => 54, + 'level' => '28-54', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'loginlog@empty', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587467221, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + ), + ), + 4 => + array( + 'id' => 55, + 'permission_name' => '操作日志', + 'parent_id' => 28, + 'level' => '28', + 'route' => '/system/log/login', + 'icon' => 'profile', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'operateLog', + 'component' => 'operateLog', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 1, + 'created_at' => 1587467180, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 58, + 'permission_name' => '列表', + 'parent_id' => 55, + 'level' => '28-55', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'operatelog@list', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587467246, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 59, + 'permission_name' => '清空', + 'parent_id' => 55, + 'level' => '28-55', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'operatelog@empty', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1587467266, + 'updated_at' => 1587547118, + 'deleted_at' => 0, + ), + ), + ), + 5 => + array( + 'id' => 80, + 'permission_name' => '代码生成', + 'parent_id' => 28, + 'level' => '28', + 'route' => '/generate', + 'icon' => 'scissor', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'generate', + 'component' => 'generate', + 'redirect' => '', + 'hide_children_in_menu' => 2, + 'keepalive' => 1, + 'type' => 1, + 'sort' => 1, + 'created_at' => 1587717452, + 'updated_at' => 1587717452, + 'deleted_at' => 0, + 'children' => + array( + 0 => + array( + 'id' => 81, + 'permission_name' => '生成', + 'parent_id' => 80, + 'level' => '28-80', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'generate@save', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1588110923, + 'updated_at' => 1588110923, + 'deleted_at' => 0, + ), + 1 => + array( + 'id' => 82, + 'permission_name' => '预览', + 'parent_id' => 80, + 'level' => '28-80', + 'route' => '', + 'icon' => '', + 'module' => 'system', + 'creator_id' => 1, + 'method' => 'get', + 'permission_mark' => 'generate@preview', + 'component' => '', + 'redirect' => '', + 'hide_children_in_menu' => 1, + 'keepalive' => 1, + 'type' => 2, + 'sort' => 1, + 'created_at' => 1588110962, + 'updated_at' => 1588110962, + 'deleted_at' => 0, + ), + ), + ), + ), + ), + ); + } +} diff --git a/catch/permissions/database/seeds/UsersSeed.php b/catch/permissions/database/seeds/UsersSeed.php new file mode 100644 index 0000000..bd10764 --- /dev/null +++ b/catch/permissions/database/seeds/UsersSeed.php @@ -0,0 +1,24 @@ + 'admin', + 'password' => 'admin', + 'email' => 'admin@gmail.com', + 'creator_id' => 1, + ]); + } +} diff --git a/catch/permissions/model/Department.php b/catch/permissions/model/Department.php new file mode 100644 index 0000000..dfa6afe --- /dev/null +++ b/catch/permissions/model/Department.php @@ -0,0 +1,43 @@ +withoutField(['department_name']) + ->addFields(['department_name as title']) + ->catchSearch() + ->select()->toArray(); + } +} diff --git a/catch/permissions/model/HasDepartmentsTrait.php b/catch/permissions/model/HasDepartmentsTrait.php new file mode 100644 index 0000000..55ea036 --- /dev/null +++ b/catch/permissions/model/HasDepartmentsTrait.php @@ -0,0 +1,57 @@ +belongsToMany(Department::class, 'role_has_departments', 'department_id', 'role_id'); + } + + /** + * + * @time 2019年12月08日 + * @return mixed + */ + public function getDepartments() + { + return $this->departments()->select(); + } + + /** + * + * @time 2019年12月08日 + * @param array $departments + * @return mixed + */ + public function attachDepartments(array $departments) + { + if (empty($departments)) { + return true; + } + + sort($departments); + + return $this->departments()->attach($departments); + } + + /** + * + * @time 2019年12月08日 + * @param array $departments + * @return mixed + */ + public function detachDepartments(array $departments = []) + { + if (empty($departments)) { + return $this->departments()->detach(); + } + + return $this->departments()->detach($departments); + } +} diff --git a/catch/permissions/model/HasJobsTrait.php b/catch/permissions/model/HasJobsTrait.php new file mode 100644 index 0000000..7a1ac78 --- /dev/null +++ b/catch/permissions/model/HasJobsTrait.php @@ -0,0 +1,58 @@ +belongsToMany(Job::class, 'user_has_jobs', 'job_id', 'uid'); + } + + /** + * + * @time 2019年12月08日 + * @param array $fields + * @return mixed + */ + public function getJobs() + { + return $this->jobs()->select(); + } + + /** + * + * @time 2019年12月08日 + * @param array $jobs + * @return mixed + */ + public function attachJobs(array $jobs) + { + if (empty($jobs)) { + return true; + } + + sort($jobs); + + return $this->jobs()->attach($jobs); + } + + /** + * + * @time 2019年12月08日 + * @param array $jobs + * @return mixed + */ + public function detachJobs(array $jobs = []) + { + if (empty($jobs)) { + return $this->jobs()->detach(); + } + + return $this->jobs()->detach($jobs); + } +} diff --git a/catch/permissions/model/HasPermissionsTrait.php b/catch/permissions/model/HasPermissionsTrait.php new file mode 100644 index 0000000..64b95ce --- /dev/null +++ b/catch/permissions/model/HasPermissionsTrait.php @@ -0,0 +1,76 @@ + + * @copyright By CatchAdmin + * @license https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt + */ +namespace catchAdmin\permissions\model; + +trait HasPermissionsTrait +{ + /** + * + * @time 2019年12月09日 + * @return \think\model\relation\BelongsToMany + */ + public function permissions(): \think\model\relation\BelongsToMany + { + return $this->belongsToMany(Permissions::class, 'role_has_permissions', 'permission_id', 'role_id'); + } + + /** + * + * @time 2019年12月08日 + * @param array $condition + * @param array $field + * @return mixed + */ + public function getPermissions($condition = [], $field = []) + { + return $this->permissions() + ->when(!empty($field), function ($query) use ($field){ + $query->field($field); + }) + ->when(!empty($condition), function ($query) use ($condition){ + $query->where($condition); + }) + ->select(); + } + + /** + * + * @time 2019年12月08日 + * @param array $permissions + * @return mixed + * @throws \think\db\exception\DbException + */ + public function attach(array $permissions) + { + if (empty($permissions)) { + return true; + } + + sort($permissions); + + return $this->permissions()->attach($permissions); + } + + /** + * + * @time 2019年12月08日 + * @param array $roles + * @return mixed + */ + public function detach(array $roles = []) + { + if (empty($roles)) { + return $this->permissions()->detach(); + } + + return $this->permissions()->detach($roles); + } +} diff --git a/catch/permissions/model/HasRolesTrait.php b/catch/permissions/model/HasRolesTrait.php new file mode 100644 index 0000000..8b4cd04 --- /dev/null +++ b/catch/permissions/model/HasRolesTrait.php @@ -0,0 +1,58 @@ +belongsToMany(Roles::class, 'user_has_roles', 'role_id', 'uid'); + } + + /** + * + * @time 2019年12月08日 + * @param array $fields + * @return mixed + */ + public function getRoles() + { + return $this->roles()->select(); + } + + /** + * + * @time 2019年12月08日 + * @param array $roles + * @return mixed + */ + public function attach(array $roles) + { + if (empty($roles)) { + return true; + } + + sort($roles); + + return $this->roles()->attach($roles); + } + + /** + * + * @time 2019年12月08日 + * @param array $roles + * @return mixed + */ + public function detach(array $roles = []) + { + if (empty($roles)) { + return $this->roles()->detach(); + } + + return $this->roles()->detach($roles); + } +} diff --git a/catch/permissions/model/Job.php b/catch/permissions/model/Job.php new file mode 100644 index 0000000..d0ab1d6 --- /dev/null +++ b/catch/permissions/model/Job.php @@ -0,0 +1,36 @@ +catchSearch() + ->paginate(); + } +} diff --git a/catch/permissions/model/Permissions.php b/catch/permissions/model/Permissions.php new file mode 100644 index 0000000..0a0bba2 --- /dev/null +++ b/catch/permissions/model/Permissions.php @@ -0,0 +1,103 @@ +catchSearch() + ->order('sort', 'desc') + ->order('id', 'desc') + ->when($isMenu, function ($query){ + $query->where('type', self::MENU_TYPE); + }) + ->select(); + } + + public function roles(): \think\model\relation\BelongsToMany + { + return $this->belongsToMany(Roles::class, 'role_has_permissions', 'role_id', 'permission_id'); + } + + /** + * 获取当前用户权限 + * + * @time 2020年01月14日 + * @param array $permissionIds + * @return \think\Collection + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\db\exception\DataNotFoundException + */ + public static function getCurrentUserPermissions(array $permissionIds): \think\Collection + { + return parent::whereIn('id', $permissionIds) + ->field(['permission_name as title', 'id', 'parent_id', + 'route', 'icon', 'component', 'redirect', + 'keepalive as keepAlive', 'hide_children_in_menu', 'type' + ]) + ->select(); + } + + /** + * 插入后回调 更新 level + * + * @time 2020年04月22日 + * @param Model $model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return array|bool|Model|void|null + */ + public static function onAfterInsert(Model $model) + { + $model = self::where('id', $model->id)->find(); + + if ($model && $model->parent_id) { + $parent = self::where('id', $model->parent_id)->find(); + $level = $parent->level ? $parent->level . '-' . $parent->id : $parent->id; + return $model->where('id', $model->id)->update([ + 'level' => $level + ]); + } + + return true; + } +} diff --git a/catch/permissions/model/Roles.php b/catch/permissions/model/Roles.php new file mode 100644 index 0000000..e8b321b --- /dev/null +++ b/catch/permissions/model/Roles.php @@ -0,0 +1,90 @@ +0 已删除 + + ]; + + public function getList() + { + return $this->catchSearch() + ->order('id', 'desc') + ->select() + ->toArray(); + } + + /** + * + * @time 2019年12月08日 + * @return \think\model\relation\BelongsToMany + */ + public function users(): \think\model\relation\BelongsToMany + { + return $this->belongsToMany(Users::class, 'user_has_roles', 'uid', 'role_id'); + } + + + public static function getDepartmentUserIdsBy($roles) + { + $uids = []; + + $isAll = false; + + $user = request()->user(); + + foreach ($roles as $role) { + switch ($role->data_range) { + case self::ALL_DATA: + $isAll = true; + break; + case self::SELF_CHOOSE: + $departmentIds = array_merge(array_column($role->getDepartments()->toArray(), 'id')); + $uids = array_merge($uids, Users::getUserIdsByDepartmentIds($departmentIds)); + break; + case self::SELF_DATA: + $uids[] = $user->id; + break; + case self::DEPARTMENT_DOWN_DATA: + case self::DEPARTMENT_DATA: + $uids = array_merge($uids, Users::getUserIdsByDepartmentIds([$user->department_id])); + break; + default: + break; + } + + // 如果有全部数据 直接跳出 + if ($isAll) { + break; + } + } + + return $uids; + } +} diff --git a/catch/permissions/model/Users.php b/catch/permissions/model/Users.php new file mode 100644 index 0000000..b7e9d5b --- /dev/null +++ b/catch/permissions/model/Users.php @@ -0,0 +1,85 @@ +0 已删除 + + ]; + + /** + * set password + * + * @time 2019年12月07日 + * @param $value + * @return false|string + */ + public function setPasswordAttr($value) + { + return password_hash($value, PASSWORD_DEFAULT); + } + + /** + * 用户列表 + * + * @time 2019年12月08日 + * @throws \think\db\exception\DbException + * @return \think\Paginator + */ + public function getList(): \think\Paginator + { + return $this->withoutField(['updated_at'], true) + ->catchSearch() + ->catchLeftJoin(Department::class, 'id', 'department_id', ['department_name']) + ->order($this->getTable() . '.id', 'desc') + ->paginate(); + } + + /** + * 获取权限 + * + * @time 2019年12月12日 + * @param $uid + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return array + */ + public function getPermissionsBy($uid = 0): array + { + // 获取超级管理配置 超级管理员全部权限 + if ($uid == config('catch.permissions.super_admin_id')) { + return Permissions::select()->column('id'); + } + + $roles = $uid ? $this->findBy($uid)->getRoles() : $this->getRoles(); + + $permissionIds = []; + foreach ($roles as $role) { + $permissionIds = array_merge($permissionIds, $role->getPermissions()->column('id')); + } + + return array_unique($permissionIds); + } +} diff --git a/catch/permissions/model/search/DepartmentSearch.php b/catch/permissions/model/search/DepartmentSearch.php new file mode 100644 index 0000000..95df0ad --- /dev/null +++ b/catch/permissions/model/search/DepartmentSearch.php @@ -0,0 +1,15 @@ +whereLike('department_name', $value); + } + + public function searchStatusAttr($query, $value, $data) + { + return $query->where('status', $value); + } +} diff --git a/catch/permissions/model/search/JobsSearch.php b/catch/permissions/model/search/JobsSearch.php new file mode 100644 index 0000000..1d28aac --- /dev/null +++ b/catch/permissions/model/search/JobsSearch.php @@ -0,0 +1,20 @@ +whereLike('job_name', $value); + } + + public function searchCodingAttr($query, $value, $data) + { + return $query->whereLike('coding', $value); + } + + public function searchStatusAttr($query, $value, $data) + { + return $query->where('status', $value); + } +} diff --git a/catch/permissions/model/search/PermissionsSearch.php b/catch/permissions/model/search/PermissionsSearch.php new file mode 100644 index 0000000..735487e --- /dev/null +++ b/catch/permissions/model/search/PermissionsSearch.php @@ -0,0 +1,31 @@ +whereLike('permission_name', $value); + } + + public function searchIdAttr($query, $value, $data) + { + $query->where('parent_id', $value)->whereOr('id', $value); + } + + public function searchRoleIdAttr($query, $value, $data) + { + $permissionIds = []; + $permissions = Roles::where('id', $value)->find()->getPermissions(); + + foreach ($permissions as $_permission) { + $permissionIds[] = $_permission->pivot->permission_id; + } + + if(!empty($permissionIds)) { + $query->whereIn('id', $permissionIds); + } + } +} diff --git a/catch/permissions/model/search/RolesSearch.php b/catch/permissions/model/search/RolesSearch.php new file mode 100644 index 0000000..fa723b9 --- /dev/null +++ b/catch/permissions/model/search/RolesSearch.php @@ -0,0 +1,16 @@ +whereLike('role_name', $value); + } + + public function searchIdAttr($query, $value, $data) + { + $query->where('parent_id', $value)->whereOr('id', $value); + } + +} diff --git a/catch/permissions/model/search/UserSearch.php b/catch/permissions/model/search/UserSearch.php new file mode 100644 index 0000000..fc1cc05 --- /dev/null +++ b/catch/permissions/model/search/UserSearch.php @@ -0,0 +1,25 @@ +whereLike('username', $value); + } + + public function searchEmailAttr($query, $value, $data) + { + return $query->whereLike('email', $value); + } + + public function searchStatusAttr($query, $value, $data) + { + return $query->where($this->aliasField('status'), $value); + } + + public function searchDepartmentIdAttr($query, $value, $data) + { + return $query->where($this->aliasField('department_id'), $value); + } +} diff --git a/catch/permissions/module.json b/catch/permissions/module.json new file mode 100644 index 0000000..82a671c --- /dev/null +++ b/catch/permissions/module.json @@ -0,0 +1,11 @@ +{ + "name": "权限管理", + "alias": "permissions", + "description": "", + "keywords": [], + "order": 2, + "services": [], + "aliases": {}, + "files": [], + "requires": [] +} \ No newline at end of file diff --git a/catch/permissions/request/CreateRequest.php b/catch/permissions/request/CreateRequest.php new file mode 100644 index 0000000..ddc8bdb --- /dev/null +++ b/catch/permissions/request/CreateRequest.php @@ -0,0 +1,24 @@ + 'require|max:20', + 'password|密码' => 'require|min:5|max:12', + 'email|邮箱' => 'require|email|unique:'.Users::class, + ]; + } + + protected function message(): array + { + // TODO: Implement message() method. + } +} \ No newline at end of file diff --git a/catch/permissions/request/UpdateRequest.php b/catch/permissions/request/UpdateRequest.php new file mode 100644 index 0000000..5d69de4 --- /dev/null +++ b/catch/permissions/request/UpdateRequest.php @@ -0,0 +1,23 @@ + 'require|max:20', + 'password|密码' => 'sometimes|min:5|max:12', + 'email|邮箱' => 'require|email|unique:'.Users::class, + ]; + } + + protected function message(): array + { + // TODO: Implement message() method. + } +} diff --git a/catch/permissions/route.php b/catch/permissions/route.php new file mode 100644 index 0000000..33dd83f --- /dev/null +++ b/catch/permissions/route.php @@ -0,0 +1,21 @@ +resource('roles', '\catchAdmin\permissions\controller\Role'); +// 角色列表 +$router->get('/role/get/permissions', '\catchAdmin\permissions\controller\Role@getPermissions'); +// 权限 +$router->resource('permissions', '\catchAdmin\permissions\controller\Permission'); +// 部门 +$router->resource('departments', '\catchAdmin\permissions\controller\Department'); +// 岗位 +$router->resource('jobs', '\catchAdmin\permissions\controller\Job'); + +$router->get('jobs/all', '\catchAdmin\permissions\controller\Job@getAll'); + +// 用户 +$router->resource('users', '\catchAdmin\permissions\controller\User'); +// 切换状态 +$router->put('users/switch/status/', '\catchAdmin\permissions\controller\User@switchStatus'); +$router->put('users/recover/', '\catchAdmin\permissions\controller\User@recover'); +$router->get('users/get/roles', '\catchAdmin\permissions\controller\User@getRoles'); +$router->get('user/info', '\catchAdmin\permissions\controller\User@info'); \ No newline at end of file diff --git a/catch/system/controller/Attachments.php b/catch/system/controller/Attachments.php new file mode 100644 index 0000000..646d564 --- /dev/null +++ b/catch/system/controller/Attachments.php @@ -0,0 +1,31 @@ +getList()); + } + + public function delete($id, AttachmentsModel $model) + { + $ids = Utils::stringToArrayBy($id); + + foreach ($ids as $id) { + $attachment = $model->findBy($id); + if ($attachment && $model->deleteBy($id)) { + Filesystem::delete($attachment->path); + } + } + + return CatchResponse::success(); + } +} diff --git a/catch/system/controller/Config.php b/catch/system/controller/Config.php new file mode 100644 index 0000000..0a3c2b5 --- /dev/null +++ b/catch/system/controller/Config.php @@ -0,0 +1,65 @@ +configModel = $configModel; + } + + /** + * 获取父级别配置 + * + * @time 2020年04月17日 + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return Json + */ + public function parent() + { + return CatchResponse::success($this->configModel->getParentConfig()); + } + + /** + * 存储配置 + * + * @time 2020年04月17日 + * @param Request $request + * @return Json + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\db\exception\DataNotFoundException + */ + public function save(Request $request) + { + return CatchResponse::success([ + 'id' => $this->configModel->storeBy($request->param()), + 'parents' => $this->configModel->getParentConfig(), + ]); + } + + /** + * 获取配置 + * + * @time 2020年04月20日 + * @param $id + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return Json + */ + public function read($id) + { + return CatchResponse::success($this->configModel->getConfig($id)); + } +} \ No newline at end of file diff --git a/catch/system/controller/DataDictionary.php b/catch/system/controller/DataDictionary.php new file mode 100644 index 0000000..1246c35 --- /dev/null +++ b/catch/system/controller/DataDictionary.php @@ -0,0 +1,106 @@ +get('tablename'); + $engine = $request->get('engine'); + + $searchTables = []; + $searchMode = false; + if ($tablename || $engine) { + $searchMode = true; + } + + foreach ($tables as $key => &$table) { + $table = array_change_key_case($table); + $table['index_length'] = $table['index_length'] > 1024 ? intval($table['index_length']/1024) .'MB' : $table['index_length'].'KB'; + $table['data_length'] = $table['data_length'] > 1024 ? intval($table['data_length']/1024) .'MB' : $table['data_length'].'KB'; + $table['create_time'] = date('Y-m-d', strtotime($table['create_time'])); + // 搜索 + if ($tablename && !$engine && stripos($table['name'], $tablename) !== false) { + $searchTables[] = $table; + } + // 搜索 + if (!$tablename && $engine && stripos($table['engine'], $engine) !== false) { + $searchTables[] = $table; + } + + if ($tablename && $engine && stripos($table['engine'], $engine) !== false && stripos($table['name'], $tablename) !== false) { + $searchTables[] = $table; + } + } + + + return CatchResponse::paginate(Paginator::make(!$searchMode ? $tables : $searchTables, $request->get('limit') ?? 10, $request->get('page') ?? 1, $searchMode ? count($searchTables) : count($tables), false, [])); + } + + /** + * + * @time 2019年12月13日 + * @param $table + * @return \think\response\Json + * @throws \Exception + */ + public function view($table): \think\response\Json + { + $fields = Db::query('show full columns from ' . $table); + + array_walk($fields, function (&$item){ + $item = array_change_key_case($item); + }); + + return CatchResponse::success($fields); + } + + /** + * + * @time 2019年12月13日 + * @return \think\response\Json + */ + public function optimize(): \think\response\Json + { + $tables = \request()->post('data'); + + foreach ($tables as $table) { + Db::query(sprintf('optimize table %s', $table)); + } + + return CatchResponse::success([], '优化成功'); + } + + /** + * + * @time 2019年12月13日 + * @throws FailedException + * @return \think\response\Json + */ + public function backup(): \think\response\Json + { + try { + Console::call('backup:data', [trim(implode(',', \request()->post('data')), ','), '-z']); + }catch (\Exception $e) { + throw new FailedException($e->getMessage()); + } + + return CatchResponse::success([], '备份成功'); + } +} diff --git a/catch/system/controller/Generate.php b/catch/system/controller/Generate.php new file mode 100644 index 0000000..a3cdbd6 --- /dev/null +++ b/catch/system/controller/Generate.php @@ -0,0 +1,28 @@ +done($request->param())); + } + + /** + * 预览 + * + * @time 2020年04月29日 + * @param Request $request + * @param Generator $generator + * @return \think\response\Json + */ + public function preview(Request $request, Generator $generator) + { + return CatchResponse::success($generator->preview($request->param())); + } +} diff --git a/catch/system/controller/LoginLog.php b/catch/system/controller/LoginLog.php new file mode 100644 index 0000000..5b45351 --- /dev/null +++ b/catch/system/controller/LoginLog.php @@ -0,0 +1,35 @@ +paginate()); + } + + /** + * 清空 + * + * @time 2020年04月28日 + * @param Log $log + * @throws \Exception + * @return \think\response\Json + */ + public function empty(Log $log) + { + return CatchResponse::success($log->where('id', '>', 0)->delete(), '清空成功'); + } +} diff --git a/catch/system/controller/OperateLog.php b/catch/system/controller/OperateLog.php new file mode 100644 index 0000000..0e6baf8 --- /dev/null +++ b/catch/system/controller/OperateLog.php @@ -0,0 +1,34 @@ +getList()); + } + + /** + * + * @time 2020年04月28日 + * @param Log $log + * @throws \Exception + * @return \think\response\Json + */ + public function empty(Log $log) + { + return CatchResponse::success($log->where('id', '>', 0)->delete(), '清空成功'); + } +} diff --git a/catch/system/controller/Upload.php b/catch/system/controller/Upload.php new file mode 100644 index 0000000..d3d5f39 --- /dev/null +++ b/catch/system/controller/Upload.php @@ -0,0 +1,57 @@ + + * @copyright By CatchAdmin + * @license https://github.com/yanwenwu/catch-admin/blob/master/LICENSE.txt + */ +namespace catchAdmin\system\controller; + +use catchAdmin\system\model\Attachments; +use catcher\base\CatchController; +use catcher\base\CatchRequest; +use catcher\CatchResponse; +use catcher\CatchUpload; + +class Upload extends CatchController +{ + protected $attachment; + + public function __construct(Attachments $attachment) + { + $this->attachment = $attachment; + } + + /** + * image upload + * + * @time 2020年01月25日 + * @param CatchRequest $request + * @param CatchUpload $upload + * @return \think\response\Json + */ + public function image(CatchRequest $request, CatchUpload $upload): \think\response\Json + { + $images = $request->file(); + + return CatchResponse::success($upload->checkImages($images)->multiUpload($images['image'])); + } + + /** + * file upload + * + * @time 2020年01月25日 + * @param CatchRequest $request + * @param CatchUpload $upload + * @return \think\response\Json + */ + public function file(CatchRequest $request, CatchUpload $upload): \think\response\Json + { + $files = $request->file(); + + return CatchResponse::success($upload->checkFiles($files)->multiUpload($files['file'])); + } +} diff --git a/catch/system/database/migrations/20191212110921_login_log.php b/catch/system/database/migrations/20191212110921_login_log.php new file mode 100644 index 0000000..45965d0 --- /dev/null +++ b/catch/system/database/migrations/20191212110921_login_log.php @@ -0,0 +1,40 @@ +table('login_log',['engine'=>'Myisam', 'comment' => '登录日志', 'signed' => false]); + $table->addColumn('login_name', 'string',['limit' => 50,'default'=>'','comment'=>'用户名']) + ->addColumn('login_ip', 'string',['default'=>0, 'limit' => 20, 'comment'=>'登录地点ip', 'signed' => false]) + ->addColumn('browser', 'string',['default'=> '','comment'=>'浏览器']) + ->addColumn('os', 'string',['default'=> '','comment'=>'操作系统']) + ->addColumn('login_at', 'integer', array('default'=>0,'comment'=>'登录时间', 'signed' => false )) + ->addColumn('status', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 1,'comment'=>'1 成功 2 失败']) + ->create(); + } +} diff --git a/catch/system/database/migrations/20191212110930_operate_log.php b/catch/system/database/migrations/20191212110930_operate_log.php new file mode 100644 index 0000000..e445ec0 --- /dev/null +++ b/catch/system/database/migrations/20191212110930_operate_log.php @@ -0,0 +1,42 @@ +table('operate_log',['engine'=>'Myisam', 'comment' => '操作日志', 'signed' => false]); + $table->addColumn('module', 'string',['limit' => 50,'default'=>'','comment'=>'模块名称']) + ->addColumn('operate', 'string',['default'=> '', 'limit' => 20, 'comment'=>'操作模块']) + ->addColumn('route', 'string',['default'=> '','limit' => 100, 'comment'=>'路由']) + ->addColumn('params', 'string',['default'=> '','limit' => 1000, 'comment'=>'参数']) + ->addColumn('ip', 'string',['default'=>'', 'limit' => 20,'comment'=>'ip', 'signed' => false]) + ->addColumn('creator_id', 'integer',['default'=> 0,'comment'=>'创建人ID', 'signed' => false]) + ->addColumn('method', 'string',['default'=> '','comment'=>'请求方法']) + ->addColumn('created_at', 'integer', array('default'=>0,'comment'=>'登录时间', 'signed' => false )) + ->create(); + } +} diff --git a/catch/system/database/migrations/20200125133249_attachments.php b/catch/system/database/migrations/20200125133249_attachments.php new file mode 100644 index 0000000..c007140 --- /dev/null +++ b/catch/system/database/migrations/20200125133249_attachments.php @@ -0,0 +1,44 @@ +table('attachments',['engine'=>'Myisam', 'comment' => '附件管理', 'signed' => false]); + $table->addColumn('path', 'string',['limit' => 50,'default'=>'','comment'=>'附件存储路径']) + ->addColumn('url', 'string',['default'=> '', 'limit' => 100, 'comment'=>'资源地址']) + ->addColumn('mime_type', 'string',['default'=> '', 'limit' => 100, 'comment'=>'资源mimeType']) + ->addColumn('file_ext', 'string',['default'=> '','limit' => 100, 'comment'=>'资源后缀']) + ->addColumn('file_size', 'integer',['default'=> 0, 'comment'=>'资源大小']) + ->addColumn('filename', 'string',['default'=>'', 'limit' => 255, 'comment'=>'资源名称']) + ->addColumn('driver', 'string',['default'=> 0, 'limit' => 20, 'comment' => 'local,oss,qcloud,qiniu']) + ->addColumn('created_at', 'integer', array('default'=>0, 'comment'=>'创建时间', 'signed' => false )) + ->addColumn('updated_at', 'integer', array('default'=>0, 'comment'=>'更新时间', 'signed' => false )) + ->addColumn('deleted_at', 'integer', array('default'=>0, 'comment'=>'删除时间', 'signed' => false )) + ->create(); + } +} diff --git a/catch/system/database/migrations/20200417083602_config.php b/catch/system/database/migrations/20200417083602_config.php new file mode 100644 index 0000000..2d7e03e --- /dev/null +++ b/catch/system/database/migrations/20200417083602_config.php @@ -0,0 +1,44 @@ +table('config',['engine'=>'InnoDB', 'comment' => '配置管理', 'signed' => false]); + $table->addColumn('name', 'string',['limit' => 50,'default'=>'','comment'=>'配置名称']) + ->addColumn('pid', 'integer', array('default'=> 0,'comment'=>'父级配置', 'signed' => false )) + ->addColumn('component', 'string', ['default'=> '', 'limit' => 100, 'comment'=>'tab 引入的组件名称']) + ->addColumn('key', 'string',['default'=> '', 'limit' => 100, 'comment'=>'配置键名']) + ->addColumn('value', 'string',['default'=> '', 'limit' => 255, 'comment'=>'配置键值']) + ->addColumn('status', 'integer',['limit' => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY,'default'=> 1,'comment'=>'1 启用 2 禁用']) + ->addColumn('creator_id', 'integer', array('default'=> 0,'comment'=>'创建人', 'signed' => false )) + ->addColumn('created_at', 'integer', ['default'=> 0,'comment'=>'创建时间', 'signed' => false]) + ->addColumn('updated_at', 'integer', ['default'=> 0,'comment'=>'更新时间', 'signed' => false]) + ->addColumn('deleted_at', 'integer', ['default'=> 0,'comment'=>'删除时间', 'signed' => false]) + ->create(); + } +} diff --git a/catch/system/database/seeds/ConfigSeed.php b/catch/system/database/seeds/ConfigSeed.php new file mode 100644 index 0000000..8d4ebbf --- /dev/null +++ b/catch/system/database/seeds/ConfigSeed.php @@ -0,0 +1,36 @@ + '基础配置', + 'pid' => 0, + 'component' => 'basis', + 'key' => 'basis', + ], + [ + 'name' => '上传配置', + 'pid' => 0, + 'component' => 'upload', + 'key' => 'upload', + ], + ]; + + foreach ($data as $item) { + \catchAdmin\system\model\Config::create($item); + } + } +} diff --git a/catch/system/model/Attachments.php b/catch/system/model/Attachments.php new file mode 100644 index 0000000..9a340c0 --- /dev/null +++ b/catch/system/model/Attachments.php @@ -0,0 +1,45 @@ +order('id', 'desc') + ->catchSearch() + ->paginate(); + } + + public function searchFileExtAttr($query, $value, $data) + { + return $query->where('file_ext', $value); + } + + public function searchMimeTypesAttr($query, $value, $data) + { + return $query->where('mime_type', $value); + } + + public function searchDriver($query, $value, $data) + { + return $query->where('driver', $value); + } +} diff --git a/catch/system/model/Config.php b/catch/system/model/Config.php new file mode 100644 index 0000000..1f3d3d1 --- /dev/null +++ b/catch/system/model/Config.php @@ -0,0 +1,210 @@ +where('pid', 0) + ->field(['id', 'name', 'component'])->select(); + } + + /** + * 存储配置 + * + * @time 2020年04月20日 + * @param array $data + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return bool + */ + public function storeBy(array $data) + { + if (empty($data)) { + return true; + } + + // 子配置 + if ($data['pid'] ?? false) { + $config = \json_decode($data['config'], true); + $pid = $data['pid']; + unset($data['pid']); + /**[ + 'key' => [ + 'k' => 'v' + ], + + 'k' => 'v' + ]*/ + foreach ($config as $key => $value) { + if (empty($value)) { + continue; + } + // 如果二级配置存在 + $secondLevel = $this->isExistConfig($key, $pid); + if ($secondLevel) { + // value 是字符串 + if (!is_array($value)) { + if ($value != $secondLevel->value) { + $secondLevel->value = $value; + $secondLevel->save(); + } + } else { + // 数组 + $thirdLevel = []; + $this->subConfig($secondLevel->id, ['id', 'key', 'value']) + ->each(function ($item, $key) use (&$thirdLevel){ + $thirdLevel[$item['key']] = $item; + }); + + if (!empty($value)) { + $new = []; + foreach ($value as $k => $v) { + if (isset($thirdLevel[$k])) { + if ($v != $thirdLevel[$k]->value) { + $thirdLevel[$k]->value = $v; + $thirdLevel[$k]->save(); + } + } else { + $new[] = [ + 'pid' => $secondLevel->id, + 'key' => $k, + 'value' => $v, + ]; + } + } + + if (!empty($new)) { + parent::insertAllBy($new); + } + } + } + } else { + if (!is_array($value)) { + parent::createBy([ + 'pid' => $pid, + 'key' => $key, + 'value' => $value, + ]); + } else { + $id = parent::createBy([ + 'pid' => $pid, + 'key' => $key, + ]); + if (!empty($value)) { + $newConfig = []; + foreach ($value as $k => $v) { + $newConfig[] = [ + 'key' => $k, + 'value' => $v, + 'pid' => $id, + ]; + } + parent::insertAllBy($newConfig); + } + } + } + } + + return true; + } + + return parent::storeBy($data); + } + + /** + * 配置是否存在 + * + * @time 2020年04月19日 + * @param $key + * @param int $pid + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return array|Model|null + */ + public function isExistConfig($key, $pid = 0) + { + return $this->where('pid', $pid) + ->where('key', $key) + ->find(); + } + + /** + * 获取子配置 + * + * @time 2020年04月19日 + * @param int $pid + * @param array $field + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return \think\Collection + */ + public function subConfig($pid = 0, array $field = ['*']) + { + return $this->where('pid', $pid) + ->field($field) + ->select(); + } + + /** + * 获取配置 + * + * @time 2020年04月20日 + * @param int $pid + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @return array|mixed + */ + public function getConfig($pid = 0) + { + $data = []; + + $configs = $this->where('pid', $pid) + ->field('id,`key` as k,value,pid') + ->select(); + + foreach ($configs as $config) { + if ($config->value !== '') { + $data[$config->k] = $config->value; + } else { + $data[$config->k] = $this->getConfig($config->id); + } + } + + return $data; + } +} \ No newline at end of file diff --git a/catch/system/model/LoginLog.php b/catch/system/model/LoginLog.php new file mode 100644 index 0000000..13ebf37 --- /dev/null +++ b/catch/system/model/LoginLog.php @@ -0,0 +1,21 @@ +field([$this->aliasField('*')]) + ->catchJoin(Users::class, 'id', 'creator_id', ['username as creator']) + ->order($this->aliasField('id'), 'desc') + ->paginate(); + } +} \ No newline at end of file diff --git a/catch/system/module.json b/catch/system/module.json new file mode 100644 index 0000000..e5d44e9 --- /dev/null +++ b/catch/system/module.json @@ -0,0 +1,11 @@ +{ + "name": "系统管理", + "alias": "system", + "description": "", + "keywords": [], + "order": 2, + "services": [], + "aliases": {}, + "files": [], + "requires": [] +} \ No newline at end of file diff --git a/catch/system/route.php b/catch/system/route.php new file mode 100644 index 0000000..a6e3a7e --- /dev/null +++ b/catch/system/route.php @@ -0,0 +1,28 @@ +get('log/login', '\catchAdmin\system\controller\LoginLog@list'); +$router->delete('loginLog/empty', '\catchAdmin\system\controller\LoginLog@empty'); +// 操作日志 +$router->get('log/operate', '\catchAdmin\system\controller\OperateLog@list'); +$router->delete('operateLog/empty', '\catchAdmin\system\controller\OperateLog@empty'); + +// 数据字典 +$router->get('tables', '\catchAdmin\system\controller\DataDictionary@tables'); +$router->get('table/view/', '\catchAdmin\system\controller\DataDictionary@view'); +$router->post('table/optimize', '\catchAdmin\system\controller\DataDictionary@optimize'); +$router->post('table/backup', '\catchAdmin\system\controller\DataDictionary@backup'); + +// 上传 +$router->post('upload/image', '\catchAdmin\system\controller\Upload@image'); +$router->post('upload/file', '\catchAdmin\system\controller\Upload@file'); + +// 附件 +$router->resource('attachments', '\catchAdmin\system\controller\Attachments'); + +// 配置 +$router->get('config/parent', '\catchAdmin\system\controller\Config@parent'); +$router->resource('config', '\catchAdmin\system\controller\Config'); + +// 代码生成 +$router->post('generate', '\catchAdmin\system\controller\Generate@save'); +$router->post('generate/preview', '\catchAdmin\system\controller\Generate@preview'); // 预览