功能:字体颜色持久化、等级体系升级至99级、钓鱼小游戏、补充系统参数
- 字体颜色:s_color 改为 varchar,发消息时保存颜色,进入聊天室自动恢复 - 等级体系:maxlevel 15→99,superlevel 16→100,99级经验阶梯(幂次曲线) - 管理权限等级按比例调整:禁言50、踢人60、设公告60、封号80、封IP90 - 钓鱼小游戏:FishingController(抛竿扣金币+收竿随机结果+广播) - 补充6个缺失的 sysparam 参数 + 4个钓鱼参数 - 用户列表点击用户名后自动聚焦输入框 - Pint 格式化
This commit is contained in:
@@ -2,11 +2,17 @@
|
||||
|
||||
/**
|
||||
* 文件功能:用户中心与管理控制器
|
||||
* 接管原版 USERinfo.ASP, USERSET.ASP, chpasswd.asp, KILLUSER.ASP
|
||||
* 接管原版 USERinfo.ASP, USERSET.ASP, chpasswd.asp, KILLUSER.ASP, LOCKIP.ASP
|
||||
*
|
||||
* 权限等级通过 sysparam 表动态配置:
|
||||
* level_kick - 踢人所需等级
|
||||
* level_mute - 禁言所需等级
|
||||
* level_ban - 封号所需等级
|
||||
* level_banip - 封IP所需等级
|
||||
*
|
||||
* @author ChatRoom Laravel
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @version 1.1.0
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
@@ -16,11 +22,13 @@ use App\Events\UserMuted;
|
||||
use App\Http\Requests\ChangePasswordRequest;
|
||||
use App\Http\Requests\UpdateProfileRequest;
|
||||
use App\Models\Room;
|
||||
use App\Models\Sysparam;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
@@ -36,7 +44,11 @@ class UserController extends Controller
|
||||
'username' => $user->username,
|
||||
'sex' => $user->sex,
|
||||
'headface' => $user->headface,
|
||||
'usersf' => $user->usersf,
|
||||
'user_level' => $user->user_level,
|
||||
'exp_num' => $user->exp_num ?? 0,
|
||||
'jjb' => $user->jjb ?? 0,
|
||||
'qianming' => $user->qianming,
|
||||
'sign' => $user->sign ?? '这个人很懒,什么都没留下。',
|
||||
'created_at' => $user->created_at->format('Y-m-d'),
|
||||
]);
|
||||
@@ -85,7 +97,41 @@ class UserController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员/房主操作:踢出房间 (对应 KILLUSER.ASP)
|
||||
* 通用权限校验:检查操作者是否有权操作目标用户
|
||||
*
|
||||
* @param object $operator 操作者
|
||||
* @param string $targetUsername 目标用户名
|
||||
* @param int $roomId 房间ID
|
||||
* @param string $levelKey sysparam中的等级键名(如 level_kick)
|
||||
* @param string $actionName 操作名称(用于错误提示)
|
||||
* @return array{room: Room, target: User}|JsonResponse
|
||||
*/
|
||||
private function checkPermission(object $operator, string $targetUsername, int $roomId, string $levelKey, string $actionName): array|JsonResponse
|
||||
{
|
||||
$room = Room::findOrFail($roomId);
|
||||
$requiredLevel = (int) Sysparam::getValue($levelKey, '15');
|
||||
|
||||
// 鉴权:操作者要是房间房主或达到所需等级
|
||||
if ($room->master !== $operator->username && $operator->user_level < $requiredLevel) {
|
||||
return response()->json(['status' => 'error', 'message' => "权限不足(需要{$requiredLevel}级),无法执行{$actionName}操作。"], 403);
|
||||
}
|
||||
|
||||
$targetUser = User::where('username', $targetUsername)->first();
|
||||
if (! $targetUser) {
|
||||
return response()->json(['status' => 'error', 'message' => '目标用户不存在。'], 404);
|
||||
}
|
||||
|
||||
// 防误伤:不能操作等级 >= 自己的人
|
||||
if ($targetUser->user_level >= $operator->user_level) {
|
||||
return response()->json(['status' => 'error', 'message' => "权限不足,无法对同级或高级用户执行{$actionName}。"], 403);
|
||||
}
|
||||
|
||||
return ['room' => $room, 'target' => $targetUser];
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢出房间 (对应 KILLUSER.ASP)
|
||||
* 所需等级由 sysparam level_kick 配置
|
||||
*/
|
||||
public function kick(Request $request, string $username): JsonResponse
|
||||
{
|
||||
@@ -96,54 +142,113 @@ class UserController extends Controller
|
||||
return response()->json(['status' => 'error', 'message' => '缺少房间参数。'], 422);
|
||||
}
|
||||
|
||||
$room = Room::findOrFail($roomId);
|
||||
|
||||
// 鉴权:操作者要是房间房主或者系统超管
|
||||
if ($room->master !== $operator->username && $operator->user_level < 15) {
|
||||
return response()->json(['status' => 'error', 'message' => '权限不足,无法执行踢出操作。'], 403);
|
||||
$result = $this->checkPermission($operator, $username, $roomId, 'level_kick', '踢出');
|
||||
if ($result instanceof JsonResponse) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$targetUser = User::where('username', $username)->first();
|
||||
if (! $targetUser) {
|
||||
return response()->json(['status' => 'error', 'message' => '目标用户不存在。'], 404);
|
||||
}
|
||||
// 广播踢出事件
|
||||
broadcast(new UserKicked($roomId, $result['target']->username, "管理员 [{$operator->username}] 将 [{$result['target']->username}] 踢出了聊天室。"));
|
||||
|
||||
// 防误伤高管
|
||||
if ($targetUser->user_level >= 15 && $operator->user_level < 15) {
|
||||
return response()->json(['status' => 'error', 'message' => '权限不足,无法踢出同级或高级管理人员。'], 403);
|
||||
}
|
||||
|
||||
// 核心动作:向频道内所有人发送包含“某某踢出某某”的事件
|
||||
broadcast(new UserKicked($roomId, $targetUser->username, "管理员 [{$operator->username}] 将 [{$targetUser->username}] 踢出了聊天室。"));
|
||||
|
||||
return response()->json(['status' => 'success', 'message' => "已成功将 {$targetUser->username} 踢出房间。"]);
|
||||
return response()->json(['status' => 'success', 'message' => "已成功将 {$result['target']->username} 踢出房间。"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员/具有道具者操作:禁言 (对应新加的限制功能)
|
||||
* 禁言 (对应原版限制功能)
|
||||
* 所需等级由 sysparam level_mute 配置
|
||||
* 禁言信息存入 Redis,TTL 到期自动解除
|
||||
*/
|
||||
public function mute(Request $request, string $username): JsonResponse
|
||||
{
|
||||
$operator = Auth::user();
|
||||
$roomId = $request->input('room_id');
|
||||
$duration = $request->input('duration', 5); // 默认封停分钟数
|
||||
$duration = (int) $request->input('duration', 5);
|
||||
|
||||
if (! $roomId) {
|
||||
return response()->json(['status' => 'error', 'message' => '缺少房间参数。'], 422);
|
||||
}
|
||||
|
||||
$room = Room::findOrFail($roomId);
|
||||
|
||||
// 此处只做简单鉴权演示,和踢人一致
|
||||
if ($room->master !== $operator->username && $operator->user_level < 15) {
|
||||
return response()->json(['status' => 'error', 'message' => '权限不足,无法执行禁言操作。'], 403);
|
||||
$result = $this->checkPermission($operator, $username, $roomId, 'level_mute', '禁言');
|
||||
if ($result instanceof JsonResponse) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// 后续可以在 Redis 中写入一个 `mute:{$username}` 并附带 `TTL` 以在后台拦截
|
||||
// 写入 Redis 禁言标记,TTL = 禁言分钟数 * 60
|
||||
Redis::setex("mute:{$roomId}:{$username}", $duration * 60, json_encode([
|
||||
'operator' => $operator->username,
|
||||
'reason' => '管理员禁言',
|
||||
'until' => now()->addMinutes($duration)->toDateTimeString(),
|
||||
]));
|
||||
|
||||
// 立刻向房间发送 Muted 事件
|
||||
// 广播禁言事件
|
||||
broadcast(new UserMuted($roomId, $username, $duration));
|
||||
|
||||
return response()->json(['status' => 'success', 'message' => "已对 {$username} 实施封口 {$duration} 分钟。"]);
|
||||
return response()->json(['status' => 'success', 'message' => "已对 {$username} 实施禁言 {$duration} 分钟。"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 封号(禁止登录)
|
||||
* 所需等级由 sysparam level_ban 配置
|
||||
* 将用户等级设为 -1 表示封禁
|
||||
*/
|
||||
public function ban(Request $request, string $username): JsonResponse
|
||||
{
|
||||
$operator = Auth::user();
|
||||
$roomId = $request->input('room_id');
|
||||
|
||||
if (! $roomId) {
|
||||
return response()->json(['status' => 'error', 'message' => '缺少房间参数。'], 422);
|
||||
}
|
||||
|
||||
$result = $this->checkPermission($operator, $username, $roomId, 'level_ban', '封号');
|
||||
if ($result instanceof JsonResponse) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// 封号:设置等级为 -1
|
||||
$result['target']->user_level = -1;
|
||||
$result['target']->save();
|
||||
|
||||
// 踢出聊天室
|
||||
broadcast(new UserKicked($roomId, $username, "管理员 [{$operator->username}] 已封禁用户 [{$username}] 的账号。"));
|
||||
|
||||
return response()->json(['status' => 'success', 'message' => "用户 {$username} 已被封号。"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 封IP(记录IP到黑名单并踢出)
|
||||
* 所需等级由 sysparam level_banip 配置
|
||||
*/
|
||||
public function banIp(Request $request, string $username): JsonResponse
|
||||
{
|
||||
$operator = Auth::user();
|
||||
$roomId = $request->input('room_id');
|
||||
|
||||
if (! $roomId) {
|
||||
return response()->json(['status' => 'error', 'message' => '缺少房间参数。'], 422);
|
||||
}
|
||||
|
||||
$result = $this->checkPermission($operator, $username, $roomId, 'level_banip', '封IP');
|
||||
if ($result instanceof JsonResponse) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$targetIp = $result['target']->last_ip;
|
||||
|
||||
if ($targetIp) {
|
||||
// 将IP加入 Redis 黑名单(永久)
|
||||
Redis::sadd('banned_ips', $targetIp);
|
||||
}
|
||||
|
||||
// 同时封号
|
||||
$result['target']->user_level = -1;
|
||||
$result['target']->save();
|
||||
|
||||
// 踢出聊天室
|
||||
broadcast(new UserKicked($roomId, $username, "管理员 [{$operator->username}] 已封禁用户 [{$username}] 的IP地址。"));
|
||||
|
||||
$ipInfo = $targetIp ? "(IP: {$targetIp})" : '(未记录IP)';
|
||||
|
||||
return response()->json(['status' => 'success', 'message' => "用户 {$username} 已被封号并封IP{$ipInfo}。"]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user