7.0 KiB
7.0 KiB
name, description
| name | description |
|---|---|
| chatroom-ride-development | 开发 /Users/pllx/Web/Herd/chatroom 的聊天室座驾。适用于新增 ride_<key> 独立座驾、全屏 Canvas 特效、座驾音效、后台配置、前台座驾页面和进房欢迎语。 |
Chatroom Ride Development
适用场景
- 新增或修改聊天室独立座驾。
- 新增
resources/js/effects/<key>.js全屏座驾特效。 - 调整座驾购买、续期、替换、入场欢迎语或后台价格/天数配置。
- 排查座驾进房后特效不播放、欢迎语不显示、购买记录不正确的问题。
- 排查座驾购买没有金币流水、后台座驾列表为空、前台座驾弹窗为空的问题。
必须遵守
- 座驾是独立模块:必须使用
rides和user_ride_purchases,不要写入shop_items或user_purchases。 - 商店模块只管理普通商店商品;不要给
ShopItem增加TYPE_RIDE、isRide()、rideKey()或座驾欢迎语字段。 - 座驾 slug 固定为
ride_<effect_key>。 <effect_key>必须同时出现在:rides.slugrides.effect_keyRide::rideKey()可解析结果EffectBroadcast::TYPESresources/js/effects/effect-manager.jsresources/js/effects/effect-sounds.jsresources/js/effects/<effect_key>.js
- 新增座驾默认通过迁移或 Seeder 写入
rides,字段至少包含名称、slug、effect_key、图标、价格、duration_days、排序和welcome_message。 welcome_message支持{name}和{ride},输出前必须转义,不能直接信任后台输入。- 当前版本只允许用户同时拥有一个 active 座驾;同款续购叠加有效期,不同款替换旧座驾并把旧记录置为
cancelled。 - 用户购买记录必须写入
user_ride_purchases,不要复用商店购买记录。 - 座驾购买扣金币必须走
UserCurrencyService::deductGoldIfEnough(),来源使用CurrencySource::RIDE_BUY,并写入user_currency_logs。 - 座驾购买接口必须携带房间 ID,并把
room_id传给金币流水,方便后台按房间追溯。 - 测试中禁止使用
Redis::flushall()清理聊天室状态;只允许清理room:*相关 key,避免把本机登录 session 一起删掉。
模块边界
- 前台接口:
GET /rides/items、POST /rides/buy。 - 后台入口:
GET /admin/rides,页面文件为resources/views/admin/rides/index.blade.php。 - 前台弹窗脚本:
resources/js/chat-room/ride-controls.js。 - 业务服务:
app/Services/RideService.php。 - 数据模型:
app/Models/Ride.php、app/Models/UserRidePurchase.php。 - 请求验证:
BuyRideRequest、StoreRideRequest、UpdateRideRequest。
已验收的进房展示规则
- 用户有有效座驾时,座驾优先级最高:
- 只发送一条
座驾播报文字消息。 - 不再发送普通
进出播报。 - 不再播放会员进场横幅或会员全屏特效。
- 只发送一条
- 座驾全屏特效播放范围是当前房间内所有在线用户:
- 进房用户本人通过
initialRideEffect本地播放。 - 其他在线用户通过
EffectBroadcast的room.{roomId}PresenceChannel 播放。 - 不设置
target_username,表示当前房间全员可见。
- 进房用户本人通过
- 座驾文字播报口径:
- 显示
部门 <部门> · 职务 <图标 职务> · 会员 <图标 会员>。 - 不在身份行前面显示
用户 <用户名>,因为后面的欢迎语模板已经包含{name}。 - 示例:
🚀 部门 办公厅 · 职务 🎖️ 技术总监 · 会员 👑 至尊会员 · 【流星】乘【东风-5C战略导弹】点火升空...
- 显示
- 座驾动画 HUD 标题口径:
- 第一行用户身份信息显示
用户 <用户名> · 部门 <部门> · 职务 <图标 职务> · 会员 <图标 会员>。 - 第二行标题只显示
乘坐【<座驾名称>】闪亮登场,不要重复用户名。 effect_user_info供动画 HUD 第一行使用,effect_title供动画 HUD 第二行使用,identity_text只供文字播报使用。
- 第一行用户身份信息显示
- 座驾购买成功必须向当前房间广播文字通知:
- 通知使用
系统传音,action = ride_purchase。 - 文案包含
【座驾】,前端会按百家乐同款紧凑卡片样式渲染。 - 通知末尾必须带
购买座驾按钮,点击调用openRideModal(),方便其他人快速购买。 - 购买通知必须写入
ChatStateService、广播MessageSent,并通过SaveMessageJob落库。
- 通知使用
- 前端改动后如果浏览器仍显示旧动画标题,必须运行
npm run build或确认 Vite dev server 已刷新,避免加载旧的public/build资源。
新增座驾步骤
- 新增全屏特效文件:
resources/js/effects/<effect_key>.js。 - 在
effect-manager.js注册模块加载和启动分支。 - 在
effect-sounds.js注册音效启动分支。 - 在
EffectBroadcast::TYPES加入<effect_key>。 - 在迁移或 Seeder 中新增
rides记录,slug 使用ride_<effect_key>,effect_key使用<effect_key>。 - 确认后台
座驾管理可以配置价格、使用天数、欢迎语、上下架状态和排序。 - 确认
RideService::buy()购买时写入user_ride_purchases和user_currency_logs。 - 更新座驾相关 PHPUnit 测试,至少覆盖列表、余额不足、购买成功、金币流水、续期、替换和进房触发。
金币流水要求
- 购买成功必须在
user_currency_logs中写入:currency = goldamount = -座驾价格source = ride_buyremark = 购买聊天室座驾:<座驾名称>room_id = 当前房间 ID
- 余额不足时不能写
user_ride_purchases,也不能写user_currency_logs。 - 不要用
$user->decrement('jjb', ...)直接扣金币。
旧方案清理要求
- 不要恢复
add_ride_fields_to_shop_items这类把座驾挂到商店表的迁移。 - 允许保留清理迁移,用于删除旧环境中
shop_items.slug like ride_%、shop_items.type = ride或shop_items.welcome_message残留。 - 修改座驾模块后,检查
rg 'TYPE_RIDE|ShopItem::rideKey|RideItemController|复用商店购买记录',确认没有旧方案引用。
验证清单
node --check resources/js/effects/<effect_key>.jsnode --check resources/js/effects/effect-manager.jsnode --check resources/js/effects/effect-sounds.jsphp artisan test --compact tests/Feature/RideControllerTest.php- 有进房逻辑变更时运行相关
ChatControllerTest过滤用例。 - 涉及商店边界时运行
php artisan test --compact tests/Feature/ShopControllerTest.php。 - 修改 PHP 后运行
vendor/bin/pint --dirty --format=agent。
特别注意
- 如果从 stash 恢复昨天的座驾特效,必须确认 untracked 父提交中的新特效文件也已恢复,不能只恢复已跟踪文件。
99a这种以数字开头的 key 在 JS 对象字面量里必须加引号。- 新座驾的展示名可以是中文,但 effect key 必须保持小写短横线/数字/字母风格,避免前后端匹配失败。
- 本项目 PHP 文件要求类和方法上方有中文 DocBlock;新增座驾相关 PHP 文件时必须补齐。