2026-02-26 13:35:38 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 文件功能:系统参数配置控制器
|
|
|
|
|
|
* (替代原版 VIEWSYS.ASP / SetSYS.ASP)
|
2026-03-03 15:00:54 +08:00
|
|
|
|
* 同时提供运维工具:缓存清理、路由清理、视图清理、房间在线名单清理
|
2026-02-26 13:35:38 +08:00
|
|
|
|
*
|
|
|
|
|
|
* @author ChatRoom Laravel
|
|
|
|
|
|
*
|
2026-03-03 15:00:54 +08:00
|
|
|
|
* @version 1.1.0
|
2026-02-26 13:35:38 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2026-03-03 15:00:54 +08:00
|
|
|
|
use Illuminate\Support\Facades\Artisan;
|
|
|
|
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
|
|
use Illuminate\Support\Facades\Redis;
|
2026-02-26 13:35:38 +08:00
|
|
|
|
use Illuminate\View\View;
|
|
|
|
|
|
|
|
|
|
|
|
class SystemController extends Controller
|
|
|
|
|
|
{
|
|
|
|
|
|
public function __construct(
|
|
|
|
|
|
private readonly ChatStateService $chatState
|
|
|
|
|
|
) {}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 显示全局参数配置表单
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function edit(): View
|
|
|
|
|
|
{
|
2026-02-27 09:41:47 +08:00
|
|
|
|
// 读取数据库中最新的参数 (剔除专属模块已接管的配置,避免重复显示)
|
|
|
|
|
|
$params = SysParam::whereNotIn('alias', ['chatbot_enabled'])
|
2026-02-27 09:47:47 +08:00
|
|
|
|
->where('alias', 'not like', 'smtp_%')
|
2026-02-27 09:41:47 +08:00
|
|
|
|
->get()->pluck('body', 'alias')->toArray();
|
2026-02-26 13:35:38 +08:00
|
|
|
|
|
|
|
|
|
|
// 为后台界面准备的文案对照 (可动态化或硬编码)
|
2026-02-27 09:41:47 +08:00
|
|
|
|
$descriptions = SysParam::whereNotIn('alias', ['chatbot_enabled'])
|
2026-02-27 09:47:47 +08:00
|
|
|
|
->where('alias', 'not like', 'smtp_%')
|
2026-02-27 09:41:47 +08:00
|
|
|
|
->get()->pluck('guidetxt', 'alias')->toArray();
|
2026-02-26 13:35:38 +08:00
|
|
|
|
|
|
|
|
|
|
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);
|
2026-02-26 21:10:34 +08:00
|
|
|
|
|
|
|
|
|
|
// 同时清除 Sysparam 模型的内部缓存
|
|
|
|
|
|
SysParam::clearCache($alias);
|
2026-02-26 13:35:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return redirect()->route('admin.system.edit')->with('success', '系统参数已成功更新并生效!');
|
|
|
|
|
|
}
|
2026-03-03 15:00:54 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 运维工具:清理应用缓存(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} 个房间的在线名单(幽灵在线已清除)");
|
|
|
|
|
|
}
|
2026-02-26 13:35:38 +08:00
|
|
|
|
}
|