Files
chatroom/app/Http/Controllers/Admin/SystemController.php
lkddi adb9f157e6 功能:后台系统配置页新增「运维工具」面板(仅 id=1 可见)
- 应用缓存清理:config:clear + cache:clear
- 路由缓存清理:route:clear
- 视图缓存清理:view:clear
- 幽灵在线清理:扫描并清空所有房间 Redis 在线名单

所有操作均有确认弹窗,执行结果 Flash 提示反馈。
后端 abort(403) 双重校验,非超管无法访问接口。
2026-03-03 15:00:54 +08:00

145 lines
4.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:系统参数配置控制器
* (替代原版 VIEWSYS.ASP / SetSYS.ASP)
* 同时提供运维工具:缓存清理、路由清理、视图清理、房间在线名单清理
*
* @author ChatRoom Laravel
*
* @version 1.1.0
*/
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\SysParam;
use App\Services\ChatStateService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redis;
use Illuminate\View\View;
class SystemController extends Controller
{
public function __construct(
private readonly ChatStateService $chatState
) {}
/**
* 显示全局参数配置表单
*/
public function edit(): View
{
// 读取数据库中最新的参数 (剔除专属模块已接管的配置,避免重复显示)
$params = SysParam::whereNotIn('alias', ['chatbot_enabled'])
->where('alias', 'not like', 'smtp_%')
->get()->pluck('body', 'alias')->toArray();
// 为后台界面准备的文案对照 (可动态化或硬编码)
$descriptions = SysParam::whereNotIn('alias', ['chatbot_enabled'])
->where('alias', 'not like', 'smtp_%')
->get()->pluck('guidetxt', 'alias')->toArray();
return view('admin.system.edit', compact('params', 'descriptions'));
}
/**
* 更新全局参数,并刷新全站 Cache 缓存
*/
public function update(Request $request): RedirectResponse
{
$data = $request->except(['_token', '_method']);
foreach ($data as $alias => $body) {
SysParam::updateOrCreate(
['alias' => $alias],
['body' => $body]
);
// 写入 Cache 保证极速读取
$this->chatState->setSysParam($alias, $body);
// 同时清除 Sysparam 模型的内部缓存
SysParam::clearCache($alias);
}
return redirect()->route('admin.system.edit')->with('success', '系统参数已成功更新并生效!');
}
/**
* 运维工具清理应用缓存config + cache + application
* 仅 id=1 超管可用
*/
public function clearCache(): RedirectResponse
{
if (Auth::id() !== 1) {
abort(403, '无权限操作');
}
Artisan::call('config:clear');
Artisan::call('cache:clear');
return redirect()->route('admin.system.edit')->with('ops_success', '✅ 应用缓存已清除config:clear + cache:clear');
}
/**
* 运维工具:清理路由缓存
* 仅 id=1 超管可用
*/
public function clearRoutes(): RedirectResponse
{
if (Auth::id() !== 1) {
abort(403, '无权限操作');
}
Artisan::call('route:clear');
return redirect()->route('admin.system.edit')->with('ops_success', '✅ 路由缓存已清除route:clear');
}
/**
* 运维工具:清理视图缓存
* 仅 id=1 超管可用
*/
public function clearViews(): RedirectResponse
{
if (Auth::id() !== 1) {
abort(403, '无权限操作');
}
Artisan::call('view:clear');
return redirect()->route('admin.system.edit')->with('ops_success', '✅ 视图缓存已清除view:clear');
}
/**
* 运维工具:清理所有房间 Redis 在线名单(清除幽灵在线脏数据)
* 仅 id=1 超管可用
*/
public function clearRoomOnline(): RedirectResponse
{
if (Auth::id() !== 1) {
abort(403, '无权限操作');
}
$prefix = config('database.redis.options.prefix', '');
$cursor = '0';
$cleaned = 0;
do {
[$cursor, $keys] = Redis::scan($cursor, ['match' => $prefix.'room:*:users', 'count' => 100]);
foreach ($keys ?? [] as $fullKey) {
// 去掉前缀,还原为 Laravel Facade 使用的短 Key
$shortKey = $prefix ? substr($fullKey, strlen($prefix)) : $fullKey;
Redis::del($shortKey);
$cleaned++;
}
} while ($cursor !== '0');
return redirect()->route('admin.system.edit')->with('ops_success', "✅ 已清理 {$cleaned} 个房间的在线名单(幽灵在线已清除)");
}
}