From 4bf358de6bd7c0ba735e80449a118ee5096f3f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E9=92=8A?= Date: Tue, 18 Nov 2025 10:07:09 +0800 Subject: [PATCH] =?UTF-8?q?Git=20=E6=96=87=E4=BB=B6=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/guildadmin/common.php | 1 + application/guildadmin/config.php | 6 + application/guildadmin/controller/Admin.php | 755 ++++++++++++++++++ .../guildadmin/controller/GuildData.php | 220 +++++ application/guildadmin/controller/Index.php | 176 ++++ application/guildadmin/controller/Room.php | 167 ++++ .../guildadmin/controller/Statistical.php | 142 ++++ .../guildadmin/controller/SystemMessage.php | 70 ++ application/guildadmin/controller/User.php | 320 ++++++++ application/guildadmin/lang/zh-cn.php | 102 +++ application/guildadmin/lang/zh-cn/common.php | 3 + application/guildadmin/lang/zh-cn/user.php | 39 + application/guildadmin/library/Auth.php | 620 ++++++++++++++ .../guildadmin/library/ExceptionHandle.php | 37 + application/guildadmin/model/Admin.php | 63 ++ application/guildadmin/model/AdminLog.php | 118 +++ application/guildadmin/model/AuthGroup.php | 22 + .../guildadmin/model/AuthGroupAccess.php | 11 + application/guildadmin/model/AuthRule.php | 63 ++ 19 files changed, 2935 insertions(+) create mode 100644 application/guildadmin/common.php create mode 100644 application/guildadmin/config.php create mode 100644 application/guildadmin/controller/Admin.php create mode 100644 application/guildadmin/controller/GuildData.php create mode 100644 application/guildadmin/controller/Index.php create mode 100644 application/guildadmin/controller/Room.php create mode 100644 application/guildadmin/controller/Statistical.php create mode 100644 application/guildadmin/controller/SystemMessage.php create mode 100644 application/guildadmin/controller/User.php create mode 100644 application/guildadmin/lang/zh-cn.php create mode 100644 application/guildadmin/lang/zh-cn/common.php create mode 100644 application/guildadmin/lang/zh-cn/user.php create mode 100644 application/guildadmin/library/Auth.php create mode 100644 application/guildadmin/library/ExceptionHandle.php create mode 100644 application/guildadmin/model/Admin.php create mode 100644 application/guildadmin/model/AdminLog.php create mode 100644 application/guildadmin/model/AuthGroup.php create mode 100644 application/guildadmin/model/AuthGroupAccess.php create mode 100644 application/guildadmin/model/AuthRule.php diff --git a/application/guildadmin/common.php b/application/guildadmin/common.php new file mode 100644 index 0000000..b3d9bbc --- /dev/null +++ b/application/guildadmin/common.php @@ -0,0 +1 @@ + '\\app\\guildadmin\\library\\ExceptionHandle', +]; diff --git a/application/guildadmin/controller/Admin.php b/application/guildadmin/controller/Admin.php new file mode 100644 index 0000000..1d40f3b --- /dev/null +++ b/application/guildadmin/controller/Admin.php @@ -0,0 +1,755 @@ +model = model('guildadmin/Admin'); + $this->authRuleModel = model('guildadmin/AuthRule'); + $this->authGroup = model('guildadmin/AuthGroup'); + $this->guildId = Session::get('guild_id'); + $this->childrenAdminIds = $this->auth->getChildrenAdminIds($this->auth->isSuperAdmin()); + $this->childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin()); + $groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->where('guild_id', $this->guildId)->select())->toArray(); + Tree::instance()->init($groupList); + $groupdata = []; + if ($this->auth->isSuperAdmin()) { + $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0)); + foreach ($result as $k => $v) { + $groupdata[$v['id']] = $v['name']; + } + } else { + $result = []; + $groups = $this->auth->getGroups(); + 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; + } + $this->assignconfig("admin", ['id' => $this->auth->id]); + + $this->childrenGroupIds = $this->auth->getChildrenGroupIds(true); + $groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->where('guild_id', $this->guildId)->select())->toArray(); + Tree::instance()->init($groupList); + $groupList = []; + if ($this->auth->isSuperAdmin()) { + $groupList = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0)); + } else { + $groups = $this->auth->getGroups(); + $groupIds = []; + foreach ($groups as $m => $n) { + if (in_array($n['id'], $groupIds) || in_array($n['pid'], $groupIds)) { + continue; + } + $groupList = array_merge($groupList, Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['pid']))); + foreach ($groupList as $index => $item) { + $groupIds[] = $item['id']; + } + } + } + $groupName = []; + foreach ($groupList as $k => $v) { + $groupName[$v['id']] = $v['name']; + } + $this->grouplist = $groupList; + $this->groupdata = $groupName; + $this->assignconfig("admin", ['id' => $this->auth->id, 'group_ids' => $this->auth->getGroupIds()]); + + $ruleList = db::name("vs_guild_admin_auth")->field('type,condition,remark,createtime,updatetime', true)->order('weigh DESC,id ASC')->select(); + foreach ($ruleList as $k => &$v) { + $v['title'] = __($v['title']); + } + + unset($v); + Tree::instance()->init($ruleList); + $this->rulelist = Tree::instance()->getTreeArray(0); + $ruledata = [0 => __('None')]; + foreach ($this->rulelist as $k => &$v) { + if (!$v['ismenu']) { + continue; + } + $ruledata[$v['id']] = $v['title']; + unset($v['spacer']); + } + unset($v); + } + + /** + * 权限列表 + */ + public function auth_index() + { + $ruleList = db::name("vs_guild_admin_auth")->field('type,condition,remark,createtime,updatetime', true)->order('weigh DESC,id ASC')->select(); + foreach ($ruleList as $k => &$v) { + $v['title'] = __($v['title']); + } + unset($v); + Tree::instance()->init($ruleList); + $ruleList = Tree::instance()->getTreeArray(0); + $ruledata = [0 => __('None')]; + foreach ($ruleList as $k => &$v) { + if (!$v['ismenu']) { + continue; + } + $ruledata[$v['id']] = $v['title']; + unset($v['spacer']); + } + unset($v); + $list = $ruleList; + $total = count($ruleList); + $result = array("total" => $total, "rows" => $list); + return V(1,"菜单规则列表", $result); + } + /** + * 权限添加 + */ + public function auth_add() + { + if ($this->request->isPost()) { + $params = $this->request->post(); + if ($params) { + if (!$params['ismenu'] && !$params['pid']) { + return V(0,'非菜单规则节点必须有父级', null); + } + $result = $this->authRuleModel->validate('app\admin\validate\AuthRule')->save($params); + if ($result === false) { + return V(0,'操作失败', null); + } + return V(1,'操作成功', null); + } + return V(0,'操作失败', null); + } + return V(0,'操作失败', null); + } + /** + * 权限编辑 + */ + public function auth_edit($ids = NULL) + { + if ($this->request->isPost()) { + $params = $this->request->post(); + if ($params) { + if (!$params['ismenu'] && !$params['pid']) { + return V(0,'非菜单规则节点必须有父级', null); + } + if ($params['pid'] == $params['id']) { + return V(0,'父级不能是它自己', null); + } + if ($params['pid'] != $params['pid']) { + $childrenIds = Tree::instance()->init(collection(AuthRule::select())->toArray())->getChildrenIds($params['id']); + if (in_array($params['pid'], $childrenIds)) { + return V(0,'父组别不能是它的子组别', null); + } + } + //这里需要针对name做唯一验证 + $ruleValidate = \think\Loader::validate('app\admin\validate\AuthRule'); + $ruleValidate->rule([ + 'name' => 'require|unique:AuthRule,name,' . $params['id'], + ]); + $result = $this->authRuleModel->validate('app\admin\validate\AuthRule')->save($params, $params['id']); + if ($result === false) { + return V(0,'操作失败', null); + } + return V(1,'操作成功', null); + } + return V(0,'操作失败', null); + } + } + + /* + * 权限详情 + */ + public function auth_detail(){ + $id = $this->request->param('id'); + $row = $this->authRuleModel->get($id); + if (!$row) { + return V(0,'操作失败', null); + } + return V(1,"详情", $row); + } + + /** + * 权限删除 + */ + public function auth_del($ids = "") + { + $ids = input('ids', ''); + if ($ids) { + $delIds = []; + foreach (explode(',', $ids) as $k => $v) { + $delIds = array_merge($delIds, Tree::instance()->getChildrenIds($v, true)); + } + $delIds = array_unique($delIds); + $count = $this->authRuleModel->where('id', 'in', $delIds)->delete(); + if ($count) { + Cache::rm('__guild_menu__'); + return V(1,'操作成功', null);return V(1,'操作成功', null); + } + } + return V(0,'操作失败', null); + } + /* + * 菜单接口 + */ + public function menus(){ + $ruleList = Tree::instance()->getTreeArray(0); + $ruleList = $this->getTree($ruleList,['title','url','name','icon','extend']); + return V(1,"系统菜单接口", $ruleList); + } + + public function getTree($ruleList,$fieldData=[]){ + $ruledata = []; + $i= 0; + foreach ($ruleList as $k => &$v) { + if (!$v['ismenu']) { + continue; + } + if(!$this->auth->check($v['name'])){ + continue; + } + foreach ($fieldData as $key => $value) { + $ruledata[$i][$value] = $v[$value]; + } + if(!empty($v['childlist'])){ + $ruledata[$i]['childlist'] = $this->getTree($v['childlist'],$fieldData); + if(empty($ruledata[$i]['childlist'])){ + unset($ruledata[$i]['childlist']); + } + } + $i++; + } + return $ruledata; + } + + + /** + * 角色列表 + */ + public function role_index() + { + $list = $this->grouplist; + $total = count($list); + $result = array("total" => $total, "list" => $list); + return V(1,"角色管理列表", $result); + } + /** + * 角色添加 + */ + public function role_add() + { + if ($this->request->isPost()) { + $params = $this->request->post(); + $params['rules'] = explode(',', $params['rules']); + if (!in_array($params['pid'], $this->childrenGroupIds)) { + return V(0,'请选择正确的父角色', null); + } + $parentmodel = model("guildadmin/AuthGroup")->get($params['pid']); + if (!$parentmodel) { + return V(0,'请选择正确的父角色', null); + } + // 父级别的规则节点 + $parentrules = explode(',', $parentmodel->rules); + // 当前组别的规则节点 + $currentrules = $this->auth->getRuleIds(); + $rules = $params['rules']; + // 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限 + $rules = in_array('*', $parentrules) ? $rules : array_intersect($parentrules, $rules); + // 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限 + $rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules); + $params['rules'] = implode(',', $rules); + if ($params) { + $params['guild_id'] = $this->guildId; + $this->authGroup->create($params); + return V(1,"成功", null); + } + return V(0,'操作失败', null); + } + return V(0,'操作失败', null); + } + /** + * 角色编辑 + */ + public function role_edit($ids = null) + { + $params = $this->request->post(); + $id = $params['id']; + if (!in_array($id, $this->childrenGroupIds)) { + return V(0,'你没有权限访问', null); + } + $row = $this->authGroup->get(['id' => $id]); + if (!$row) { + return V(0,'角色不存在', null); + } + if ($this->request->isPost()) { + //父节点不能是非权限内节点 + if (!in_array($params['pid'], $this->childrenGroupIds)) { + return V(0,'请选择正确的父角色', null); + } + // 父节点不能是它自身的子节点或自己本身 + if (in_array($params['pid'], Tree::instance()->getChildrenIds($row->id, true))) { + return V(0,'父节点不能是它自身的子节点或自己本身', null); + } + $params['rules'] = explode(',', $params['rules']); + + $parentmodel = model("guildadmin/AuthGroup")->get($params['pid']); + if (!$parentmodel) { + return V(0,'请选择正确的父角色', null); + } + // 父级别的规则节点 + $parentrules = explode(',', $parentmodel->rules); + // 当前组别的规则节点 + $currentrules = $this->auth->getRuleIds(); + $rules = $params['rules']; + // 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限 + $rules = in_array('*', $parentrules) ? $rules : array_intersect($parentrules, $rules); + // 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限 + $rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules); + $params['rules'] = implode(',', $rules); + if ($params) { + Db::startTrans(); + try { + $row->save($params); + $children_auth_groups = model("guildadmin/AuthGroup")->all(['id' => ['in', implode(',', (Tree::instance()->getChildrenIds($row->id)))]]); + $childparams = []; + foreach ($children_auth_groups as $key => $children_auth_group) { + $childparams[$key]['id'] = $children_auth_group->id; + $childparams[$key]['rules'] = implode(',', array_intersect(explode(',', $children_auth_group->rules), $rules)); + } + model("guildadmin/AuthGroup")->saveAll($childparams); + Db::commit(); + return V(1,"成功", null); + } catch (Exception $e) { + Db::rollback(); + return V(0,'操作失败', null); + } + } + return V(0,'操作失败', null); + } + } + + /* + * 角色详情 + */ + public function role_detail(){ + $id =input('id', 0); + if (!$id) { + return V(0,'参数错误', null); + } + $row = $this->authGroup->get($id); + if (!$row) { + return V(0,'数据不存在', null); + } + return V(1,'成功', $row); + + } + + /** + * 角色删除 + */ + public function role_del($ids = null) + { + $ids = $ids ? $ids : $this->request->post("ids"); + if (!$ids) { + return V(0,'参数错误', null); + } + $ids = explode(',', $ids); + $grouplist = $this->auth->getGroups(); + $group_ids = array_map(function ($group) { + return $group['id']; + }, $grouplist); + // 移除掉当前管理员所在组别 + $ids = array_diff($ids, $group_ids); + + // 循环判断每一个组别是否可删除 + $grouplist = $this->authGroup->where('id', 'in', $ids)->select(); + $groupaccessmodel = model('guildadmin/AuthGroupAccess'); + foreach ($grouplist as $k => $v) { + // 当前组别下有管理员 + $groupone = $groupaccessmodel->get(['group_id' => $v['id']]); + if ($groupone) { + $ids = array_diff($ids, [$v['id']]); + continue; + } + // 当前组别下有子组别 + $groupone = $this->authGroup->get(['pid' => $v['id']]); + if ($groupone) { + $ids = array_diff($ids, [$v['id']]); + continue; + } + } + $count = $this->authGroup->where('id', 'in', $ids)->delete(); + if ($count) { + return V(1,'成功', $count); + } + return V(0,'操作失败', null); + } + + /** + * 读取角色权限树 + * + * @internal + */ + public function role_tree() + { + $model = model('guildadmin/AuthGroup'); + $id = $this->request->post("id"); + $pid = $this->request->post("pid"); + $parentGroupModel = $model->get($pid); + + $currentGroupModel = null; + if ($id) { + $currentGroupModel = $model->get($id); + } + if (($pid || $parentGroupModel) && (!$id || $currentGroupModel)) { + $id = $id ? $id : null; + $ruleList = collection(model('guildadmin/AuthRule')->order('weigh', 'desc')->order('id', 'asc')->select())->toArray(); + //读取父类角色所有节点列表 + $parentRuleList = []; + if (in_array('*', explode(',', $parentGroupModel->rules))) { + $parentRuleList = $ruleList; + } else { + $parentRuleIds = explode(',', $parentGroupModel->rules); + foreach ($ruleList as $k => $v) { + if (in_array($v['id'], $parentRuleIds)) { + $parentRuleList[] = $v; + } + } + } + + $ruleTree = new Tree(); + $groupTree = new Tree(); + //当前所有正常规则列表 + $ruleTree->init($parentRuleList); + //角色组列表 + $groupTree->init(collection(model('guildadmin/AuthGroup')->where('id', 'in', $this->childrenGroupIds)->select())->toArray()); + + //读取当前角色下规则ID集合 + $adminRuleIds = $this->auth->getRuleIds(); + //是否是超级管理员 + $superadmin = $this->auth->isSuperAdmin(); + //当前拥有的规则ID集合 + $currentRuleIds = $id ? explode(',', $currentGroupModel->rules) : []; + + if (!$id || !in_array($pid, $this->childrenGroupIds) || !in_array($pid, $groupTree->getChildrenIds($id, true))) { + $parentRuleList = $ruleTree->getTreeList($ruleTree->getTreeArray(0), 'name'); + $hasChildrens = []; + foreach ($parentRuleList as $k => $v) { + if ($v['haschild']) { + $hasChildrens[] = $v['id']; + } + } + $parentRuleIds = array_map(function ($item) { + return $item['id']; + }, $parentRuleList); + $nodeList = []; + foreach ($parentRuleList as $k => $v) { + if (!$superadmin && !in_array($v['id'], $adminRuleIds)) { + continue; + } + if ($v['pid'] && !in_array($v['pid'], $parentRuleIds)) { + continue; + } + $state = array('selected' => in_array($v['id'], $currentRuleIds) && !in_array($v['id'], $hasChildrens)); + $nodeList[] = array('id' => $v['id'], 'parent' => $v['pid'] ? $v['pid'] : '#', 'text' => __($v['title']), 'type' => 'menu', 'state' => $state); + } + return V(1,'成功', $nodeList); + } else { + return V(0,'父组别不能是它的子组别或它自己', null); + } + } else { + return V(0,'角色未找到', null); + } + } + + /** + * 查看 + */ + public function admin_index() + { + //设置过滤方法 + $this->request->filter(['strip_tags', 'trim']); + //如果发送的来源是Selectpage,则转发到Selectpage + if ($this->request->request('keyField')) { + return $this->selectpage(); + } + $childrenGroupIds = $this->childrenGroupIds; + $groupName = AuthGroup::where('id', 'in', $childrenGroupIds) + ->column('id,name'); + $authGroupList = AuthGroupAccess::where('group_id', 'in', $childrenGroupIds) + ->field('uid,group_id') + ->select(); + + $adminGroupName = []; + foreach ($authGroupList as $k => $v) { + if (isset($groupName[$v['group_id']])) { + $adminGroupName[$v['uid']][$v['group_id']] = $groupName[$v['group_id']]; + } + } + $groups = $this->auth->getGroups(); + foreach ($groups as $m => $n) { + $adminGroupName[$this->auth->id][$n['id']] = $n['name']; + } + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); + $list = $this->model + ->where($where) + ->where('guild_id', $this->guildId) + ->where('id', 'in', $this->childrenAdminIds) + ->field(['password', 'salt', 'token'], true) + ->order($sort, $order) + ->paginate($limit); + + foreach ($list as $k => &$v) { + $groups = isset($adminGroupName[$v['id']]) ? $adminGroupName[$v['id']] : []; + $v['groups'] = implode(',', array_keys($groups)); + $v['groups_text'] = implode(',', array_values($groups)); + } + unset($v); + $result = array("total" => $list->total(), "rows" => $list->items()); + return V(1,"管理员列表", $result); + } + + /** + * 管理员添加 + * username + * email + * mobile + * nickname + * password + * status + */ + public function admin_add() + { + $params = $this->request->Post(); + if (empty($params)) { + return V(0,"参数错误", []); + } + if (!Validate::is($params['password'], '\S{6,30}')) { + return V(0,"密码长度必须在6-30位之间,不能包含空格", []); + } + $group = $params['group']; + unset($params['group']); + unset($params['__token__']); + $group = explode(',',$group); + if ($params) { + Db::startTrans(); + try { + $params['salt'] = Random::alnum(); + $params['password'] = $this->auth->getEncryptPassword($params['password'], $params['salt']); + $params['avatar'] = '/assets/img/avatar.png'; //设置新管理员默认头像。 + $params['guild_id'] = $this->guildId; + $result = $this->model->save($params); + if ($result === false) { + return V(0,"失败", []); + } + //过滤不允许的组别,避免越权 + $group = array_intersect($this->childrenGroupIds, $group); + if (!$group) { + return V(0,"失败", []); + } + + $dataset = []; + foreach ($group as $value) { + $dataset[] = ['uid' => $this->model->id, 'group_id' => $value]; + } + model('guildadmin/AuthGroupAccess')->saveAll($dataset); + Db::commit(); + return V(1,"添加成功", []); + } catch (\Exception $e) { + Db::rollback(); + return V(0,"失败", []); + $this->error($e->getMessage()); + } + } + } + + /** + * 管理员编辑 + */ + public function admin_edit($ids = null) + { + if ($this->request->isPost()) { + $params = $this->request->post(); + $group = $params['group']?? []; + unset($params['group']); + unset($params['__token__']); + if($group){ + $group = explode(',',$group); + } + if ($params) { + Db::startTrans(); + try { + if ($params['password']) { + if (!Validate::is($params['password'], '\S{6,30}')) { + return V(0,"密码长度必须在6-30位之间,不能包含空格", []); + } + $params['salt'] = Random::alnum(); + $params['password'] = $this->auth->getEncryptPassword($params['password'], $params['salt']); + } else { + unset($params['password'], $params['salt']); + } + //这里需要针对username和email做唯一验证 + $adminValidate = \think\Loader::validate('admin/Admin'); + $adminValidate->rule([ + 'username' => 'require|regex:\w{3,30}|unique:admin,username,' . $params['id'], + 'email' => 'require|email|unique:admin,email,' . $params['id'], + 'mobile' => 'regex:1[3-9]\d{9}|unique:admin,mobile,' . $params['id'], + 'password' => 'regex:\S{32}', + ]); + $result = $this->model->save($params, $params['id']); + if ($result === false) { + return V(0,"失败", []); + } + + if(!empty($group)){ + // 先移除所有权限 + model('guildadmin/AuthGroupAccess')->where('uid', $params['id'])->delete(); + // 过滤不允许的组别,避免越权 + $group = array_intersect($this->childrenGroupIds, $group); + if (!$group) { + return V(0,"失败", []); + } + + $dataset = []; + foreach ($group as $value) { + $dataset[] = ['uid' => $params['id'], 'group_id' => $value]; + } + model('guildadmin/AuthGroupAccess')->saveAll($dataset); + } + Db::commit(); + return V(1,"成功", []); + } catch (\Exception $e) { + Db::rollback(); + return V(0,"失败", []); + } + } + return V(0,"参数错误!", []); + }else{ + return V(0,"参数错误!", []); + } + + } + /* + * 管理员详情 + * + */ + public function admin_detail($ids = ""){ + $id = $this->request->get('id'); + if (!$id) { + return V(0,"未找到记录", []); + } + if (!in_array($id, $this->childrenAdminIds)) { + return V(0,"你没有权限访问", []); + } + $data = $this->model->where('id',$id)->find(); + $grouplist = $this->auth->getGroups($id); + $groupids = []; + foreach ($grouplist as $k => $v) { + $groupids[] = $v['id']; + } + $result = []; + $result['row'] = $data; + $result['groupids'] = $groupids; + return V(1,"管理员详情", $result); + } + /* + * 管理员状态修改 + */ + public function admin_change_status(){ + if (!$this->request->isPost()) { + return V(0,"失败", []); + } + $id = $this->request->post("id"); + if (empty($id)) { + return V(0,"失败", []); + } + if($id==1){ + return V(0,"超级管理员不能修改状态", []); + } + $status = $this->request->post("status"); + $data = []; + $data['status'] = $status; + $res = Db::name("vs_guild_admin")->where("id",$id)->update($data); + if ($res) { + return V(1,"成功", []); + }else{ + return V(0,"失败", []); + } + } + + /** + * 删除 + */ + public function admin_del($ids = "") + { + if (!$this->request->isPost()) { + return V(0,"失败", []); + } + $ids = $ids ? $ids : $this->request->post("id"); + 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('vs_guild_admin_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('guildadmin/AuthGroupAccess')->where('uid', 'in', $deleteIds)->delete(); + Db::commit(); + return V(1,"成功", []); + } catch (\Exception $e) { + Db::rollback(); + return V(0,"失败", []); + } + } + } + } + return V(0,"失败", []); + } +} diff --git a/application/guildadmin/controller/GuildData.php b/application/guildadmin/controller/GuildData.php new file mode 100644 index 0000000..b417eb5 --- /dev/null +++ b/application/guildadmin/controller/GuildData.php @@ -0,0 +1,220 @@ +guildId); + if(!$guild_id){ + return V(0,"公会ID不存在"); + } + $guild = Db::name($this->table_guild)->where('id',$guild_id)->find(); + if(!$guild){ + return V(0,"公会不存在"); + } + $guild_data = Db::name($this->table_guild_data)->where('guild_id',$guild_id)->find(); + //公会会长 + $guild_user = Db::name('user')->where('id',$guild['user_id'])->find(); + $return_data =[]; + $return_data ['company']['guild_name'] = $guild['guild_name'] ?? ''; + $return_data ['company']['company_name'] = $guild_data['company_name'] ?? ''; + $return_data ['company']['agreement'] = $guild_data['agreement'] ?? ''; + $return_data ['company']['guild_cover'] = $guild['cover'] ?? ''; + //负责人信息 + $return_data ['boss']['boss_name'] = $guild_data['boss_name'] ?? ''; + $return_data ['boss']['boss_mobile'] = $guild_data['boss_mobile'] ?? ''; + $return_data ['boss']['boss_user_code'] = $guild_user['user_code'] ?? ''; + //对公账号 + $return_data ['bank']['bank_name'] = $guild_data['bank_name'] ?? ''; + $return_data ['bank']['bank_num'] = $guild_data['bank_num'] ?? ''; + $return_data ['bank']['bank_img'] = $guild_data['bank_img'] ?? ''; + //扫描件 + $return_data ['scan']['business_license_img'] = $guild_data['business_license_img'] ?? ''; + $return_data ['scan']['id_card_1'] = $guild_data['id_card_1'] ?? ''; + $return_data ['scan']['id_card_2'] = $guild_data['id_card_2'] ?? ''; + + return V(1,"成功", $return_data); + } + + //公司信息修改 + public function company_update(){ + $guild_id = input('guild_id',$this->guildId); + if(!$guild_id){ + return V(0,"公会ID不存在"); + } + $guild = Db::name($this->table_guild)->where('id',$guild_id)->find(); + if(!$guild){ + return V(0,"公会不存在"); + } + $guild_data = Db::name($this->table_guild_data)->where('guild_id',$guild_id)->find(); + if(!$guild_data){ + return V(0,"公会资料不存在"); + } + $company_name = input('company_name', ''); + $agreement = input('agreement', ''); + $guild_cover = input('guild_cover', ''); + $data = [ + 'company_name' => $company_name, + 'agreement' => $agreement + ]; + if($guild_cover){ + db::name($this->table_guild)->where('id',$guild_id)->update(['cover' => $guild_cover]); + } + $ret = Db::name($this->table_guild_data)->where('guild_id',$guild_id)->update($data); + if($ret){ + return V(1,"修改成功"); + }else{ + return V(0,"修改失败"); + } + } + + //负责人信息修改 + public function boss_update(){ + $guild_id = input('guild_id',$this->guildId); + if(!$guild_id){ + return V(0,"公会ID不存在"); + } + $guild = Db::name($this->table_guild)->where('id',$guild_id)->find(); + if(!$guild){ + return V(0,"公会不存在"); + } + $guild_data = Db::name($this->table_guild_data)->where('guild_id',$guild_id)->find(); + if(!$guild_data){ + return V(0,"公会资料不存在"); + } + $boss_name = input('boss_name', ''); + $boss_mobile = input('boss_mobile', ''); + $data = [ + 'boss_name' => $boss_name, + 'boss_mobile' => $boss_mobile + ]; + $ret = Db::name($this->table_guild_data)->where('guild_id',$guild_id)->update($data); + if($ret){ + return V(1,"修改成功"); + }else{ + return V(0,"修改失败"); + } + } + //对公账号信息修改 + public function bank_update(){ + $guild_id = input('guild_id',$this->guildId); + if(!$guild_id){ + return V(0,"公会ID不存在"); + } + $guild = Db::name($this->table_guild)->where('id',$guild_id)->find(); + if(!$guild){ + return V(0,"公会不存在"); + } + $guild_data = Db::name($this->table_guild_data)->where('guild_id',$guild_id)->find(); + if(!$guild_data){ + return V(0,"公会资料不存在"); + } + $bank_name = input('bank_name', ''); + $bank_num = input('bank_num', ''); + $bank_img = input('bank_img', ''); + $data = [ + 'bank_name' => $bank_name, + 'bank_num' => $bank_num, + 'bank_img' => $bank_img + ]; + $ret = Db::name($this->table_guild_data)->where('guild_id',$guild_id)->update($data); + if($ret){ + return V(1,"修改成功"); + }else{ + return V(0,"修改失败"); + } + } + //扫描件信息修改 + public function scan_update(){ + $guild_id = input('guild_id',$this->guildId); + if(!$guild_id){ + return V(0,"公会ID不存在"); + } + $guild = Db::name($this->table_guild)->where('id',$guild_id)->find(); + if(!$guild){ + return V(0,"公会不存在"); + } + $guild_data = Db::name($this->table_guild_data)->where('guild_id',$guild_id)->find(); + if(!$guild_data){ + return V(0,"公会资料不存在"); + } + $business_license_img = input('business_license_img', ''); + $id_card_1 = input('id_card_1', ''); + $id_card_2 = input('id_card_2', ''); + $data = [ + 'business_license_img' => $business_license_img, + 'id_card_1' => $id_card_1, + 'id_card_2' => $id_card_2 + ]; + $ret = Db::name($this->table_guild_data)->where('guild_id',$guild_id)->update($data); + if($ret){ + return V(1,"修改成功"); + }else{ + return V(0,"修改失败"); + } + } + //后台密码修改 + public function password_update(){ + $guild_id = input('guild_id',$this->guildId); + if(!$guild_id){ + return V(0,"公会ID不存在"); + } + $guild_data = Db::name($this->table_guild_data)->where('guild_id',$guild_id)->find(); + if(!$guild_data){ + return V(0,"公会资料不存在"); + } + $password = input('password', ''); + if ($password) { + if (!Validate::is($password, '\S{6,30}')) { + return V(0,"密码长度必须在6-30位之间,不能包含空格", []); + } + $params['salt'] = Random::alnum(); + $params['password'] = $this->auth->getEncryptPassword($password, $params['salt']); + } + $ret = Db::name('vs_guild_admin')->where('guild_id',$guild_id)->update($params); + if($ret){ + $this->auth->logout(); + Hook::listen("admin_logout_after", $this->request); + return V(1,"修改成功"); + }else{ + return V(0,"修改失败"); + } + } + +} diff --git a/application/guildadmin/controller/Index.php b/application/guildadmin/controller/Index.php new file mode 100644 index 0000000..3bc9eb2 --- /dev/null +++ b/application/guildadmin/controller/Index.php @@ -0,0 +1,176 @@ +request->filter('trim,strip_tags,htmlspecialchars'); + } + /** + * 后台首页 + */ + public function index() + { + $guild_id = $this->guildId; + //昨天时间 + $tday = date("Y-m-d", strtotime("-1 day")); + $stime_input = input('search_stime',0); + $etime_input = input('search_etime',date("Y-m-d",strtotime($tday)+86400)); + $stime = $stime_input==0 ? strtotime($tday) : strtotime($stime_input); + $etime = strtotime($etime_input); + $return_data =[]; + //基础数据 + $guild_user = Db::name('vs_guild_user')->where([ + 'guild_id'=>$guild_id, + 'status'=>1, + ])->select(); + $return_data['room_num'] = 0;//房间数量 + $return_data['user_num'] = 0; //用户数量 + $rooms = []; + foreach ($guild_user as $key => $value) { + if($value['quit_time']>0 && $value['quit_time']<$stime && $value['quit_time']>$etime){ + continue; + } + if($value['createtime']>$etime){ + continue; + } + if($value['createtime']<$stime_input){ + continue; + } + if(!empty($value['room_id'])){ + $return_data['room_num']++; + $rooms[] = $value['room_id']; + } + $return_data['user_num']++; + } + //房间粉丝数 + $return_data['room_follow'] = 0; + $return_data['room_follow_new'] = 0; + $follow = Db::name('user_follow')->where([ + 'follow_id'=>['in',$rooms], + 'type'=>2, + 'createtime'=>['<',$etime], + ])->select(); + foreach ($follow as $key => $value) { + $return_data['room_follow']++; + if($value['createtime']>=$stime && $value['createtime']<$etime){ + $return_data['room_follow_new']++; + } + } + //刷礼物流水 + $return_data['all_money'] = db::name('vs_give_gift') + ->whereIn('from_id',$rooms) + ->where(['from'=>['in',[2,3,6]],'createtime'=>['<',$etime]]) + ->where(['createtime'=>['>',$stime_input]]) + ->sum('total_price'); + //礼物总分成 + $return_data['gift_money'] = db::name('vs_user_money_log')->where([ + 'room_id'=>['in',$rooms], + 'money_type'=>2, + 'change_type'=>11, + 'createtime'=>['<',$etime] + ])->where(['createtime'=>['>',$stime_input]])->sum('change_value'); + //主持分成 + $return_data['host_money'] = db::name('vs_user_money_log')->where([ + 'room_id'=>['in',$rooms], + 'money_type'=>2, + 'change_type'=>19, + 'createtime'=>['<',$etime] + ])->where(['createtime'=>['>',$stime_input]])->sum('change_value'); + //房主分成 + $return_data['room_owner_money'] = db::name('vs_user_money_log')->where([ + 'room_id'=>['in',$rooms], + 'money_type'=>2, + 'change_type'=>18, + 'createtime'=>['<',$etime] + ])->where(['createtime'=>['>',$stime_input]])->sum('change_value'); + + return V(1,"后台首页", $return_data); + } + + /** + * 管理员登录 + */ + public function login() + { + $url = $this->request->get('url', '', 'url_clean'); + $url = $url ?: 'index/index'; + if ($this->auth->isLogin()) { + return V(0,"已登录", null); + } + //保持会话有效时长,单位:小时 + $keeyloginhours = 24; + if ($this->request->isPost()) { + $username = $this->request->post('username'); + $password = $this->request->post('password', '', null); + $keeplogin = $this->request->post('keeplogin',0); + $rule = [ + 'username' => 'require|length:3,30', + 'password' => 'require|length:3,30', + ]; + $data = [ + 'username' => $username, + 'password' => $password, + ]; + $validate = new Validate($rule, [], ['username' => __('Username'), 'password' => __('Password'), 'captcha' => __('Captcha')]); + $result = $validate->check($data); + if (!$result) { + $this->error($validate->getError(), $url, ['token' => $this->request->token()]); + } +// AdminLog::setTitle(__('Login')); + $result = $this->auth->login($username, $password, $keeplogin ? $keeyloginhours * 3600 : 0); + if ($result === true) { + Hook::listen("admin_login_after", $this->request); + $admin = $this->get_admin_info(); + return V(1,"登录成功", ['__token__' => $this->request->token(), 'admin' => $admin]); + } else { + return V(0,"用户名或密码错误", null); + } + }else{ + return V(0,"用户名或密码错误", null); + } + } + /** + * 退出登录 + */ + public function logout() + { + if ($this->request->isPost()) { + $this->auth->logout(); + Hook::listen("admin_logout_after", $this->request); + return V(1,'退出成功', null); + }else{ + return V(0,'操作失败', null); + } + } + + /* + * 获取当前登录管理员信息 + */ + public function get_admin_info(){ + $admin_info = $this->auth->getUserInfo(); + $admin_info['ruleList'] = $this->auth->getRuleList(); + return $admin_info; + } + +} \ No newline at end of file diff --git a/application/guildadmin/controller/Room.php b/application/guildadmin/controller/Room.php new file mode 100644 index 0000000..d134f5c --- /dev/null +++ b/application/guildadmin/controller/Room.php @@ -0,0 +1,167 @@ +guildId; + $page = input('page', 1); + $page_limit = input('page_limit', 30); + $room_id = input('room_id',''); + $search_user_id = input('user_id',''); + $status = input('status',''); + $search_stime_str = input('search_stime',''); + $search_etime_str = input('search_etime',''); + $s_money_search = input('s_money_search',''); + $e_money_search = input('e_money_search',''); + + $where['a.guild_id'] = $guild_id; + $where['a.status'] = 1; + $where['a.room_id'] = ['>',0]; + if($room_id){ + if(is_numeric($room_id)){ + $where['b.room_number'] = $room_id; + }else{ + $where['b.room_name'] = ['like', '%'.$room_id.'%']; + } + } + if($search_user_id){ + $user_id = db::name('user')->where('user_code', $search_user_id)->value('id'); + $where['a.user_id'] = $user_id; + } + if($status){ + $where['room_status'] = $status; + } + $count = db::name($this->table_guild_user)->alias('a') + ->join('vs_room b', 'a.room_id = b.id', 'left')->where($where)->count(); + $lists = db::name($this->table_guild_user)->alias('a') + ->join('vs_room b', 'a.room_id = b.id', 'left') + ->field('a.*,b.room_name,b.room_number,b.room_cover,b.type_id,b.label_id,b.room_status') + ->where($where) + ->page($page, $page_limit) + ->select(); + $rum_lists = []; + //总流水 + $total_consumption = 0; + foreach ($lists as $k=>$v){ + $search_stime = $search_stime_str; + $search_etime = $search_etime_str; + if($search_stime!=""){ + if($search_stime!="" && $v['createtime'] < strtotime($search_stime)){ + $search_stime = $search_stime; + }else{ + $search_stime = date('Y-m-d H:i:s',$v['createtime']) ; + } + }else{ + $search_stime = $search_stime; + } + if($search_etime!=""){ + if($v['quit_time']){ + if($search_etime!="" && $v['quit_time'] > strtotime($search_etime)){ + $search_etime = $search_etime; + }else{ + $search_etime = date('Y-m-d H:i:s',$v['quit_time']); + } + }else{ + $search_etime = $search_etime; + } + }else{ + $search_etime = $search_etime; + } + $room_info = db::name('vs_room')->where(['id'=>$v['room_id']])->find(); + $rum_lists[$k]['id']=$v['id']; + $rum_lists[$k]['room_id']=$v['room_id']; + $rum_lists[$k]['room_code']= $v['room_number']; + //靓号 + $room_number = model('api/Decorate')->user_decorate_detail($v['room_id'], 7); + $rum_lists[$k]['room_number']= $room_number==$v['room_number'] ? '无' : $room_number; + //房主 + $room_user = db::name('user')->where(['id'=>$v['user_id']])->find(); + $rum_lists[$k]['room_user']= $room_user['user_code'] . '-' . $room_user['nickname']; + $rum_lists[$k]['room_name']=$room_info['room_name']?? ''; + $rum_lists[$k]['room_cover']=$room_info['room_cover']?? ''; + //房间分类 + $rum_lists[$k]['room_type']= db::name('vs_room_type')->where('id', $v['type_id'])->value('type_name')??''; + //房间标签 + $rum_lists[$k]['room_label']= db::name('vs_room_label')->where('id', $v['label_id'])->value('label_name')??''; + //房间粉丝 + $stime = $search_stime_str=="" ? strtotime(date('Y-m-d',time())) : strtotime($search_stime_str); + $etime = time(); + $rum_lists[$k]['follow_num'] = Db::name('user_follow')->where([ + 'follow_id'=>$v['room_id'], + 'type'=>2, + 'createtime'=>['<',$etime], + ])->count(); + $rum_lists[$k]['follow_num_new'] = Db::name('user_follow')->where([ + 'follow_id'=>$v['room_id'], + 'type'=>2, + 'createtime'=>['<',$etime], + ])->where('createtime', '>', $stime)->count(); + //房间状态 + $rum_lists[$k]['room_status']= $v['room_status']==1 ? '正常' : '封禁'; + //房间流水 + $rum_lists[$k]['consumption']= model('adminapi/Room')->getRoomFlow($v['room_id'],$search_stime,$search_etime); + $rum_lists[$k]['add_time'] = date('Y-m-d H:i:s',$v['createtime']); + $total_consumption += $rum_lists[$k]['consumption']; + + + } + usort($rum_lists, function($a, $b) { + return $b['consumption'] - $a['consumption']; + }); + //按流水查询 + if($s_money_search!="" && $e_money_search!=""){ + $rum_lists = array_filter($rum_lists, function($v) use ($s_money_search, $e_money_search) { + return $v['consumption'] >= $s_money_search && $v['consumption'] <= $e_money_search; + }); + } + //分页 + $rum_lists = array_slice($rum_lists, ($page-1)*$page_limit, $page_limit); + $return_data = [ + 'page' =>$page, + 'page_limit' => $page_limit, + 'total_consumption' => $total_consumption, + 'count' => $count, + 'lists' => $rum_lists + ]; + return V(1,"成功", $return_data); + } + +} diff --git a/application/guildadmin/controller/Statistical.php b/application/guildadmin/controller/Statistical.php new file mode 100644 index 0000000..1920804 --- /dev/null +++ b/application/guildadmin/controller/Statistical.php @@ -0,0 +1,142 @@ +guildId; + $page = input('page', 1); + $page_limit = input('page_limit', 30); + $search_user_id = input('user_id', ''); + $stime = input('stime', ''); + $etime = input('etime', ''); + $where = []; + $where['a.guild_id'] = $guild_id; + if ($search_user_id) { + $user_id = db::name('user')->where('user_code', $search_user_id)->value('id'); + $where['a.user_id'] = $user_id; + } + if ($stime) { + $where['a.create_time'] = ['>=', $stime]; + } + if ($etime) { + $where['a.create_time'] = ['<=', $etime]; + } + $count = Db::name($this->table_guild_user)->alias('a') + ->join('user b', 'a.user_id = b.id') + ->where($where) + ->where('a.status', 1)->count(); + $lists = Db::name($this->table_guild_user)->alias('a') + ->join('user b', 'a.user_id = b.id') + ->field('a.id,a.user_id,a.status,a.createtime,a.apply_time,b.user_code,b.nickname') + ->where($where) + ->where('a.status', 1) + ->order('a.id desc') + ->page($page, $page_limit) + ->select(); + $lists_data = []; + foreach ($lists as $key => $value) { + $lists_data[$key] = $value; + $lists_data[$key]['createtime'] = date('Y-m-d H:i:s', $value['createtime']); + } + $return_data = [ + 'page' =>$page, + 'page_limit' => $page_limit, + 'count' => $count, + 'lists' => $lists_data + ]; + return V(1,"成功", $return_data); + } + + //房间数据统计 + public function room_lists(){ + $guild_id = $this->guildId; + $page = input('page', 1); + $page_limit = input('page_limit', 30); + $search_room_id = input('room_id', ''); + $stime = input('stime', ''); + $etime = input('etime', ''); + $where = []; + $where['a.guild_id'] = $guild_id; + if ($search_room_id) { + $where['b.room_number'] = $search_room_id; + } + $search_stime = ''; + $search_etime = ''; + if ($stime) { + $where['a.create_time'] = ['>=', $stime]; + $search_stime = strtotime($stime); + } + if ($etime) { + $where['a.create_time'] = ['<=', $etime]; + $search_etime = strtotime($etime); + } + $count = Db::name($this->table_guild_user)->alias('a') + ->join('vs_room b', 'a.room_id = b.id') + ->where($where) + ->where('a.status', 1)->count(); + $lists = Db::name($this->table_guild_user)->alias('a') + ->join('vs_room b', 'a.room_id = b.id') + ->field('a.id,a.room_id,a.status,a.createtime,a.apply_time,b.room_number,b.room_name') + ->where($where) + ->where('a.status', 1) + ->order('a.id desc') + ->page($page, $page_limit) + ->select(); + $lists_data = []; + foreach ($lists as $key => $value) { + $lists_data[$key]['room_number'] = $value['room_number']; + $lists_data[$key]['room_name'] = $value['room_name']; + //送礼流水 + $lists_data[$key]['consumption']= model('adminapi/Room')->getRoomFlow($value['room_id'],$search_stime,$search_etime); + //绩效流水 + + //送礼人数 + $lists_data[$key]['gift_num'] = db::name('vs_give_gift')->where(['from_id'=>$value['room_id'],'from'=>2])->count(); + $lists_data[$key]['createtime'] = date('Y-m-d H:i:s', $value['createtime']); + } + $return_data = [ + 'page' =>$page, + 'page_limit' => $page_limit, + 'count' => $count, + 'lists' => $lists_data + ]; + return V(1,"成功", $return_data); + } +} diff --git a/application/guildadmin/controller/SystemMessage.php b/application/guildadmin/controller/SystemMessage.php new file mode 100644 index 0000000..371fe60 --- /dev/null +++ b/application/guildadmin/controller/SystemMessage.php @@ -0,0 +1,70 @@ +guildId; + $page = input('page', 1); + $page_limit = input('page_limit', 30); + $where['delete_time'] = 0; + $where['receiving_id'] = $guild_id; + $count = db::name('system_message')->where($where)->count(); + $lists = db::name('system_message')->where($where)->page($page, $page_limit)->select(); + + $lists_data =[]; + foreach ($lists as $key => $value) { + $lists_data[$key]['title'] = $value['title']; + $lists_data[$key]['content'] = $value['content']; + $lists_data[$key]['createtime'] = date('Y-m-d H:i:s', $value['createtime']); + $lists_data[$key]['type_name'] = $value['type'] == 1 ? '系统消息' : '官方公告'; + $lists_data[$key]['admin_name'] = db::name('admin')->where('id', $value['admin_id'])->value('nickname'); + //提醒方式:1 站内 2短信 + $lists_data[$key]['remind_type_str'] = $value['remind_type'] == 1 ? '站内' : '短信'; + + } + $return_data = [ + 'page' =>$page, + 'page_limit' => $page_limit, + 'count' => $count, + 'lists' => $lists_data + ]; + return V(1,"成功", $return_data); + } +} diff --git a/application/guildadmin/controller/User.php b/application/guildadmin/controller/User.php new file mode 100644 index 0000000..a09a107 --- /dev/null +++ b/application/guildadmin/controller/User.php @@ -0,0 +1,320 @@ +guildId; + $page = input('page', 1); + $page_limit = input('page_limit', 30); + $search = input('search',''); + $search_stime = input('search_stime',''); + $search_etime = input('search_etime',''); + $where = []; + if($search){ + //手机号 + if(preg_match('/^1[34578]\d{9}$/',$search)){ + $where['b.mobile'] = ['like',$search]; + }elseif(is_numeric($search) && strlen($search) <= 10){//ID 数字 + $user_id = db::name('user')->where('user_code', $search)->value('id'); + $where['a.user_id'] = ['like',$user_id]; + }else{ + $where['b.nickname'] = ['like',$search]; + } + } + if($search_stime){ + $where['a.createtime'] = ['>=',strtotime($search_stime)]; + } + if($search_etime){ + $where['a.createtime'] = ['<=',strtotime($search_etime)]; + } + $where['a.guild_id'] = $guild_id; + $where['a.status'] = 1; + $count = db::name('vs_guild_user')->alias('a')->join('user b', 'a.user_id = b.id')->where($where)->count(); + $list = db::name('vs_guild_user')->alias('a')->join('user b', 'a.user_id = b.id') + ->field('a.id, a.user_id, a.guild_id, a.room_id, b.status, b.nickname, b.avatar,b.user_code,b.sex,b.mobile,a.createtime,a.settlement_ratio') + ->where($where) + ->order('id desc') + ->page($page, $page_limit) + ->select(); + $list_data =[]; + foreach ($list as $k=>$item){ + $list_data[$k]['id'] = $item['id']; + $list_data[$k]['nickname'] = $item['user_code'].'-'.$item['nickname']; + if($item['sex']){ + $list_data[$k]['sex'] = $item['sex'] == 1 ? '男' : '女'; + }else{ + $list_data[$k]['sex'] = '未知'; + } + $list_data[$k]['mobile'] = $item['mobile']; + //粉丝数量 + $list_data[$k]['fans_num'] = db::name('user_follow')->where(['follow_id' => $item['user_id'],'type'=>1])->count(); + if($search_stime==""){ + $search_stime = strtotime(date('Y-m-d')); + } + if($search_etime==""){ + $search_etime = time(); + } + $list_data[$k]['fans_num_new'] = db::name('user_follow')->where(['follow_id' => $item['user_id'],'type'=>1]) + ->where('createtime', '>=', strtotime($search_stime)) + ->where('createtime', '<=', strtotime($search_etime)) + ->count(); + $list_data[$k]['settlement_ratio'] = $item['settlement_ratio']; + //最高比例 + //结算比例 + $configs = get_system_config(); + $list_data[$k]['max_settlement_ratio'] = $configs['room_gift_ratio'] + $configs['room_gift_guild_ratio']; + $list_data[$k]['createtime'] = date('Y-m-d H:i:s',$item['createtime']); + //状态 1正常,2禁止登录,0注销 + $list_data[$k]['status'] = $item['status']; + $list_data[$k]['status_text'] = $item['status'] == 1 ? '正常' : ($item['status'] == 2 ? '禁止登录' : '注销'); + } + $return_data =[ + 'page' => $page, + 'limit' => $page_limit, + 'count' => $count, + 'list' => $list_data + ]; + return V(1,"成功", $return_data); + } + //用户申请列表 + public function apply_list(){ + $guild_id = $this->guildId; + $page = input('page', 1); + $page_limit = input('page_limit', 30); + $search = input('search',''); + $search_stime = input('search_stime',''); + $search_etime = input('search_etime',''); + $where = []; + if($search){ + //手机号 + if(preg_match('/^1[34578]\d{9}$/',$search)){ + $where['b.mobile'] = ['like',$search]; + }elseif(is_numeric($search) && strlen($search) <= 10){//ID 数字 + $user_id = db::name('user')->where('user_code', $search)->value('id'); + $where['a.user_id'] = ['like',$user_id]; + }else{ + $where['b.nickname'] = ['like',$search]; + } + } + if($search_stime){ + $where['a.createtime'] = ['>=',strtotime($search_stime)]; + } + if($search_etime){ + $where['a.createtime'] = ['<=',strtotime($search_etime)]; + } + $where['a.guild_id'] = $guild_id; + $where['a.status'] = ['in','2,3']; + $count = db::name('vs_guild_user')->alias('a')->join('user b', 'a.user_id = b.id')->where($where)->count(); + $list = db::name('vs_guild_user')->alias('a')->join('user b', 'a.user_id = b.id') + ->field('a.id, a.user_id, a.guild_id, a.room_id, a.status, b.nickname, b.avatar,b.user_code,b.sex,b.mobile,a.createtime') + ->where($where) + ->order('id desc') + ->page($page, $page_limit) + ->select(); + $list_data =[]; + foreach ($list as $k=>$item){ + $list_data[$k]['id'] = $item['id']; + $list_data[$k]['nickname'] = $item['user_code'].'-'.$item['nickname']; + if($item['sex']){ + $list_data[$k]['sex'] = $item['sex'] == 1 ? '男' : '女'; + }else{ + $list_data[$k]['sex'] = '未知'; + } + $list_data[$k]['mobile'] = $item['mobile']; + //粉丝数量 + $list_data[$k]['fans_num'] = db::name('user_follow')->where(['follow_id' => $item['user_id'],'type'=>1])->count(); + if($search_stime==""){ + $search_stime = strtotime(date('Y-m-d')); + } + if($search_etime==""){ + $search_etime = time(); + } + $list_data[$k]['fans_num_new'] = db::name('user_follow')->where(['follow_id' => $item['user_id'],'type'=>1]) + ->where('createtime', '>=', strtotime($search_stime)) + ->where('createtime', '<=', strtotime($search_etime)) + ->count(); + $list_data[$k]['createtime'] = date('Y-m-d H:i:s',$item['createtime']); + $list_data[$k]['status'] = $item['status']; + $list_data[$k]['status_text'] = $item['status'] == 2 ? '待审核' : '审核失败'; + } + $return_data =[ + 'page' => $page, + 'limit' => $page_limit, + 'count' => $count, + 'list' => $list_data + ]; + return V(1,"成功", $return_data); + } + /* + * 同意,拒绝申请 + */ + public function operate_guild(){ + $id = input('id',''); + $status = input('status',''); + $remarks = input('remarks',''); + if(!$id){ + return V(0,"参数错误"); + } + $guild_user = db::name('vs_guild_user')->where(['id'=>$id])->find(); + if(!$guild_user){ + return V(0,"参数错误"); + } + $result = model('api/Guild')->operate_guild($id, $status,$remarks); + if($result['code'] == 1){ + return V(1,"操作成功"); + }else{ + return V(0,$result['msg']); + } + } + + //结算比例编辑 + public function settlement_ratio_edit(){ + $id = input('id',''); + $settlement_ratio = input('settlement_ratio',''); + if(!$id){ + return V(0,"参数错误"); + } + $guild_user = db::name('vs_guild_user')->where(['id'=>$id])->find(); + if(!$guild_user){ + return V(0,"参数错误"); + } + $configs = get_system_config(); + $ratio = $configs['room_gift_ratio'] + $configs['room_gift_guild_ratio']; + if($settlement_ratio > $ratio){ + return V(0,"最高比例不能超过".$ratio); + } + $result = db::name('vs_guild_user')->where(['id'=>$id])->update(['settlement_ratio'=>$settlement_ratio]); + if($result){ + return V(1,"操作成功"); + }else{ + return V(0,"操作失败"); + } + } + //踢出工会 + public function kick_out_user(){ + $id = input('id',''); + if(!$id){ + return V(0,"参数错误"); + } + $guild_user = db::name('vs_guild_user')->where(['id'=>$id])->find(); + $guild = db::name('vs_guild')->where(['id'=>$guild_user['guild_id']])->find(); + $result = model('api/Guild')->kick_out_guild($guild['user_id'],$guild_user['user_id'], $guild_user['guild_id']); + if($result['code'] == 1){ + return V(1,"操作成功"); + }else{ + return V(0,$result['msg']); + } + } + + //退出申请列表 + public function quit_apply_list(){ + $guild_id = $this->guildId; + $page = input('page', 1); + $page_limit = input('page_limit', 30); + $search = input('search',''); + $search_stime = input('search_stime',''); + $search_etime = input('search_etime',''); + $where = []; + if($search){ + //手机号 + if(preg_match('/^1[34578]\d{9}$/',$search)){ + $where['b.mobile'] = ['like',$search]; + }elseif(is_numeric($search) && strlen($search) <= 10){//ID 数字 + $user_id = db::name('user')->where('user_code', $search)->value('id'); + $where['a.user_id'] = ['like',$user_id]; + }else{ + $where['b.nickname'] = ['like',$search]; + } + } + if($search_stime){ + $where['a.createtime'] = ['>=',strtotime($search_stime)]; + } + if($search_etime){ + $where['a.createtime'] = ['<=',strtotime($search_etime)]; + } + $where['a.guild_id'] = $guild_id; + $list = db::name('vs_guild_user_quit_log')->alias('a')->join('user b', 'a.user_id = b.id') + ->field('a.id, a.user_id, a.guild_id,a.createtime,a.status,b.nickname, b.avatar,b.user_code,b.mobile,a.type') + ->where($where) + ->order('id desc') + ->page($page, $page_limit) + ->select(); + $count = db::name('vs_guild_user_quit_log')->alias('a')->join('user b', 'a.user_id = b.id')->where($where)->count(); + $list_data = []; + foreach ($list as $k => $item){ + $list_data[$k]['id'] = $item['id']; + $list_data[$k]['nickname'] = $item['user_code'].'-'.$item['nickname']; + $list_data[$k]['mobile'] = $item['mobile']; + $list_data[$k]['type'] = $item['type']==1?'主动退出':'付费退出'; + $list_data[$k]['createtime'] = date('Y-m-d H:i:s',$item['createtime']); + // 审核状态 0默认待审核 1已通过 2已拒绝 + $list_data[$k]['status'] = $item['status']; + $list_data[$k]['status_text'] = $item['status'] == 0 ? '待审核' : ($item['status'] == 1 ? '已通过' : '已拒绝'); + } + + $return_data =[ + 'page' => $page, + 'limit' => $page_limit, + 'count' => $count, + 'list' => $list_data + ]; + return V(1,"成功", $return_data); + } + //退出申请审核 + public function quit_apply_operate(){ + $id = input('id',''); + $status = input('status',1); + if(!$id){ + return V(0,"参数错误"); + } + $quit_apply = db::name('vs_guild_user_quit_log')->where(['id'=>$id])->find(); + if(!$quit_apply){ + return V(0,"参数错误"); + } + $result = model('api/Guild')->quit_apply_audit($quit_apply['user_id'],$id,$status); + if($result['code'] == 1){ + return V(1,"操作成功"); + }else{ + return V(0,$result['msg']); + } + } + +} diff --git a/application/guildadmin/lang/zh-cn.php b/application/guildadmin/lang/zh-cn.php new file mode 100644 index 0000000..e0531bf --- /dev/null +++ b/application/guildadmin/lang/zh-cn.php @@ -0,0 +1,102 @@ + '保持会话', + 'Username' => '用户名', + 'User id' => '会员ID', + 'Nickname' => '昵称', + 'Password' => '密码', + 'Sign up' => '注 册', + 'Sign in' => '登 录', + 'Sign out' => '退 出', + 'Guest' => '游客', + 'Welcome' => '%s,你好!', + 'Add' => '添加', + 'Edit' => '编辑', + 'Delete' => '删除', + 'Move' => '移动', + 'Name' => '名称', + 'Status' => '状态', + 'Weigh' => '权重', + 'Operate' => '操作', + 'Warning' => '温馨提示', + 'Default' => '默认', + 'Article' => '文章', + 'Page' => '单页', + 'OK' => '确定', + 'Cancel' => '取消', + 'Loading' => '加载中', + 'More' => '更多', + 'Normal' => '正常', + 'Hidden' => '隐藏', + 'Submit' => '提交', + 'Reset' => '重置', + 'Execute' => '执行', + 'Close' => '关闭', + 'Search' => '搜索', + 'Refresh' => '刷新', + 'First' => '首页', + 'Previous' => '上一页', + 'Next' => '下一页', + 'Last' => '末页', + 'None' => '无', + 'Home' => '主页', + 'Online' => '在线', + 'Logout' => '退出', + 'Profile' => '个人资料', + 'Index' => '首页', + 'Hot' => '热门', + 'Recommend' => '推荐', + 'Dashboard' => '控制台', + 'Code' => '编号', + 'Message' => '内容', + 'Line' => '行号', + 'File' => '文件', + 'Menu' => '菜单', + 'Type' => '类型', + 'Title' => '标题', + 'Content' => '内容', + 'Append' => '追加', + 'Memo' => '备注', + 'Parent' => '父级', + 'Params' => '参数', + 'Permission' => '权限', + 'Advance search' => '高级搜索', + 'Check all' => '选中全部', + 'Expand all' => '展开全部', + 'Begin time' => '开始时间', + 'End time' => '结束时间', + 'Create time' => '创建时间', + 'Flag' => '标志', + 'Please login first' => '请登录后操作', + 'Uploaded successful' => '上传成功', + 'You can upload up to %d file%s' => '你最多还可以上传%d个文件', + 'You can choose up to %d file%s' => '你最多还可以选择%d个文件', + 'Chunk file write error' => '分片写入失败', + 'Chunk file info error' => '分片文件错误', + 'Chunk file merge error' => '分片合并错误', + 'Chunk file disabled' => '未开启分片上传功能', + 'Cancel upload' => '取消上传', + 'Upload canceled' => '上传已取消', + 'No file upload or server upload limit exceeded' => '未上传文件或超出服务器上传限制', + 'Uploaded file format is limited' => '上传文件格式受限制', + 'Uploaded file is not a valid image' => '上传文件不是有效的图片文件', + 'Are you sure you want to cancel this upload?' => '确定取消上传?', + 'Remove file' => '移除文件', + 'You can only upload a maximum of %s files' => '你最多允许上传 %s 个文件', + 'You can\'t upload files of this type' => '不允许上传的文件类型', + 'Server responded with %s code' => '服务端响应(Code:%s)', + 'File is too big (%sMiB), Max filesize: %sMiB.' => '当前上传(%sM),最大允许上传文件大小:%sM', + 'Redirect now' => '立即跳转', + 'Operation completed' => '操作成功!', + 'Operation failed' => '操作失败!', + 'Unknown data format' => '未知的数据格式!', + 'Network error' => '网络错误!', + 'Advanced search' => '高级搜索', + 'Invalid parameters' => '未知参数', + 'No results were found' => '记录未找到', + 'Parameter %s can not be empty' => '参数%s不能为空', + 'You have no permission' => '你没有权限访问', + 'An unexpected error occurred' => '发生了一个意外错误,程序猿正在紧急处理中', + 'This page will be re-directed in %s seconds' => '页面将在 %s 秒后自动跳转', +]; diff --git a/application/guildadmin/lang/zh-cn/common.php b/application/guildadmin/lang/zh-cn/common.php new file mode 100644 index 0000000..0b67a5f --- /dev/null +++ b/application/guildadmin/lang/zh-cn/common.php @@ -0,0 +1,3 @@ + '会员中心', + 'Register' => '注册', + 'Login' => '登录', + 'Sign up successful' => '注册成功', + 'Username can not be empty' => '用户名不能为空', + 'Username must be 3 to 30 characters' => '用户名必须3-30个字符', + 'Username must be 6 to 30 characters' => '用户名必须6-30个字符', + 'Password can not be empty' => '密码不能为空', + 'Password must be 6 to 30 characters' => '密码必须6-30个字符', + 'Mobile is incorrect' => '手机格式不正确', + 'Username already exist' => '用户名已经存在', + 'Nickname already exist' => '昵称已经存在', + 'Email already exist' => '邮箱已经存在', + 'Mobile already exist' => '手机号已经存在', + 'Username is incorrect' => '用户名不正确', + 'Email is incorrect' => '邮箱不正确', + 'Account is locked' => '账户已经被锁定', + 'Password is incorrect' => '密码不正确', + 'Account is incorrect' => '账户不正确', + 'Account not exist' => '账户不存在', + 'Account can not be empty' => '账户不能为空', + 'Username or password is incorrect' => '用户名或密码不正确', + 'You are not logged in' => '你当前还未登录', + 'You\'ve logged in, do not login again' => '你已经存在,请不要重复登录', + 'Profile' => '个人资料', + 'Verify email' => '邮箱验证', + 'Change password' => '修改密码', + 'Captcha is incorrect' => '验证码不正确', + 'Logged in successful' => '登录成功', + 'Logout successful' => '退出成功', + 'Operation failed' => '操作失败', + 'Invalid parameters' => '参数不正确', + 'Change password failure' => '修改密码失败', + 'Change password successful' => '修改密码成功', + 'Reset password successful' => '重置密码成功', +]; diff --git a/application/guildadmin/library/Auth.php b/application/guildadmin/library/Auth.php new file mode 100644 index 0000000..46839f1 --- /dev/null +++ b/application/guildadmin/library/Auth.php @@ -0,0 +1,620 @@ + $username]); + if (!$admin) { + $this->setError('Username is incorrect'); + return false; + } + if ($admin['status'] == 'hidden') { + $this->setError('Admin is forbidden'); + return false; + } + if (Config::get('fastadmin.login_failure_retry') && $admin->loginfailure >= 10 && time() - $admin->updatetime < 86400) { + $this->setError('Please try again after 1 day'); + return false; + } + if ($admin->password != $this->getEncryptPassword($password, $admin->salt)) { + $admin->loginfailure++; + $admin->save(); + $this->setError('Password is incorrect'); + return false; + } + $admin->loginfailure = 0; + $admin->logintime = time(); + $admin->loginip = request()->ip(); + $admin->token = Random::uuid(); + $admin->save(); + Session::set("guild_admin", $admin->toArray()); + Session::set("guild_admin_id", $admin['id']); + Session::set("guild_admin.safecode", $this->getEncryptSafecode($admin)); + Cache::set("guild_admin_" . $admin->token, json_encode($admin->toArray()), 86400); + Session::set("guild_id", $admin['guild_id']); + $this->keeplogin($admin, $keeptime); + return true; + } + + /** + * 退出登录 + */ + public function logout() + { + $admin = Admin::get(intval($this->id)); + if ($admin) { + Cache::rm("guild_admin_" . $admin->token); + $admin->token = ''; + $admin->save(); + } + $this->logined = false; //重置登录状态 + Session::delete("guild_admin"); + Cookie::delete("guild_keeplogin"); + Cache::rm("guild_admin_" . $admin->token); + setcookie('guild_userinfo', '', $_SERVER['REQUEST_TIME'] - 3600, rtrim(url("/" . request()->module(), '', false), '/')); + return true; + } + + /** + * 自动登录 + * @return boolean + */ + public function autologin() + { + $keeplogin = Cookie::get('guild_keeplogin'); + if (!$keeplogin) { + return false; + } + list($id, $keeptime, $expiretime, $key) = explode('|', $keeplogin); + if ($id && $keeptime && $expiretime && $key && $expiretime > time()) { + $admin = Admin::get($id); + if (!$admin || !$admin->token) { + return false; + } + //token有变更 + if ($key != $this->getKeeploginKey($admin, $keeptime, $expiretime)) { + return false; + } + $ip = request()->ip(); + //IP有变动 + if ($admin->loginip != $ip) { + return false; + } + Session::set("guild_admin", $admin->toArray()); + Session::set("guild_admin.safecode", $this->getEncryptSafecode($admin)); + //刷新自动登录的时效 + $this->keeplogin($admin, $keeptime); + return true; + } else { + return false; + } + } + + /** + * 刷新保持登录的Cookie + * + * @param int $keeptime + * @return boolean + */ + protected function keeplogin($admin, $keeptime = 0) + { + if ($keeptime) { + $expiretime = time() + $keeptime; + $key = $this->getKeeploginKey($admin, $keeptime, $expiretime); + Cookie::set('guild_keeplogin', implode('|', [$admin['id'], $keeptime, $expiretime, $key]), $keeptime); + return true; + } + return false; + } + + /** + * 获取密码加密后的字符串 + * @param string $password 密码 + * @param string $salt 密码盐 + * @return string + */ + public function getEncryptPassword($password, $salt = '') + { + return md5(md5($password) . $salt); + } + + /** + * 获取密码加密后的自动登录码 + * @param string $password 密码 + * @param string $salt 密码盐 + * @return string + */ + public function getEncryptKeeplogin($params, $keeptime) + { + $expiretime = time() + $keeptime; + $key = md5(md5($params['id']) . md5($keeptime) . md5($expiretime) . $params['token'] . config('token.key')); + return implode('|', [$this->id, $keeptime, $expiretime, $key]); + } + + /** + * 获取自动登录Key + * @param $params + * @param $keeptime + * @param $expiretime + * @return string + */ + public function getKeeploginKey($params, $keeptime, $expiretime) + { + $key = md5(md5($params['id']) . md5($keeptime) . md5($expiretime) . $params['token'] . config('token.key')); + return $key; + } + + /** + * 获取加密后的安全码 + * @param $params + * @return string + */ + public function getEncryptSafecode($params) + { + return md5(md5($params['username']) . md5(substr($params['password'], 0, 6)) . config('token.key')); + } + + public function check($name, $uid = '', $relation = 'or', $mode = 'url') + { + $uid = $uid ? $uid : $this->id; + return parent::check($name, $uid, $relation, $mode); + } + + /** + * 检测当前控制器和方法是否匹配传递的数组 + * + * @param array $arr 需要验证权限的数组 + * @return bool + */ + public function match($arr = []) + { + $request = Request::instance(); + $arr = is_array($arr) ? $arr : explode(',', $arr); + if (!$arr) { + return false; + } + + $arr = array_map('strtolower', $arr); + // 是否存在 + if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) { + return true; + } + + // 没找到匹配 + return false; + } + + /** + * 检测是否登录 + * + * @return boolean + */ + public function isLogin($token = null) + { + if ($this->logined) { + return true; + } + $admin = Session::get('guild_admin'); + if (!$admin) { + $admin = Cache::get("guild_admin_" . $token); + $admin = json_decode($admin, true); + if($admin){ + Session::set("guild_admin", $admin); + Session::set("guild_admin_id", $admin['id']); +// Session::set("admin.safecode", $this->getEncryptSafecode($admin)); + } + } + if (!$admin) { + return false; + } + $my = Admin::get($admin['id']); + if (!$my) { + return false; + } + //校验安全码,可用于判断关键信息发生了变更需要重新登录 +// if (!isset($admin['safecode']) || $this->getEncryptSafecode($my) !== $admin['safecode']) { +// $this->logout(); +// return false; +// } + //判断是否同一时间同一账号只能在一个地方登录 + if (Config::get('fastadmin.login_unique')) { + if ($my['token'] != $admin['token']) { + $this->logout(); + return false; + } + } + //判断管理员IP是否变动 + if (Config::get('guild.loginip_check')) { + if (!isset($admin['loginip']) || $admin['loginip'] != request()->ip()) { + $this->logout(); + return false; + } + } + $this->logined = true; + return true; + } + + /** + * 获取当前请求的URI + * @return string + */ + public function getRequestUri() + { + return $this->requestUri; + } + + /** + * 设置当前请求的URI + * @param string $uri + */ + public function setRequestUri($uri) + { + $this->requestUri = $uri; + } + + public function getGroups($uid = null) + { + $uid = is_null($uid) ? $this->id : $uid; +// return parent::getGroups($uid); + $user_groups = Db::name('vs_guild_admin_auth_group_access') + ->alias('aga') + ->join('fa_vs_guild_admin_auth_group ag', 'aga.group_id = ag.id', 'LEFT') + ->field('aga.uid,aga.group_id,ag.id,ag.pid,ag.name,ag.rules') + ->where("aga.uid='{$uid}' and ag.status='normal'") + ->where('ag.guild_id', Session::get('guild_id')) + ->select(); + $groups[$uid] = $user_groups ?: []; + return $groups[$uid]; + } + + public function getRuleList($uid = null) + { + $uid = is_null($uid) ? $this->id : $uid; + return parent::getRuleList($uid); + } + + public function getUserInfo($uid = null) + { + $uid = is_null($uid) ? $this->id : $uid; + + return $uid != $this->id ? Admin::get(intval($uid)) : Session::get('guild_admin'); + } + + public function getRuleIds($uid = null) + { + $uid = is_null($uid) ? $this->id : $uid; + // 执行查询 + if($uid==1){ + return parent::getRuleIds($uid); + }else{ + $user_groups = Db::name('vs_guild_admin_auth_group_access') + ->alias('aga') + ->join('fa_vs_guild_admin_auth_group ag', 'aga.group_id = ag.id', 'LEFT') + ->field('aga.uid,aga.group_id,ag.id,ag.pid,ag.name,ag.rules') + ->where("aga.uid='{$uid}' and ag.status='normal'") + ->where('ag.guild_id', Session::get('guild_id')) + ->select(); + $groups[$uid] = $user_groups ?: []; + $ids = []; //保存用户所属用户组设置的所有权限规则id + foreach ($groups[$uid] as $g) { + $ids = array_merge($ids, explode(',', trim($g['rules'], ','))); + } + $ids = array_unique($ids); + return $ids; + } + } + + public function isSuperAdmin() + { + return in_array('*', $this->getRuleIds()) ? true : false; + } + + /** + * 获取管理员所属于的分组ID + * @param int $uid + * @return array + */ + public function getGroupIds($uid = null) + { + $groups = $this->getGroups($uid); + $groupIds = []; + foreach ($groups as $K => $v) { + $groupIds[] = (int)$v['group_id']; + } + return $groupIds; + } + + /** + * 取出当前管理员所拥有权限的分组 + * @param boolean $withself 是否包含当前所在的分组 + * @return array + */ + public function getChildrenGroupIds($withself = false) + { + //取出当前管理员所有的分组 + $groups = $this->getGroups(); + $groupIds = array_column($groups, 'id'); + $originGroupIds = $groupIds; + foreach ($groups as $k => $v) { + if (in_array($v['pid'], $originGroupIds)) { + $groupIds = array_diff($groupIds, [$v['id']]); + unset($groups[$k]); + } + } + // 取出所有分组 + $groupList = \app\guildadmin\model\AuthGroup::where($this->isSuperAdmin() ? '1=1' : ['status' => 'normal'])->where('guild_id', Session::get('guild_id'))->select(); + $objList = []; + foreach ($groups as $k => $v) { + if ($v['rules'] === '*') { + $objList = $groupList; + break; + } + // 取出包含自己的所有子节点 + $childrenList = Tree::instance()->init($groupList, 'pid')->getChildren($v['id'], true); + $obj = Tree::instance()->init($childrenList, 'pid')->getTreeArray($v['pid']); + $objList = array_merge($objList, Tree::instance()->getTreeList($obj)); + } + $childrenGroupIds = []; + foreach ($objList as $k => $v) { + $childrenGroupIds[] = $v['id']; + } + if (!$withself) { + $childrenGroupIds = array_diff($childrenGroupIds, $groupIds); + } + return $childrenGroupIds; + } + + /** + * 取出当前管理员所拥有权限的管理员 + * @param boolean $withself 是否包含自身 + * @return array + */ + public function getChildrenAdminIds($withself = false) + { + $childrenAdminIds = []; + if (!$this->isSuperAdmin()) { + $groupIds = $this->getChildrenGroupIds(false); + $childrenAdminIds = \app\guildadmin\model\AuthGroupAccess::where('group_id', 'in', $groupIds) + ->column('uid'); + } else { + //超级管理员拥有所有人的权限 + $childrenAdminIds = Admin::where('guild_id', Session::get('guild_id'))->column('id'); + } + + if ($withself) { + if (!in_array($this->id, $childrenAdminIds)) { + $childrenAdminIds[] = $this->id; + } + } else { + $childrenAdminIds = array_diff($childrenAdminIds, [$this->id]); + } + return $childrenAdminIds; + } + + /** + * 获得面包屑导航 + * @param string $path + * @return array + */ + public function getBreadCrumb($path = '') + { + if ($this->breadcrumb || !$path) { + return $this->breadcrumb; + } + $titleArr = []; + $menuArr = []; + $urlArr = explode('/', $path); + foreach ($urlArr as $index => $item) { + $pathArr[implode('/', array_slice($urlArr, 0, $index + 1))] = $index; + } + if (!$this->rules && $this->id) { + $this->getRuleList(); + } + foreach ($this->rules as $rule) { + if (isset($pathArr[$rule['name']])) { + $rule['title'] = __($rule['title']); + $rule['url'] = url($rule['name']); + $titleArr[$pathArr[$rule['name']]] = $rule['title']; + $menuArr[$pathArr[$rule['name']]] = $rule; + } + } + ksort($menuArr); + $this->breadcrumb = $menuArr; + return $this->breadcrumb; + } + + /** + * 获取左侧和顶部菜单栏 + * + * @param array $params URL对应的badge数据 + * @param string $fixedPage 默认页 + * @return array + */ + public function getSidebar($params = [], $fixedPage = 'dashboard') + { + // 边栏开始 + Hook::listen("admin_sidebar_begin", $params); + $colorArr = ['red', 'green', 'yellow', 'blue', 'teal', 'orange', 'purple']; + $colorNums = count($colorArr); + $badgeList = []; + $module = request()->module(); + // 生成菜单的badge + foreach ($params as $k => $v) { + $url = $k; + if (is_array($v)) { + $nums = $v[0] ?? 0; + $color = $v[1] ?? $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums]; + $class = $v[2] ?? 'label'; + } else { + $nums = $v; + $color = $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums]; + $class = 'label'; + } + //必须nums大于0才显示 + if ($nums) { + $badgeList[$url] = '' . $nums . ''; + } + } + + // 读取管理员当前拥有的权限节点 + $userRule = $this->getRuleList(); + $selected = $referer = []; + $refererUrl = Session::get('referer'); + // 必须将结果集转换为数组 + $ruleList = collection(\app\guildadmin\model\AuthRule::where('status', 'normal') + ->where('ismenu', 1) + ->order('weigh', 'desc') + ->cache("__menu__") + ->select())->toArray(); + $indexRuleList = \app\guildadmin\model\AuthRule::where('status', 'normal') + ->where('ismenu', 0) + ->where('name', 'like', '%/index') + ->column('name,pid'); + $pidArr = array_unique(array_filter(array_column($ruleList, 'pid'))); + foreach ($ruleList as $k => &$v) { + if (!in_array(strtolower($v['name']), $userRule)) { + unset($ruleList[$k]); + continue; + } + $indexRuleName = $v['name'] . '/index'; + if (isset($indexRuleList[$indexRuleName]) && !in_array($indexRuleName, $userRule)) { + unset($ruleList[$k]); + continue; + } + $v['icon'] = $v['icon'] . ' fa-fw'; + $v['url'] = isset($v['url']) && $v['url'] ? $v['url'] : '/' . $module . '/' . $v['name']; + $v['badge'] = $badgeList[$v['name']] ?? ''; + $v['title'] = __($v['title']); + $v['url'] = preg_match("/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i", $v['url']) ? $v['url'] : url($v['url']); + $v['menuclass'] = in_array($v['menutype'], ['dialog', 'ajax']) ? 'btn-' . $v['menutype'] : ''; + $v['menutabs'] = !$v['menutype'] || in_array($v['menutype'], ['default', 'addtabs']) ? 'addtabs="' . $v['id'] . '"' : ''; + $selected = $v['name'] == $fixedPage ? $v : $selected; + $referer = $v['url'] == $refererUrl ? $v : $referer; + } + $lastArr = array_unique(array_filter(array_column($ruleList, 'pid'))); + $pidDiffArr = array_diff($pidArr, $lastArr); + foreach ($ruleList as $index => $item) { + if (in_array($item['id'], $pidDiffArr)) { + unset($ruleList[$index]); + } + } + if ($selected == $referer) { + $referer = []; + } + + $select_id = $referer ? $referer['id'] : ($selected ? $selected['id'] : 0); + $menu = $nav = ''; + $showSubmenu = config('fastadmin.show_submenu'); + if (Config::get('fastadmin.multiplenav')) { + $topList = []; + foreach ($ruleList as $index => $item) { + if (!$item['pid']) { + $topList[] = $item; + } + } + $selectParentIds = []; + $tree = Tree::instance(); + $tree->init($ruleList); + if ($select_id) { + $selectParentIds = $tree->getParentsIds($select_id, true); + } + foreach ($topList as $index => $item) { + $childList = Tree::instance()->getTreeMenu( + $item['id'], + '
  • @title @caret @badge @childlist
  • ', + $select_id, + '', + 'ul', + 'class="treeview-menu' . ($showSubmenu ? ' menu-open' : '') . '"' + ); + $current = in_array($item['id'], $selectParentIds); + $url = $childList ? 'javascript:;' : $item['url']; + $addtabs = $childList || !$url ? "" : (stripos($url, "?") !== false ? "&" : "?") . "ref=" . ($item['menutype'] ? $item['menutype'] : 'addtabs'); + $childList = str_replace( + '" pid="' . $item['id'] . '"', + ' ' . ($current ? '' : 'hidden') . '" pid="' . $item['id'] . '"', + $childList + ); + $nav .= '
  • ' . $item['title'] . '
  • '; + $menu .= $childList; + } + } else { + // 构造菜单数据 + Tree::instance()->init($ruleList); + $menu = Tree::instance()->getTreeMenu( + 0, + '
  • @title @caret @badge @childlist
  • ', + $select_id, + '', + 'ul', + 'class="treeview-menu' . ($showSubmenu ? ' menu-open' : '') . '"' + ); + if ($selected) { + $nav .= ''; + } + if ($referer) { + $nav .= ''; + } + } + + return [$menu, $nav, $selected, $referer]; + } + + /** + * 设置错误信息 + * + * @param string $error 错误信息 + * @return Auth + */ + public function setError($error) + { + $this->_error = $error; + return $this; + } + + /** + * 获取错误信息 + * @return string + */ + public function getError() + { + return $this->_error ? __($this->_error) : ''; + } +} diff --git a/application/guildadmin/library/ExceptionHandle.php b/application/guildadmin/library/ExceptionHandle.php new file mode 100644 index 0000000..df2b03d --- /dev/null +++ b/application/guildadmin/library/ExceptionHandle.php @@ -0,0 +1,37 @@ +getError(); + } + // Http异常 + if ($e instanceof \think\exception\HttpException) { + $statuscode = $code = $e->getStatusCode(); + } + return json(['code' => $code, 'msg' => $msg, 'time' => time(), 'data' => null], $statuscode); + } + + //其它此交由系统处理 + return parent::render($e); + } + +} diff --git a/application/guildadmin/model/Admin.php b/application/guildadmin/model/Admin.php new file mode 100644 index 0000000..46004f8 --- /dev/null +++ b/application/guildadmin/model/Admin.php @@ -0,0 +1,63 @@ +getChangedData(); + //如果修改了用户或或密码则需要重新登录 + if (isset($changed['username']) || isset($changed['password']) || isset($changed['salt'])) { + $row->token = ''; + } + }); + } + + //创建管理员(公会创建调用) + public function createAdmin($data){ + $params['salt'] = Random::alnum(); + $params['username'] = $data['username']; + $params['nickname'] = $data['nickname']; + $params['password'] = md5(md5($data['password']) . $params['salt']); + $params['guild_id'] = $data['guild_id']; + $result = $this->save($params); + if ($result === false) { + return V(0,"失败", []); + } + //创建角色组 + $group_data = [ + 'guild_id' => $data['guild_id'], + 'pid' => 1, + 'name' => '超级管理员', + 'rules' => '*', + 'status' => 'normal' + ]; + $group = model('guildadmin/AuthGroup')->create($group_data); + if (!$group) { + return V(0,"失败", []); + } + $dataset = []; + $dataset[] = ['uid' => $this->id, 'group_id' => $group['id']]; + model('guildadmin/AuthGroupAccess')->saveAll($dataset); + } + +} diff --git a/application/guildadmin/model/AdminLog.php b/application/guildadmin/model/AdminLog.php new file mode 100644 index 0000000..08664bf --- /dev/null +++ b/application/guildadmin/model/AdminLog.php @@ -0,0 +1,118 @@ +isLogin() ? $auth->id : 0; + $username = $auth->isLogin() ? $auth->username : __('Unknown'); + + // 设置过滤函数 + request()->filter('trim,strip_tags,htmlspecialchars'); + + $controllername = Loader::parseName(request()->controller()); + $actionname = strtolower(request()->action()); + $path = str_replace('.', '/', $controllername) . '/' . $actionname; + if (self::$ignoreRegex) { + foreach (self::$ignoreRegex as $index => $item) { + if (preg_match($item, $path)) { + return; + } + } + } + $content = $content ?: self::$content; + if (!$content) { + $content = request()->param('') ?: file_get_contents("php://input"); + $content = self::getPureContent($content); + } + $title = $title ?: self::$title; + if (!$title) { + $title = []; + $breadcrumb = Auth::instance()->getBreadcrumb($path); + foreach ($breadcrumb as $k => $v) { + $title[] = $v['title']; + } + $title = implode(' / ', $title); + } + self::create([ + 'title' => $title, + 'content' => !is_scalar($content) ? json_encode($content, JSON_UNESCAPED_UNICODE) : $content, + 'url' => substr(xss_clean(strip_tags(request()->url())), 0, 1500), + 'admin_id' => $admin_id, + 'username' => $username, + 'useragent' => substr(request()->server('HTTP_USER_AGENT'), 0, 255), + 'ip' => xss_clean(strip_tags(request()->ip())) + ]); + } + + /** + * 获取已屏蔽关键信息的数据 + * @param $content + * @return array + */ + protected static function getPureContent($content) + { + if (!is_array($content)) { + return $content; + } + foreach ($content as $index => &$item) { + if (preg_match("/(password|salt|token)/i", $index)) { + $item = "***"; + } else { + if (is_array($item)) { + $item = self::getPureContent($item); + } + } + } + return $content; + } + + public function admin() + { + return $this->belongsTo('Admin', 'admin_id')->setEagerlyType(0); + } +} diff --git a/application/guildadmin/model/AuthGroup.php b/application/guildadmin/model/AuthGroup.php new file mode 100644 index 0000000..45651c6 --- /dev/null +++ b/application/guildadmin/model/AuthGroup.php @@ -0,0 +1,22 @@ + __('Addtabs'), 'dialog' => __('Dialog'), 'ajax' => __('Ajax'), 'blank' => __('Blank')]; + } + + public function setPyAttr($value, $data) + { + if (isset($data['title']) && $data['title']) { + return self::$pinyin->abbr(__($data['title'])); + } + return ''; + } + + public function setPinyinAttr($value, $data) + { + if (isset($data['title']) && $data['title']) { + return self::$pinyin->permalink(__($data['title']), ''); + } + return ''; + } +}