- 任命/撤销事件增加 type 字段区分类型 - 任命:全屏礼花 + 紫色弹窗 + 紫色系统消息 - 撤销:灰色弹窗 + 灰色系统消息,无礼花 - 消息分发:操作者/被操作者显示在私聊面板,其他人显示在公屏 - 系统消息加随机鼓励语(各5条轮换) - ChatStateService 修复 Redis key 前缀扫描问题(getAllActiveRoomIds) - 用户名片折叠优化:管理员视野、职务履历均可折叠 - 管理操作 + 职务操作合并为「🔧 管理操作」折叠区 - 悄悄话改为「🎁 送礼物」按钮,礼物面板内联展开
192 lines
6.3 KiB
PHP
192 lines
6.3 KiB
PHP
<?php
|
||
|
||
/**
|
||
* 文件功能:后台开发日志管理控制器(仅 id=1 超级管理员可访问)
|
||
* 提供开发日志的 CRUD 功能,发布时可选择向 Room 1 大厅广播通知
|
||
*
|
||
* @author ChatRoom Laravel
|
||
*
|
||
* @version 1.0.0
|
||
*/
|
||
|
||
namespace App\Http\Controllers\Admin;
|
||
|
||
use App\Events\ChangelogPublished;
|
||
use App\Http\Controllers\Controller;
|
||
use App\Jobs\SaveMessageJob;
|
||
use App\Models\DevChangelog;
|
||
use Illuminate\Http\RedirectResponse;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Carbon;
|
||
use Illuminate\View\View;
|
||
|
||
class ChangelogController extends Controller
|
||
{
|
||
/**
|
||
* 后台日志列表(含草稿)
|
||
*/
|
||
public function index(): View
|
||
{
|
||
$logs = DevChangelog::orderByDesc('created_at')->paginate(20);
|
||
|
||
return view('admin.changelog.index', compact('logs'));
|
||
}
|
||
|
||
/**
|
||
* 新增日志表单页(预填今日日期)
|
||
*/
|
||
public function create(): View
|
||
{
|
||
// 预填今日日期为版本号
|
||
$todayVersion = now()->format('Y-m-d');
|
||
|
||
return view('admin.changelog.form', [
|
||
'log' => null,
|
||
'todayVersion' => $todayVersion,
|
||
'typeOptions' => DevChangelog::TYPE_CONFIG,
|
||
'isCreate' => true,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 保存新日志
|
||
* 若勾选"立即发布",则记录 published_at 并可选向大厅广播通知
|
||
*/
|
||
public function store(Request $request): RedirectResponse
|
||
{
|
||
$data = $request->validate([
|
||
'version' => 'required|string|max:30',
|
||
'title' => 'required|string|max:200',
|
||
'type' => 'required|in:feature,fix,improve,other',
|
||
'content' => 'required|string',
|
||
'is_published' => 'nullable|boolean',
|
||
'notify_chat' => 'nullable|boolean',
|
||
]);
|
||
|
||
$isPublished = (bool) ($data['is_published'] ?? false);
|
||
$notifyChat = (bool) ($data['notify_chat'] ?? false);
|
||
|
||
/** @var DevChangelog $log */
|
||
$log = DevChangelog::create([
|
||
'version' => $data['version'],
|
||
'title' => $data['title'],
|
||
'type' => $data['type'],
|
||
'content' => $data['content'],
|
||
'is_published' => $isPublished,
|
||
// 只有同时勾选"通知"才记录 notify_chat,否则置 false
|
||
'notify_chat' => $isPublished && $notifyChat,
|
||
// 首次发布时记录发布时间
|
||
'published_at' => $isPublished ? Carbon::now() : null,
|
||
]);
|
||
|
||
// 如果发布且勾选了"通知大厅用户",则触发 WebSocket 广播 + 持久化到消息库
|
||
if ($isPublished && $notifyChat) {
|
||
event(new ChangelogPublished($log));
|
||
$this->saveChangelogNotification($log);
|
||
}
|
||
|
||
return redirect()->route('admin.changelogs.index')
|
||
->with('success', '开发日志创建成功!'.($isPublished ? '(已发布)' : '(草稿已保存)'));
|
||
}
|
||
|
||
/**
|
||
* 编辑日志表单页
|
||
*
|
||
* @param DevChangelog $changelog 路由模型自动注入
|
||
*/
|
||
public function edit(DevChangelog $changelog): View
|
||
{
|
||
return view('admin.changelog.form', [
|
||
'log' => $changelog,
|
||
'todayVersion' => $changelog->version,
|
||
'typeOptions' => DevChangelog::TYPE_CONFIG,
|
||
'isCreate' => false,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 更新日志内容(编辑操作不更新 published_at,不触发通知)
|
||
*
|
||
* @param DevChangelog $changelog 路由模型自动注入
|
||
*/
|
||
public function update(Request $request, DevChangelog $changelog): RedirectResponse
|
||
{
|
||
$log = $changelog;
|
||
|
||
$data = $request->validate([
|
||
'version' => 'required|string|max:30',
|
||
'title' => 'required|string|max:200',
|
||
'type' => 'required|in:feature,fix,improve,other',
|
||
'content' => 'required|string',
|
||
'is_published' => 'nullable|boolean',
|
||
'notify_chat' => 'nullable|boolean',
|
||
]);
|
||
|
||
$isPublished = (bool) ($data['is_published'] ?? false);
|
||
|
||
// 如果从草稿切换为发布,记录首次发布时间
|
||
$publishedAt = $log->published_at;
|
||
if ($isPublished && ! $log->is_published) {
|
||
$publishedAt = Carbon::now();
|
||
} elseif (! $isPublished) {
|
||
// 从发布退回草稿,清除发布时间
|
||
$publishedAt = null;
|
||
}
|
||
|
||
$log->update([
|
||
'version' => $data['version'],
|
||
'title' => $data['title'],
|
||
'type' => $data['type'],
|
||
'content' => $data['content'],
|
||
'is_published' => $isPublished,
|
||
'published_at' => $publishedAt,
|
||
]);
|
||
|
||
// 若勾选了「通知大厅用户」且当前已发布,则广播通知 + 持久化到消息库
|
||
$notifyChat = (bool) ($data['notify_chat'] ?? false);
|
||
if ($notifyChat && $isPublished) {
|
||
event(new ChangelogPublished($log));
|
||
$this->saveChangelogNotification($log);
|
||
}
|
||
|
||
return redirect()->route('admin.changelogs.index')
|
||
->with('success', '开发日志已更新!');
|
||
}
|
||
|
||
/**
|
||
* 删除日志
|
||
*
|
||
* @param DevChangelog $changelog 路由模型自动注入
|
||
*/
|
||
public function destroy(DevChangelog $changelog): RedirectResponse
|
||
{
|
||
$changelog->delete();
|
||
|
||
return redirect()->route('admin.changelogs.index')
|
||
->with('success', '日志已删除。');
|
||
}
|
||
|
||
/**
|
||
* 将版本更新通知持久化为 Room 1 系统消息
|
||
* 确保用户重进聊天室时仍能在历史消息中看到该通知
|
||
*
|
||
* @param DevChangelog $log 已发布的日志
|
||
*/
|
||
private function saveChangelogNotification(DevChangelog $log): void
|
||
{
|
||
$typeLabel = DevChangelog::TYPE_CONFIG[$log->type]['label'] ?? '更新';
|
||
$url = url('/changelog').'#v'.$log->version;
|
||
|
||
SaveMessageJob::dispatch([
|
||
'room_id' => 1,
|
||
'from_user' => '系统公告',
|
||
'to_user' => '大家',
|
||
'content' => "📢 【版本更新 {$typeLabel}】v{$log->version}《{$log->title}》— <a href=\"{$url}\" target=\"_blank\" class=\"underline\">点击查看详情</a>",
|
||
'is_secret' => false,
|
||
'font_color' => '#7c3aed',
|
||
'action' => '',
|
||
'sent_at' => now()->toIso8601String(),
|
||
]);
|
||
}
|
||
}
|