From f3e754c6103ff57479a74dae9e26fd3e1378ab33 Mon Sep 17 00:00:00 2001 From: amplam Date: Thu, 10 Mar 2022 16:38:50 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BB=84=E7=BB=87?= =?UTF-8?q?=E6=9E=B6=E6=9E=84=E9=83=A8=E9=97=A8=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/command/Install/fastadmin.sql | 39 ++ .../admin/controller/department/Admin.php | 435 ++++++++++++++++++ .../admin/controller/department/Index.php | 193 ++++++++ application/admin/model/department/Admin.php | 156 +++++++ .../admin/model/department/AuthAdmin.php | 29 ++ .../model/department/AuthGroupAccess.php | 17 + .../admin/model/department/Department.php | 158 +++++++ .../admin/view/department/admin/add.html | 54 +++ .../admin/view/department/admin/edit.html | 61 +++ .../admin/view/department/admin/index.html | 117 +++++ .../view/department/admin/principal.html | 30 ++ .../admin/view/department/index/add.html | 52 +++ .../admin/view/department/index/edit.html | 57 +++ .../admin/view/department/index/index.html | 27 ++ public/assets/js/backend/department/admin.js | 170 +++++++ public/assets/js/backend/department/index.js | 341 ++++++++++++++ 16 files changed, 1936 insertions(+) create mode 100644 application/admin/controller/department/Admin.php create mode 100644 application/admin/controller/department/Index.php create mode 100644 application/admin/model/department/Admin.php create mode 100644 application/admin/model/department/AuthAdmin.php create mode 100644 application/admin/model/department/AuthGroupAccess.php create mode 100644 application/admin/model/department/Department.php create mode 100644 application/admin/view/department/admin/add.html create mode 100644 application/admin/view/department/admin/edit.html create mode 100644 application/admin/view/department/admin/index.html create mode 100644 application/admin/view/department/admin/principal.html create mode 100644 application/admin/view/department/index/add.html create mode 100644 application/admin/view/department/index/edit.html create mode 100644 application/admin/view/department/index/index.html create mode 100644 public/assets/js/backend/department/admin.js create mode 100644 public/assets/js/backend/department/index.js diff --git a/application/admin/command/Install/fastadmin.sql b/application/admin/command/Install/fastadmin.sql index 1b816535f..cd8c465a2 100755 --- a/application/admin/command/Install/fastadmin.sql +++ b/application/admin/command/Install/fastadmin.sql @@ -267,6 +267,20 @@ INSERT INTO `fa_auth_rule` VALUES (81, 'file', 79, 'user/rule/del', 'Del', 'fa f INSERT INTO `fa_auth_rule` VALUES (82, 'file', 79, 'user/rule/add', 'Add', 'fa fa-circle-o', '', '', '', 0, NULL, '', '', '', 1491635035, 1491635035, 0, 'normal'); INSERT INTO `fa_auth_rule` VALUES (83, 'file', 79, 'user/rule/edit', 'Edit', 'fa fa-circle-o', '', '', '', 0, NULL, '', '', '', 1491635035, 1491635035, 0, 'normal'); INSERT INTO `fa_auth_rule` VALUES (84, 'file', 79, 'user/rule/multi', 'Multi', 'fa fa-circle-o', '', '', '', 0, NULL, '', '', '', 1491635035, 1491635035, 0, 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('85', 'file', '0', 'department', '组织架构', 'fa fa-list', '', '', '', '1', null, '', '1645779501', '1645781822', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('86', 'file', '85', 'department/admin', '部门成员', 'fa fa-circle-o', '', '', '', '1', null, '', '1645779501', '1645779501', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('87', 'file', '86', 'department/admin/index', '成员列表', 'fa fa-circle-o', '', '', '', '0', null, '', '1645779501', '1645867468', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('88', 'file', '86', 'department/admin/add', '添加', 'fa fa-circle-o', '', '', '', '0', null, '', '1645779501', '1645867469', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('89', 'file', '86', 'department/admin/edit', '修改', 'fa fa-circle-o', '', '', '', '0', null, '', '1645779501', '1645867469', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('90', 'file', '86', 'department/admin/del', '删除', 'fa fa-circle-o', '', '', '', '0', null, '', '1645779501', '1645867469', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('91', 'file', '86', 'department/admin/multi', '批量更新', 'fa fa-circle-o', '', '', '', '0', null, '', '1645779501', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('92', 'file', '85', 'department/index', '部门管理', 'fa fa-circle-o', '', '', '', '1', null, '', '1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('93', 'file', '92', 'department/index/index', '部门列表', 'fa fa-circle-o', '', '', '', '0', null, '', '1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('94', 'file', '92', 'department/index/add', '添加', 'fa fa-circle-o', '', '', '', '0', null, '', '1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('95', 'file', '92', 'department/index/edit', '修改', 'fa fa-circle-o', '', '', '', '0', null, '', '1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('96', 'file', '92', 'department/index/del', '删除', 'fa fa-circle-o', '', '', '', '0', null, '', '1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('97', 'file', '92', 'department/index/multi', '批量更新', 'fa fa-circle-o', '', '', '', '0', null, '', '1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES ('98', 'file', '86', 'department/admin/principal', '设置负责人', 'fa fa-circle-o', '', '', '', '0', null, '', '1646898376', '1646898376', '0', 'normal'); COMMIT; -- ---------------------------- @@ -602,3 +616,28 @@ CREATE TABLE `fa_version` ( ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='版本表'; SET FOREIGN_KEY_CHECKS = 1; + +CREATE TABLE `fa_department` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(30) DEFAULT NULL COMMENT '名称', + `parent_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父ID', + `weigh` int(11) DEFAULT '0' COMMENT '排序', + `create_time` varchar(20) DEFAULT NULL COMMENT '创建时间', + `update_time` int(10) DEFAULT NULL COMMENT '更新时间', + `status` enum('normal','hidden') NOT NULL DEFAULT 'normal' COMMENT '状态', + `organise_id` int(11) DEFAULT '0' COMMENT '组织id(最顶级)', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='组织部门表'; + + +CREATE TABLE `fa_department_admin` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `department_id` int(11) DEFAULT NULL COMMENT '部门id', + `organise_id` int(11) DEFAULT NULL COMMENT '组织id(最顶级)', + `admin_id` int(11) DEFAULT NULL COMMENT '成员id', + `create_time` int(11) NOT NULL COMMENT '加入时间', + `update_time` int(11) NOT NULL COMMENT '更新时间', + `is_principal` tinyint(1) DEFAULT NULL COMMENT '是否负责人', + `is_owner` tinyint(1) DEFAULT '0' COMMENT '拥有者', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='组织部门-成员表'; diff --git a/application/admin/controller/department/Admin.php b/application/admin/controller/department/Admin.php new file mode 100644 index 000000000..565fe7d54 --- /dev/null +++ b/application/admin/controller/department/Admin.php @@ -0,0 +1,435 @@ +childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin()); + + $this->dadminModel = new DepartmentAdminModel; + $departmentList = []; + $this->allDepartment = collection(DepartmentModel::allDepartment())->toArray(); + $departmentdata = []; + foreach ($this->allDepartment as $k => $v) { + $state = ['opened' => true]; + $departmentList[] = [ + 'id' => $v['id'], + 'parent' => $v['parent_id'] ? $v['parent_id'] : '#', + 'text' => __($v['name']), + 'state' => $state + ]; + } + $tree = Tree::instance()->init($this->allDepartment, 'parent_id'); + $departmentOptions = $tree->getTree(0, ""); + + $this->view->assign('departmentOptions', $departmentOptions); + $this->assignconfig('departmentList', $departmentList); + + $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0)); + foreach ($result as $k => $v) { + $departmentdata[$v['id']] = $v['name']; + } + $this->view->assign('departmentdata', $departmentdata); + } + + /** + * 成员列表 + */ + public function index() + { + + //测试 + //设置过滤方法 + $this->request->filter(['strip_tags']); + $department_id = $this->request->request("department_id"); + if ($this->request->isAjax()) { + $this->model = new \app\admin\model\department\AuthAdmin(); + $filter = $this->request->get("filter", ''); + $filter = (array)json_decode($filter, true); + $filter_w = []; + + if (isset($filter['department_id'])) { + $department_id = $filter['department_id']; + unset($filter['department_id']); + $this->request->get(['filter' => json_encode($filter)]); + } + if ($department_id) { + $admin_ids = $this->dadminModel->where('department_id', 'in', $department_id)->column('admin_id'); + $filter_w['id'] = ['in', $admin_ids]; + } + + + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); + $total = $this->model + ->where($where) + ->where($filter_w) + ->order($sort, $order)->fetchSql(false) + ->count(); + $list = $this->model + ->where($where) + ->with(['dadmin.department']) + ->with(['groups.getGroup']) + ->where($filter_w) + ->order($sort, $order) + ->limit($offset, $limit)->fetchSql(false) + ->select(); + + + $result = array("total" => $total, "rows" => $list); + + return json($result); + } + return $this->view->fetch(); + } + + /** + * 添加 + * @return string|\think\response\Json + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function add() + { + $groupdata = DepartmentModel::getGroupdata( + $this->childrenGroupIds, + $this->auth->isSuperAdmin() ? null : $this->auth->getGroups() + ); + + if ($this->request->isPost()) { + + $adminModel = new AdminModel(); + $departmentModel = new DepartmentModel(); + + $params = $this->request->post("row/a"); + if ($params) { + Db::startTrans(); + try { + $department_id = $this->request->post("department_id/a"); + + //获取部门信息 + if (!$department_id) { + exception(__("部门不能为空")); + } + $d_list = $departmentModel->where('id', 'in', $department_id)->select(); + + if (!$d_list) { + exception(__("部门不能为空")); + } + + if (!Validate::is($params['password'], '\S{6,16}')) { + exception(__("Please input correct password")); + } + $params['salt'] = Random::alnum(); + $params['password'] = md5(md5($params['password']) . $params['salt']); + $params['avatar'] = '/assets/img/avatar.png'; //设置新管理员默认头像。 + $result = $adminModel->validate('Admin.add')->save($params); + if ($result === false) { + exception($adminModel->getError()); + } + + $admin_id = $adminModel->id; + $dadmin = array(); + //添加部门信息 + foreach ($d_list as $d_row) { + $dadmin[] = ['department_id' => $d_row->id, 'organise_id' => $d_row->organise_id, 'admin_id' => $admin_id]; + } + $this->dadminModel->saveAll($dadmin); + + $group = $this->request->post("group/a"); + //过滤不允许的组别,避免越权 + $group = array_intersect($this->childrenGroupIds, $group); + + //添加权限默认第一个部门 + if (!$group) { + exception(__('The parent group exceeds permission limit')); + } + + $dataset = []; + foreach ($group as $value) { + $dataset[] = ['uid' => $admin_id, 'group_id' => $value]; + } + model('AuthGroupAccess')->saveAll($dataset); + + + Db::commit(); + } catch (\Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + $this->success(); + } + $this->error(__('Parameter %s can not be empty', '')); + } + $this->view->assign('groupdata', $groupdata); + return $this->view->fetch(); + } + + /** + * 修改 + * @param null $ids + * @return string|\think\response\Json + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function edit($ids = null) + { + + $this->model = new AdminModel(); + $departmentModel = new DepartmentModel(); + $row = $this->model->get($ids); + if ($this->request->isPost()) { + $params = $this->request->post("row/a"); + if ($params) { + Db::startTrans(); + try { + $department_id = $this->request->post("department_id/a"); + //获取部门信息 + if (!$department_id) { + exception(__("部门不能为空")); + } + $d_list = $departmentModel->where('id', 'in', $department_id)->select(); + + if (!$d_list) { + exception(__("部门不能为空")); + } + + if ($params['password']) { + if (!Validate::is($params['password'], '\S{6,16}')) { + exception(__("Please input correct password")); + } + $params['salt'] = Random::alnum(); + $params['password'] = md5(md5($params['password']) . $params['salt']); + } else { + unset($params['password'], $params['salt']); + } + //这里需要针对username和email做唯一验证 + $adminValidate = \think\Loader::validate('Admin'); + $adminValidate->rule([ + 'username' => 'require|regex:\w{3,12}|unique:admin,username,' . $row->id, + 'email' => 'require|email|unique:admin,email,' . $row->id, + 'password' => 'regex:\S{32}', + ]); + $result = $row->validate('Admin.edit')->save($params); + if ($result === false) { + exception($row->getError()); + } + $exist_departmentids=$this->dadminModel->where('admin_id', $row->id)->column('department_id'); + $dadmin = array(); + $deleteids=array(); + //添加部门信息 + foreach ($d_list as $d_row) { + if (!in_array($d_row->id,$exist_departmentids)){ + $dadmin[] = ['department_id' => $d_row->id, 'organise_id' => $d_row->organise_id, 'admin_id' => $row->id]; + }else{ + $deleteids[]=$d_row->id; + } + } + if ($deleteids){ + $this->dadminModel->where('admin_id', $row->id)->where('department_id','in',$deleteids)->delete(); + } + if (count($dadmin)>0){ + $this->dadminModel->saveAll($dadmin); + } + + + + // 先移除所有权限 + model('AuthGroupAccess')->where('uid', $row->id)->delete(); + + $group = $this->request->post("group/a"); + // 过滤不允许的组别,避免越权 + $group = array_intersect($this->childrenGroupIds, $group); + if (!$group) { + exception(__('The parent group exceeds permission limit')); + } + + $dataset = []; + foreach ($group as $value) { + $dataset[] = ['uid' => $row->id, 'group_id' => $value]; + } + model('AuthGroupAccess')->saveAll($dataset); + + Db::commit(); + } catch (\Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + $this->success(); + } + $this->error(__('Parameter %s can not be empty', '')); + } + $groupdata = DepartmentModel::getGroupdata( + $this->childrenGroupIds, + $this->auth->isSuperAdmin() ? null : $this->auth->getGroups() + ); + $grouplist = $this->auth->getGroups($row['id']); + $groupids = []; + foreach ($grouplist as $k => $v) { + $groupids[] = $v['id']; + } + $this->view->assign("groupids", $groupids); + + $this->view->assign('row', $row); + $this->view->assign('department_ids', $this->dadminModel->getDepartmentIds($ids)); + $this->view->assign('groupdata', $groupdata); + return $this->view->fetch(); + } + + + /** + * 删除 + */ + public function del($ids = "") + { + if (!$this->request->isPost()) { + $this->error(__("Invalid parameters")); + } + $this->childrenAdminIds = $this->auth->getChildrenAdminIds($this->auth->isSuperAdmin()); + $this->model = new AdminModel(); + + $ids = $ids ? $ids : $this->request->post("ids"); + if ($ids) { + $ids = array_intersect($this->childrenAdminIds, array_filter(explode(',', $ids))); + // 避免越权删除管理员 + $childrenGroupIds = $this->childrenGroupIds; + $adminList = $this->model->where('id', 'in', $ids)->where('id', 'in', function ($query) use ($childrenGroupIds) { + $query->name('auth_group_access')->where('group_id', 'in', $childrenGroupIds)->field('uid'); + })->select(); + if ($adminList) { + $deleteIds = []; + foreach ($adminList as $k => $v) { + $deleteIds[] = $v->id; + } + $deleteIds = array_values(array_diff($deleteIds, [$this->auth->id])); + if ($deleteIds) { + Db::startTrans(); + try { + $this->model->destroy($deleteIds); + model('AuthGroupAccess')->where('uid', 'in', $deleteIds)->delete(); + //删除部门员工信息 + $this->dadminModel->where('admin_id', 'in', $deleteIds)->delete();; + + Db::commit(); + } catch (\Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + $this->success(); + } + $this->error(__('No rows were deleted')); + } + } + $this->error(__('You have no permission')); + } + + /** + * 批量更新 + * @internal + */ + public function multi($ids = "") + { + // 管理员禁止批量操作 + $this->error(); + } + + /** + * 设置部门负责人 + */ + public function principal($ids = "") + { + + $this->model = new AdminModel(); + $departmentModel = new DepartmentModel(); + $row = $this->model->get($ids); + if ($this->request->isPost()) { + $department_id = $this->request->post("department_id/a"); + if ($department_id&&$department_id[0]) { + Db::startTrans(); + try { + $d_list = $departmentModel->where('id', 'in', $department_id)->select(); + + if (!$d_list) { + exception(__("部门不能为空")); + } + //先移除他所有负责的部门 + $this->dadminModel->where('admin_id', $row->id)->update(['is_principal'=>0]); + + //判断选择的部门是否存在,不存在就先把他加入 + $p_departmentids = array_column($d_list, 'id'); + $exist_departmentids=$this->dadminModel->where('admin_id', $row->id)->column('department_id'); + + $dadmin = array(); + //添加部门信息 + foreach ($d_list as $d_row) { + if (!in_array($d_row->id,$exist_departmentids)){ + $dadmin[] = ['department_id' => $d_row->id, 'organise_id' => $d_row->organise_id, 'admin_id' => $row->id]; + } + } + if (count($dadmin)>0){ + $this->dadminModel->saveAll($dadmin); + } + //更改为负责人 + $this->dadminModel->where('admin_id', $row->id)->where('department_id','in',$p_departmentids)->update(['is_principal'=>1]); + + + + Db::commit(); + } catch (\Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + + }else{ + //先移除他所有负责的部门 + $this->dadminModel->where('admin_id', $row->id)->update(['is_principal'=>0]); + } + $this->success(); + } + + + $this->view->assign('row', $row); + $this->view->assign('department_ids', $this->dadminModel::getPrincipalIds($ids)); + return $this->view->fetch(); + } + + +} diff --git a/application/admin/controller/department/Index.php b/application/admin/controller/department/Index.php new file mode 100644 index 000000000..9b679f867 --- /dev/null +++ b/application/admin/controller/department/Index.php @@ -0,0 +1,193 @@ +model = new DepartmentModel; + + $this->tree = Tree::instance(); + $this->tree->init(DepartmentModel::allDepartment(), 'parent_id'); + $this->departmentList = $this->tree->getTreeList($this->tree->getTreeArray(0), 'name'); + $this->view->assign("departmentList", $this->departmentList); + + $this->view->assign("statusList", DepartmentModel::getStatusList()); + } + + /** + * 部门列表 + */ + public function index() + { + //设置过滤方法 + $this->request->filter(['strip_tags', 'trim']); + if ($this->request->isAjax()) { + //如果发送的来源是Selectpage,则转发到Selectpage + if ($this->request->request('keyField')) { + //return $this->selectpage(); + } + + $search = $this->request->request("search"); + //构造父类select列表选项数据 + $list = []; + if ($search) { + foreach ($this->departmentList as $k => $v) { + if (stripos($v['name'], $search) !== false) { + $list[] = $v; + } + } + } else { + $list = $this->departmentList; + } + + $list = array_values($list); + + foreach ($list as $k => &$v) { + $v['pid'] = $v['parent_id']; + } + $total = count($list); + $result = array("total" => $total, "rows" => $list); + + return json($result); + + } + return $this->view->fetch(); + } + + /** + * 添加 + */ + public function add() + { + if ($this->request->isPost()) { + $params = $this->request->post("row/a"); + if ($params) { + if ($this->dataLimit && $this->dataLimitFieldAutoFill) { + $params[$this->dataLimitField] = $this->auth->id; + } + try { + //是否采用模型验证 + if ($this->modelValidate) { + $name = basename(str_replace('\\', '/', get_class($this->model))); + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate; + $this->model->validate($validate); + } + $nameArr = array_filter(explode("\n", str_replace("\r\n", "\n", $params['name']))); + + //获取组织最高的ID; + $params['organise_id'] = DepartmentModel::getOrganiseID(isset($params['parent_id']) ? $params['parent_id'] : 0); + + if (count($nameArr) > 1) { + foreach ($nameArr as $index => $item) { + $params['name'] = $item; + $result = $this->model->allowField(true)->isUpdate(false)->data($params)->save(); + } + } else { + $result = $this->model->allowField(true)->save($params); + } + if ($result !== false) { + //清空部门缓存 + DepartmentModel::clearCache(); + $this->success(); + } else { + $this->error($this->model->getError()); + } + } catch (\think\exception\PDOException $e) { + $this->error($e->getMessage()); + } + } + $this->error(__('Parameter %s can not be empty', '')); + } + return $this->view->fetch(); + } + + public function edit($ids = null) + { + $row = DepartmentModel::get($ids); + if (!$row) { + $this->error(__('No Results were found')); + } + if ($this->request->isPost()) { + $params = $this->request->post("row/a"); + if ($params) { + $params = $this->preExcludeFields($params); + $result = false; + Db::startTrans(); + try { + //是否采用模型验证 + if ($this->modelValidate) { + $name = str_replace("\\model\\", "\\validate\\", get_class($this->model)); + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate; + $row->validateFailException(true)->validate($validate); + } + //最顶级的不能修改成下级 + if ($row['parent_id']==0&&$params['parent_id']){ + \exception(__("顶级组织不能修改成下级")); + } + + //获取修改后的组织最高的ID; + //获取组织最高的ID; + $organise_id = isset($params['parent_id']) ? DepartmentModel::getOrganiseID($params['parent_id']) : 0; + //判断修改的父类是否和之前的一样并且organise_id不一样就要修改,含子类 + if ($params['parent_id'] != $row['parent_id'] && $organise_id != $row['organise_id']) { + $departmentIds = DepartmentModel::getChildrenIds($row->id, true); + $mapwhere['id'] = ['in', $departmentIds]; + $departmentIds = DepartmentModel::update(['organise_id' => $organise_id], $mapwhere); + } + $result = $row->allowField(true)->save($params); + Db::commit(); + } catch (ValidateException $e) { + Db::rollback(); + $this->error($e->getMessage()); + } catch (PDOException $e) { + Db::rollback(); + $this->error($e->getMessage()); + } catch (Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + if ($result !== false) { + //清空部门缓存 + DepartmentModel::clearCache(); + $this->success(); + } else { + $this->error(__('No rows were updated')); + } + } + $this->error(__('Parameter %s can not be empty', '')); + } else { + + $row = $row->toArray(); + $childrenIds = $this->tree->getChildrenIds($row['id'], true); + $this->view->assign('childrenIds', $childrenIds); + $this->view->assign("row", $row); + return $this->view->fetch(); + } + + + } + + + +} diff --git a/application/admin/model/department/Admin.php b/application/admin/model/department/Admin.php new file mode 100644 index 000000000..db2555483 --- /dev/null +++ b/application/admin/model/department/Admin.php @@ -0,0 +1,156 @@ +hasOne('app\admin\model\department\Department', 'id', 'department_id'); + } + + /** + * 获取管理者的部门ids + * @param $admin_id + * @param string $type + * @return array|bool|string + */ + public function getDepartmentIds($admin_id, $type = "self") + { + return $this->where('admin_id', $admin_id)->column('department_id'); + } + + /** + * 获取负责的部门IDs + * @param $admin_id + * @return array|bool|string + */ + public static function getPrincipalIds($admin_id){ + return self::where('admin_id', $admin_id)->where('is_principal',1)->column('department_id'); + } + /** + * 当前负责人下属ids + * @param int $admin_id 某个管理员ID + * @param boolean $withself 是否包含自身 + * @param string $department_ids 是否指定某个管理部门id,多个逗号id隔开 + * @return array + */ + public static function getChildrenAdminIds($admin_id, $withself = false, $department_ids = null) + { + $childrenAdminIds=[]; + if (self::isSuperAdmin($admin_id)) { + $childrenAdminIds = \app\admin\model\department\AuthAdmin::column('id'); + }else{ + $departmentIds = self::getChildrenDepartmentIds($admin_id); + $authDepartmentList = self::field('admin_id,department_id') + ->where('department_id', 'in', $departmentIds) + ->select(); + foreach ($authDepartmentList as $k => $v) { + $childrenAdminIds[] = $v['admin_id']; + } + } + if ($withself) { + if (!in_array($admin_id, $childrenAdminIds)) { + $childrenAdminIds[] = $admin_id; + } + } else { + $childrenAdminIds = array_diff($childrenAdminIds, [$admin_id]); + } + return $childrenAdminIds; + + + } + + /** + * 判断是否是超级管理员 + * @return bool + */ + public static function isSuperAdmin($admin_id) + { + $auth = new \app\admin\library\Auth(); + return in_array('*', $auth->getRuleIds($admin_id)) ? true : false; + } + + /** + * 取出当前负责人管理的下级部门 + * @param boolean $withself 是否包含当前所在的分组 + * @return array + */ + public static function getChildrenDepartmentIds($admin_id,$withself = false) + { + //取出当前负责人所有部门 + $departments =self::getDepartments($admin_id); + $departmenIds = []; + foreach ($departments as $k => $v) { + $departmenIds[] = $v['id']; + } + $originDepartmenId = $departmenIds; + foreach ($departments as $k => $v) { + if (in_array($v['parent_id'], $originDepartmenId)) { + $departmenIds = array_diff($departmenIds, [$v['id']]); + unset($departments[$k]); + } + } + // 取出所有部门 + $departmentList = \app\admin\model\department\Department::allDepartment(); + $objList = []; + foreach ($departments as $k => $v) { + // 取出包含自己的所有子节点 + $childrenList = Tree::instance()->init($departmentList, 'parent_id')->getChildren($v['id'], true); + $obj = Tree::instance()->init($childrenList, 'parent_id')->getTreeArray($v['parent_id']); + $objList = array_merge($objList, Tree::instance()->getTreeList($obj)); + } + $childrenDepartmenIds = []; + foreach ($objList as $k => $v) { + $childrenDepartmenIds[] = $v['id']; + } + if (!$withself) { + $childrenDepartmenIds = array_diff($childrenDepartmenIds, $departmenIds); + } + return $childrenDepartmenIds; + } + + + + /** + * 根据用户id获取部门组,返回值为数组 + * @param int $admin_id admin_id + * @return array 用户所属的部门 array( + * array('admin_id'=>'员工id','department_id'=>'部门id','name'=>'部门名称'), + * ...) + */ + public static function getDepartments($admin_id) + { + static $departments = []; + if (isset($departments[$admin_id])) { + return $departments[$admin_id]; + } + + // 执行查询 + $user_departments = Db::name('department_admin') + ->alias('da') + ->join('__'.strtoupper('department').'__ d', 'da.department_id = d.id', 'LEFT') + ->field('da.admin_id,da.department_id,d.id,d.parent_id,d.name') + ->where("da.admin_id='{$admin_id}' and is_principal=1 and d.status='normal'") + ->select(); + $departments[$admin_id] = $user_departments ?: []; + return $departments[$admin_id]; + } + +} \ No newline at end of file diff --git a/application/admin/model/department/AuthAdmin.php b/application/admin/model/department/AuthAdmin.php new file mode 100644 index 000000000..7f438dacd --- /dev/null +++ b/application/admin/model/department/AuthAdmin.php @@ -0,0 +1,29 @@ +hasMany('\app\admin\model\department\Admin', 'admin_id', 'id'); + } + + /** + * 关联角色组 + * @return \think\model\relation\HasMany + */ + public function groups() + { + return $this->hasMany('\app\admin\model\department\AuthGroupAccess', 'uid', 'id'); + } + +} \ No newline at end of file diff --git a/application/admin/model/department/AuthGroupAccess.php b/application/admin/model/department/AuthGroupAccess.php new file mode 100644 index 000000000..a5d16f6f5 --- /dev/null +++ b/application/admin/model/department/AuthGroupAccess.php @@ -0,0 +1,17 @@ +belongsTo('\app\admin\model\AuthGroup', 'group_id', 'id'); + } +} diff --git a/application/admin/model/department/Department.php b/application/admin/model/department/Department.php new file mode 100644 index 000000000..02dfba5e9 --- /dev/null +++ b/application/admin/model/department/Department.php @@ -0,0 +1,158 @@ +getPk(); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + self::clearCache(); + }); + self::afterDelete(function ($row) { + //删除时,删除子节点,同时将所有相关部门成员删除 + $childIds = self::getChildrenIds($row['id']); + if ($childIds) { + Department::destroy(function ($query) use ($childIds) { + $query->where('id', 'in', $childIds); + }); + } + $childIds[] = $row['id']; + db('department_admin')->where('department_id', 'in', $childIds)->delete(); + self::clearCache(); + }); + self::afterWrite(function ($row) use ($config) { + $changed = $row->getChangedData(); + //隐藏时判断是否有子节点,有则隐藏 + if (isset($changed['status']) && $changed['status'] == 'hidden') { + $childIds = self::getChildrenIds($row['id']); + db('department')->where('id', 'in', $childIds)->update(['status' => 'hidden']); + } + self::clearCache(); + + }); + } + + public static function getStatusList() + { + return ['normal' => __('Normal'), 'hidden' => __('Hidden')]; + } + + + /** + * 获取栏目的所有子节点ID + * @param int $id 栏目ID + * @param bool $withself 是否包含自身 + * @return array + */ + public static function getChildrenIds($id, $withself = false) + { + static $tree; + if (!$tree) { + $tree = \fast\Tree::instance(); + $tree->init(collection(self::order('weigh desc,id desc')->field('id,parent_id,name,status')->cache(self::$cachekey)->select())->toArray(), 'parent_id'); + } + $childIds = $tree->getChildrenIds($id, $withself); + return $childIds; + } + + /** + * 所有部门 + */ + public static function allDepartment() + { + return self::order('weigh desc,id desc')->where(['status' => 'normal'])->cache(self::$cachekey)->select(); + } + + /** + * 清空缓存 + * @param $name + */ + public static function clearCache() + { + Cache::rm(self::$cachekey); + } + + + /** + * 获取权限组 + * @param array $childrenGroupIds + * @param null $groups 如果不是超级管理员传auth->getGroups(),的值 + * @return array + */ + public static function getGroupdata($childrenGroupIds = [], $groups = null) + { + $groupList = collection(AuthGroup::where('id', 'in', $childrenGroupIds)->select())->toArray(); + Tree::instance()->init($groupList, 'pid'); + $groupdata = []; + if ($groups) { + $result = []; + foreach ($groups as $m => $n) { + $childlist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['id'])); + $temp = []; + foreach ($childlist as $k => $v) { + $temp[$v['id']] = $v['name']; + } + $result[__($n['name'])] = $temp; + } + $groupdata = $result; + + } else { + + $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0)); + foreach ($result as $k => $v) { + $groupdata[$v['id']] = $v['name']; + } + } + return $groupdata; + } + + /** + * 获取当前部门归属的最高组织id(最顶级) + */ + public static function getOrganiseID($departmentid) + { + if (!$departmentid) return 0; + $organise_id = self::where(['id' => $departmentid])->value('organise_id'); + return $organise_id ? $organise_id : $departmentid;//如果没有最高,本身自己就是最高; + + } + + +} \ No newline at end of file diff --git a/application/admin/view/department/admin/add.html b/application/admin/view/department/admin/add.html new file mode 100644 index 000000000..1306f10db --- /dev/null +++ b/application/admin/view/department/admin/add.html @@ -0,0 +1,54 @@ +
+ {:token()} +
+ +
+ {:build_select('department_id', $departmentdata, null, ['class'=>'form-control selectpicker', 'multiple'=>'false', 'data-rule'=>'required'])} +
+
+ +
+ +
+ {:build_select('group[]', $groupdata, null, ['class'=>'form-control selectpicker', 'multiple'=>'false', 'data-rule'=>'required'])} +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])} +
+
+ +
\ No newline at end of file diff --git a/application/admin/view/department/admin/edit.html b/application/admin/view/department/admin/edit.html new file mode 100644 index 000000000..c399c8a90 --- /dev/null +++ b/application/admin/view/department/admin/edit.html @@ -0,0 +1,61 @@ +
+ {:token()} +
+ +
+ + {:build_select('department_id[]', $departmentdata, $department_ids, ['class'=>'form-control selectpicker', 'multiple'=>'false', 'data-rule'=>'required'])} +
+
+
+ +
+ {:build_select('group[]', $groupdata, $groupids, ['class'=>'form-control selectpicker', 'multiple'=>'false', 'data-rule'=>'required'])} +
+
+ + +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])} +
+
+ +
\ No newline at end of file diff --git a/application/admin/view/department/admin/index.html b/application/admin/view/department/admin/index.html new file mode 100644 index 000000000..98fa838d5 --- /dev/null +++ b/application/admin/view/department/admin/index.html @@ -0,0 +1,117 @@ + + +
+ +
+ +
+ {:build_heading()} + +
+
+
+
+
+ {:build_toolbar('refresh,add,delete')} +
+ +
+
+
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/application/admin/view/department/admin/principal.html b/application/admin/view/department/admin/principal.html new file mode 100644 index 000000000..21aa7ba9b --- /dev/null +++ b/application/admin/view/department/admin/principal.html @@ -0,0 +1,30 @@ +
+ {:token()} +
+ +
+ {:build_select('department_id[]', $departmentdata, $department_ids, ['class'=>'form-control selectpicker', 'multiple'=>'false'])} + {:__('可选择多个部门赋予负责人,如果未加入该部门会加入')} +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ + +
\ No newline at end of file diff --git a/application/admin/view/department/index/add.html b/application/admin/view/department/index/add.html new file mode 100644 index 000000000..9c527e8cd --- /dev/null +++ b/application/admin/view/department/index/add.html @@ -0,0 +1,52 @@ +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+ + + +
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+ +
diff --git a/application/admin/view/department/index/edit.html b/application/admin/view/department/index/edit.html new file mode 100644 index 000000000..d1075822e --- /dev/null +++ b/application/admin/view/department/index/edit.html @@ -0,0 +1,57 @@ + +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+ + + +
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+ +
+ + diff --git a/application/admin/view/department/index/index.html b/application/admin/view/department/index/index.html new file mode 100644 index 000000000..6d8e198f2 --- /dev/null +++ b/application/admin/view/department/index/index.html @@ -0,0 +1,27 @@ +
+ +
+ {:build_heading(null,FALSE)} +
+ +
+
+
+
+
+ {:build_toolbar('refresh,add,edit,del')} + + + +
+ +
+
+
+ +
+
+
diff --git a/public/assets/js/backend/department/admin.js b/public/assets/js/backend/department/admin.js new file mode 100644 index 000000000..d788725ee --- /dev/null +++ b/public/assets/js/backend/department/admin.js @@ -0,0 +1,170 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'department/admin/index', + add_url: 'department/admin/add', + edit_url: 'department/admin/edit', + del_url: 'department/admin/del', + multi_url: 'department/admin/multi', + } + }); + + var table = $("#table"); + + //在表格内容渲染完成后回调的事件 + table.on('post-body.bs.table', function (e, json) { + + }); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + columns: [ + [ + {field: 'state', checkbox: true, }, + {field: 'id', title: 'ID'}, + + {field: 'username', title: __('Username')}, + {field: 'nickname', title: __('Nickname')}, + {field: 'email', title: __('Email')}, + { + field: 'department_id', + title: __('部门'), + visible: false, + addclass: 'selectpage', + extend: 'data-source="department/index/index" data-field="name"', + operate: 'in', + formatter: Table.api.formatter.search + }, + { + field: 'dadmin', + title: __('部门'), + formatter: function (value, row, index) { + if (value.length == 0) + return '无' ; + var department=""; + $.each(value,function(i,v){ //arrTmp数组数据 + if (v.department){ + department+=department?','+v.department.name:v.department.name; + } + }); + return Table.api.formatter.label(department); + } + , operate:false + }, + + { + field: 'groups', + title: __('Group'), + formatter: function (value, row, index) { + if (value.length == 0) + return '无' ; + var groups_text=""; + $.each(value,function(i,v){ //arrTmp数组数据 + if (v.get_group){ + groups_text+=groups_text?','+v.get_group.name:v.get_group.name; + } + }); + return Table.api.formatter.label(groups_text,row,index); + } + , operate:false + }, + + {field: 'dadmin', title: __('负责人') , operate:false, + formatter: function (value, row, index) { + var str= '否'; + if (value.length == 0) + return str ; + $.each(value,function(i,v){ //arrTmp数组数据 + if (v.is_principal==1){ + str='' ; + } + }); + return str ; + } + }, + {field: 'status', title: __("Status"), searchList: {"normal":__('Normal'),"hidden":__('Hidden')}, formatter: Table.api.formatter.status}, + {field: 'logintime', title: __('登录时间'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true}, + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, + buttons: [ + { + name: 'record', + text: '负责人', + title: '设置为部门负责人', + icon: 'fa fa-street-view', + classname: 'btn btn-xs btn-danger btn-dialog', + url: 'department/admin/principal', + }, + ], + formatter: function (value, row, index) { + return Table.api.formatter.operate.call(this, value, row, index); + }} + ] + ] + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + + require(['jstree'], function () { + //全选和展开 + $(document).on("click", "#checkall", function () { + $("#departmenttree").jstree($(this).prop("checked") ? "check_all" : "uncheck_all"); + }); + $(document).on("click", "#expandall", function () { + $("#departmenttree").jstree($(this).prop("checked") ? "open_all" : "close_all"); + }); + $('#departmenttree').on("changed.jstree", function (e, data) { + console.log(data.selected.join(",")); + $(".commonsearch-table input[name=department_id]").val(data.selected.join(",")); + table.bootstrapTable('refresh', {}); + return false; + }); + $('#departmenttree').jstree({ + "themes": { + "stripes": true + }, + "checkbox": { + "keep_selected_style": false, + }, + "types": { + "channel": { + "icon": false, + }, + "list": { + "icon": false, + }, + "link": { + "icon": false, + }, + "disabled": { + "check_node": false, + "uncheck_node": false + } + }, + 'plugins': ["types", "checkbox"], + "core": { + "multiple": true, + 'check_callback': true, + "data": Config.departmentList + } + }); + }); + + }, + add: function () { + Form.api.bindevent($("form[role=form]")); + }, + principal:function(){ + Form.api.bindevent($("form[role=form]")); + }, + edit: function () { + Form.api.bindevent($("form[role=form]")); + } + }; + return Controller; +}); diff --git a/public/assets/js/backend/department/index.js b/public/assets/js/backend/department/index.js new file mode 100644 index 000000000..e303d5567 --- /dev/null +++ b/public/assets/js/backend/department/index.js @@ -0,0 +1,341 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'department/index/index', + add_url: 'department/index/add', + edit_url: 'department/index/edit', + del_url: 'department/index/del', + multi_url: 'department/index/multi', + dragsort_url: '', + table: 'department', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'weigh', + pagination: false, + escape: false, + fixedColumns: true, + fixedRightNumber: 1, + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + + {field: 'name', title: __('Name'), align: 'left'}, + + { + field: 'weigh', + title: __('Weigh'), + formatter: function (value, row, index) { + return ''; + }, + events: { + "dblclick .text-weigh": function (e) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + } + }, + { + field: 'createtime', + title: __('Createtime'), + visible: false, + operate: 'RANGE', + addclass: 'datetimerange', + formatter: Table.api.formatter.datetime + }, + { + field: 'updatetime', + title: __('Updatetime'), + visible: false, + operate: 'RANGE', + addclass: 'datetimerange', + formatter: Table.api.formatter.datetime + }, + {field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, + { + field: 'id', + title: '', + operate: false, + formatter: Controller.api.formatter.subnode + }, + { + field: 'operate', + title: __('Operate'), + table: table, + width: 160, + events: Table.api.events.operate, + formatter: Table.api.formatter.operate, + buttons: [ + { + name: 'addsub', + text: '子部门', + classname: 'btn btn-info btn-xs btn-dialog', + icon: 'fa fa-plus', + url: 'department/index/add/parent_id/{ids}' + }, + { + name: 'adminlist', + text: '成员', + classname: 'btn btn-info btn-xs btn-dialog', + icon: 'fa fa-users', + url: 'department/admin/index/department_id/{ids}' + } + + ] + } + ] + ], + search: false, + commonSearch: false + }); + + // 绑定TAB事件 + $('.panel-heading a[data-toggle="tab"]').on('shown.bs.tab', function (e) { + var field = $(this).closest("ul").data("field"); + var value = $(this).data("value"); + var options = table.bootstrapTable('getOptions'); + options.pageNumber = 1; + options.queryParams = function (params) { + params.model_id = value; + return params; + }; + table.bootstrapTable('refresh', {}); + return false; + }); + + $(document).on("change", ".text-weigh", function () { + $(this).data("params", {weigh: $(this).val()}); + Table.api.multi('', [$(this).data("id")], table, this); + return false; + }); + + //当内容渲染完成后 + table.on('post-body.bs.table', function (e, settings, json, xhr) { + //默认隐藏所有子节点 + //$("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").hide(); + //$(".btn-node-sub.disabled[data-pid!=0]").closest("tr").hide(); + + //显示隐藏子节点 + $(".btn-node-sub").off("click").on("click", function (e) { + var status = $(this).data("shown") || $("a.btn[data-pid='" + $(this).data("id") + "']:visible").size() > 0 ? true : false; + $("a.btn[data-pid='" + $(this).data("id") + "']").each(function () { + $(this).closest("tr").toggle(!status); + if (!$(this).hasClass("disabled")) { + $(this).trigger("click"); + } + }); + $(this).data("shown", !status); + return false; + }); + + }); + //展开隐藏一级 + $(document.body).on("click", ".btn-toggle", function (e) { + $("a.btn[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide(); + var that = this; + var show = $("i", that).hasClass("fa-chevron-down"); + $("i", that).toggleClass("fa-chevron-down", !show); + $("i", that).toggleClass("fa-chevron-up", show); + $("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").toggle(show); + $(".btn-node-sub[data-pid=0]").data("shown", show); + }); + //展开隐藏全部 + $(document.body).on("click", ".btn-toggle-all", function (e) { + var that = this; + var show = $("i", that).hasClass("fa-plus"); + $("i", that).toggleClass("fa-plus", !show); + $("i", that).toggleClass("fa-minus", show); + $(".btn-node-sub.disabled[data-pid!=0]").closest("tr").toggle(show); + $(".btn-node-sub[data-pid!=0]").data("shown", show); + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + }, + add: function () { + Controller.api.bindevent(); + $("input[name='row[type]'][value=list]").trigger("click"); + $("select[name='row[model_id]']").trigger("change"); + }, + edit: function () { + Controller.api.bindevent(); + $("input[name='row[type]']:checked").trigger("fa.event.typeupdated", "edit"); + }, + admin: function () { + + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'cms/channel/admin', + dragsort_url: '', + table: 'channel_admin', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'weigh', + pagination: false, + escape: false, + columns: [ + [ + { + field: 'superadmin', title: __('Type'), formatter: function (value, row, index) { + return row.superadmin ? "超级管理员" : "普通管理员"; + } + }, + {field: 'username', title: __('Username')}, + {field: 'nickname', title: __('Nickname')}, + {field: 'channels', title: __('Channels')}, + { + field: 'operate', + title: __('Operate'), + table: table, + formatter: Table.api.formatter.buttons, + buttons: [ + { + name: 'authorization', + text: __('Authorization'), + classname: 'btn btn-xs btn-success btn-authorization', + icon: 'fa fa-list', + url: 'cms/channel/admin/act/authorization', + visible: function (row) { + return !row.superadmin; + }, + }, + { + name: 'remove', + text: __('Remove'), + classname: 'btn btn-xs btn-danger btn-remove btn-ajax', + icon: 'fa fa-times', + url: 'cms/channel/admin/act/remove', + visible: function (row) { + return row.channels > 0; + }, + confirm: __('Are you sure you want to remove this item?'), + success: function (ret) { + $(".btn-refresh").trigger("click"); + } + } + ] + } + ] + ], + search: false, + commonSearch: false + }); + // 为表格绑定事件 + Table.api.bindevent(table); + + require(['jstree'], function () { + //全选和展开 + $(document).on("click", "#checkall", function () { + $("#channeltree").jstree($(this).prop("checked") ? "check_all" : "uncheck_all"); + }); + $(document).on("click", "#expandall", function () { + $("#channeltree").jstree($(this).prop("checked") ? "open_all" : "close_all"); + }); + + // 点击授权 + $(document).on("click", ".btn-authorization", function () { + var row = Table.api.getrowbyindex(table, $(this).data("row-index")); + Fast.api.ajax($(this).attr("href"), function (data, ret) { + Layer.open({ + id: "auth", + type: 1, + title: __('Authorization'), + btn: [__('Save')], + area: ["600px", "400px"], + content: Template("authorizationtpl", {}), + success: function () { + $('#channeltree').jstree({ + "themes": { + "stripes": true + }, + "checkbox": { + "keep_selected_style": false, + }, + "types": { + "channel": { + "icon": "fa fa-th", + }, + "list": { + "icon": "fa fa-list", + }, + "link": { + "icon": "fa fa-link", + }, + "disabled": { + "check_node": false, + "uncheck_node": false + } + }, + 'plugins': ["types", "checkbox"], + "core": { + "multiple": true, + 'check_callback': true, + "data": data + } + }); + }, + yes: function (index, o) { + var selected = $("#channeltree", o).jstree("get_selected"); + if (selected.length <= 0) { + Layer.msg(__('You must choose at least one channel'), {id: "aaafd"}); + } else { + Fast.api.ajax({ + url: "cms/channel/admin/act/save/ids/" + row.id, + data: {"ids": selected.join(",")} + }, function (data, ret) { + $(".btn-refresh").trigger("click"); + Layer.close(index); + }); + } + } + }); + return false; + }); + return false; + }); + }); + }, + api: { + formatter: { + title: function (value, row, index) { + return !row.ismenu || row.status == 'hidden' ? "" + value + "" : value; + }, + name: function (value, row, index) { + return !row.ismenu || row.status == 'hidden' ? "" + value + "" : value; + }, + icon: function (value, row, index) { + return ''; + }, + subnode: function (value, row, index) { + return ''; + } + }, + bindevent: function () { + Form.api.bindevent($("form[role=form]")); + + } + } + }; + return Controller; +}); -- Gitee From 6de7bd35c628f1ee97d0e5ac6cb50811a17e85b1 Mon Sep 17 00:00:00 2001 From: amplam Date: Thu, 10 Mar 2022 16:38:50 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BB=84=E7=BB=87?= =?UTF-8?q?=E6=9E=B6=E6=9E=84=E9=83=A8=E9=97=A8=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/command/Install/fastadmin.sql | 39 ++ .../admin/controller/department/Admin.php | 433 ++++++++++++++++++ .../admin/controller/department/Index.php | 193 ++++++++ application/admin/lang/zh-cn.php | 17 +- .../admin/lang/zh-cn/department/admin.php | 10 + .../admin/lang/zh-cn/department/index.php | 10 + application/admin/model/department/Admin.php | 156 +++++++ .../admin/model/department/AuthAdmin.php | 29 ++ .../model/department/AuthGroupAccess.php | 17 + .../admin/model/department/Department.php | 158 +++++++ .../admin/view/department/admin/add.html | 54 +++ .../admin/view/department/admin/edit.html | 61 +++ .../admin/view/department/admin/index.html | 117 +++++ .../view/department/admin/principal.html | 30 ++ .../admin/view/department/index/add.html | 52 +++ .../admin/view/department/index/edit.html | 57 +++ .../admin/view/department/index/index.html | 27 ++ public/assets/js/backend/department/admin.js | 170 +++++++ public/assets/js/backend/department/index.js | 341 ++++++++++++++ 19 files changed, 1962 insertions(+), 9 deletions(-) create mode 100644 application/admin/controller/department/Admin.php create mode 100644 application/admin/controller/department/Index.php create mode 100644 application/admin/lang/zh-cn/department/admin.php create mode 100644 application/admin/lang/zh-cn/department/index.php create mode 100644 application/admin/model/department/Admin.php create mode 100644 application/admin/model/department/AuthAdmin.php create mode 100644 application/admin/model/department/AuthGroupAccess.php create mode 100644 application/admin/model/department/Department.php create mode 100644 application/admin/view/department/admin/add.html create mode 100644 application/admin/view/department/admin/edit.html create mode 100644 application/admin/view/department/admin/index.html create mode 100644 application/admin/view/department/admin/principal.html create mode 100644 application/admin/view/department/index/add.html create mode 100644 application/admin/view/department/index/edit.html create mode 100644 application/admin/view/department/index/index.html create mode 100644 public/assets/js/backend/department/admin.js create mode 100644 public/assets/js/backend/department/index.js diff --git a/application/admin/command/Install/fastadmin.sql b/application/admin/command/Install/fastadmin.sql index 1b816535f..d84751e59 100755 --- a/application/admin/command/Install/fastadmin.sql +++ b/application/admin/command/Install/fastadmin.sql @@ -267,6 +267,20 @@ INSERT INTO `fa_auth_rule` VALUES (81, 'file', 79, 'user/rule/del', 'Del', 'fa f INSERT INTO `fa_auth_rule` VALUES (82, 'file', 79, 'user/rule/add', 'Add', 'fa fa-circle-o', '', '', '', 0, NULL, '', '', '', 1491635035, 1491635035, 0, 'normal'); INSERT INTO `fa_auth_rule` VALUES (83, 'file', 79, 'user/rule/edit', 'Edit', 'fa fa-circle-o', '', '', '', 0, NULL, '', '', '', 1491635035, 1491635035, 0, 'normal'); INSERT INTO `fa_auth_rule` VALUES (84, 'file', 79, 'user/rule/multi', 'Multi', 'fa fa-circle-o', '', '', '', 0, NULL, '', '', '', 1491635035, 1491635035, 0, 'normal'); +INSERT INTO `fa_auth_rule` VALUES (85, 'file', 0, 'department', 'Organizational', 'fa fa-sitemap', '', '', '', '1', null, '','','', '1645779501', '1645781822', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (86, 'file', 85, 'department/admin', 'Employee', 'fa fa-users', '', '', '', '1', null, '', '','','1645779501', '1645779501', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (87, 'file', 86, 'department/admin/index', 'View', 'fa fa-users', '', '', '', '0', null, '','','', '1645779501', '1645867468', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (88, 'file', 86, 'department/admin/add', 'Add', 'fa fa-circle-o', '', '', '', '0', null, '','','', '1645779501', '1645867469', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (89, 'file', 86, 'department/admin/edit', 'Edit', 'fa fa-circle-o', '', '', '', '0', null, '','','', '1645779501', '1645867469', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (90, 'file', 86, 'department/admin/del', 'Del', 'fa fa-circle-o', '', '', '', '0', null, '','','', '1645779501', '1645867469', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (91, 'file', 86, 'department/admin/multi', 'Multi', 'fa fa-circle-o', '', '', '', '0', null, '','','', '1645779501', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (92, 'file', 85, 'department/index', 'Department list', 'fa fa-sliders', '', '', '', '1', null, '', '','','1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (93, 'file', 92, 'department/index/index', 'View', 'fa fa-circle-o', '', '', '', '0', null, '','','', '1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (94, 'file', 92, 'department/index/add', 'Add', 'fa fa-circle-o', '', '', '', '0', null, '', '','','1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (95, 'file', 92, 'department/index/edit', 'Edit', 'fa fa-circle-o', '', '', '', '0', null, '', '','','1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (96, 'file', 92, 'department/index/del', 'Del', 'fa fa-circle-o', '', '', '', '0', null, '', '','','1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (97, 'file', 92, 'department/index/multi', 'Multi', 'fa fa-circle-o', '', '', '', '0', null, '','','', '1645780539', '1645780539', '0', 'normal'); +INSERT INTO `fa_auth_rule` VALUES (98, 'file', 86, 'department/admin/principal', 'Principal set', 'fa fa-circle-o', '', '', '', '0', null, '', '','','1646898376', '1646898376', '0', 'normal'); COMMIT; -- ---------------------------- @@ -602,3 +616,28 @@ CREATE TABLE `fa_version` ( ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='版本表'; SET FOREIGN_KEY_CHECKS = 1; + +CREATE TABLE `fa_department` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(30) DEFAULT NULL COMMENT '名称', + `parent_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父ID', + `weigh` int(11) DEFAULT '0' COMMENT '排序', + `create_time` varchar(20) DEFAULT NULL COMMENT '创建时间', + `update_time` int(10) DEFAULT NULL COMMENT '更新时间', + `status` enum('normal','hidden') NOT NULL DEFAULT 'normal' COMMENT '状态', + `organise_id` int(11) DEFAULT '0' COMMENT '组织id(最顶级)', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='组织部门表'; + + +CREATE TABLE `fa_department_admin` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `department_id` int(11) DEFAULT NULL COMMENT '部门id', + `organise_id` int(11) DEFAULT NULL COMMENT '组织id(最顶级)', + `admin_id` int(11) DEFAULT NULL COMMENT '成员id', + `create_time` int(11) NOT NULL COMMENT '加入时间', + `update_time` int(11) NOT NULL COMMENT '更新时间', + `is_principal` tinyint(1) DEFAULT NULL COMMENT '是否负责人', + `is_owner` tinyint(1) DEFAULT '0' COMMENT '拥有者', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='组织部门-成员表'; diff --git a/application/admin/controller/department/Admin.php b/application/admin/controller/department/Admin.php new file mode 100644 index 000000000..108a381e3 --- /dev/null +++ b/application/admin/controller/department/Admin.php @@ -0,0 +1,433 @@ +childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin()); + + $this->dadminModel = new DepartmentAdminModel; + $departmentList = []; + $this->allDepartment = collection(DepartmentModel::allDepartment())->toArray(); + $departmentdata = []; + foreach ($this->allDepartment as $k => $v) { + $state = ['opened' => true]; + $departmentList[] = [ + 'id' => $v['id'], + 'parent' => $v['parent_id'] ? $v['parent_id'] : '#', + 'text' => __($v['name']), + 'state' => $state + ]; + } + $tree = Tree::instance()->init($this->allDepartment, 'parent_id'); + $departmentOptions = $tree->getTree(0, ""); + + $this->view->assign('departmentOptions', $departmentOptions); + $this->assignconfig('departmentList', $departmentList); + + $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0)); + foreach ($result as $k => $v) { + $departmentdata[$v['id']] = $v['name']; + } + $this->view->assign('departmentdata', $departmentdata); + } + + /** + * 成员列表 + */ + public function index() + { + + //测试 + //设置过滤方法 + $this->request->filter(['strip_tags']); + $department_id = $this->request->request("department_id"); + if ($this->request->isAjax()) { + $this->model = new \app\admin\model\department\AuthAdmin(); + $filter = $this->request->get("filter", ''); + $filter = (array)json_decode($filter, true); + $filter_w = []; + + if (isset($filter['department_id'])) { + $department_id = $filter['department_id']; + unset($filter['department_id']); + $this->request->get(['filter' => json_encode($filter)]); + } + if ($department_id) { + $admin_ids = $this->dadminModel->where('department_id', 'in', $department_id)->column('admin_id'); + $filter_w['id'] = ['in', $admin_ids]; + } + + + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); + $total = $this->model + ->where($where) + ->where($filter_w) + ->order($sort, $order)->fetchSql(false) + ->count(); + $list = $this->model + ->where($where) + ->with(['dadmin.department']) + ->with(['groups.getGroup']) + ->where($filter_w) + ->order($sort, $order) + ->limit($offset, $limit)->fetchSql(false) + ->select(); + + + $result = array("total" => $total, "rows" => $list); + + return json($result); + } + return $this->view->fetch(); + } + + /** + * 添加 + * @return string|\think\response\Json + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function add() + { + $groupdata = DepartmentModel::getGroupdata( + $this->childrenGroupIds, + $this->auth->isSuperAdmin() ? null : $this->auth->getGroups() + ); + + if ($this->request->isPost()) { + + $adminModel = new AdminModel(); + $departmentModel = new DepartmentModel(); + + $params = $this->request->post("row/a"); + if ($params) { + Db::startTrans(); + try { + $department_id = $this->request->post("department_id/a"); + + //获取部门信息 + if (!$department_id) { + exception(__("部门不能为空")); + } + $d_list = $departmentModel->where('id', 'in', $department_id)->select(); + + if (!$d_list) { + exception(__("部门不能为空")); + } + + if (!Validate::is($params['password'], '\S{6,16}')) { + exception(__("Please input correct password")); + } + $params['salt'] = Random::alnum(); + $params['password'] = md5(md5($params['password']) . $params['salt']); + $params['avatar'] = '/assets/img/avatar.png'; //设置新管理员默认头像。 + $result = $adminModel->validate('Admin.add')->save($params); + if ($result === false) { + exception($adminModel->getError()); + } + + $admin_id = $adminModel->id; + $dadmin = array(); + //添加部门信息 + foreach ($d_list as $d_row) { + $dadmin[] = ['department_id' => $d_row->id, 'organise_id' => $d_row->organise_id? $d_row->organise_id: $d_row->id, 'admin_id' => $admin_id]; + } + $this->dadminModel->saveAll($dadmin); + + $group = $this->request->post("group/a"); + //过滤不允许的组别,避免越权 + $group = array_intersect($this->childrenGroupIds, $group); + + //添加权限默认第一个部门 + if (!$group) { + exception(__('The parent group exceeds permission limit')); + } + + $dataset = []; + foreach ($group as $value) { + $dataset[] = ['uid' => $admin_id, 'group_id' => $value]; + } + model('AuthGroupAccess')->saveAll($dataset); + + + Db::commit(); + } catch (\Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + $this->success(); + } + $this->error(__('Parameter %s can not be empty', '')); + } + $this->view->assign('groupdata', $groupdata); + return $this->view->fetch(); + } + + /** + * 修改 + * @param null $ids + * @return string|\think\response\Json + * @throws \think\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function edit($ids = null) + { + + $this->model = new AdminModel(); + $departmentModel = new DepartmentModel(); + $row = $this->model->get($ids); + if ($this->request->isPost()) { + $params = $this->request->post("row/a"); + if ($params) { + Db::startTrans(); + try { + $department_id = $this->request->post("department_id/a"); + //获取部门信息 + if (!$department_id) { + exception(__("Department can't null")); + } + $d_list = $departmentModel->where('id', 'in', $department_id)->select(); + + if (!$d_list) { + exception(__("Department can't null")); + } + + if ($params['password']) { + if (!Validate::is($params['password'], '\S{6,16}')) { + exception(__("Please input correct password")); + } + $params['salt'] = Random::alnum(); + $params['password'] = md5(md5($params['password']) . $params['salt']); + } else { + unset($params['password'], $params['salt']); + } + //这里需要针对username和email做唯一验证 + $adminValidate = \think\Loader::validate('Admin'); + $adminValidate->rule([ + 'username' => 'require|regex:\w{3,12}|unique:admin,username,' . $row->id, + 'email' => 'require|email|unique:admin,email,' . $row->id, + 'password' => 'regex:\S{32}', + ]); + $result = $row->validate('Admin.edit')->save($params); + if ($result === false) { + exception($row->getError()); + } + $exist_departmentids=$this->dadminModel->where('admin_id', $row->id)->column('department_id'); + $dadmin = array(); + $deleteids=array_diff($exist_departmentids,$department_id); + //添加部门信息 + foreach ($d_list as $d_row) { + if (!in_array($d_row->id,$exist_departmentids)){ + $dadmin[] = ['department_id' => $d_row->id, 'organise_id' => $d_row->organise_id? $d_row->organise_id: $d_row->id, 'admin_id' => $row->id]; + } + } + if ($deleteids){ + $this->dadminModel->where('admin_id', $row->id)->where('department_id','in',$deleteids)->delete(); + } + if (count($dadmin)>0){ + $this->dadminModel->saveAll($dadmin); + } + + + + // 先移除所有权限 + model('AuthGroupAccess')->where('uid', $row->id)->delete(); + + $group = $this->request->post("group/a"); + // 过滤不允许的组别,避免越权 + $group = array_intersect($this->childrenGroupIds, $group); + if (!$group) { + exception(__('The parent group exceeds permission limit')); + } + + $dataset = []; + foreach ($group as $value) { + $dataset[] = ['uid' => $row->id, 'group_id' => $value]; + } + model('AuthGroupAccess')->saveAll($dataset); + + Db::commit(); + } catch (\Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + $this->success(); + } + $this->error(__('Parameter %s can not be empty', '')); + } + $groupdata = DepartmentModel::getGroupdata( + $this->childrenGroupIds, + $this->auth->isSuperAdmin() ? null : $this->auth->getGroups() + ); + $grouplist = $this->auth->getGroups($row['id']); + $groupids = []; + foreach ($grouplist as $k => $v) { + $groupids[] = $v['id']; + } + $this->view->assign("groupids", $groupids); + + $this->view->assign('row', $row); + $this->view->assign('department_ids', $this->dadminModel->getDepartmentIds($ids)); + $this->view->assign('groupdata', $groupdata); + return $this->view->fetch(); + } + + + /** + * 删除 + */ + public function del($ids = "") + { + if (!$this->request->isPost()) { + $this->error(__("Invalid parameters")); + } + $this->childrenAdminIds = $this->auth->getChildrenAdminIds($this->auth->isSuperAdmin()); + $this->model = new AdminModel(); + + $ids = $ids ? $ids : $this->request->post("ids"); + if ($ids) { + $ids = array_intersect($this->childrenAdminIds, array_filter(explode(',', $ids))); + // 避免越权删除管理员 + $childrenGroupIds = $this->childrenGroupIds; + $adminList = $this->model->where('id', 'in', $ids)->where('id', 'in', function ($query) use ($childrenGroupIds) { + $query->name('auth_group_access')->where('group_id', 'in', $childrenGroupIds)->field('uid'); + })->select(); + if ($adminList) { + $deleteIds = []; + foreach ($adminList as $k => $v) { + $deleteIds[] = $v->id; + } + $deleteIds = array_values(array_diff($deleteIds, [$this->auth->id])); + if ($deleteIds) { + Db::startTrans(); + try { + $this->model->destroy($deleteIds); + model('AuthGroupAccess')->where('uid', 'in', $deleteIds)->delete(); + //删除部门员工信息 + $this->dadminModel->where('admin_id', 'in', $deleteIds)->delete();; + + Db::commit(); + } catch (\Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + $this->success(); + } + $this->error(__('No rows were deleted')); + } + } + $this->error(__('You have no permission')); + } + + /** + * 批量更新 + * @internal + */ + public function multi($ids = "") + { + // 管理员禁止批量操作 + $this->error(); + } + + /** + * 设置部门负责人 + */ + public function principal($ids = "") + { + + $this->model = new AdminModel(); + $departmentModel = new DepartmentModel(); + $row = $this->model->get($ids); + if ($this->request->isPost()) { + $department_id = $this->request->post("department_id/a"); + if ($department_id&&$department_id[0]) { + Db::startTrans(); + try { + $d_list = $departmentModel->where('id', 'in', $department_id)->select(); + + if (!$d_list) { + exception(__("Department can't null")); + } + //先移除他所有负责的部门 + $this->dadminModel->where('admin_id', $row->id)->update(['is_principal'=>0]); + + //判断选择的部门是否存在,不存在就先把他加入 + $p_departmentids = array_column($d_list, 'id'); + $exist_departmentids=$this->dadminModel->where('admin_id', $row->id)->column('department_id'); + + $dadmin = array(); + //添加部门信息 + foreach ($d_list as $d_row) { + if (!in_array($d_row->id,$exist_departmentids)){ + $dadmin[] = ['department_id' => $d_row->id, 'organise_id' => $d_row->organise_id? $d_row->organise_id: $d_row->id, 'admin_id' => $row->id]; + } + } + if (count($dadmin)>0){ + $this->dadminModel->saveAll($dadmin); + } + //更改为负责人 + $this->dadminModel->where('admin_id', $row->id)->where('department_id','in',$p_departmentids)->update(['is_principal'=>1]); + + + + Db::commit(); + } catch (\Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + + }else{ + //移除他所有负责的部门 + $this->dadminModel->where('admin_id', $row->id)->update(['is_principal'=>0]); + } + $this->success(); + } + + + $this->view->assign('row', $row); + $this->view->assign('department_ids', $this->dadminModel::getPrincipalIds($ids)); + return $this->view->fetch(); + } + + +} diff --git a/application/admin/controller/department/Index.php b/application/admin/controller/department/Index.php new file mode 100644 index 000000000..5aeb2812b --- /dev/null +++ b/application/admin/controller/department/Index.php @@ -0,0 +1,193 @@ +model = new DepartmentModel; + + $this->tree = Tree::instance(); + $this->tree->init(DepartmentModel::allDepartment(), 'parent_id'); + $this->departmentList = $this->tree->getTreeList($this->tree->getTreeArray(0), 'name'); + $this->view->assign("departmentList", $this->departmentList); + + $this->view->assign("statusList", DepartmentModel::getStatusList()); + } + + /** + * 部门列表 + */ + public function index() + { + //设置过滤方法 + $this->request->filter(['strip_tags', 'trim']); + if ($this->request->isAjax()) { + //如果发送的来源是Selectpage,则转发到Selectpage + if ($this->request->request('keyField')) { + //return $this->selectpage(); + } + + $search = $this->request->request("search"); + //构造父类select列表选项数据 + $list = []; + if ($search) { + foreach ($this->departmentList as $k => $v) { + if (stripos($v['name'], $search) !== false) { + $list[] = $v; + } + } + } else { + $list = $this->departmentList; + } + + $list = array_values($list); + + foreach ($list as $k => &$v) { + $v['pid'] = $v['parent_id']; + } + $total = count($list); + $result = array("total" => $total, "rows" => $list); + + return json($result); + + } + return $this->view->fetch(); + } + + /** + * 添加 + */ + public function add() + { + if ($this->request->isPost()) { + $params = $this->request->post("row/a"); + if ($params) { + if ($this->dataLimit && $this->dataLimitFieldAutoFill) { + $params[$this->dataLimitField] = $this->auth->id; + } + try { + //是否采用模型验证 + if ($this->modelValidate) { + $name = basename(str_replace('\\', '/', get_class($this->model))); + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate; + $this->model->validate($validate); + } + $nameArr = array_filter(explode("\n", str_replace("\r\n", "\n", $params['name']))); + + //获取组织最高的ID; + $params['organise_id'] = DepartmentModel::getOrganiseID(isset($params['parent_id']) ? $params['parent_id'] : 0); + + if (count($nameArr) > 1) { + foreach ($nameArr as $index => $item) { + $params['name'] = $item; + $result = $this->model->allowField(true)->isUpdate(false)->data($params)->save(); + } + } else { + $result = $this->model->allowField(true)->save($params); + } + if ($result !== false) { + //清空部门缓存 + DepartmentModel::clearCache(); + $this->success(); + } else { + $this->error($this->model->getError()); + } + } catch (\think\exception\PDOException $e) { + $this->error($e->getMessage()); + } + } + $this->error(__('Parameter %s can not be empty', '')); + } + return $this->view->fetch(); + } + + public function edit($ids = null) + { + $row = DepartmentModel::get($ids); + if (!$row) { + $this->error(__('No Results were found')); + } + if ($this->request->isPost()) { + $params = $this->request->post("row/a"); + if ($params) { + $params = $this->preExcludeFields($params); + $result = false; + Db::startTrans(); + try { + //是否采用模型验证 + if ($this->modelValidate) { + $name = str_replace("\\model\\", "\\validate\\", get_class($this->model)); + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate; + $row->validateFailException(true)->validate($validate); + } + //最顶级的不能修改成下级 + if ($row['parent_id']==0&&$params['parent_id']){ + \exception(__("Top-level organization cannot be modified to lower level organization")); + } + + //获取修改后的组织最高的ID; + //获取组织最高的ID; + $organise_id = isset($params['parent_id']) ? DepartmentModel::getOrganiseID($params['parent_id']) : 0; + //判断修改的父类是否和之前的一样并且organise_id不一样就要修改,含子类 + if ($params['parent_id'] != $row['parent_id'] && $organise_id != $row['organise_id']) { + $departmentIds = DepartmentModel::getChildrenIds($row->id, true); + $mapwhere['id'] = ['in', $departmentIds]; + $departmentIds = DepartmentModel::update(['organise_id' => $organise_id], $mapwhere); + } + $result = $row->allowField(true)->save($params); + Db::commit(); + } catch (ValidateException $e) { + Db::rollback(); + $this->error($e->getMessage()); + } catch (PDOException $e) { + Db::rollback(); + $this->error($e->getMessage()); + } catch (Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + if ($result !== false) { + //清空部门缓存 + DepartmentModel::clearCache(); + $this->success(); + } else { + $this->error(__('No rows were updated')); + } + } + $this->error(__('Parameter %s can not be empty', '')); + } else { + + $row = $row->toArray(); + $childrenIds = $this->tree->getChildrenIds($row['id'], true); + $this->view->assign('childrenIds', $childrenIds); + $this->view->assign("row", $row); + return $this->view->fetch(); + } + + + } + + + +} diff --git a/application/admin/lang/zh-cn.php b/application/admin/lang/zh-cn.php index 5f2df6fdc..7344b1cf5 100755 --- a/application/admin/lang/zh-cn.php +++ b/application/admin/lang/zh-cn.php @@ -114,13 +114,6 @@ return [ '%d week%s ago' => '%d周前', '%d month%s ago' => '%d月前', '%d year%s ago' => '%d年前', - '%d second%s after' => '%d秒后', - '%d minute%s after' => '%d分钟后', - '%d hour%s after' => '%d小时后', - '%d day%s after' => '%d天后', - '%d week%s after' => '%d周后', - '%d month%s after' => '%d月后', - '%d year%s after' => '%d年后', 'Set to normal' => '设为正常', 'Set to hidden' => '设为隐藏', 'Recycle bin' => '回收站', @@ -201,19 +194,25 @@ return [ 'Third group 2' => '三级管理组2', 'Dashboard tips' => '用于展示当前系统中的统计数据、统计报表及重要实时数据', 'Config tips' => '可以在此增改系统的变量和分组,也可以自定义分组和变量', - 'Category tips' => '分类类型请在常规管理->系统配置->字典配置中添加', + 'Category tips' => '用于管理网站的所有分类,分类可进行无限级分类,分类类型请在常规管理->系统配置->字典配置中添加', 'Attachment tips' => '主要用于管理上传到服务器或第三方存储的数据', 'Addon tips' => '可在线安装、卸载、禁用、启用、配置、升级插件,插件升级前请做好备份。', 'Admin tips' => '一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成', 'Admin log tips' => '管理员可以查看自己所拥有的权限的管理员日志', 'Group tips' => '角色组可以有多个,角色有上下级层级关系,如果子角色有角色组和管理员的权限则可以派生属于自己组别的下级角色组或管理员', - 'Rule tips' => '菜单规则通常对应一个控制器的方法,同时菜单栏数据也从规则中获取', + 'Rule tips' => '规则通常对应一个控制器的方法,同时左侧的菜单栏数据也从规则中体现,通常建议通过命令行进行生成规则节点', 'Access is allowed only to the super management group' => '仅超级管理组能访问', 'Local addon' => '本地插件', + 'Organizational' => '组织架构', + 'Employee' => '部门成员', + 'Department list' => '部门管理', + 'Principal set' => '设置负责人', + // 前台菜单 'Frontend' => '前台', 'API Interface' => 'API接口', 'User Module' => '会员模块', 'Register' => '注册', 'User Center' => '会员中心', + ]; diff --git a/application/admin/lang/zh-cn/department/admin.php b/application/admin/lang/zh-cn/department/admin.php new file mode 100644 index 000000000..2515b15c9 --- /dev/null +++ b/application/admin/lang/zh-cn/department/admin.php @@ -0,0 +1,10 @@ + '部门', + 'Principal' => '负责人', + 'Login time' => '最后登录', + 'You can select multiple departments to assign the person in charge. If you do not join the Department, you will join'=> '可选择多个部门赋予负责人,如果未加入该部门会加入', + 'Parent' => '上级', + 'Loginfailure' => '登录失败次数', + "Department can't null" => '部门不能为空', +]; diff --git a/application/admin/lang/zh-cn/department/index.php b/application/admin/lang/zh-cn/department/index.php new file mode 100644 index 000000000..19b15b41c --- /dev/null +++ b/application/admin/lang/zh-cn/department/index.php @@ -0,0 +1,10 @@ + '部门', + 'Principal' => '负责人', + 'Children' => '子类', + 'Batch entry is supported, one record per line' => '支持批量录入,一行一条记录', + 'Toggle sub menu' => '切换菜单', + "Top-level organization cannot be modified to lower level organization"=>"顶级组织不能修改成下级", + +]; diff --git a/application/admin/model/department/Admin.php b/application/admin/model/department/Admin.php new file mode 100644 index 000000000..db2555483 --- /dev/null +++ b/application/admin/model/department/Admin.php @@ -0,0 +1,156 @@ +hasOne('app\admin\model\department\Department', 'id', 'department_id'); + } + + /** + * 获取管理者的部门ids + * @param $admin_id + * @param string $type + * @return array|bool|string + */ + public function getDepartmentIds($admin_id, $type = "self") + { + return $this->where('admin_id', $admin_id)->column('department_id'); + } + + /** + * 获取负责的部门IDs + * @param $admin_id + * @return array|bool|string + */ + public static function getPrincipalIds($admin_id){ + return self::where('admin_id', $admin_id)->where('is_principal',1)->column('department_id'); + } + /** + * 当前负责人下属ids + * @param int $admin_id 某个管理员ID + * @param boolean $withself 是否包含自身 + * @param string $department_ids 是否指定某个管理部门id,多个逗号id隔开 + * @return array + */ + public static function getChildrenAdminIds($admin_id, $withself = false, $department_ids = null) + { + $childrenAdminIds=[]; + if (self::isSuperAdmin($admin_id)) { + $childrenAdminIds = \app\admin\model\department\AuthAdmin::column('id'); + }else{ + $departmentIds = self::getChildrenDepartmentIds($admin_id); + $authDepartmentList = self::field('admin_id,department_id') + ->where('department_id', 'in', $departmentIds) + ->select(); + foreach ($authDepartmentList as $k => $v) { + $childrenAdminIds[] = $v['admin_id']; + } + } + if ($withself) { + if (!in_array($admin_id, $childrenAdminIds)) { + $childrenAdminIds[] = $admin_id; + } + } else { + $childrenAdminIds = array_diff($childrenAdminIds, [$admin_id]); + } + return $childrenAdminIds; + + + } + + /** + * 判断是否是超级管理员 + * @return bool + */ + public static function isSuperAdmin($admin_id) + { + $auth = new \app\admin\library\Auth(); + return in_array('*', $auth->getRuleIds($admin_id)) ? true : false; + } + + /** + * 取出当前负责人管理的下级部门 + * @param boolean $withself 是否包含当前所在的分组 + * @return array + */ + public static function getChildrenDepartmentIds($admin_id,$withself = false) + { + //取出当前负责人所有部门 + $departments =self::getDepartments($admin_id); + $departmenIds = []; + foreach ($departments as $k => $v) { + $departmenIds[] = $v['id']; + } + $originDepartmenId = $departmenIds; + foreach ($departments as $k => $v) { + if (in_array($v['parent_id'], $originDepartmenId)) { + $departmenIds = array_diff($departmenIds, [$v['id']]); + unset($departments[$k]); + } + } + // 取出所有部门 + $departmentList = \app\admin\model\department\Department::allDepartment(); + $objList = []; + foreach ($departments as $k => $v) { + // 取出包含自己的所有子节点 + $childrenList = Tree::instance()->init($departmentList, 'parent_id')->getChildren($v['id'], true); + $obj = Tree::instance()->init($childrenList, 'parent_id')->getTreeArray($v['parent_id']); + $objList = array_merge($objList, Tree::instance()->getTreeList($obj)); + } + $childrenDepartmenIds = []; + foreach ($objList as $k => $v) { + $childrenDepartmenIds[] = $v['id']; + } + if (!$withself) { + $childrenDepartmenIds = array_diff($childrenDepartmenIds, $departmenIds); + } + return $childrenDepartmenIds; + } + + + + /** + * 根据用户id获取部门组,返回值为数组 + * @param int $admin_id admin_id + * @return array 用户所属的部门 array( + * array('admin_id'=>'员工id','department_id'=>'部门id','name'=>'部门名称'), + * ...) + */ + public static function getDepartments($admin_id) + { + static $departments = []; + if (isset($departments[$admin_id])) { + return $departments[$admin_id]; + } + + // 执行查询 + $user_departments = Db::name('department_admin') + ->alias('da') + ->join('__'.strtoupper('department').'__ d', 'da.department_id = d.id', 'LEFT') + ->field('da.admin_id,da.department_id,d.id,d.parent_id,d.name') + ->where("da.admin_id='{$admin_id}' and is_principal=1 and d.status='normal'") + ->select(); + $departments[$admin_id] = $user_departments ?: []; + return $departments[$admin_id]; + } + +} \ No newline at end of file diff --git a/application/admin/model/department/AuthAdmin.php b/application/admin/model/department/AuthAdmin.php new file mode 100644 index 000000000..7f438dacd --- /dev/null +++ b/application/admin/model/department/AuthAdmin.php @@ -0,0 +1,29 @@ +hasMany('\app\admin\model\department\Admin', 'admin_id', 'id'); + } + + /** + * 关联角色组 + * @return \think\model\relation\HasMany + */ + public function groups() + { + return $this->hasMany('\app\admin\model\department\AuthGroupAccess', 'uid', 'id'); + } + +} \ No newline at end of file diff --git a/application/admin/model/department/AuthGroupAccess.php b/application/admin/model/department/AuthGroupAccess.php new file mode 100644 index 000000000..a5d16f6f5 --- /dev/null +++ b/application/admin/model/department/AuthGroupAccess.php @@ -0,0 +1,17 @@ +belongsTo('\app\admin\model\AuthGroup', 'group_id', 'id'); + } +} diff --git a/application/admin/model/department/Department.php b/application/admin/model/department/Department.php new file mode 100644 index 000000000..02dfba5e9 --- /dev/null +++ b/application/admin/model/department/Department.php @@ -0,0 +1,158 @@ +getPk(); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + self::clearCache(); + }); + self::afterDelete(function ($row) { + //删除时,删除子节点,同时将所有相关部门成员删除 + $childIds = self::getChildrenIds($row['id']); + if ($childIds) { + Department::destroy(function ($query) use ($childIds) { + $query->where('id', 'in', $childIds); + }); + } + $childIds[] = $row['id']; + db('department_admin')->where('department_id', 'in', $childIds)->delete(); + self::clearCache(); + }); + self::afterWrite(function ($row) use ($config) { + $changed = $row->getChangedData(); + //隐藏时判断是否有子节点,有则隐藏 + if (isset($changed['status']) && $changed['status'] == 'hidden') { + $childIds = self::getChildrenIds($row['id']); + db('department')->where('id', 'in', $childIds)->update(['status' => 'hidden']); + } + self::clearCache(); + + }); + } + + public static function getStatusList() + { + return ['normal' => __('Normal'), 'hidden' => __('Hidden')]; + } + + + /** + * 获取栏目的所有子节点ID + * @param int $id 栏目ID + * @param bool $withself 是否包含自身 + * @return array + */ + public static function getChildrenIds($id, $withself = false) + { + static $tree; + if (!$tree) { + $tree = \fast\Tree::instance(); + $tree->init(collection(self::order('weigh desc,id desc')->field('id,parent_id,name,status')->cache(self::$cachekey)->select())->toArray(), 'parent_id'); + } + $childIds = $tree->getChildrenIds($id, $withself); + return $childIds; + } + + /** + * 所有部门 + */ + public static function allDepartment() + { + return self::order('weigh desc,id desc')->where(['status' => 'normal'])->cache(self::$cachekey)->select(); + } + + /** + * 清空缓存 + * @param $name + */ + public static function clearCache() + { + Cache::rm(self::$cachekey); + } + + + /** + * 获取权限组 + * @param array $childrenGroupIds + * @param null $groups 如果不是超级管理员传auth->getGroups(),的值 + * @return array + */ + public static function getGroupdata($childrenGroupIds = [], $groups = null) + { + $groupList = collection(AuthGroup::where('id', 'in', $childrenGroupIds)->select())->toArray(); + Tree::instance()->init($groupList, 'pid'); + $groupdata = []; + if ($groups) { + $result = []; + foreach ($groups as $m => $n) { + $childlist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['id'])); + $temp = []; + foreach ($childlist as $k => $v) { + $temp[$v['id']] = $v['name']; + } + $result[__($n['name'])] = $temp; + } + $groupdata = $result; + + } else { + + $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0)); + foreach ($result as $k => $v) { + $groupdata[$v['id']] = $v['name']; + } + } + return $groupdata; + } + + /** + * 获取当前部门归属的最高组织id(最顶级) + */ + public static function getOrganiseID($departmentid) + { + if (!$departmentid) return 0; + $organise_id = self::where(['id' => $departmentid])->value('organise_id'); + return $organise_id ? $organise_id : $departmentid;//如果没有最高,本身自己就是最高; + + } + + +} \ No newline at end of file diff --git a/application/admin/view/department/admin/add.html b/application/admin/view/department/admin/add.html new file mode 100644 index 000000000..ff0ace4ce --- /dev/null +++ b/application/admin/view/department/admin/add.html @@ -0,0 +1,54 @@ +
+ {:token()} +
+ +
+ {:build_select('department_id', $departmentdata, null, ['class'=>'form-control selectpicker', 'multiple'=>'false', 'data-rule'=>'required'])} +
+
+ +
+ +
+ {:build_select('group[]', $groupdata, null, ['class'=>'form-control selectpicker', 'multiple'=>'false', 'data-rule'=>'required'])} +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])} +
+
+ +
\ No newline at end of file diff --git a/application/admin/view/department/admin/edit.html b/application/admin/view/department/admin/edit.html new file mode 100644 index 000000000..4e0dd1791 --- /dev/null +++ b/application/admin/view/department/admin/edit.html @@ -0,0 +1,61 @@ +
+ {:token()} +
+ +
+ + {:build_select('department_id[]', $departmentdata, $department_ids, ['class'=>'form-control selectpicker', 'multiple'=>'false', 'data-rule'=>'required'])} +
+
+
+ +
+ {:build_select('group[]', $groupdata, $groupids, ['class'=>'form-control selectpicker', 'multiple'=>'false', 'data-rule'=>'required'])} +
+
+ + +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])} +
+
+ +
\ No newline at end of file diff --git a/application/admin/view/department/admin/index.html b/application/admin/view/department/admin/index.html new file mode 100644 index 000000000..4fd8ac3bc --- /dev/null +++ b/application/admin/view/department/admin/index.html @@ -0,0 +1,117 @@ + + +
+ +
+ +
+ {:build_heading()} + +
+
+
+
+
+ {:build_toolbar('refresh,add,delete')} +
+ +
+
+
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/application/admin/view/department/admin/principal.html b/application/admin/view/department/admin/principal.html new file mode 100644 index 000000000..b468cf757 --- /dev/null +++ b/application/admin/view/department/admin/principal.html @@ -0,0 +1,30 @@ +
+ {:token()} +
+ +
+ {:build_select('department_id[]', $departmentdata, $department_ids, ['class'=>'form-control selectpicker', 'multiple'=>'false'])} + {:__('You can select multiple departments to assign the person in charge. If you do not join the Department, you will join')} +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ + +
\ No newline at end of file diff --git a/application/admin/view/department/index/add.html b/application/admin/view/department/index/add.html new file mode 100644 index 000000000..a9cdd0c8d --- /dev/null +++ b/application/admin/view/department/index/add.html @@ -0,0 +1,52 @@ +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+ + + +
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+ +
diff --git a/application/admin/view/department/index/edit.html b/application/admin/view/department/index/edit.html new file mode 100644 index 000000000..b612e457d --- /dev/null +++ b/application/admin/view/department/index/edit.html @@ -0,0 +1,57 @@ + +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+ + + +
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+ +
+ + diff --git a/application/admin/view/department/index/index.html b/application/admin/view/department/index/index.html new file mode 100644 index 000000000..6d8e198f2 --- /dev/null +++ b/application/admin/view/department/index/index.html @@ -0,0 +1,27 @@ +
+ +
+ {:build_heading(null,FALSE)} +
+ +
+
+
+
+
+ {:build_toolbar('refresh,add,edit,del')} + + + +
+ +
+
+
+ +
+
+
diff --git a/public/assets/js/backend/department/admin.js b/public/assets/js/backend/department/admin.js new file mode 100644 index 000000000..a6e680ba9 --- /dev/null +++ b/public/assets/js/backend/department/admin.js @@ -0,0 +1,170 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'department/admin/index', + add_url: 'department/admin/add', + edit_url: 'department/admin/edit', + del_url: 'department/admin/del', + multi_url: 'department/admin/multi', + } + }); + + var table = $("#table"); + + //在表格内容渲染完成后回调的事件 + table.on('post-body.bs.table', function (e, json) { + + }); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + columns: [ + [ + {field: 'state', checkbox: true, }, + {field: 'id', title: 'ID'}, + + {field: 'username', title: __('Username')}, + {field: 'nickname', title: __('Nickname')}, + {field: 'email', title: __('Email')}, + { + field: 'department_id', + title: __('Department'), + visible: false, + addclass: 'selectpage', + extend: 'data-source="department/index/index" data-field="name"', + operate: 'in', + formatter: Table.api.formatter.search + }, + { + field: 'dadmin', + title: __('Department'), + formatter: function (value, row, index) { + if (value.length == 0) + return '-' ; + var department=""; + $.each(value,function(i,v){ //arrTmp数组数据 + if (v.department){ + department+=department?','+v.department.name:v.department.name; + } + }); + return Table.api.formatter.label(department); + } + , operate:false + }, + + { + field: 'groups', + title: __('Group'), + formatter: function (value, row, index) { + if (value.length == 0) + return '-' ; + var groups_text=""; + $.each(value,function(i,v){ //arrTmp数组数据 + if (v.get_group){ + groups_text+=groups_text?','+v.get_group.name:v.get_group.name; + } + }); + return Table.api.formatter.label(groups_text,row,index); + } + , operate:false + }, + + {field: 'dadmin', title: __('Principal') , operate:false, + formatter: function (value, row, index) { + var str=__('No'); + if (value.length == 0) + return str ; + $.each(value,function(i,v){ //arrTmp数组数据 + if (v.is_principal==1){ + str=''+__('Yes')+'' ; + } + }); + return str ; + } + }, + {field: 'status', title: __("Status"), searchList: {"normal":__('Normal'),"hidden":__('Hidden')}, formatter: Table.api.formatter.status}, + {field: 'logintime', title: __('Login time'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true}, + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, + buttons: [ + { + name: 'principal', + text: __('Principal'), + title: __('Principal set'), + icon: 'fa fa-street-view', + classname: 'btn btn-xs btn-danger btn-dialog', + url: 'department/admin/principal', + }, + ], + formatter: function (value, row, index) { + return Table.api.formatter.operate.call(this, value, row, index); + }} + ] + ] + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + + require(['jstree'], function () { + //全选和展开 + $(document).on("click", "#checkall", function () { + $("#departmenttree").jstree($(this).prop("checked") ? "check_all" : "uncheck_all"); + }); + $(document).on("click", "#expandall", function () { + $("#departmenttree").jstree($(this).prop("checked") ? "open_all" : "close_all"); + }); + $('#departmenttree').on("changed.jstree", function (e, data) { + console.log(data.selected.join(",")); + $(".commonsearch-table input[name=department_id]").val(data.selected.join(",")); + table.bootstrapTable('refresh', {}); + return false; + }); + $('#departmenttree').jstree({ + "themes": { + "stripes": true + }, + "checkbox": { + "keep_selected_style": false, + }, + "types": { + "channel": { + "icon": false, + }, + "list": { + "icon": false, + }, + "link": { + "icon": false, + }, + "disabled": { + "check_node": false, + "uncheck_node": false + } + }, + 'plugins': ["types", "checkbox"], + "core": { + "multiple": true, + 'check_callback': true, + "data": Config.departmentList + } + }); + }); + + }, + add: function () { + Form.api.bindevent($("form[role=form]")); + }, + principal:function(){ + Form.api.bindevent($("form[role=form]")); + }, + edit: function () { + Form.api.bindevent($("form[role=form]")); + } + }; + return Controller; +}); diff --git a/public/assets/js/backend/department/index.js b/public/assets/js/backend/department/index.js new file mode 100644 index 000000000..e78005393 --- /dev/null +++ b/public/assets/js/backend/department/index.js @@ -0,0 +1,341 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'department/index/index', + add_url: 'department/index/add', + edit_url: 'department/index/edit', + del_url: 'department/index/del', + multi_url: 'department/index/multi', + dragsort_url: '', + table: 'department', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'weigh', + pagination: false, + escape: false, + fixedColumns: true, + fixedRightNumber: 1, + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + + {field: 'name', title: __('Name'), align: 'left'}, + + { + field: 'weigh', + title: __('Weigh'), + formatter: function (value, row, index) { + return ''; + }, + events: { + "dblclick .text-weigh": function (e) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + } + }, + { + field: 'createtime', + title: __('Createtime'), + visible: false, + operate: 'RANGE', + addclass: 'datetimerange', + formatter: Table.api.formatter.datetime + }, + { + field: 'updatetime', + title: __('Updatetime'), + visible: false, + operate: 'RANGE', + addclass: 'datetimerange', + formatter: Table.api.formatter.datetime + }, + {field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, + { + field: 'id', + title: '', + operate: false, + formatter: Controller.api.formatter.subnode + }, + { + field: 'operate', + title: __('Operate'), + table: table, + width: 160, + events: Table.api.events.operate, + formatter: Table.api.formatter.operate, + buttons: [ + { + name: 'add', + text: __('Children'), + classname: 'btn btn-info btn-xs btn-dialog', + icon: 'fa fa-plus', + url: 'department/index/add/parent_id/{ids}' + }, + { + name: 'index', + text: __('Employee'), + classname: 'btn btn-info btn-xs btn-dialog', + icon: 'fa fa-users', + url: 'department/admin/index/department_id/{ids}' + } + + ] + } + ] + ], + search: false, + commonSearch: false + }); + + // 绑定TAB事件 + $('.panel-heading a[data-toggle="tab"]').on('shown.bs.tab', function (e) { + var field = $(this).closest("ul").data("field"); + var value = $(this).data("value"); + var options = table.bootstrapTable('getOptions'); + options.pageNumber = 1; + options.queryParams = function (params) { + params.model_id = value; + return params; + }; + table.bootstrapTable('refresh', {}); + return false; + }); + + $(document).on("change", ".text-weigh", function () { + $(this).data("params", {weigh: $(this).val()}); + Table.api.multi('', [$(this).data("id")], table, this); + return false; + }); + + //当内容渲染完成后 + table.on('post-body.bs.table', function (e, settings, json, xhr) { + //默认隐藏所有子节点 + //$("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").hide(); + //$(".btn-node-sub.disabled[data-pid!=0]").closest("tr").hide(); + + //显示隐藏子节点 + $(".btn-node-sub").off("click").on("click", function (e) { + var status = $(this).data("shown") || $("a.btn[data-pid='" + $(this).data("id") + "']:visible").size() > 0 ? true : false; + $("a.btn[data-pid='" + $(this).data("id") + "']").each(function () { + $(this).closest("tr").toggle(!status); + if (!$(this).hasClass("disabled")) { + $(this).trigger("click"); + } + }); + $(this).data("shown", !status); + return false; + }); + + }); + //展开隐藏一级 + $(document.body).on("click", ".btn-toggle", function (e) { + $("a.btn[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide(); + var that = this; + var show = $("i", that).hasClass("fa-chevron-down"); + $("i", that).toggleClass("fa-chevron-down", !show); + $("i", that).toggleClass("fa-chevron-up", show); + $("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").toggle(show); + $(".btn-node-sub[data-pid=0]").data("shown", show); + }); + //展开隐藏全部 + $(document.body).on("click", ".btn-toggle-all", function (e) { + var that = this; + var show = $("i", that).hasClass("fa-plus"); + $("i", that).toggleClass("fa-plus", !show); + $("i", that).toggleClass("fa-minus", show); + $(".btn-node-sub.disabled[data-pid!=0]").closest("tr").toggle(show); + $(".btn-node-sub[data-pid!=0]").data("shown", show); + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + }, + add: function () { + Controller.api.bindevent(); + $("input[name='row[type]'][value=list]").trigger("click"); + $("select[name='row[model_id]']").trigger("change"); + }, + edit: function () { + Controller.api.bindevent(); + $("input[name='row[type]']:checked").trigger("fa.event.typeupdated", "edit"); + }, + admin: function () { + + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'cms/channel/admin', + dragsort_url: '', + table: 'channel_admin', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'weigh', + pagination: false, + escape: false, + columns: [ + [ + { + field: 'superadmin', title: __('Type'), formatter: function (value, row, index) { + return row.superadmin ? "超级管理员" : "普通管理员"; + } + }, + {field: 'username', title: __('Username')}, + {field: 'nickname', title: __('Nickname')}, + {field: 'channels', title: __('Channels')}, + { + field: 'operate', + title: __('Operate'), + table: table, + formatter: Table.api.formatter.buttons, + buttons: [ + { + name: 'authorization', + text: __('Authorization'), + classname: 'btn btn-xs btn-success btn-authorization', + icon: 'fa fa-list', + url: 'cms/channel/admin/act/authorization', + visible: function (row) { + return !row.superadmin; + }, + }, + { + name: 'remove', + text: __('Remove'), + classname: 'btn btn-xs btn-danger btn-remove btn-ajax', + icon: 'fa fa-times', + url: 'cms/channel/admin/act/remove', + visible: function (row) { + return row.channels > 0; + }, + confirm: __('Are you sure you want to remove this item?'), + success: function (ret) { + $(".btn-refresh").trigger("click"); + } + } + ] + } + ] + ], + search: false, + commonSearch: false + }); + // 为表格绑定事件 + Table.api.bindevent(table); + + require(['jstree'], function () { + //全选和展开 + $(document).on("click", "#checkall", function () { + $("#channeltree").jstree($(this).prop("checked") ? "check_all" : "uncheck_all"); + }); + $(document).on("click", "#expandall", function () { + $("#channeltree").jstree($(this).prop("checked") ? "open_all" : "close_all"); + }); + + // 点击授权 + $(document).on("click", ".btn-authorization", function () { + var row = Table.api.getrowbyindex(table, $(this).data("row-index")); + Fast.api.ajax($(this).attr("href"), function (data, ret) { + Layer.open({ + id: "auth", + type: 1, + title: __('Authorization'), + btn: [__('Save')], + area: ["600px", "400px"], + content: Template("authorizationtpl", {}), + success: function () { + $('#channeltree').jstree({ + "themes": { + "stripes": true + }, + "checkbox": { + "keep_selected_style": false, + }, + "types": { + "channel": { + "icon": "fa fa-th", + }, + "list": { + "icon": "fa fa-list", + }, + "link": { + "icon": "fa fa-link", + }, + "disabled": { + "check_node": false, + "uncheck_node": false + } + }, + 'plugins': ["types", "checkbox"], + "core": { + "multiple": true, + 'check_callback': true, + "data": data + } + }); + }, + yes: function (index, o) { + var selected = $("#channeltree", o).jstree("get_selected"); + if (selected.length <= 0) { + Layer.msg(__('You must choose at least one channel'), {id: "aaafd"}); + } else { + Fast.api.ajax({ + url: "cms/channel/admin/act/save/ids/" + row.id, + data: {"ids": selected.join(",")} + }, function (data, ret) { + $(".btn-refresh").trigger("click"); + Layer.close(index); + }); + } + } + }); + return false; + }); + return false; + }); + }); + }, + api: { + formatter: { + title: function (value, row, index) { + return !row.ismenu || row.status == 'hidden' ? "" + value + "" : value; + }, + name: function (value, row, index) { + return !row.ismenu || row.status == 'hidden' ? "" + value + "" : value; + }, + icon: function (value, row, index) { + return ''; + }, + subnode: function (value, row, index) { + return ''; + } + }, + bindevent: function () { + Form.api.bindevent($("form[role=form]")); + + } + } + }; + return Controller; +}); -- Gitee