# ChatRoom 开发计划与注意事项 > **技术栈**:Laravel 12 · PHP 8.4 · Laravel Reverb (WebSocket) · Redis · MySQL 8.0 · Laravel Horizon > **原项目**:`/Users/pllx/Web/chat/hp0709`(VBScript ASP + MS Access 聊天室) > **目标域名**:`http://chatroom.test`(Herd 自动配置)| `https://chat.ay.lc`(生产环境) --- ## 一、环境版本要求 | 组件 | 版本 | | --------------------- | -------------------------- | | **PHP** | 8.4.5+ | | **Laravel Framework** | v12.x | | **Laravel Reverb** | latest(WebSocket 服务器) | | **Laravel Horizon** | v5(Redis 队列可视化管理) | | **PHPUnit** | v11(测试框架) | | **Node.js** | 20.x LTS | | **MySQL** | 8.0+ | | **Redis** | 7.x | --- ## 二、代码规范(强制执行) ### 2.1 Laravel Pint 格式化 ```bash # 提交代码前必须运行,修复格式问题 vendor/bin/pint --dirty # 检查格式问题(不修复) vendor/bin/pint --test # 格式化整个项目 vendor/bin/pint ``` ### 2.2 PHP 8.4 类型系统(必须遵守) ```php // ✅ 正确:构造函数属性提升 (Constructor Property Promotion) class ChatController extends Controller { public function __construct( private readonly ChatStateService $chatState, private readonly MessageFilterService $filter, ) {} } // ❌ 错误:不允许无参空构造函数 class SomeClass { public function __construct() {} // 禁止! } // ✅ 正确:显式返回类型 + 参数类型提示 public function send(SendMessageRequest $request): JsonResponse { // ... } // ✅ 正确:使用 PHP 8.4 新特性 // 联合类型 public function findUser(int|string $id): User|null {} // readonly 属性 class MessageDto { public function __construct( public readonly string $content, public readonly string $fromUser, public readonly int $roomId, ) {} } ``` ### 2.3 Laravel 12 中间件配置(重要) > [!IMPORTANT] > Laravel 12 已废弃 `Kernel.php`,中间件在 `bootstrap/app.php` 中配置。 ```php // bootstrap/app.php return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', api: __DIR__.'/../routes/api.php', // API 路由 channels: __DIR__.'/../routes/channels.php', // WebSocket 频道 commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware): void { // 注册聊天室登录验证中间件 $middleware->alias([ 'chat.auth' => \App\Http\Middleware\ChatAuthenticate::class, 'chat.level' => \App\Http\Middleware\LevelRequired::class, 'chat.site_owner' => \App\Http\Middleware\SiteOwnerOnly::class, ]); }) ->withExceptions(function (Exceptions $exceptions): void { // })->create(); ``` ### 2.4 中文注释规范(每个文件必须) ```php redis->hset("room:{$roomId}:users", $username, json_encode($userInfo)); } } ``` --- ## 三、首次启动(必须先执行) ```bash cd /Users/pllx/Web/Herd/chatroom # 安装 PHP 依赖(已完成) composer install # 创建数据库(已完成) mysql -u root -proot -e "CREATE DATABASE IF NOT EXISTS chatroom CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" # 运行数据库迁移 + 基础数据填充 php artisan migrate --seed # 安装前端依赖并构建(已完成) npm install npm run build ``` **开发时运行的服务**: ```bash php artisan reverb:start --debug # WebSocket 服务器 :8080 php artisan horizon # 队列 Worker(含 Web 监控 /horizon) npm run dev # Vite 热更新(开发阶段) # HTTP 由 Herd 自动提供 chatroom.test ``` --- ## 四、数据库迁移对照表 **原 Access 表** → **Laravel Migration** 对应关系: | 原 ASP 表 | Laravel 迁移文件 | Model 类 | 说明 | | ----------- | ---------------------------------- | ------------------- | ---------------------------------- | | `user` | `create_users_table` | `User` | 主用户表(含 jjb 金币 / exp 经验) | | `room` | `create_rooms_table` | `Room` | 聊天房间 | | _(内存)_ | `create_messages_table` | `Message` | 消息归档(实时用 Redis) | | `sysparam` | `create_sys_params_table` | `Sysparam` | 系统参数(alias/guidetxt/body) | | `ip_lock` | `create_ip_locks_table` | `IpLock` | IP 封锁 | | `record` | `create_audit_logs_table` | `AuditLog` | 管理操作日志 | | `guestbook` | `create_guestbooks_table` | `Guestbook` | 留言板 | | `calls` | `create_friend_calls_table` | `FriendCall` | 好友呼叫 | | `friendrq` | `create_friend_requests_table` | `FriendRequest` | 好友申请 | | `action` | `create_actions_table` | `Action` | 表情/动作定义 | | `admincz` | `create_admin_logs_table` | `AdminLog` | 管理员操作统计 | | `gg` | `create_user_items_table` | `UserItem` | 道具(封口令等) | | `scrollad` | `create_scroll_ads_table` | `ScrollAd` | 滚动公告 | | `hy` / `lh` | `create_marriages_table` | `Marriage` | 婚姻关系 | | `ip` | `create_ip_logs_table` | `IpLog` | IP 登录日志 | | `room_des` | `create_room_descriptions_table` | `RoomDescription` | 房间描述模板 | | `autoact` | `create_autoacts_table` | `Autoact` | 机器人随机事件 | | _(新增)_ | `create_gifts_table` | `Gift` | 礼物/鲜花定义(名称/图标/金币) | | _(新增)_ | `create_shop_items_table` | `ShopItem` | 商店商品(特效卡/改名卡等) | | _(新增)_ | `create_user_purchases_table` | `UserPurchase` | 用户购买记录 | | _(新增)_ | `create_vip_levels_table` | `VipLevel` | VIP 会员等级(倍率/进入模板) | | _(新增)_ | `create_ai_provider_configs_table` | `AiProviderConfig` | AI 服务商配置(多厂商支持) | | _(新增)_ | `create_ai_usage_logs_table` | `AiUsageLog` | AI 使用日志(Token 用量记录) | | _(新增)_ | `create_username_blacklist_table` | `UsernameBlacklist` | 用户名黑名单 | --- ## 五、推荐目录结构 ``` app/ ├── Events/ # WebSocket 广播事件(ShouldBroadcast) │ ├── MessageSent.php # 消息发送(替代 NEWSAY.ASP) │ ├── UserJoined.php # 用户进房(替代 INIT.ASP) │ ├── UserLeft.php # 用户离开(替代 LEAVE.ASP) │ ├── UserKicked.php # 踢人 │ ├── UserMuted.php # 封口 │ ├── UserLevelUp.php # 用户升级通知 │ ├── RoomTitleUpdated.php # 房间标题更新 │ ├── ScreenCleared.php # 管理员清屏 │ └── EffectBroadcast.php # 特效广播(烟花/下雨等) │ ├── Services/ # 业务逻辑服务层(纯 PHP,不含 HTTP 逻辑) │ ├── ChatStateService.php # Redis 全局状态(替代 Application 对象) │ ├── MessageFilterService.php # 敏感词/HTML 过滤 │ ├── UserLevelService.php # 等级权限判断(替代 getLevel()) │ ├── AiChatService.php # AI 聊天服务(多厂商适配:OpenAI/DeepSeek 等) │ ├── VipService.php # VIP 开通/到期检查 │ └── ShopService.php # 商店购买 + 道具激活逻辑 │ ├── Http/ │ ├── Controllers/ │ │ ├── AuthController.php # DEFAULT.asp + CHECK.asp + CLOSE.ASP │ │ ├── ChatController.php # NEWSAY.ASP + INIT.ASP + LEAVE.ASP + 心跳 │ │ ├── RoomController.php # ROOM*.ASP 系列(大厅/创建/编辑/删除/转让) │ │ ├── UserController.php # USERSET + DOUSER + KILLUSER + 封禁/解封 │ │ ├── GuestbookController.php # GUEST.ASP(留言板) │ │ ├── LeaderboardController.php # TOP10.ASP(排行榜) │ │ ├── ShopController.php # 商店购买 + 改名 │ │ ├── ChatBotController.php # AI 聊天机器人接口 │ │ ├── FishingController.php # 钓鱼小游戏(复刻原版 diaoyu/ 功能) │ │ ├── AdminCommandController.php # 聊天室内管理员快捷命令 │ │ └── Admin/ │ │ ├── DashboardController.php # 后台首页总览 │ │ ├── SystemController.php # VIEWSYS.ASP 系统参数配置 │ │ ├── UserManagerController.php # 用户大盘管理 │ │ ├── RoomManagerController.php # 房间大盘管理 │ │ ├── AutoactController.php # 随机事件管理 │ │ ├── VipController.php # VIP 等级 CRUD │ │ ├── AiProviderController.php # AI 厂商配置管理 │ │ └── SmtpController.php # 邮件发信配置 │ │ │ ├── Middleware/ │ │ ├── ChatAuthenticate.php # 聊天室登录验证(检查 Session) │ │ ├── LevelRequired.php # 等级权限中间件(chat.level:super) │ │ └── SiteOwnerOnly.php # 超级站长专属(chat.site_owner) │ │ │ └── Requests/ # Form Request 验证 │ ├── LoginRequest.php │ ├── SendMessageRequest.php │ └── CreateRoomRequest.php │ ├── Models/ │ ├── User.php ├── Room.php ├── Message.php │ ├── Sysparam.php ├── IpLock.php ├── IpLog.php │ ├── AuditLog.php ├── AdminLog.php ├── Guestbook.php │ ├── FriendCall.php ├── FriendRequest.php ├── Marriage.php │ ├── Action.php ├── Autoact.php ├── ScrollAd.php │ ├── RoomDescription.php ├── UserItem.php ├── Gift.php │ ├── ShopItem.php ├── UserPurchase.php ├── VipLevel.php │ ├── AiProviderConfig.php ├── AiUsageLog.php ├── UsernameBlacklist.php │ └── System/ │ └── PlatformSmtpAccount.php │ └── Jobs/ └── SaveMessageJob.php # 异步将消息持久化到 MySQL bootstrap/ └── app.php # ⚠ Laravel 12:中间件/路由在此配置(无 Kernel.php) routes/ ├── web.php # 所有 HTTP 路由 ├── api.php # API 路由(验证码等) └── channels.php # WebSocket Presence Channel 鉴权 ``` --- ## 六、具体开发任务计划 > **图例**:`[x]` 已完成 · `[/]` 进行中 · `[ ]` 待开发 --- ### ✅ 第一阶段:数据库层 - [x] 修改默认 `users` 迁移(username/jjb/exp/sex/headface/user_level/email 等) - [x] 创建 `rooms` 迁移(room_name/owner/auto/des/title/permit_level/door_open) - [x] 创建 `messages` 迁移(room_id/from_user/to_user/content/is_secret/font_color/action/sent_at) - [x] 创建 `sys_params` 迁移(alias/guidetxt/body) - [x] 创建 `ip_locks` 迁移 - [x] 创建 `audit_logs` 迁移 - [x] 创建 `guestbooks` 迁移 - [x] 创建 `friend_calls` 迁移 - [x] 创建 `friend_requests` 迁移 - [x] 创建 `actions` 迁移 - [x] 创建 `admin_logs` 迁移 - [x] 创建 `user_items` 迁移(封口令道具) - [x] 创建 `scroll_ads` 迁移 - [x] 创建 `marriages` 迁移 - [x] 创建 `ip_logs` 迁移 - [x] 创建 `room_descriptions` 迁移 - [x] 创建 `autoacts` 迁移(随机事件/机器人自动发言) - [x] 创建 `gifts` 迁移(礼物定义:emoji/cost/charm) - [x] 创建 `shop_items` 迁移(商店商品:特效卡/改名卡) - [x] 创建 `user_purchases` 迁移(购买记录) - [x] 创建 `vip_levels` 迁移(VIP 等级:倍率/进入模板/价格) - [x] 创建 `ai_provider_configs` 迁移(AI 服务商配置) - [x] 创建 `ai_usage_logs` 迁移(AI 用量日志) - [x] 创建 `username_blacklist` 迁移(用户名黑名单) - [x] 创建所有 Model 文件(含 `$fillable`、`$casts`、关联关系、中文 DocBlock) - [x] 创建 `DatabaseSeeder`(默认房间「公共大厅」、系统参数) - [x] 运行 `php artisan migrate --seed` 验证建表成功 --- ### ✅ 第二阶段:Auth 认证 - [x] `AuthController::login()` — 登录(含 IP 封锁检查 + 密码 bcrypt) - [x] `AuthController::logout()` — 退出并清理 Redis 用户状态 - [x] `ChatAuthenticate` 中间件 — 检查 Session 是否有效 - [x] `LevelRequired` 中间件 — 权限等级检查(`chat.level:super`) - [x] `SiteOwnerOnly` 中间件 — 超级站长专属(最高权限区块) - [x] 登录 Blade 视图 `resources/views/index.blade.php` - [x] 测试:登录 → 退出完整流程 --- ### ✅ 第三阶段:Redis 状态层 - [x] `ChatStateService` — 完整实现(userJoin/userLeave/getRoomUsers/pushMessage/nextMsgId/withLock/getSysParam) - [x] `MessageFilterService` — 敏感词替换 + HTML 过滤 - [x] `UserLevelService` — 等级权限判断 --- ### ✅ 第四阶段:WebSocket 广播 - [x] `MessageSent` Event(广播到 `room.{id}` Presence Channel) - [x] `UserJoined` Event — 用户进入广播 - [x] `UserLeft` Event — 用户离开广播 - [x] `UserKicked` Event — 踢人广播(私有频道) - [x] `UserMuted` Event — 封口广播 - [x] `UserLevelUp` Event — 升级通知广播 - [x] `RoomTitleUpdated` Event — 标题更新广播 - [x] `ScreenCleared` Event — 管理员清屏广播 - [x] `EffectBroadcast` Event — 特效广播(烟花/下雨/闪电/彩带) - [x] `routes/channels.php` — Presence Channel 鉴权 - [x] `resources/js/chat.js` — Laravel Echo 接入 - [x] Reverb 连通性测试通过 --- ### ✅ 第五阶段:聊天核心 - [x] `ChatController::init()` — 进入房间(历史消息 + 在线用户) - [x] `ChatController::send()` — 发言(过滤 → Redis → SaveMessageJob → 广播) - [x] `ChatController::heartbeat()` — 挂机心跳(限流:每分钟6次) - [x] `ChatController::leave()` — 离开房间 - [x] `ChatController::headfaceList()` — 头像列表 - [x] `ChatController::changeAvatar()` — 修改头像 - [x] `ChatController::setAnnouncement()` — 设置房间公告 - [x] `ChatController::sendFlower()` — 送花/礼物(扣金币 + 增魅力) - [x] `SaveMessageJob` — 异步消息持久化到 MySQL - [x] 聊天主界面 Blade 视图 `resources/views/chat/frame.blade.php` - [x] 测试:进房 → 发言 → 实时收到消息 --- ### ✅ 第六阶段:房间管理 - [x] `RoomController::index()` — 大厅房间列表 - [x] `RoomController::store()` — 创建房间 - [x] `RoomController::update()` — 修改设置 - [x] `RoomController::destroy()` — 删除/解散房间 - [x] `RoomController::transfer()` — 转让房主 - [x] 对应 Blade 视图(大厅列表、引导页) --- ### ✅ 第七阶段:用户管理 - [x] `UserController::show()` — 用户名片/资料页 - [x] `UserController::updateProfile()` — 修改个人资料 - [x] `UserController::changePassword()` — 改密码 - [x] `UserController::kick()` — 踢人 - [x] `UserController::mute()` — 封口 - [x] `UserController::ban()` — 封号 - [x] `UserController::banIp()` — 封 IP - [x] 邮箱验证码发送(`Api\VerificationController`) --- ### ✅ 第八阶段:管理后台 - [x] `Admin\DashboardController` — 后台首页总览 - [x] `Admin\SystemController` — 系统参数配置 - [x] `Admin\SmtpController` — 邮件发信配置 - [x] `Admin\UserManagerController` — 用户大盘管理(编辑/删除) - [x] `Admin\RoomManagerController` — 房间大盘管理 - [x] `Admin\AutoactController` — 随机事件 CRUD 管理 - [x] `Admin\VipController` — VIP 等级 CRUD 管理 - [x] `Admin\AiProviderController` — AI 厂商配置管理(含启用/禁用/设为默认) - [x] Horizon 面板 `/horizon`(队列监控) - [x] 对应 Blade 视图 --- ### ✅ 第九阶段:外围功能 - [x] `LeaderboardController` — 风云排行榜(经验/金币/魅力榜) - [x] `GuestbookController` — 留言板(发表/删除) --- ### ✅ 第十阶段:扩展玩法 - [x] **钓鱼小游戏** `FishingController` — 复刻原版 `diaoyu/` 功能(投竿/收竿/随机收益) - [x] **AI 聊天机器人** `ChatBotController` + `AiChatService`(多厂商:OpenAI/DeepSeek/Gemini 等) - [x] **礼物/送花系统** — `Gift` 模型 + `ChatController::sendFlower()`(金币消耗 + 魅力增量) - [x] **商店系统** `ShopController` + `ShopService`(购买特效卡/改名卡,`ShopItem` + `UserPurchase`) - [x] **VIP 会员系统** `VipService` + `VipLevel`(进入/离开专属模板、倍率加成) - [x] **管理员快捷命令** `AdminCommandController`(警告/踢人/封口/冻结/清屏/全服广播/特效) - [x] **特效系统** `EffectBroadcast` Event(烟花/下雨/闪电/彩带,支持单次卡/周卡) --- ### 🔲 待完善事项 - [ ] **用户名黑名单管理**(后台 CRUD,`UsernameBlacklist` 模型已建,路由/界面待完成) - [ ] **滚动公告管理**(后台 CRUD,`ScrollAd` 模型已建,界面待完成) - [ ] **好友系统**(`FriendCall` / `FriendRequest` 模型已建,Controller 待完成) - [ ] **婚姻系统**(`Marriage` 模型已建,界面待完成) - [ ] **历史数据迁移**(从 Access 导入旧用户数据:GBK→UTF-8 转换) - [ ] **密码兼容过渡**(旧 MD5 用户登录时自动升级为 bcrypt) - [ ] **单元测试**(核心 Service 层测试覆盖率) - [ ] **Flash 游戏替代**(`game/`、`pig/` 等 .swf 文件,考虑 HTML5/Canvas 重写) --- ## 七、注意事项 ### 7.1 密码兼容策略 - 导入旧数据时,`password` 字段存原始 MD5 值(32位字符串) - 登录时双模式验证:`md5($input) === $storedPass` 成功后升级为 `bcrypt` - 新注册用户直接用 `bcrypt`(`Hash::make()`) ### 7.2 字符编码 - 原 Access 数据库为 **GBK 编码** - 所有 MySQL 表必须 `utf8mb4_unicode_ci` - 导入历史数据前转换: ```bash iconv -f GBK -t UTF-8 原文件.csv > 目标文件_utf8.csv ``` ### 7.3 REFRESH.ASP 已废弃 原系统的 6 秒 `` **完全由 Reverb WebSocket 实时推送取代**,无需任何轮询逻辑。 ### 7.4 Application 对象替代 | 原 ASP | Laravel 替代 | | ------------------------------- | --------------------------------------------- | | `Application("_user_list")` | `Redis::hgetall("room:{id}:users")` | | `Application("_says")` 环形缓冲 | `Redis::lrange("room:{id}:messages", 0, 199)` | | `Application("_room_list")` | `Redis::get("room:{id}:info")` + `rooms` 表 | | `Application.Lock/Unlock` | `Cache::lock("key", 10)->block(5, fn)` | ### 7.5 Flash 游戏(暂不处理) `game/`、`pig/`、`Gupiao/` 等目录内的 `.swf` Flash 文件现代浏览器已不支持,**本期不做转换**。 ### 7.6 AI 机器人多厂商支持 `AiChatService` 支持以下 Provider,通过 `ai_provider_configs` 后台配置切换: | Provider | 推荐模型 | 说明 | | ---------- | ------------------ | ---------------------------- | | `openai` | `gpt-4o-mini` | OpenAI 官方 API | | `deepseek` | `deepseek-chat` | 国产低成本,兼容 OpenAI 接口 | | `gemini` | `gemini-1.5-flash` | Google Gemini | ### 7.7 商店商品类型说明 | type | slug 示例 | 说明 | | ---------- | ---------------- | ---------------------- | | `instant` | `once_fireworks` | 单次特效卡(即时生效) | | `duration` | `week_fireworks` | 周卡(7天内持续生效) | | `rename` | `rename` | 改名卡(改变显示名称) | --- ## 八、常用命令速查 ```bash # 创建 Model + Migration(-m 同时生成迁移) php artisan make:model Room -m # 创建 Controller(-r 生成 RESTful 方法) php artisan make:controller ChatController # 创建广播 Event php artisan make:event MessageSent # 创建队列 Job php artisan make:job SaveMessageJob # 创建 Middleware php artisan make:middleware ChatAuthenticate # 创建 Form Request php artisan make:request SendMessageRequest # 重置迁移(开发阶段) php artisan migrate:fresh --seed # 查看路由列表 php artisan route:list --columns=method,uri,name,action # 代码格式化(提交前必须运行) vendor/bin/pint --dirty # Horizon 队列监控(生产环境) php artisan horizon # 重启 Horizon(更新代码后) php artisan horizon:terminate # 清理所有缓存 php artisan optimize:clear ``` --- > 原 ASP 源码参考路径:`/Users/pllx/Web/chat/hp0709/` > 数据库 SQL 参考:`/Users/pllx/Web/chat/hp0709_php/database.sql`