filled('username')) { $query->where('username', 'like', '%'.$request->input('username').'%'); } // 排序:允许的字段白名单,防止 SQL 注入 $sortable = ['user_level', 'exp_num', 'jjb', 'meili', 'id']; $sortBy = in_array($request->input('sort_by'), $sortable) ? $request->input('sort_by') : 'id'; $sortDir = $request->input('sort_dir') === 'asc' ? 'asc' : 'desc'; $users = $query->orderBy($sortBy, $sortDir)->paginate(20)->withQueryString(); // VIP 等级选项列表(供编辑弹窗使用) $vipLevels = \App\Models\VipLevel::orderBy('sort_order')->get(); return view('admin.users.index', compact('users', 'vipLevels', 'sortBy', 'sortDir')); } /** * 修改用户资料、等级或密码 (AJAX 或表单) */ public function update(Request $request, int $id): JsonResponse|RedirectResponse { $targetUser = User::findOrFail($id); $currentUser = Auth::user(); // 越权防护:不能修改 等级大于或等于自己 的目标(除非修改自己) if ($targetUser->id !== $currentUser->id && $targetUser->user_level >= $currentUser->user_level) { return response()->json(['status' => 'error', 'message' => '权限不足:您无法修改同级或高级管理人员资料。'], 403); } // 管理员级别 = 最高等级 + 1,后台编辑最高可设到管理员级别 $adminLevel = (int) \App\Models\Sysparam::getValue('maxlevel', '15') + 1; $validated = $request->validate([ 'sex' => 'sometimes|integer|in:0,1,2', 'user_level' => "sometimes|integer|min:0|max:{$adminLevel}", 'exp_num' => 'sometimes|integer|min:0', 'jjb' => 'sometimes|integer|min:0', 'meili' => 'sometimes|integer|min:0', 'qianming' => 'sometimes|nullable|string|max:255', 'headface' => 'sometimes|string|max:50', 'password' => 'nullable|string|min:6', 'vip_level_id' => 'sometimes|nullable|integer|exists:vip_levels,id', 'hy_time' => 'sometimes|nullable|date', ]); // 如果传了且没超权,直接赋予 if (isset($validated['user_level'])) { if ($currentUser->id !== $targetUser->id) { // 修改别人:只有真正的创始人 (ID=1) 才能修改别人的等级 if ($currentUser->id !== 1) { return response()->json(['status' => 'error', 'message' => '权限越界:只有星系创始人(站长)才能调整其他用户的行政等级!'], 403); } } $targetUser->user_level = $validated['user_level']; } if (isset($validated['sex'])) { $targetUser->sex = $validated['sex']; } if (isset($validated['exp_num'])) { // 计算差值并通过统一服务记录流水(管理员手动调整) $expDiff = $validated['exp_num'] - ($targetUser->exp_num ?? 0); if ($expDiff !== 0) { $this->currencyService->change( $targetUser, 'exp', $expDiff, CurrencySource::ADMIN_ADJUST, "管理员 {$currentUser->username} 手动调整经验", ); $targetUser->refresh(); } } if (isset($validated['jjb'])) { $jjbDiff = $validated['jjb'] - ($targetUser->jjb ?? 0); if ($jjbDiff !== 0) { $this->currencyService->change( $targetUser, 'gold', $jjbDiff, CurrencySource::ADMIN_ADJUST, "管理员 {$currentUser->username} 手动调整金币", ); $targetUser->refresh(); } } if (isset($validated['meili'])) { $meiliDiff = $validated['meili'] - ($targetUser->meili ?? 0); if ($meiliDiff !== 0) { $this->currencyService->change( $targetUser, 'charm', $meiliDiff, CurrencySource::ADMIN_ADJUST, "管理员 {$currentUser->username} 手动调整魅力", ); $targetUser->refresh(); } } if (array_key_exists('qianming', $validated)) { $targetUser->qianming = $validated['qianming']; } if (isset($validated['headface'])) { $targetUser->headface = $validated['headface']; } // VIP 会员等级设置 if (array_key_exists('vip_level_id', $validated)) { $targetUser->vip_level_id = $validated['vip_level_id'] ?: null; } if (array_key_exists('hy_time', $validated)) { $targetUser->hy_time = $validated['hy_time'] ?: null; } if (! empty($validated['password'])) { $targetUser->password = Hash::make($validated['password']); } $targetUser->save(); if ($request->wantsJson()) { return response()->json(['status' => 'success', 'message' => '用户资料已强行更新完毕!']); } return back()->with('success', '用户资料已更新!'); } /** * 物理删除杀封用户 */ public function destroy(Request $request, int $id): RedirectResponse { $targetUser = User::findOrFail($id); $currentUser = Auth::user(); // 越权防护:不允许删除同级或更高等级的账号 if ($targetUser->id !== $currentUser->id && $targetUser->user_level >= $currentUser->user_level) { abort(403, '权限不足:无法删除同级或高级账号!'); } // 管理员保护:达到踢人等级(level_kick)的用户视为管理员,不可被强杀 $levelKick = (int) \App\Models\Sysparam::getValue('level_kick', '10'); if ($targetUser->user_level >= $levelKick) { abort(403, '该用户为管理员,不允许强杀!请先在用户编辑中降低其等级。'); } $targetUser->delete(); return back()->with('success', '目标已被物理删除。'); } }