From 019b536a894857c3692dcb77f009f012077e9a88 Mon Sep 17 00:00:00 2001 From: zhenhui <1276357500@qq.com> Date: Thu, 19 Mar 2026 18:04:52 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=91=98=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=B8=A0=E9=81=93channel=5Fid=E5=92=8C=E4=BB=A3=E7=90=86angent?= =?UTF-8?q?=5Fid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/auth/Admin.php | 23 +++++++++++++++-- app/admin/controller/channel/Manage.php | 25 +++++++++++++++++-- app/admin/lang/en/auth/admin.php | 2 ++ app/admin/lang/zh-cn/auth/admin.php | 2 ++ app/admin/model/Admin.php | 10 ++++++++ composer.json | 3 ++- web/src/lang/backend/en/auth/admin.ts | 4 +++ web/src/lang/backend/zh-cn/auth/admin.ts | 4 +++ web/src/views/backend/auth/admin/index.vue | 16 +++++++++++- .../views/backend/auth/admin/popupForm.vue | 24 ++++++++++++++++++ 10 files changed, 107 insertions(+), 6 deletions(-) diff --git a/app/admin/controller/auth/Admin.php b/app/admin/controller/auth/Admin.php index d0cc557..18f3dbf 100644 --- a/app/admin/controller/auth/Admin.php +++ b/app/admin/controller/auth/Admin.php @@ -17,7 +17,7 @@ class Admin extends Backend { protected ?object $model = null; - protected array|string $preExcludeFields = ['create_time', 'update_time', 'password', 'salt', 'login_failure', 'last_login_time', 'last_login_ip']; + protected array|string $preExcludeFields = ['create_time', 'update_time', 'password', 'salt', 'login_failure', 'last_login_time', 'last_login_ip', 'agent_id']; protected array|string $quickSearchField = ['username', 'nickname']; @@ -25,6 +25,8 @@ class Admin extends Backend protected string $dataLimitField = 'id'; + protected array $withJoinTable = ['channel']; + protected function initController(Request $request): ?Response { $this->model = new AdminModel(); @@ -44,7 +46,8 @@ class Admin extends Backend list($where, $alias, $limit, $order) = $this->queryBuilder(); $res = $this->model ->withoutField('login_failure,password,salt') - ->withJoin($this->withJoinTable, $this->withJoinType) + ->withJoin($this->withJoinTable, $this->withJoinType ?? 'LEFT') + ->visible(['channel' => ['name']]) ->alias($alias) ->where($where) ->order($order) @@ -78,9 +81,13 @@ class Admin extends Backend 'mobile' => 'regex:/^1[3-9]\d{9}$/|unique:admin,mobile', 'group_arr' => 'required|array', ]; + if ($this->auth->isSuperAdmin()) { + $rules['channel_id'] = 'required|integer|min:1'; + } $messages = [ 'username.regex' => __('Please input correct username'), 'password.regex' => __('Please input correct password'), + 'channel_id.required' => __('Please select channel'), ]; Validator::make($data, $rules, $messages)->validate(); } catch (ValidationException $e) { @@ -88,6 +95,14 @@ class Admin extends Backend } } + if (!$this->auth->isSuperAdmin()) { + $currentChannelId = (int) ($this->auth->model->channel_id ?? 0); + if ($currentChannelId <= 0) { + return $this->error(__('Current admin has no channel bound')); + } + $data['channel_id'] = $currentChannelId; + } + $passwd = $data['password'] ?? ''; $data = $this->excludeFields($data); $result = false; @@ -98,6 +113,10 @@ class Admin extends Backend $this->model->startTrans(); try { $result = $this->model->save($data); + if ($result !== false) { + $agentId = strtolower(md5($this->model->username . $this->model->id)); + $this->model->where('id', $this->model->id)->update(['agent_id' => $agentId]); + } if (!empty($data['group_arr'])) { $groupAccess = []; foreach ($data['group_arr'] as $datum) { diff --git a/app/admin/controller/channel/Manage.php b/app/admin/controller/channel/Manage.php index 7d9b7a3..54ab16d 100644 --- a/app/admin/controller/channel/Manage.php +++ b/app/admin/controller/channel/Manage.php @@ -43,8 +43,7 @@ class Manage extends Backend } if ($request->get('select') || $request->post('select')) { - $this->_select(); - return $this->success(); + return $this->select($request); } /** @@ -81,6 +80,28 @@ class Manage extends Backend return $this->success(); } + /** + * 渠道下拉选择(供 remoteSelect 使用) + */ + public function select(\Webman\Http\Request $request): \support\Response + { + $response = $this->initializeBackend($request); + if ($response !== null) { + return $response; + } + list($where, $alias, $limit, $order) = $this->queryBuilder(); + $res = $this->model + ->field('id,name,title') + ->alias($alias) + ->where($where) + ->order($order) + ->paginate($limit); + return $this->success('', [ + 'list' => $res->items(), + 'total' => $res->total(), + ]); + } + /** * add、edit、del、sortable 已由父类 Backend 实现,无需重写即可直接使用 * 若需重写,请确保调用 initializeBackend($request) 并传入 Request 参数 diff --git a/app/admin/lang/en/auth/admin.php b/app/admin/lang/en/auth/admin.php index b1a3073..0044be3 100644 --- a/app/admin/lang/en/auth/admin.php +++ b/app/admin/lang/en/auth/admin.php @@ -2,4 +2,6 @@ return [ 'Group Name Arr' => 'Administrator Grouping ', 'Please use another administrator account to disable the current account!' => 'Disable the current account, please use another administrator account!', + 'Please select channel' => 'Please select channel', + 'Current admin has no channel bound' => 'Current admin has no channel bound', ]; \ No newline at end of file diff --git a/app/admin/lang/zh-cn/auth/admin.php b/app/admin/lang/zh-cn/auth/admin.php index efa0622..e5501f4 100644 --- a/app/admin/lang/zh-cn/auth/admin.php +++ b/app/admin/lang/zh-cn/auth/admin.php @@ -3,4 +3,6 @@ return [ 'Group Name Arr' => '管理员分组', 'Please use another administrator account to disable the current account!' => '请使用另外的管理员账户禁用当前账户!', 'You have no permission to add an administrator to this group!' => '您没有权限向此分组添加管理员!', + 'Please select channel' => '请选择渠道', + 'Current admin has no channel bound' => '当前管理员未绑定渠道', ]; \ No newline at end of file diff --git a/app/admin/model/Admin.php b/app/admin/model/Admin.php index b368554..11db421 100644 --- a/app/admin/model/Admin.php +++ b/app/admin/model/Admin.php @@ -21,6 +21,8 @@ use support\think\Db; * @property string $password 密码密文 * @property string $salt 密码盐 * @property string $status 状态:enable=启用,disable=禁用 + * @property string $agent_id 代理ID(关联渠道) + * @property int $channel_id 渠道ID */ class Admin extends Model { @@ -64,4 +66,12 @@ class Admin extends Model { return $this->where(['id' => $uid])->update(['password' => hash_password($newPassword), 'salt' => '']); } + + /** + * 关联渠道 + */ + public function channel(): \think\model\relation\BelongsTo + { + return $this->belongsTo(\app\common\model\ChannelManage::class, 'channel_id', 'id'); + } } diff --git a/composer.json b/composer.json index 1affa36..fdd55e8 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,8 @@ "robmorgan/phinx": "^0.15", "nelexa/zip": "^4.0.0", "voku/anti-xss": "^4.1", - "topthink/think-validate": "^3.0" + "topthink/think-validate": "^3.0", + "firebase/php-jwt": "^7.0" }, "suggest": { "ext-event": "For better performance. " diff --git a/web/src/lang/backend/en/auth/admin.ts b/web/src/lang/backend/en/auth/admin.ts index 285962a..d0ccaf3 100644 --- a/web/src/lang/backend/en/auth/admin.ts +++ b/web/src/lang/backend/en/auth/admin.ts @@ -1,12 +1,16 @@ export default { username: 'Username', nickname: 'Nickname', + channel_id: 'Channel', + channel_name: 'Channel name', + 'Please select channel': 'Please select channel', group: 'Group', avatar: 'Avatar', email: 'Email', mobile: 'Mobile Number', 'Last login': 'Last login', Password: 'Password', + agent_id: 'agent', 'Please leave blank if not modified': 'Please leave blank if you do not modify.', 'Personal signature': 'Personal Signature', 'Administrator login': 'Administrator Login Name', diff --git a/web/src/lang/backend/zh-cn/auth/admin.ts b/web/src/lang/backend/zh-cn/auth/admin.ts index e5c671f..b26c15e 100644 --- a/web/src/lang/backend/zh-cn/auth/admin.ts +++ b/web/src/lang/backend/zh-cn/auth/admin.ts @@ -1,12 +1,16 @@ export default { username: '用户名', nickname: '昵称', + channel_id: '渠道', + channel_name: '渠道名称', + 'Please select channel': '请选择渠道', group: '角色组', avatar: '头像', email: '电子邮箱', mobile: '手机号', 'Last login': '最后登录', Password: '密码', + agent_id: '代理', 'Please leave blank if not modified': '不修改请留空', 'Personal signature': '个性签名', 'Administrator login': '管理员登录名', diff --git a/web/src/views/backend/auth/admin/index.vue b/web/src/views/backend/auth/admin/index.vue index 295f068..63679f9 100644 --- a/web/src/views/backend/auth/admin/index.vue +++ b/web/src/views/backend/auth/admin/index.vue @@ -48,7 +48,7 @@ const baTable = new baTableClass( { label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 }, { label: t('auth.admin.username'), prop: 'username', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') }, { label: t('auth.admin.nickname'), prop: 'nickname', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') }, - { label: t('auth.admin.group'), prop: 'group_name_arr', align: 'center', operator: false, render: 'tags' }, + { label: t('auth.admin.group'), prop: 'group_name_arr', align: 'center', minWidth: 120, operator: false, render: 'tags' }, { label: t('auth.admin.avatar'), prop: 'avatar', align: 'center', render: 'image', operator: false }, { label: t('auth.admin.email'), prop: 'email', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') }, { label: t('auth.admin.mobile'), prop: 'mobile', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') }, @@ -61,6 +61,20 @@ const baTable = new baTableClass( operator: 'RANGE', width: 160, }, + { + label: t('auth.admin.channel_name'), + prop: 'channel.name', + align: 'center', + minWidth: 120, + operator: false, + }, + { + label: t('auth.admin.agent_id'), + prop: 'agent_id', + align: 'center', + width: '160', + showOverflowTooltip: true, + }, { label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 }, { label: t('State'), diff --git a/web/src/views/backend/auth/admin/popupForm.vue b/web/src/views/backend/auth/admin/popupForm.vue index cf3e43c..fa93f02 100644 --- a/web/src/views/backend/auth/admin/popupForm.vue +++ b/web/src/views/backend/auth/admin/popupForm.vue @@ -41,6 +41,19 @@ prop="nickname" :placeholder="t('Please input field', { field: t('auth.admin.nickname') })" /> + > = reactive({ username: [buildValidatorData({ name: 'required', title: t('auth.admin.username') }), buildValidatorData({ name: 'account' })], nickname: [buildValidatorData({ name: 'required', title: t('auth.admin.nickname') })], + channel_id: [ + { + validator: (_rule: any, val: any, callback: Function) => { + if (baTable.form.operate === 'Add' && adminInfo.super && !val) { + return callback(new Error(t('auth.admin.Please select channel'))) + } + return callback() + }, + trigger: 'change', + }, + ], group_arr: [buildValidatorData({ name: 'required', message: t('Please select field', { field: t('auth.admin.group') }) })], email: [buildValidatorData({ name: 'email', message: t('Please enter the correct field', { field: t('auth.admin.email') }) })], mobile: [buildValidatorData({ name: 'mobile', message: t('Please enter the correct field', { field: t('auth.admin.mobile') }) })],