Files
chatroom/app/Http/Controllers/Admin/UserManagerController.php

177 lines
6.4 KiB
PHP
Raw Normal View History

<?php
/**
* 文件功能:后台用户大盘管理控制器
* (替代原版 gl/ 下的各种管理面)
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Http\Controllers\Admin;
use App\Enums\CurrencySource;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\UserCurrencyService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\View\View;
class UserManagerController extends Controller
{
/**
* 注入统一积分服务(用于管理员调整经验/金币/魅力时记录流水)
*/
public function __construct(
private readonly UserCurrencyService $currencyService,
) {}
/**
* 显示用户列表及搜索(支持按等级/经验/金币/魅力排序)
*/
public function index(Request $request): View
{
$query = User::query();
if ($request->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
->with(['activePosition.position.department', 'vipLevel'])
->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 或表单)
*
* @param User $user 路由模型自动注入
*/
public function update(Request $request, User $user): JsonResponse|RedirectResponse
{
$targetUser = $user;
$currentUser = Auth::user();
// 越权防护:不能修改 等级大于或等于自己 的目标(除非修改自己)
if ($targetUser->id !== $currentUser->id && $targetUser->user_level >= $currentUser->user_level) {
return response()->json(['status' => 'error', 'message' => '权限不足:您无法修改同级或高级管理人员资料。'], 403);
}
$validated = $request->validate([
'sex' => 'sometimes|integer|in:0,1,2',
'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['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', '用户资料已更新!');
}
/**
* 物理删除杀封用户
*
* @param User $user 路由模型自动注入
*/
public function destroy(Request $request, User $user): RedirectResponse
{
$targetUser = $user;
$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', '目标已被物理删除。');
}
}