From 2ee78b3239ce1a9b18f1e7f9755eea6fb936639a Mon Sep 17 00:00:00 2001 From: zhenhui <1276357500@qq.com> Date: Wed, 1 Apr 2026 16:16:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=B8=E6=88=8F-=E6=B8=A0=E9=81=93=E7=AE=A1?= =?UTF-8?q?=E7=90=86-=E4=BC=98=E5=8C=96=E6=B8=A0=E9=81=93=E5=92=8C?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=91=98=E6=B7=BB=E5=8A=A0=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/auth/Admin.php | 86 +++++++++- app/admin/controller/game/Channel.php | 148 ++++++++++++++++++ .../views/backend/game/channel/popupForm.vue | 11 +- 3 files changed, 233 insertions(+), 12 deletions(-) diff --git a/app/admin/controller/auth/Admin.php b/app/admin/controller/auth/Admin.php index 2931e19..8ab0762 100644 --- a/app/admin/controller/auth/Admin.php +++ b/app/admin/controller/auth/Admin.php @@ -42,11 +42,23 @@ class Admin extends Backend } list($where, $alias, $limit, $order) = $this->queryBuilder(); - $res = $this->model + $query = $this->model ->withoutField('login_failure,password,salt') ->withJoin($this->withJoinTable, $this->withJoinType) ->alias($alias) - ->where($where) + ->where($where); + + // 仅返回“顶级角色组(pid=0)”下的管理员(用于远程下拉等场景) + $topGroup = $request->get('top_group') ?? $request->post('top_group'); + if ($topGroup === '1' || $topGroup === 1 || $topGroup === true) { + $query = $query + ->join('admin_group_access aga', $alias['admin'] . '.id = aga.uid') + ->join('admin_group ag', 'aga.group_id = ag.id') + ->where('ag.pid', 0) + ->distinct(true); + } + + $res = $query ->order($order) ->paginate($limit); @@ -57,6 +69,76 @@ class Admin extends Backend ]); } + /** + * 远程下拉(重写:支持 top_group=1 仅返回顶级组管理员) + */ + protected function _select(): Response + { + if (empty($this->model)) { + return $this->success('', [ + 'list' => [], + 'total' => 0, + ]); + } + + $pk = $this->model->getPk(); + + $fields = [$pk]; + $quickSearchArr = is_array($this->quickSearchField) ? $this->quickSearchField : explode(',', (string) $this->quickSearchField); + foreach ($quickSearchArr as $f) { + $f = trim((string) $f); + if ($f === '') continue; + $f = str_contains($f, '.') ? substr($f, strrpos($f, '.') + 1) : $f; + if ($f !== '' && !in_array($f, $fields, true)) { + $fields[] = $f; + } + } + + list($where, $alias, $limit, $order) = $this->queryBuilder(); + $modelTable = strtolower($this->model->getTable()); + $mainAlias = ($alias[$modelTable] ?? $modelTable) . '.'; + + // 联表时避免字段歧义:主表字段统一 select 为 "admin.xxx as xxx" + $selectFields = []; + foreach ($fields as $f) { + $f = trim((string) $f); + if ($f === '') continue; + $selectFields[] = $mainAlias . $f . ' as ' . $f; + } + + // 联表时避免排序字段歧义:无前缀的字段默认加主表前缀 + $qualifiedOrder = []; + if (is_array($order)) { + foreach ($order as $k => $v) { + $k = (string) $k; + $qualifiedOrder[str_contains($k, '.') ? $k : ($mainAlias . $k)] = $v; + } + } + + $query = $this->model + ->field($selectFields) + ->alias($alias) + ->where($where); + + $topGroup = $this->request ? ($this->request->get('top_group') ?? $this->request->post('top_group')) : null; + if ($topGroup === '1' || $topGroup === 1 || $topGroup === true) { + $query = $query + ->join('admin_group_access aga', $mainAlias . 'id = aga.uid') + ->join('admin_group ag', 'aga.group_id = ag.id') + ->where('ag.pid', 0) + ->distinct(true); + } + + $res = $query + ->order($qualifiedOrder ?: $order) + ->paginate($limit); + + return $this->success('', [ + 'list' => $res->items(), + 'total' => $res->total(), + ]); + } + public function add(Request $request): Response { $response = $this->initializeBackend($request); diff --git a/app/admin/controller/game/Channel.php b/app/admin/controller/game/Channel.php index f075f1f..684fabf 100644 --- a/app/admin/controller/game/Channel.php +++ b/app/admin/controller/game/Channel.php @@ -4,6 +4,7 @@ namespace app\admin\controller\game; use Throwable; use app\common\controller\Backend; +use support\think\Db; use support\Response; use Webman\Http\Request as WebmanRequest; @@ -31,6 +32,153 @@ class Channel extends Backend return null; } + /** + * 添加(重写:管理员只选顶级组;admin_group_id 后端自动写入) + * @throws Throwable + */ + protected function _add(): Response + { + if ($this->request && $this->request->method() === 'POST') { + $data = $this->request->post(); + if (!$data) { + return $this->error(__('Parameter %s can not be empty', [''])); + } + + $data = $this->applyInputFilter($data); + $data = $this->excludeFields($data); + + $adminId = $data['admin_id'] ?? null; + if ($adminId === null || $adminId === '') { + return $this->error(__('Parameter %s can not be empty', ['admin_id'])); + } + + // 不允许前端填写,统一后端根据管理员所属“顶级角色组(pid=0)”自动回填 + if (array_key_exists('admin_group_id', $data)) { + unset($data['admin_group_id']); + } + + $topGroupId = Db::name('admin_group_access') + ->alias('aga') + ->join('admin_group ag', 'aga.group_id = ag.id') + ->where('aga.uid', $adminId) + ->where('ag.pid', 0) + ->value('ag.id'); + + if ($topGroupId === null || $topGroupId === '') { + return $this->error(__('Record not found')); + } + $data['admin_group_id'] = $topGroupId; + + if ($this->dataLimit && $this->dataLimitFieldAutoFill) { + $data[$this->dataLimitField] = $this->auth->id; + } + + $result = false; + $this->model->startTrans(); + try { + if ($this->modelValidate) { + $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model)); + if (class_exists($validate)) { + $validate = new $validate(); + if ($this->modelSceneValidate) { + $validate->scene('add'); + } + $validate->check($data); + } + } + $result = $this->model->save($data); + $this->model->commit(); + } catch (Throwable $e) { + $this->model->rollback(); + return $this->error($e->getMessage()); + } + if ($result !== false) { + return $this->success(__('Added successfully')); + } + return $this->error(__('No rows were added')); + } + + return $this->error(__('Parameter error')); + } + + /** + * 编辑(重写:管理员只选顶级组;admin_group_id 后端自动写入) + * @throws Throwable + */ + protected function _edit(): Response + { + $pk = $this->model->getPk(); + $id = $this->request ? ($this->request->post($pk) ?? $this->request->get($pk)) : null; + $row = $this->model->find($id); + if (!$row) { + return $this->error(__('Record not found')); + } + + $dataLimitAdminIds = $this->getDataLimitAdminIds(); + if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) { + return $this->error(__('You have no permission')); + } + + if ($this->request && $this->request->method() === 'POST') { + $data = $this->request->post(); + if (!$data) { + return $this->error(__('Parameter %s can not be empty', [''])); + } + + $data = $this->applyInputFilter($data); + $data = $this->excludeFields($data); + + // 不允许前端填写,统一后端根据管理员所属“顶级角色组(pid=0)”自动回填 + if (array_key_exists('admin_group_id', $data)) { + unset($data['admin_group_id']); + } + + $nextAdminId = array_key_exists('admin_id', $data) ? $data['admin_id'] : ($row['admin_id'] ?? null); + if ($nextAdminId !== null && $nextAdminId !== '') { + $topGroupId = Db::name('admin_group_access') + ->alias('aga') + ->join('admin_group ag', 'aga.group_id = ag.id') + ->where('aga.uid', $nextAdminId) + ->where('ag.pid', 0) + ->value('ag.id'); + + if ($topGroupId === null || $topGroupId === '') { + return $this->error(__('Record not found')); + } + $data['admin_group_id'] = $topGroupId; + } + + $result = false; + $this->model->startTrans(); + try { + if ($this->modelValidate) { + $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model)); + if (class_exists($validate)) { + $validate = new $validate(); + if ($this->modelSceneValidate) { + $validate->scene('edit'); + } + $data[$pk] = $row[$pk]; + $validate->check($data); + } + } + $result = $row->save($data); + $this->model->commit(); + } catch (Throwable $e) { + $this->model->rollback(); + return $this->error($e->getMessage()); + } + if ($result !== false) { + return $this->success(__('Update successful')); + } + return $this->error(__('No rows updated')); + } + + return $this->success('', [ + 'row' => $row + ]); + } + /** * 查看 * @throws Throwable diff --git a/web/src/views/backend/game/channel/popupForm.vue b/web/src/views/backend/game/channel/popupForm.vue index 43a2e50..bfa5ceb 100644 --- a/web/src/views/backend/game/channel/popupForm.vue +++ b/web/src/views/backend/game/channel/popupForm.vue @@ -60,20 +60,12 @@ @keyup.ctrl.enter="baTable.onSubmit(formRef)" :placeholder="t('Please input field', { field: t('game.channel.remark') })" /> - @@ -110,7 +102,6 @@ const rules: Partial> = reactive({ name: [buildValidatorData({ name: 'required', title: t('game.channel.name') })], user_count: [buildValidatorData({ name: 'integer', title: t('game.channel.user_count') })], profit_amount: [buildValidatorData({ name: 'float', title: t('game.channel.profit_amount') })], - admin_group_id: [buildValidatorData({ name: 'required', title: t('game.channel.admin_group_id') })], admin_id: [buildValidatorData({ name: 'required', title: t('game.channel.admin_id') })], create_time: [buildValidatorData({ name: 'date', title: t('game.channel.create_time') })], update_time: [buildValidatorData({ name: 'date', title: t('game.channel.update_time') })],