diff --git a/server/app/api/controller/v1/GameController.php b/server/app/api/controller/v1/GameController.php index 9f1be07..8e0c018 100644 --- a/server/app/api/controller/v1/GameController.php +++ b/server/app/api/controller/v1/GameController.php @@ -43,11 +43,13 @@ class GameController extends BaseController } $adminId = null; + $adminIdsInTopDept = null; $agentId = trim((string) ($request->agent_id ?? '')); if ($agentId !== '') { $systemUser = SystemUser::where('agent_id', $agentId)->find(); if ($systemUser) { $adminId = (int) $systemUser->id; + $adminIdsInTopDept = UserLogic::getAdminIdsByAgentIdTopDept($agentId); } } @@ -56,7 +58,7 @@ class GameController extends BaseController try { $logic = new UserLogic(); - $result = $logic->loginByUsername($username, $password, $lang === 'en' ? 'en' : 'chs', 0.0, $time, $adminId); + $result = $logic->loginByUsername($username, $password, $lang === 'en' ? 'en' : 'chs', 0.0, $time, $adminId, $adminIdsInTopDept); } catch (\plugin\saiadmin\exception\ApiException $e) { return $this->fail($e->getMessage(), ReturnCode::PARAMS_ERROR); } diff --git a/server/app/api/logic/UserLogic.php b/server/app/api/logic/UserLogic.php index 41d00d7..d79576d 100644 --- a/server/app/api/logic/UserLogic.php +++ b/server/app/api/logic/UserLogic.php @@ -5,6 +5,8 @@ namespace app\api\logic; use app\dice\model\player\DicePlayer; use app\api\cache\UserCache; +use plugin\saiadmin\app\model\system\SystemDept; +use plugin\saiadmin\app\model\system\SystemUser; use plugin\saiadmin\exception\ApiException; use Tinywan\Jwt\JwtToken; @@ -41,21 +43,98 @@ class UserLogic return md5(self::PASSWORD_SALT . $password); } + /** + * 根据 parent_id 向上遍历找到顶级部门(parent_id=0) + */ + private static function getTopDeptIdByParentId(int $deptId): ?int + { + $currentId = $deptId; + $visited = []; + while ($currentId > 0 && !isset($visited[$currentId])) { + $visited[$currentId] = true; + $dept = SystemDept::find($currentId); + if (!$dept) { + return null; + } + $parentId = (int) ($dept->parent_id ?? 0); + if ($parentId === 0) { + return $currentId; + } + $currentId = $parentId; + } + return $currentId > 0 ? $currentId : null; + } + + /** + * 根据顶级部门 id,递归获取其下所有部门 id(含自身),仅用 id 和 parent_id + */ + private static function getAllDeptIdsUnderTop(int $topId): array + { + $deptIds = [$topId]; + $prevCount = 0; + while (count($deptIds) > $prevCount) { + $prevCount = count($deptIds); + $children = SystemDept::whereIn('parent_id', $deptIds)->column('id'); + $deptIds = array_unique(array_merge($deptIds, array_map('intval', $children))); + } + return array_values($deptIds); + } + + /** + * 根据 agent_id 获取当前管理员所在顶级部门下的所有管理员 ID 列表 + * 使用 SystemDept 的 id 和 parent_id 字段遍历:先向上找顶级部门(parent_id=0),再向下收集所有子部门 + * 用于 getGameUrl 接口判断 DicePlayer 是否属于该部门,同顶级部门下不重复创建玩家 + * + * @param string $agentId 代理标识(sa_system_user.agent_id) + * @return int[] 管理员 ID 列表,空数组表示未找到或无法解析 + */ + public static function getAdminIdsByAgentIdTopDept(string $agentId): array + { + $agentId = trim($agentId); + if ($agentId === '') { + return []; + } + $admin = SystemUser::where('agent_id', $agentId)->find(); + if (!$admin) { + return []; + } + $deptId = $admin->dept_id ?? null; + if ($deptId === null || $deptId === '') { + return [(int) $admin->id]; + } + $deptId = (int) $deptId; + $topId = self::getTopDeptIdByParentId($deptId); + if ($topId === null) { + return [(int) $admin->id]; + } + $deptIds = self::getAllDeptIdsUnderTop($topId); + if (empty($deptIds)) { + $deptIds = [$deptId]; + } + $adminIds = SystemUser::whereIn('dept_id', $deptIds)->column('id'); + return array_map('intval', $adminIds); + } + /** * 登录(JSON:username, password, lang, coin, time) * 存在则校验密码并更新 coin(累加);不存在则创建用户并写入 coin。 * 将会话写入 Redis,返回 token 与前端连接地址。 * * @param int|null $adminId 创建新用户时关联的后台管理员ID(sa_system_user.id),可选 + * @param int[]|null $adminIdsInTopDept 当前管理员顶级部门下的所有管理员ID,用于按部门范围查找玩家;为空时退化为仅按 username 查找 */ - public function loginByUsername(string $username, string $password, string $lang, float $coin, string $time, ?int $adminId = null): array + public function loginByUsername(string $username, string $password, string $lang, float $coin, string $time, ?int $adminId = null, ?array $adminIdsInTopDept = null): array { $username = trim($username); if ($username === '') { throw new ApiException('username is required'); } - $player = DicePlayer::where('username', $username)->find(); + $query = DicePlayer::where('username', $username); + if ($adminIdsInTopDept !== null && !empty($adminIdsInTopDept)) { + $query->whereIn('admin_id', $adminIdsInTopDept); + } + $player = $query->find(); if ($player) { if ((int) ($player->status ?? 1) === 0) { throw new ApiException('Account is disabled and cannot log in');