Files
thebet365/AGENTS.md
mars e7e2b77906 feat(player): theme-3 移动端/PC 双端拆分与桌面投注工作台
新增 DesktopShell 及桌面端首页、赛事、钱包、记录等页面,原 H5 视图迁移至 Mobile* 并由路由 wrapper 按视口切换。补齐右侧投注单栏、赔率快捷浮层、联赛/赛事侧栏、串关与定位能力;桌面下注成功改为全局 Toast,修复侧栏成功遮罩被裁剪与底部汇总黑底。同步悬浮客服、公告卡片、三语 i18n、桌面样式体系,以及 API 赛事与 shared 包相关调整。
2026-07-07 17:07:38 +08:00

221 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md
> 给 AI 编程助手Cursor 等)看的项目速查手册,浓缩开发约定与易错点。
> 人类日常开发请优先看 `README.md` 与 `docs/`。
## 目录
| 章节 | 何时查 |
| ------------------------- | ----------------------- |
| [运行环境与仓库结构](#运行环境与仓库结构) | 不确定 monorepo 各 app 分工 |
| [本地启动](#本地启动) | 起 dev、数据库、端口 |
| [常用命令](#常用命令) | build / test / 打镜像 |
| [API 领域结构](#api-领域结构) | 业务代码该放哪个 domain |
| [API 约定](#api-约定) | 鉴权、钱包、迁移、赔率快照 |
| [前端约定](#前端约定) | 改 .vue/.ts、权限、dist |
| [i18n 改文案流程](#i18n-改文案流程) | 三语文案改哪几个文件 |
| [主题分支](#主题分支player-多皮肤) | theme-2/3/4 与 main 同步禁忌 |
| [演示账号](#演示账号开发-seed) | 本地登录测试号 |
| [文档索引](#文档索引) | 详细说明在 `docs/` 哪篇 |
| [测试与冒烟](#测试与冒烟) | Jest、UAT、smoke-tests |
| [部署注意](#部署注意) | 生产 compose、seed、打包 |
| [AI 改代码时请避免](#ai-改代码时请避免) | 常见踩坑清单 |
> **AI 会读吗?** Cursor 等工具会在对话开始时把 `AGENTS.md` 注入上下文;当前约 200 行,一般能整篇读入。文件继续变长时,索引有助于人和 AI 快速定位章节;细节仍以 `docs/` 为准,此处只写约定与指针。
## 运行环境与仓库结构
- 使用 Node 22+、pnpm 11`packageManager` 固定为 `pnpm@11.5.2`
- pnpm workspace`apps/api`NestJS/Prisma`apps/player`Vue H5`:5173`)、`apps/admin`(平台管理 + 代理合一,`:5174`)、`packages/shared`(共享类型/常量与 `public` 静态资源)。
- 前端将 `@thebet365/shared` 别名到 `packages/shared/src/index.ts`(构建产物为 CommonJS改 shared 时须更新源码导出,不要只改 `dist`
- `packages/shared` 构建前会执行 `scripts/generate-phone-countries.mjs`,再跑 `tsc`
- 本地开发 compose`docker-compose.yml`(仅 Postgres + Redis生产 compose`docker-compose.prod.yml` + `.env.docker`
## 本地启动
- 基础设施:`docker compose up -d`PostgreSQL `5432`、Redis `6379`)。
- API 环境变量:`cp .env.example apps/api/.env`;通过 workspace filter 启动时Nest 从 API 工作目录读 `.env`
- 首次数据库(仓库根目录):`pnpm db:generate``pnpm db:migrate``pnpm db:seed`
- `pnpm dev:api` 会先执行 `scripts/ensure-port-free.mjs 3000`,释放 3000 端口再启动 watch。
- 分应用启动时,**先 API**,再 `pnpm dev:player``pnpm dev:admin`;两个 Vite 都把 `/api` 代理到 `http://localhost:3000`
- Windows PowerShell 不支持 `&&` 链式命令,需分步执行或用 `;`
## 常用命令
- `pnpm dev`:先构建 shared再并行跑各 workspace 的 `dev`
- `pnpm dev:admin``pnpm dev:manage` 是同一个管理端应用。
- 全量校验:`pnpm build``pnpm test`;根目录**没有**统一的 lint/format 脚本。
- API 测试:`pnpm --filter @thebet365/api test`
- 单测文件:`pnpm --filter @thebet365/api exec jest settlement-calculator.spec.ts --runInBand`;不要用 `pnpm ... test -- ...` 传参pnpm 会把字面量 `--` 传给 Jest。
- 前端构建:`pnpm --filter @thebet365/player build``pnpm --filter @thebet365/admin build`
- 管理端体积分析:`pnpm --filter @thebet365/admin build:analyze`
- 本地镜像打包Windows`docs\docker\build-and-export-images.bat --tag latest`
- 生产更新(服务器):`./scripts/deploy-update.sh --images thebet365-images-<tag>.tar --tag <tag>`(详见 `docs/Docker部署指南.md` 第八节)。
## API 领域结构
业务规则放在 `apps/api/src/domains/*`,应用层只做编排:
| 领域 | 路径 | 职责 |
| -------------------------- | --------------------- | ------------- |
| identity | `domains/identity/` | 登录、用户、员工、RBAC |
| agent | `domains/agent/` | 代理网络、授信 |
| ledger | `domains/ledger/` | 钱包、账变 |
| catalog | `domains/catalog/` | 赛事 |
| odds | `domains/odds/` | 盘口 |
| betting | `domains/betting/` | 注单 |
| settlement | `domains/settlement/` | 结算 |
| operations | `domains/operations/` | 返水、内容、审计等 |
| player-messages / presence | 各子模块 | 站内信、在线状态 |
门户控制器:`applications/{player,admin,agent}/`
## API 约定
- 全局前缀 `/api`;非生产或 `ENABLE_SWAGGER=true` 时 Swagger 在 `/api/docs`
- `AppModule` 注册了全局 `JwtAuthGuard`;公开接口须加 `@Public()``apps/api/src/shared/common/decorators.ts`)。
- 业务规则放在 `domains/*``applications/*` 只做门户/控制器编排,不要写领域规则。
- 钱包变动走 ledger/wallet 服务UAT 明确禁止为修结算直接改余额。
- 下注赔率以提交时快照为准(`BetSelection.odds` + `oddsVersion`),结算用快照,不受后续盘口变动影响。
-`apps/api/prisma/schema.prisma` 后执行 `pnpm db:generate`;开发迁移 `pnpm db:migrate`,部署由 `deploy-update.sh` 执行 `prisma migrate deploy`
- 新增迁移后theme 分支若只改 player 样式,也须同步 API/Admin 与迁移文件。
## 前端约定
-`apps/player/src``apps/admin/src` 下的 `**.ts` / `.vue`**`src` 下虽有 `.js` 旁文件,但 `index.html` 入口是 `/src/main.ts`Vite 优先解析 TS。
- 管理端同一应用服务 `ADMIN``AGENT` 账号;路由/菜单权限在 `router/index.ts``stores/auth.ts`;员工可见菜单字段 `visibleMenus`
- 管理端权限常量:`apps/admin/src/constants/permissions.ts``AdminPerm`)。
- 玩家端移动优先;性能验收见 `docs/player-mobile-performance.md`
- 管理端切页慢的分析与优化任务见 `docs/admin-page-switch-performance.md`
- **不要**把 `apps/player/dist/` 提交进 Git生产由 Docker 构建生成静态资源。
## i18n 改文案流程
支持语言均为 **zh-CN / en-US / ms-MY**(马来语)。改文案须**三语同步**,不要只改中文。
### 玩家端(`apps/player`
| 项 | 说明 |
| ------ | ---------------------------------------------------------------- |
| 文案文件 | `apps/player/src/i18n/zh-CN.ts``en-US.ts``ms-MY.ts` |
| 结构 | **嵌套对象**(如 `bet.place_bet``nav.home` |
| 组件用法 | `useI18n()``t('bet.odds_changed')` |
| 语言切换 | `useAppLocale().setLocale()`;按需 `ensurePlayerLocale` 懒加载对应 ts 文件 |
| 存储 key | `localStorage.locale`;登录用户会 `POST /player/language` 同步后端 |
**改文案步骤:**
1. 在 Vue 里用 `t('模块.key')` 引用,**不要**在模板写死中文。
2.**三个** locale 文件的**相同路径**下各加一条(保持 key 一致)。
3. 带占位符用 vue-i18n 约定,如 `'共 {n} 场': '共 {n} 场'``t('key', { n: 3 })`
4. 本地 `pnpm dev:player` 切换语言各看一遍;热更新一般即时生效。
5. theme 分支合并 main 功能时:**只合并新增 key**,勿用 main 文件整文件覆盖theme 可能有不同措辞)。
### 管理端(`apps/admin`
| 项 | 说明 |
| --------- | ----------------------------------------------------------------------------------- |
| 核心入口 | `apps/admin/src/i18n/admin-messages.ts`(三语扁平 `Record<string, string>` |
| 列表/弹窗大段文案 | `admin-pages.ts`(中/英)、`admin-pages-ms.ts`(马来)→ 通过 spread 并入 `admin-messages` |
| 表单校验 key | `form-validation.ts``err.`* 等,用 `resolveFormError` 展示) |
| 组件用法 | `useAdminLocale().t('nav.bets')``t('key', { n: 1 })` 占位符 `{n}` |
| 语言切换 | `useAdminLocale().setLocale()``preloadAdminLocale` + `localStorage.admin_locale` |
| 动态拆包 | `bundles/{zh-CN,en-US,ms-MY}.ts` + `locale-loader.ts`(当前主包仍含三语全文,拆包未完全落地) |
**改文案步骤:**
1. 确定 key 命名:导航 `nav.`*、通用 `common.*`、页面 `user.*` / `match.*` / `deposit.*` 等,与现有前缀保持一致。
2.`admin-messages.ts` 的 **zh / en / ms 三个对象**里各加同名 key核心短文案
3. 若属于某列表页/弹窗长文案,优先加到 `admin-pages.ts`(中/英)与 `admin-pages-ms.ts`(马来)的对应 export它们会 spread 进 `admin-messages`
4. 表单校验错误throw `FormValidationError('err.xxx')` 并在三语里定义 `err.xxx`
5. 本地 `pnpm dev:admin`,右上角切换语言验证;改 `admin-pages`* 后若未刷新,重启 dev 一次。
6. Admin 与 Player **文案独立**,改玩家端不要只改 admin 文件(反之亦然)。
### 常见错误
- 只改 `zh-CN` 未改 `en-US``ms-MY` → 切换语言显示 key 或英文 fallback。
- 玩家端 key 层级不一致(如中文有 `bet.foo` 英文漏了 `bet` 层)→ `t()` 返回 key 字符串。
- 管理端在 `admin-pages.ts` 只加了 `adminPagesZh` 未加 `adminPagesEn` / `adminPagesMs`
- theme 分支用 `git checkout main -- apps/player/src/i18n/` 覆盖 → 冲掉主题分支已有翻译。
### 与业务/后台内容的关系
- **i18n 文件**:前端固定 UI 标签、按钮、提示。
- **管理端「公共管理」/ 公告 / Banner**:运营可配正文,走 API 与数据库,**不要**硬编码进 i18n玩家端公告详情等展示 API 返回内容)。
## 主题分支player 多皮肤)
| 分支 | 风格 | 注意 |
| --------- | ----------- | ------------------------------------------------------------------- |
| `main` | 暗金主题 | 生产默认发版分支 |
| `theme-2` | Pinnacle 蓝白 | 玩家 UI 与 main 分叉,**禁止** `git checkout main -- apps/player/...` 整文件覆盖 |
| `theme-3` | Dusk Coral 珊瑚玻璃(移动 + PC双端 | 同 theme-2 |
| `theme-4` | 海军蓝暗色极简 | 含悬浮客服等独有组件 |
同步功能到 theme 分支API/Admin/迁移可整目录 checkoutPlayer 只做逻辑合并 + 保留各分支 `styles.css` 与主题资源。发版前在目标分支打包镜像。
## 演示账号(开发 seed
| 角色 | 用户名 | 密码 |
| ----- | ------- | ---------- |
| 超级管理员 | admin | Admin@123 |
| 一级代理 | agent1 | Agent@123 |
| 二级代理 | agent2 | Agent@123 |
| 玩家 | player1 | Player@123 |
生产 seed 仅创建 admin + WC2026 样例数据,不含代理/玩家演示号。详见 `docs/默认数据说明.md`
## 文档索引
| 文档 | 用途 |
| ------------------------------------------- | ------------------- |
| `docs/项目启动指南.md` | 本地开发、排错、端口 |
| `docs/Docker部署指南.md` | 生产部署、备份、回滚、发版流程 |
| `docs/docker/镜像构建与导出.md` | 本地打镜像 tar |
| `docs/默认数据说明.md` | seed 数据、WC2026、48 强 |
| `docs/投注玩法说明.md` | 玩法与判赢规则 |
| `docs/结算与返水金额规则.md` | 派彩/返水金额公式 |
| `docs/settlement-and-fund-flow-analysis.md` | 结算操作流程 |
| `docs/手动充值功能说明.md` | 充值审核流程 |
| `docs/短信调试与日志说明.md` | 创蓝短信排错 |
| `docs/UAT_CHECKLIST.md` | 上线前回归清单 |
| `docs/player-mobile-performance.md` | 玩家端性能验收 |
| `docs/admin-page-switch-performance.md` | 管理端切页优化任务 |
## 测试与冒烟
- Jest 用例在 `apps/api/src/**/*.spec.ts``rootDir: src`;文档中的单元/规则测试一般不依赖真实数据库。
- 管理端「冒烟测试」页调用 DB 相关检查;`SmokeTestService` 非生产默认可用,生产需 `ALLOW_SMOKE_TESTS=true`
- UAT 回归流程见 `docs/UAT_CHECKLIST.md`(含管理端 UI 冒烟与钱包/代理额度手工检查)。
## 部署注意
- 生产 compose 使用 `.env.docker``docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --build`,或配置好后 `pnpm docker:up`
- **不要**用 example 覆盖线上 `.env.docker`;部署脚本通常只回写 `IMAGE_TAG`
- 生产首次 seed 后保持 `SEED_DATABASE=false`;迁移由 `deploy-update.sh` 执行,勿在 API 容器设 `RUN_MIGRATIONS_ON_START=true`(除非应急)。
- `scripts/prod-init-db.sh` **会清空业务数据**:须 `CONFIRM=YES`,默认先备份,再 truncate 并灌生产数据。
- 打包部署 zip`pnpm pack:deploy``pack.mjs` 会删除 `packages/shared/public` 下除 `flags``players` 外的遗留中文目录。
- 构建 player/admin 若报 `ENOENT ... public/球员`:清理 `packages/shared/public` 下错误中文目录后重试。
## AI 改代码时请避免
- 不要 `git merge main` 进 theme 分支做 player 同步(会把 main 暗金样式大量带入)。
- 不要直接改数据库余额修结算;走结算/钱包服务。
- 不要提交 `.env``.env.docker`、镜像 tar、`apps/*/dist/`
- 改 player 主题相关文件时,先确认当前分支是 `main` 还是 `theme-`*,避免用错 CSS 变量(如 theme-2 无 `--gold`)。
- 管理端改列表页性能时,参考 `docs/admin-page-switch-performance.md` 任务清单,优先 KeepAlive + 缓存而非盲目减 API 字段。