activePosition?->position; $query = Position::query() ->with('department') ->orderByDesc('rank'); // 仅有具体职务(非 superlevel 直通)的操作人才限制 rank 范围 if ($operatorPosition && $operator->user_level < $superLevel) { $query->where('rank', '<', $operatorPosition->rank); } $positions = $query->get()->map(fn ($p) => [ 'id' => $p->id, 'name' => $p->name, 'icon' => $p->icon, 'rank' => $p->rank, 'department' => $p->department?->name, ]); return response()->json(['status' => 'success', 'positions' => $positions]); } /** * 快速任命:将目标用户任命为指定职务 * 成功后向操作人所在聊天室广播任命公告 */ public function appoint(Request $request): JsonResponse { $request->validate([ 'username' => 'required|string|exists:users,username', 'position_id' => 'required|exists:positions,id', 'remark' => 'nullable|string|max:100', 'room_id' => 'nullable|integer|exists:rooms,id', ]); $operator = Auth::user(); $target = User::where('username', $request->username)->firstOrFail(); $position = Position::with('department')->findOrFail($request->position_id); $result = $this->appointmentService->appoint($operator, $target, $position, $request->remark); // 任命成功后广播礼花通知:优先用前端传来的 room_id,否则从 Redis 查操作人所在房间 if ($result['ok']) { $roomId = $request->integer('room_id') ?: ($this->chatState->getUserRooms($operator->username)[0] ?? null); if ($roomId) { broadcast(new AppointmentAnnounced( roomId: (int) $roomId, targetUsername: $target->username, positionIcon: $position->icon ?? '🎖️', positionName: $position->name, departmentName: $position->department?->name ?? '', operatorName: $operator->username, )); } } return response()->json([ 'status' => $result['ok'] ? 'success' : 'error', 'message' => $result['message'], ], $result['ok'] ? 200 : 422); } /** * 快速撤销:撤销目标用户当前的职务 */ public function revoke(Request $request): JsonResponse { $request->validate([ 'username' => 'required|string|exists:users,username', 'remark' => 'nullable|string|max:100', 'room_id' => 'nullable|integer|exists:rooms,id', ]); $operator = Auth::user(); $target = User::where('username', $request->username)->firstOrFail(); // 撤销前先取目标当前职务信息(撤销后就查不到了) $activeUp = $target->activePosition?->load('position.department'); $posIcon = $activeUp?->position?->icon ?? '🎖️'; $posName = $activeUp?->position?->name ?? ''; $deptName = $activeUp?->position?->department?->name ?? ''; $result = $this->appointmentService->revoke($operator, $target, $request->remark); // 撤销成功后广播通知到聊天室 if ($result['ok'] && $posName) { $roomId = $request->integer('room_id') ?: ($this->chatState->getUserRooms($operator->username)[0] ?? null); if ($roomId) { broadcast(new AppointmentAnnounced( roomId: (int) $roomId, targetUsername: $target->username, positionIcon: $posIcon, positionName: $posName, departmentName: $deptName, operatorName: $operator->username, type: 'revoke', )); } } return response()->json([ 'status' => $result['ok'] ? 'success' : 'error', 'message' => $result['message'], ], $result['ok'] ? 200 : 422); } }