367 lines
12 KiB
PHP
367 lines
12 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
|
||
namespace app\dice\helper;
|
||
|
||
use app\dice\model\player\DicePlayer;
|
||
use plugin\saiadmin\app\model\system\SystemUser;
|
||
use plugin\saiadmin\exception\ApiException;
|
||
|
||
/**
|
||
* 大富翁数据范围:按渠道 dept_id 隔离(关联 sa_system_dept)
|
||
*/
|
||
class AdminScopeHelper
|
||
{
|
||
/** 超管查看默认配置模板 */
|
||
public const DEFAULT_TEMPLATE_DEPT = 0;
|
||
|
||
/**
|
||
* 当前管理员所属渠道 ID;超级管理员(id=1) 返回 null 表示不限制
|
||
*/
|
||
public static function getDeptId(?array $adminInfo): ?int
|
||
{
|
||
if (empty($adminInfo) || !isset($adminInfo['id'])) {
|
||
return null;
|
||
}
|
||
$adminId = (int) $adminInfo['id'];
|
||
if ($adminId <= 1) {
|
||
return null;
|
||
}
|
||
$deptList = $adminInfo['deptList'] ?? [];
|
||
if (!empty($deptList['id'])) {
|
||
return (int) $deptList['id'];
|
||
}
|
||
if (!empty($adminInfo['dept_id'])) {
|
||
return (int) $adminInfo['dept_id'];
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
public static function isSuperAdmin(?array $adminInfo): bool
|
||
{
|
||
return !empty($adminInfo['id']) && (int) $adminInfo['id'] <= 1;
|
||
}
|
||
|
||
/**
|
||
* 解析配置类接口的渠道 ID(请求参数 dept_id)
|
||
* 超管:0 或空=默认模板(null);>0=指定渠道
|
||
* 普通管理员:固定本渠道
|
||
*/
|
||
public static function resolveConfigDeptId(?array $adminInfo, $requestDeptId): int
|
||
{
|
||
$scopeDeptId = self::getDeptId($adminInfo);
|
||
if ($scopeDeptId !== null) {
|
||
return $scopeDeptId > 0 ? $scopeDeptId : self::DEFAULT_TEMPLATE_DEPT;
|
||
}
|
||
if ($requestDeptId === null || $requestDeptId === '') {
|
||
return self::DEFAULT_TEMPLATE_DEPT;
|
||
}
|
||
$id = (int) $requestDeptId;
|
||
if ($id === self::DEFAULT_TEMPLATE_DEPT) {
|
||
return self::DEFAULT_TEMPLATE_DEPT;
|
||
}
|
||
return $id > 0 ? $id : self::DEFAULT_TEMPLATE_DEPT;
|
||
}
|
||
|
||
public static function isTemplateDeptId($deptId): bool
|
||
{
|
||
return $deptId === null || $deptId === '' || (int) $deptId === self::DEFAULT_TEMPLATE_DEPT;
|
||
}
|
||
|
||
/**
|
||
* 同渠道下可访问的管理员 ID
|
||
*
|
||
* @return int[]|null null=不限制
|
||
*/
|
||
public static function getAllowedAdminIds(?array $adminInfo): ?array
|
||
{
|
||
if (empty($adminInfo) || !isset($adminInfo['id'])) {
|
||
return [];
|
||
}
|
||
$adminId = (int) $adminInfo['id'];
|
||
if ($adminId <= 1) {
|
||
return null;
|
||
}
|
||
$deptId = self::getDeptId($adminInfo);
|
||
if ($deptId === null) {
|
||
return null;
|
||
}
|
||
if ($deptId <= 0) {
|
||
return [$adminId];
|
||
}
|
||
$ids = SystemUser::where('dept_id', $deptId)->column('id');
|
||
return array_map('intval', $ids ?: [$adminId]);
|
||
}
|
||
|
||
public static function fillDeptId(array &$data, ?array $adminInfo, $requestDeptId = null): void
|
||
{
|
||
if (isset($data['dept_id']) && $data['dept_id'] !== '' && $data['dept_id'] !== null) {
|
||
return;
|
||
}
|
||
$deptId = self::resolveConfigDeptId($adminInfo, $requestDeptId ?? ($data['filter_dept_id'] ?? null));
|
||
if ($deptId > 0) {
|
||
$data['dept_id'] = $deptId;
|
||
} elseif (!isset($data['dept_id']) || self::isTemplateDeptId($data['dept_id'])) {
|
||
$data['dept_id'] = self::DEFAULT_TEMPLATE_DEPT;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 业务数据新增:按渠道写入 dept_id(玩家、记录等)
|
||
* 优先级:已有 dept_id → 所属管理员 admin_id → 请求渠道 → 当前登录人渠道
|
||
*/
|
||
public static function fillBusinessDeptId(array &$data, ?array $adminInfo, $requestDeptId = null): void
|
||
{
|
||
if (isset($data['dept_id']) && $data['dept_id'] !== '' && $data['dept_id'] !== null) {
|
||
$data['dept_id'] = (int) $data['dept_id'];
|
||
if ($data['dept_id'] > 0) {
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (!empty($data['player_id'])) {
|
||
$playerDeptId = self::resolveDeptIdByPlayerId($data['player_id']);
|
||
if ($playerDeptId !== null && $playerDeptId > 0) {
|
||
$data['dept_id'] = $playerDeptId;
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (!empty($data['admin_id'])) {
|
||
$ownerDeptId = self::resolveDeptIdByAdminId($data['admin_id']);
|
||
if ($ownerDeptId !== null && $ownerDeptId > 0) {
|
||
$data['dept_id'] = $ownerDeptId;
|
||
return;
|
||
}
|
||
}
|
||
|
||
$deptId = self::resolveBusinessDeptId($adminInfo, $requestDeptId);
|
||
if ($deptId !== null && $deptId > 0) {
|
||
$data['dept_id'] = $deptId;
|
||
return;
|
||
}
|
||
|
||
$scopeDeptId = self::getDeptId($adminInfo);
|
||
if ($scopeDeptId !== null && $scopeDeptId > 0) {
|
||
$data['dept_id'] = $scopeDeptId;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 业务新增:解析请求渠道并填充 dept_id,缺失时抛错
|
||
*/
|
||
public static function prepareBusinessSaveData(
|
||
array &$data,
|
||
?array $adminInfo,
|
||
$inputDeptId = null,
|
||
array $body = []
|
||
): void {
|
||
$requestDeptId = self::pickRequestDeptId($inputDeptId, $body);
|
||
self::fillBusinessDeptId($data, $adminInfo, $requestDeptId);
|
||
self::assertBusinessDeptId($data);
|
||
}
|
||
|
||
/**
|
||
* 配置新增:解析请求渠道并填充 dept_id
|
||
*/
|
||
public static function prepareConfigSaveData(
|
||
array &$data,
|
||
?array $adminInfo,
|
||
$inputDeptId = null,
|
||
array $body = []
|
||
): void {
|
||
$requestDeptId = self::pickRequestDeptId($inputDeptId, $body);
|
||
self::fillDeptId($data, $adminInfo, $requestDeptId);
|
||
}
|
||
|
||
/**
|
||
* 业务表 dept_id 必须 > 0(非默认模板)
|
||
*/
|
||
public static function assertBusinessDeptId(array $data): void
|
||
{
|
||
if (!isset($data['dept_id']) || $data['dept_id'] === '' || $data['dept_id'] === null) {
|
||
throw new ApiException('CHANNEL_DEPT_ID_REQUIRED');
|
||
}
|
||
if ((int) $data['dept_id'] <= 0) {
|
||
throw new ApiException('INVALID_CHANNEL_DEPT_ID');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 根据玩家 ID 解析所属渠道
|
||
*/
|
||
public static function resolveDeptIdByPlayerId($playerId): ?int
|
||
{
|
||
if ($playerId === null || $playerId === '') {
|
||
return null;
|
||
}
|
||
$player = DicePlayer::field('dept_id,admin_id')->find($playerId);
|
||
if (!$player || $player->isEmpty()) {
|
||
return null;
|
||
}
|
||
$deptId = $player->dept_id ?? null;
|
||
if ($deptId !== null && $deptId !== '' && (int) $deptId > 0) {
|
||
return (int) $deptId;
|
||
}
|
||
if (!empty($player->admin_id)) {
|
||
return self::resolveDeptIdByAdminId($player->admin_id);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 根据后台管理员 ID 解析所属渠道
|
||
*/
|
||
public static function resolveDeptIdByAdminId($adminId): ?int
|
||
{
|
||
if ($adminId === null || $adminId === '') {
|
||
return null;
|
||
}
|
||
$admin = SystemUser::find($adminId);
|
||
if (!$admin || $admin->isEmpty()) {
|
||
return null;
|
||
}
|
||
$deptId = $admin->dept_id ?? null;
|
||
if ($deptId !== null && $deptId !== '' && (int) $deptId > 0) {
|
||
return (int) $deptId;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 规范化记录上的 dept_id(null 视为默认模板 0)
|
||
*/
|
||
public static function normalizeRecordDeptId($recordDeptId): int
|
||
{
|
||
if ($recordDeptId === null || $recordDeptId === '') {
|
||
return self::DEFAULT_TEMPLATE_DEPT;
|
||
}
|
||
return (int) $recordDeptId;
|
||
}
|
||
|
||
/**
|
||
* 玩家端读取游戏配置时使用的渠道 ID(玩家 dept_id 优先,否则按所属管理员)
|
||
*/
|
||
public static function resolvePlayerConfigDeptId($player): int
|
||
{
|
||
$deptId = null;
|
||
$adminId = null;
|
||
if (is_array($player)) {
|
||
$deptId = $player['dept_id'] ?? null;
|
||
$adminId = $player['admin_id'] ?? null;
|
||
} elseif (is_object($player)) {
|
||
$deptId = $player->dept_id ?? null;
|
||
$adminId = $player->admin_id ?? null;
|
||
}
|
||
if ($deptId !== null && $deptId !== '' && (int) $deptId > 0) {
|
||
return (int) $deptId;
|
||
}
|
||
if ($adminId !== null && $adminId !== '') {
|
||
$fromAdmin = self::resolveDeptIdByAdminId($adminId);
|
||
if ($fromAdmin !== null && $fromAdmin > 0) {
|
||
return $fromAdmin;
|
||
}
|
||
}
|
||
return self::DEFAULT_TEMPLATE_DEPT;
|
||
}
|
||
|
||
/**
|
||
* 从请求参数或请求体中解析 dept_id(兼容 PUT JSON 仅出现在 body 的情况)
|
||
*/
|
||
public static function pickRequestDeptId($inputDeptId, array $body = [])
|
||
{
|
||
if ($inputDeptId !== null && $inputDeptId !== '') {
|
||
return $inputDeptId;
|
||
}
|
||
if (isset($body['dept_id']) && $body['dept_id'] !== '' && $body['dept_id'] !== null) {
|
||
return $body['dept_id'];
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public static function canAccessDept(?array $adminInfo, $recordDeptId, $requestDeptId = null): bool
|
||
{
|
||
$recordDeptId = self::normalizeRecordDeptId($recordDeptId);
|
||
$scopeDeptId = self::getDeptId($adminInfo);
|
||
if ($scopeDeptId === null) {
|
||
if ($requestDeptId === null || $requestDeptId === '') {
|
||
return true;
|
||
}
|
||
$target = self::resolveConfigDeptId($adminInfo, $requestDeptId);
|
||
if (self::isTemplateDeptId($target)) {
|
||
return self::isTemplateDeptId($recordDeptId);
|
||
}
|
||
return $recordDeptId === $target;
|
||
}
|
||
if ($recordDeptId === self::DEFAULT_TEMPLATE_DEPT && $scopeDeptId > 0) {
|
||
return false;
|
||
}
|
||
return $recordDeptId === $scopeDeptId;
|
||
}
|
||
|
||
/**
|
||
* 业务页渠道 ID:超管通过请求 dept_id 筛选;未传或 <=0 时不限制
|
||
*/
|
||
public static function resolveBusinessDeptId(?array $adminInfo, $requestDeptId): ?int
|
||
{
|
||
$scopeDeptId = self::getDeptId($adminInfo);
|
||
if ($scopeDeptId !== null) {
|
||
return $scopeDeptId > 0 ? $scopeDeptId : null;
|
||
}
|
||
if ($requestDeptId === null || $requestDeptId === '') {
|
||
return null;
|
||
}
|
||
$id = (int) $requestDeptId;
|
||
return $id > 0 ? $id : null;
|
||
}
|
||
|
||
/**
|
||
* 业务数据列表(玩家、记录、工作台等)
|
||
*/
|
||
public static function applyAdminScope($query, ?array $adminInfo, $requestDeptId = null): void
|
||
{
|
||
if (self::getDeptId($adminInfo) === null) {
|
||
$target = self::resolveBusinessDeptId($adminInfo, $requestDeptId);
|
||
if ($target !== null && $target > 0) {
|
||
$query->where('dept_id', $target);
|
||
}
|
||
return;
|
||
}
|
||
$deptId = self::getDeptId($adminInfo);
|
||
if ($deptId <= 0) {
|
||
$query->whereRaw('1=0');
|
||
return;
|
||
}
|
||
$query->where('dept_id', $deptId);
|
||
}
|
||
|
||
/**
|
||
* 配置类列表:超管按所选渠道/默认模板筛选
|
||
*/
|
||
public static function applyConfigScope($query, ?array $adminInfo, $requestDeptId = null, string $deptColumn = 'dept_id'): void
|
||
{
|
||
$targetDeptId = self::resolveConfigDeptId($adminInfo, $requestDeptId);
|
||
$scopeDeptId = self::getDeptId($adminInfo);
|
||
|
||
if ($scopeDeptId !== null && !self::isSuperAdmin($adminInfo)) {
|
||
if ($scopeDeptId <= 0) {
|
||
$query->whereRaw('1=0');
|
||
return;
|
||
}
|
||
$query->where($deptColumn, $scopeDeptId);
|
||
return;
|
||
}
|
||
|
||
if (self::isTemplateDeptId($targetDeptId)) {
|
||
$templateId = self::DEFAULT_TEMPLATE_DEPT;
|
||
$query->where(function ($q) use ($templateId, $deptColumn) {
|
||
$q->where($deptColumn, $templateId)->whereOr($deptColumn, null);
|
||
});
|
||
return;
|
||
}
|
||
$query->where($deptColumn, $targetDeptId);
|
||
}
|
||
}
|