新增职务权限管理与聊天室管理权限控制
This commit is contained in:
@@ -13,9 +13,14 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\StoreBaccaratLossCoverEventRequest;
|
||||
use App\Models\BaccaratLossCoverEvent;
|
||||
use App\Services\BaccaratLossCoverService;
|
||||
use App\Services\PositionPermissionService;
|
||||
use App\Support\PositionPermissionRegistry;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* 类功能:处理聊天室顶部快捷入口创建与结束百家乐买单活动。
|
||||
*/
|
||||
class BaccaratLossCoverEventController extends Controller
|
||||
{
|
||||
/**
|
||||
@@ -23,6 +28,7 @@ class BaccaratLossCoverEventController extends Controller
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly BaccaratLossCoverService $lossCoverService,
|
||||
private readonly PositionPermissionService $positionPermissionService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -30,6 +36,13 @@ class BaccaratLossCoverEventController extends Controller
|
||||
*/
|
||||
public function store(StoreBaccaratLossCoverEventRequest $request): JsonResponse
|
||||
{
|
||||
if (! $this->positionPermissionService->hasPermission($request->user(), PositionPermissionRegistry::ROOM_BACCARAT_LOSS_COVER)) {
|
||||
return response()->json([
|
||||
'ok' => false,
|
||||
'message' => '当前职务无权创建买单活动。',
|
||||
], 403);
|
||||
}
|
||||
|
||||
try {
|
||||
$event = $this->lossCoverService->createEvent($request->user(), $request->validated());
|
||||
} catch (\RuntimeException $exception) {
|
||||
@@ -51,6 +64,13 @@ class BaccaratLossCoverEventController extends Controller
|
||||
*/
|
||||
public function close(Request $request, BaccaratLossCoverEvent $event): JsonResponse
|
||||
{
|
||||
if (! $this->positionPermissionService->hasPermission($request->user(), PositionPermissionRegistry::ROOM_BACCARAT_LOSS_COVER)) {
|
||||
return response()->json([
|
||||
'ok' => false,
|
||||
'message' => '当前职务无权结束买单活动。',
|
||||
], 403);
|
||||
}
|
||||
|
||||
$event = $this->lossCoverService->forceCloseEvent($event, $request->user());
|
||||
|
||||
return response()->json([
|
||||
|
||||
@@ -16,10 +16,15 @@ use App\Http\Controllers\Controller;
|
||||
use App\Models\Department;
|
||||
use App\Models\Position;
|
||||
use App\Models\Sysparam;
|
||||
use App\Support\PositionPermissionRegistry;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
* 类功能:负责后台职务资料、任命白名单与聊天室权限配置的维护。
|
||||
*/
|
||||
class PositionController extends Controller
|
||||
{
|
||||
/**
|
||||
@@ -29,16 +34,25 @@ class PositionController extends Controller
|
||||
{
|
||||
// 按部门分组展示
|
||||
$departments = Department::with([
|
||||
'positions' => fn ($q) => $q->withCount(['activeUserPositions'])->ordered(),
|
||||
'positions' => fn ($q) => $q->withCount(['activeUserPositions'])->with('appointablePositions')->ordered(),
|
||||
])->ordered()->get();
|
||||
|
||||
// 全部职务(供任命白名单多选框使用)
|
||||
$allPositions = Position::with('department')->orderByDesc('rank')->get();
|
||||
$allPositions = Position::with('department')->ordered()->get();
|
||||
|
||||
// 全局奖励接收次数上限(0 = 不限)
|
||||
$globalRecipientDailyMax = (int) Sysparam::getValue('reward_recipient_daily_max', '0');
|
||||
|
||||
return view('admin.positions.index', compact('departments', 'allPositions', 'globalRecipientDailyMax'));
|
||||
$positionPermissions = PositionPermissionRegistry::groupedDefinitions();
|
||||
$permissionLabels = PositionPermissionRegistry::labelMap();
|
||||
|
||||
return view('admin.positions.index', compact(
|
||||
'departments',
|
||||
'allPositions',
|
||||
'globalRecipientDailyMax',
|
||||
'positionPermissions',
|
||||
'permissionLabels',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,10 +73,13 @@ class PositionController extends Controller
|
||||
'sort_order' => 'required|integer|min:0',
|
||||
'appointable_ids' => 'nullable|array',
|
||||
'appointable_ids.*' => 'exists:positions,id',
|
||||
'permissions' => 'nullable|array',
|
||||
'permissions.*' => ['string', Rule::in(PositionPermissionRegistry::codes())],
|
||||
]);
|
||||
|
||||
$appointableIds = $data['appointable_ids'] ?? [];
|
||||
unset($data['appointable_ids']);
|
||||
$data['permissions'] = array_values(array_unique($data['permissions'] ?? []));
|
||||
|
||||
$position = Position::create($data);
|
||||
|
||||
@@ -147,10 +164,13 @@ class PositionController extends Controller
|
||||
'sort_order' => 'required|integer|min:0',
|
||||
'appointable_ids' => 'nullable|array',
|
||||
'appointable_ids.*' => 'exists:positions,id',
|
||||
'permissions' => 'nullable|array',
|
||||
'permissions.*' => ['string', Rule::in(PositionPermissionRegistry::codes())],
|
||||
]);
|
||||
|
||||
$appointableIds = $data['appointable_ids'] ?? [];
|
||||
unset($data['appointable_ids']);
|
||||
$data['permissions'] = array_values(array_unique($data['permissions'] ?? []));
|
||||
|
||||
$position->update($data);
|
||||
$position->appointablePositions()->sync($appointableIds);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* 文件功能:管理员聊天室实时命令控制器
|
||||
*
|
||||
* 提供管理员在聊天室内对用户执行的管理操作:
|
||||
* 警告(=J)、踢出(=T)、禁言(=B)、冻结(=Y)、查看私信(=S)、站长公屏讲话。
|
||||
* 警告(=J)、踢出(=T)、禁言(=B)、冻结(=Y)、查看私信(=S)、职务公屏讲话。
|
||||
*
|
||||
* 对应原 ASP 文件:DOUSER.ASP / KILLUSER.ASP / LOCKIP.ASP / NEWSAY.ASP
|
||||
*
|
||||
@@ -24,13 +24,18 @@ use App\Models\PositionAuthorityLog;
|
||||
use App\Models\Sysparam;
|
||||
use App\Models\User;
|
||||
use App\Services\ChatStateService;
|
||||
use App\Services\PositionPermissionService;
|
||||
use App\Services\UserCurrencyService;
|
||||
use App\Support\PositionPermissionRegistry;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
/**
|
||||
* 类功能:处理聊天室内的实时管理命令与部分职务奖励操作。
|
||||
*/
|
||||
class AdminCommandController extends Controller
|
||||
{
|
||||
/**
|
||||
@@ -39,6 +44,7 @@ class AdminCommandController extends Controller
|
||||
public function __construct(
|
||||
private readonly ChatStateService $chatState,
|
||||
private readonly UserCurrencyService $currencyService,
|
||||
private readonly PositionPermissionService $positionPermissionService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -347,9 +353,10 @@ class AdminCommandController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* 站长公屏讲话
|
||||
* 聊天室公屏讲话
|
||||
*
|
||||
* 站长发送全聊天室公告,以特殊样式显示。
|
||||
* 拥有 room.public_broadcast 权限的职务可以发送全聊天室公告,
|
||||
* id=1 站长仍然拥有完整兜底权限。
|
||||
*
|
||||
* @param Request $request 请求对象,需包含 content, room_id
|
||||
* @return JsonResponse 操作结果
|
||||
@@ -362,22 +369,21 @@ class AdminCommandController extends Controller
|
||||
]);
|
||||
|
||||
$admin = Auth::user();
|
||||
$superLevel = (int) Sysparam::getValue('superlevel', '100');
|
||||
|
||||
if ($admin->user_level < $superLevel) {
|
||||
return response()->json(['status' => 'error', 'message' => '仅站长可发布公屏讲话'], 403);
|
||||
if (! $this->positionPermissionService->hasPermission($admin, PositionPermissionRegistry::ROOM_PUBLIC_BROADCAST)) {
|
||||
return response()->json(['status' => 'error', 'message' => '当前职务无权发布公屏讲话'], 403);
|
||||
}
|
||||
|
||||
$roomId = $request->input('room_id');
|
||||
$content = $request->input('content');
|
||||
|
||||
// 广播站长公告
|
||||
// 按当前在职职务拼装发布者身份,避免继续显示为固定“站长公告”
|
||||
$publisherLabel = $this->buildAnnouncementPublisherLabel($admin);
|
||||
$msg = [
|
||||
'id' => $this->chatState->nextMessageId($roomId),
|
||||
'room_id' => $roomId,
|
||||
'from_user' => '系统公告',
|
||||
'to_user' => '大家',
|
||||
'content' => "📢 站长 <b>{$admin->username}</b> 讲话:{$content}",
|
||||
'content' => "📢 <b>{$publisherLabel}</b> <b>{$admin->username}</b> 发布公告:{$content}",
|
||||
'is_secret' => false,
|
||||
'font_color' => '#b91c1c',
|
||||
'action' => '',
|
||||
@@ -390,6 +396,28 @@ class AdminCommandController extends Controller
|
||||
return response()->json(['status' => 'success', 'message' => '公告已发送']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成公屏公告发布者身份标签。
|
||||
*
|
||||
* 普通在职用户按“部门+职务”显示;站长无在职职务时保持“站长”标识兜底。
|
||||
*/
|
||||
private function buildAnnouncementPublisherLabel(User $user): string
|
||||
{
|
||||
$position = $user->activePosition?->position;
|
||||
|
||||
if ($position) {
|
||||
$departmentName = (string) ($position->department?->name ?? '');
|
||||
|
||||
return $departmentName.$position->name;
|
||||
}
|
||||
|
||||
if ($user->id === 1) {
|
||||
return '站长';
|
||||
}
|
||||
|
||||
return '管理员';
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员全员清屏
|
||||
*
|
||||
@@ -407,11 +435,9 @@ class AdminCommandController extends Controller
|
||||
|
||||
$admin = Auth::user();
|
||||
$roomId = $request->input('room_id');
|
||||
$superLevel = (int) Sysparam::getValue('superlevel', '100');
|
||||
|
||||
// 需要站长权限才能全员清屏
|
||||
if ($admin->user_level < $superLevel) {
|
||||
return response()->json(['status' => 'error', 'message' => '仅站长可执行全员清屏'], 403);
|
||||
// 改为按职务权限控制聊天室顶部“清屏”按钮。
|
||||
if (! $this->positionPermissionService->hasPermission($admin, PositionPermissionRegistry::ROOM_CLEAR_SCREEN)) {
|
||||
return response()->json(['status' => 'error', 'message' => '当前职务无权执行全员清屏'], 403);
|
||||
}
|
||||
|
||||
// 清除 Redis 中该房间的消息缓存
|
||||
@@ -427,7 +453,7 @@ class AdminCommandController extends Controller
|
||||
* 管理员触发全屏特效。
|
||||
*
|
||||
* 向房间内所有用户广播 EffectBroadcast 事件,前端收到后播放对应 Canvas 动画。
|
||||
* 仅 superlevel 等级管理员可触发。
|
||||
* 仅拥有 room.fullscreen_effect 权限的职务可触发。
|
||||
*
|
||||
* @param Request $request 请求对象,需包含 room_id, type
|
||||
* @return JsonResponse 操作结果
|
||||
@@ -442,11 +468,8 @@ class AdminCommandController extends Controller
|
||||
$admin = Auth::user();
|
||||
$roomId = $request->input('room_id');
|
||||
$type = $request->input('type');
|
||||
$superLevel = (int) Sysparam::getValue('superlevel', '100');
|
||||
|
||||
// 仅 superlevel 等级可触发特效
|
||||
if ($admin->user_level < $superLevel) {
|
||||
return response()->json(['status' => 'error', 'message' => '仅站长可触发特效'], 403);
|
||||
if (! $this->positionPermissionService->hasPermission($admin, PositionPermissionRegistry::ROOM_FULLSCREEN_EFFECT)) {
|
||||
return response()->json(['status' => 'error', 'message' => '当前职务无权触发特效'], 403);
|
||||
}
|
||||
|
||||
// 广播特效事件给房间内所有在线用户
|
||||
|
||||
@@ -26,9 +26,11 @@ use App\Models\User;
|
||||
use App\Services\AppointmentService;
|
||||
use App\Services\ChatStateService;
|
||||
use App\Services\MessageFilterService;
|
||||
use App\Services\PositionPermissionService;
|
||||
use App\Services\RoomBroadcastService;
|
||||
use App\Services\UserCurrencyService;
|
||||
use App\Services\VipService;
|
||||
use App\Support\PositionPermissionRegistry;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
@@ -58,6 +60,7 @@ class ChatController extends Controller
|
||||
private readonly UserCurrencyService $currencyService,
|
||||
private readonly AppointmentService $appointmentService,
|
||||
private readonly RoomBroadcastService $broadcast,
|
||||
private readonly PositionPermissionService $positionPermissionService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -278,7 +281,9 @@ class ChatController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
// 渲染主聊天框架视图
|
||||
// 渲染主聊天框架视图前,先计算当前用户的聊天室顶部管理权限。
|
||||
$roomPermissionMap = $this->positionPermissionService->permissionMapForUser($user);
|
||||
|
||||
return view('chat.frame', [
|
||||
'room' => $room,
|
||||
'user' => $user,
|
||||
@@ -289,6 +294,8 @@ class ChatController extends Controller
|
||||
'historyMessages' => $historyMessages,
|
||||
'pendingProposal' => $pendingProposalData,
|
||||
'pendingDivorce' => $pendingDivorceData,
|
||||
'roomPermissionMap' => $roomPermissionMap,
|
||||
'hasRoomManagementPermission' => in_array(true, $roomPermissionMap, true),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -892,7 +899,8 @@ class ChatController extends Controller
|
||||
|
||||
/**
|
||||
* 设置房间公告/祝福语(滚动显示在聊天室顶部)
|
||||
* 需要房间主人或等级达到 level_announcement 配置值
|
||||
* 需要当前在职职务拥有 room.announcement 权限,
|
||||
* id=1 站长始终允许操作。
|
||||
*
|
||||
* @param int $id 房间ID
|
||||
*/
|
||||
@@ -901,9 +909,8 @@ class ChatController extends Controller
|
||||
$user = Auth::user();
|
||||
$room = Room::findOrFail($id);
|
||||
|
||||
// 权限检查:房间主人 或 等级 >= level_announcement
|
||||
$requiredLevel = (int) Sysparam::getValue('level_announcement', '10');
|
||||
if ($user->username !== $room->master && $user->user_level < $requiredLevel) {
|
||||
// 改为统一走职务权限判断,不再给房主单独保留公告特权。
|
||||
if (! $this->positionPermissionService->hasPermission($user, PositionPermissionRegistry::ROOM_ANNOUNCEMENT)) {
|
||||
return response()->json(['status' => 'error', 'message' => '权限不足,无法修改公告'], 403);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* 文件功能:聊天室礼包(红包)控制器
|
||||
*
|
||||
* 提供两个核心接口:
|
||||
* - send() :superlevel 站长凭空发出 888 数量 10 份礼包(金币 or 经验)
|
||||
* - send() :拥有权限的职务用户凭空发出 8888 数量 10 份礼包(金币 or 经验)
|
||||
* - claim() :在线用户抢礼包(先到先得,每人一份)
|
||||
*
|
||||
* 接入 UserCurrencyService 记录所有货币变动流水。
|
||||
@@ -23,9 +23,10 @@ use App\Events\RedPacketSent;
|
||||
use App\Jobs\SaveMessageJob;
|
||||
use App\Models\RedPacketClaim;
|
||||
use App\Models\RedPacketEnvelope;
|
||||
use App\Models\Sysparam;
|
||||
use App\Services\ChatStateService;
|
||||
use App\Services\PositionPermissionService;
|
||||
use App\Services\UserCurrencyService;
|
||||
use App\Support\PositionPermissionRegistry;
|
||||
use Illuminate\Database\UniqueConstraintViolationException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -54,10 +55,11 @@ class RedPacketController extends Controller
|
||||
public function __construct(
|
||||
private readonly ChatStateService $chatState,
|
||||
private readonly UserCurrencyService $currencyService,
|
||||
private readonly PositionPermissionService $positionPermissionService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* superlevel 站长凭空发出礼包。
|
||||
* 拥有权限的职务用户凭空发出礼包。
|
||||
*
|
||||
* 不扣发包人自身货币,888 数量凭空发出分 10 份。
|
||||
* type 参数决定本次发出的是金币(gold)还是经验(exp)。
|
||||
@@ -75,10 +77,9 @@ class RedPacketController extends Controller
|
||||
$roomId = (int) $request->input('room_id');
|
||||
$type = $request->input('type'); // 'gold' 或 'exp'
|
||||
|
||||
// 权限校验:仅 superlevel 可发礼包
|
||||
$superLevel = (int) Sysparam::getValue('superlevel', '100');
|
||||
if ($user->user_level < $superLevel) {
|
||||
return response()->json(['status' => 'error', 'message' => '仅站长可发礼包红包'], 403);
|
||||
// 改为按职务权限码控制礼包发放。
|
||||
if (! $this->positionPermissionService->hasPermission($user, PositionPermissionRegistry::ROOM_RED_PACKET)) {
|
||||
return response()->json(['status' => 'error', 'message' => '当前职务无权发礼包红包'], 403);
|
||||
}
|
||||
|
||||
// 检查该用户在此房间是否有进行中的红包(防止刷包)
|
||||
|
||||
+22
-1
@@ -3,7 +3,8 @@
|
||||
/**
|
||||
* 文件功能:职务模型
|
||||
* 对应 positions 表,职务属于某个部门,包含等级、图标、人数上限和奖励上限
|
||||
* 任命权限通过 position_appoint_limits 中间表多对多关联定义
|
||||
* 任命权限通过 position_appoint_limits 中间表多对多关联定义,
|
||||
* 聊天室顶部管理权限通过 permissions JSON 字段配置
|
||||
*
|
||||
* @author ChatRoom Laravel
|
||||
*
|
||||
@@ -35,6 +36,7 @@ class Position extends Model
|
||||
'daily_reward_limit',
|
||||
'recipient_daily_limit',
|
||||
'sort_order',
|
||||
'permissions',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -50,6 +52,7 @@ class Position extends Model
|
||||
'daily_reward_limit' => 'integer',
|
||||
'recipient_daily_limit' => 'integer',
|
||||
'sort_order' => 'integer',
|
||||
'permissions' => 'array',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -123,6 +126,24 @@ class Position extends Model
|
||||
return $this->currentCount() >= $this->max_persons;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前职务是否拥有指定权限码。
|
||||
*/
|
||||
public function hasPermission(string $permission): bool
|
||||
{
|
||||
return in_array($permission, $this->permissions ?? [], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前职务的权限码列表。
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
public function permissionCodes(): array
|
||||
{
|
||||
return array_values($this->permissions ?? []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询范围:按位阶降序
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:职务权限判断服务
|
||||
* 负责把当前用户的在职职务权限转换为统一布尔判断,
|
||||
* 供控制器和 Blade 视图复用。
|
||||
*/
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Support\PositionPermissionRegistry;
|
||||
|
||||
/**
|
||||
* 类功能:统一提供用户职务权限读取与校验方法。
|
||||
*/
|
||||
class PositionPermissionService
|
||||
{
|
||||
/**
|
||||
* 返回当前用户拥有的全部聊天室权限码。
|
||||
*
|
||||
* 规则:
|
||||
* - id=1 站长始终拥有全部权限
|
||||
* - 其他用户仅按当前在职职务的 permissions 生效
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
public function permissionsForUser(?User $user): array
|
||||
{
|
||||
if (! $user) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($user->id === 1) {
|
||||
return PositionPermissionRegistry::codes();
|
||||
}
|
||||
|
||||
$position = $user->activePosition?->position;
|
||||
if (! $position) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_values(array_intersect(
|
||||
PositionPermissionRegistry::codes(),
|
||||
$position->permissions ?? [],
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前用户全部权限的布尔映射表。
|
||||
*
|
||||
* @return array<string, bool>
|
||||
*/
|
||||
public function permissionMapForUser(?User $user): array
|
||||
{
|
||||
$permissionMap = array_fill_keys(PositionPermissionRegistry::codes(), false);
|
||||
|
||||
foreach ($this->permissionsForUser($user) as $permission) {
|
||||
$permissionMap[$permission] = true;
|
||||
}
|
||||
|
||||
return $permissionMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否拥有指定权限码。
|
||||
*/
|
||||
public function hasPermission(?User $user, string $permission): bool
|
||||
{
|
||||
if (! in_array($permission, PositionPermissionRegistry::codes(), true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($permission, $this->permissionsForUser($user), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否至少拥有一项指定权限。
|
||||
*
|
||||
* @param list<string> $permissions
|
||||
*/
|
||||
public function hasAnyPermission(?User $user, array $permissions): bool
|
||||
{
|
||||
foreach ($permissions as $permission) {
|
||||
if ($this->hasPermission($user, $permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:职务权限码注册表
|
||||
* 统一维护聊天室顶部管理菜单可配置的全部权限码、
|
||||
* 中文标题、说明文案与默认分配规则,便于后续继续扩展。
|
||||
*/
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
/**
|
||||
* 类功能:集中定义职务权限元数据与默认权限策略。
|
||||
*/
|
||||
class PositionPermissionRegistry
|
||||
{
|
||||
/**
|
||||
* 房间公告权限。
|
||||
*/
|
||||
public const ROOM_ANNOUNCEMENT = 'room.announcement';
|
||||
|
||||
/**
|
||||
* 房间公屏讲话权限。
|
||||
*/
|
||||
public const ROOM_PUBLIC_BROADCAST = 'room.public_broadcast';
|
||||
|
||||
/**
|
||||
* 房间全员清屏权限。
|
||||
*/
|
||||
public const ROOM_CLEAR_SCREEN = 'room.clear_screen';
|
||||
|
||||
/**
|
||||
* 礼包红包权限。
|
||||
*/
|
||||
public const ROOM_RED_PACKET = 'room.red_packet';
|
||||
|
||||
/**
|
||||
* 百家乐买单活动权限。
|
||||
*/
|
||||
public const ROOM_BACCARAT_LOSS_COVER = 'room.baccarat_loss_cover';
|
||||
|
||||
/**
|
||||
* 全屏特效权限。
|
||||
*/
|
||||
public const ROOM_FULLSCREEN_EFFECT = 'room.fullscreen_effect';
|
||||
|
||||
/**
|
||||
* 返回全部权限定义。
|
||||
*
|
||||
* @return array<string, array{group: string, label: string, description: string}>
|
||||
*/
|
||||
public static function definitions(): array
|
||||
{
|
||||
return [
|
||||
self::ROOM_ANNOUNCEMENT => [
|
||||
'group' => '聊天室管理',
|
||||
'label' => '设置公告',
|
||||
'description' => '允许修改聊天室顶部滚动公告。',
|
||||
],
|
||||
self::ROOM_PUBLIC_BROADCAST => [
|
||||
'group' => '聊天室管理',
|
||||
'label' => '公屏讲话',
|
||||
'description' => '允许在聊天室内发送管理员公屏讲话。',
|
||||
],
|
||||
self::ROOM_CLEAR_SCREEN => [
|
||||
'group' => '聊天室管理',
|
||||
'label' => '全员清屏',
|
||||
'description' => '允许清除当前房间所有人的普通聊天记录。',
|
||||
],
|
||||
self::ROOM_RED_PACKET => [
|
||||
'group' => '活动管理',
|
||||
'label' => '礼包红包',
|
||||
'description' => '允许在聊天室内发出金币或经验礼包。',
|
||||
],
|
||||
self::ROOM_BACCARAT_LOSS_COVER => [
|
||||
'group' => '活动管理',
|
||||
'label' => '买单活动',
|
||||
'description' => '允许创建和结束百家乐买单活动。',
|
||||
],
|
||||
self::ROOM_FULLSCREEN_EFFECT => [
|
||||
'group' => '全屏特效',
|
||||
'label' => '全屏特效',
|
||||
'description' => '允许触发聊天室内全部全屏动画特效。',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回全部权限码列表。
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
public static function codes(): array
|
||||
{
|
||||
return array_keys(self::definitions());
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回权限码到中文标题的映射。
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public static function labelMap(): array
|
||||
{
|
||||
$labels = [];
|
||||
|
||||
foreach (self::definitions() as $code => $definition) {
|
||||
$labels[$code] = $definition['label'];
|
||||
}
|
||||
|
||||
return $labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按分组返回权限定义,供后台表单渲染。
|
||||
*
|
||||
* @return array<string, array<string, array{label: string, description: string}>>
|
||||
*/
|
||||
public static function groupedDefinitions(): array
|
||||
{
|
||||
$grouped = [];
|
||||
|
||||
foreach (self::definitions() as $code => $definition) {
|
||||
$grouped[$definition['group']][$code] = [
|
||||
'label' => $definition['label'],
|
||||
'description' => $definition['description'],
|
||||
];
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将权限码数组转换为中文标题列表。
|
||||
*
|
||||
* @param list<string> $codes
|
||||
* @return list<string>
|
||||
*/
|
||||
public static function summaryLabels(array $codes): array
|
||||
{
|
||||
$labels = self::labelMap();
|
||||
|
||||
return array_values(array_map(
|
||||
fn (string $code): string => $labels[$code] ?? $code,
|
||||
array_values(array_intersect(self::codes(), $codes))
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据职务等级返回默认权限。
|
||||
*
|
||||
* 默认策略:
|
||||
* - Lv.60 及以上默认拥有「设置公告」
|
||||
* - Lv.97 及以上默认拥有顶部管理菜单全部权限
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
public static function defaultPermissionsForLevel(int $level): array
|
||||
{
|
||||
if ($level >= 97) {
|
||||
return self::codes();
|
||||
}
|
||||
|
||||
if ($level >= 60) {
|
||||
return [self::ROOM_ANNOUNCEMENT];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user