Files
chatroom/plugins/chatroom-ride-development/skills/chatroom-ride-development/SKILL.md
T
2026-04-30 11:27:53 +08:00

7.0 KiB
Raw Blame History

name, description
name description
chatroom-ride-development 开发 /Users/pllx/Web/Herd/chatroom 的聊天室座驾。适用于新增 ride_<key> 独立座驾、全屏 Canvas 特效、座驾音效、后台配置、前台座驾页面和进房欢迎语。

Chatroom Ride Development

适用场景

  • 新增或修改聊天室独立座驾。
  • 新增 resources/js/effects/<key>.js 全屏座驾特效。
  • 调整座驾购买、续期、替换、入场欢迎语或后台价格/天数配置。
  • 排查座驾进房后特效不播放、欢迎语不显示、购买记录不正确的问题。
  • 排查座驾购买没有金币流水、后台座驾列表为空、前台座驾弹窗为空的问题。

必须遵守

  • 座驾是独立模块:必须使用 ridesuser_ride_purchases,不要写入 shop_itemsuser_purchases
  • 商店模块只管理普通商店商品;不要给 ShopItem 增加 TYPE_RIDEisRide()rideKey() 或座驾欢迎语字段。
  • 座驾 slug 固定为 ride_<effect_key>
  • <effect_key> 必须同时出现在:
    • rides.slug
    • rides.effect_key
    • Ride::rideKey() 可解析结果
    • EffectBroadcast::TYPES
    • resources/js/effects/effect-manager.js
    • resources/js/effects/effect-sounds.js
    • resources/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/itemsPOST /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.phpapp/Models/UserRidePurchase.php
  • 请求验证:BuyRideRequestStoreRideRequestUpdateRideRequest

已验收的进房展示规则

  • 用户有有效座驾时,座驾优先级最高:
    • 只发送一条 座驾播报 文字消息。
    • 不再发送普通 进出播报
    • 不再播放会员进场横幅或会员全屏特效。
  • 座驾全屏特效播放范围是当前房间内所有在线用户:
    • 进房用户本人通过 initialRideEffect 本地播放。
    • 其他在线用户通过 EffectBroadcastroom.{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 资源。

新增座驾步骤

  1. 新增全屏特效文件:resources/js/effects/<effect_key>.js
  2. effect-manager.js 注册模块加载和启动分支。
  3. effect-sounds.js 注册音效启动分支。
  4. EffectBroadcast::TYPES 加入 <effect_key>
  5. 在迁移或 Seeder 中新增 rides 记录,slug 使用 ride_<effect_key>effect_key 使用 <effect_key>
  6. 确认后台 座驾管理 可以配置价格、使用天数、欢迎语、上下架状态和排序。
  7. 确认 RideService::buy() 购买时写入 user_ride_purchasesuser_currency_logs
  8. 更新座驾相关 PHPUnit 测试,至少覆盖列表、余额不足、购买成功、金币流水、续期、替换和进房触发。

金币流水要求

  • 购买成功必须在 user_currency_logs 中写入:
    • currency = gold
    • amount = -座驾价格
    • source = ride_buy
    • remark = 购买聊天室座驾:<座驾名称>
    • 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 = rideshop_items.welcome_message 残留。
  • 修改座驾模块后,检查 rg 'TYPE_RIDE|ShopItem::rideKey|RideItemController|复用商店购买记录',确认没有旧方案引用。

验证清单

  • node --check resources/js/effects/<effect_key>.js
  • node --check resources/js/effects/effect-manager.js
  • node --check resources/js/effects/effect-sounds.js
  • php 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 文件时必须补齐。