# moyu **Repository Path**: litcpu/moyu ## Basic Information - **Project Name**: moyu - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-24 - **Last Updated**: 2026-07-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 网页版「你画我猜」 > 打开网页就能和朋友一起画一起猜的多人联机小游戏。 详细设计见 [`你画我猜-开发计划.md`](./你画我猜-开发计划.md)。本文只覆盖工程层面的使用方式。 ## 状态 - ✅ 阶段 0 — 工程初始化 - ✅ 阶段 1 — 房间大厅(创建/加入/准备/房主转移/断线重连) - ✅ 阶段 2 — 游戏状态机与词库 - ✅ 阶段 3 — 实时画布(由其他 AI 完成) - ✅ 阶段 4 — 聊天、猜词与完整 UI - ✅ 阶段 5 — 测试与部署 - ⏳ 阶段 6 — 生产扩展 阶段 5 已具备:Dockerfile(apps/server + apps/web)、docker-compose 一键启动、Nginx 反向代理(含 WebSocket)、GitHub Actions CI(lint/typecheck/test/build)、Playwright E2E 测试(需 Node 18+)、单元测试 91 个全通过(含状态机非法转换、撤销、超时选词等边界 case)。 阶段 4 已具备:每局过程中任意玩家可在右侧(桌面)/底部抽屉(移动)聊天;非画手猜中按 100-500 区间得分并广播「某某猜中了」;画手聊天若含答案被拒(DRAWER_LEAK);1 秒最多 3 条速率限制;输入框在猜中后显示「你猜对了」并 10s 后恢复;房主在结算页可点「再来一局」;GamePage 三列网格 + 移动端 tab 切换 + 360px 兼容;`role=log/aria-live` + `prefers-reduced-motion` 全部尊重。服务端对 ROUND_END/GAME_END 广播链路补全,全员猜中、画手超时、所有轮结束都能正常推进。 ## 阶段 4 验收 1. A 创建房间,邀请 B 加入;2 人开始 2. A 选词开始画;B 在聊天框输入「苹果」→ 服务端标准化 + 匹配 → 广播 chat:guessed,本人收到「你猜对了」系统消息,输入框置灰 3. A 在聊天框输入「苹果」→ ACK 返回 DRAWER_LEAK,前端提示 4. A 1 秒内连发 4 条 → 第 4 条返回 RATE_LIMITED 5. 所有轮结束后显示 FinalRanking;A 点「再来一局」→ 房间进入 WORD_SELECTING,新一轮开始 6. 360px 移动端浏览器:三个 tab 切换「玩家/画布/聊天」,聊天为底部 sheet ## 目录 ``` . ├─ apps/ │ ├─ server/ NestJS + Socket.IO Gateway │ │ ├─ src/common/ 加密安全随机(sid/room code) │ │ ├─ src/health/ /health 接口 │ │ ├─ src/realtime/ 接入日志日志 Gateway │ │ └─ src/room/ 房间业务 │ │ ├─ domain/ Room/Player 聚合根、领域错误 │ │ ├─ application/ RoomService(用例) │ │ ├─ adapters/ InMemoryRoomRepository │ │ └─ room.gateway.ts 5 个房间事件 + 统一 ACK │ └─ web/ Vite + React 18 │ ├─ src/socket/ socket 客户端 + sessionStorage + 命令 │ ├─ src/stores/ roomStore / playerStore │ ├─ src/components/ PlayerList / InviteLink / RoomConfigPanel / SocketStatus │ └─ src/pages/ HomePage / RoomPage ├─ packages/ │ └─ shared/ 事件名、模型、Zod 校验、错误码、常量、ACK ├─ 你画我猜-开发计划.md └─ pnpm-workspace.yaml ``` ## 环境要求 - Node.js **>= 16.20.0** (推荐 18 / 20 LTS) - pnpm **>= 7.33.0** ```bash corepack enable corepack prepare pnpm@7.33.7 --activate ``` ## 安装 ```bash pnpm install ``` ## 常用命令 > 所有命令在仓库根目录执行。 | 命令 | 作用 | |------|------| | `pnpm dev` | 并行启动 server (NestJS, watch) 与 web (Vite) | | `pnpm build` | 构建所有包 | | `pnpm lint` | 全量 ESLint (--max-warnings=0) | | `pnpm format` | Prettier 写回 | | `pnpm format:check` | Prettier 检查 | | `pnpm typecheck` | 全量 tsc --noEmit | | `pnpm test` | 全量单元测试 | | `pnpm test:e2e` | server E2E (启动 Nest + socket.io-client) | | `pnpm clean` | 清理 dist / coverage | ### 单包命令 ```bash pnpm --filter @draw-and-guess/shared build pnpm --filter @draw-and-guess/server dev pnpm --filter @draw-and-guess/web dev pnpm --filter @draw-and-guess/server test:e2e ``` ## 环境变量 ### `apps/server/.env` ```env NODE_ENV=development PORT=3000 WEB_ORIGIN=http://localhost:5173 LOG_LEVEL=info ``` ### `apps/web/.env` ```env VITE_API_URL=http://localhost:3000 ``` ## 端口 - Web: - Server HTTP / Socket.IO: - Health: ## 阶段 1 验收 ```bash # 1. 启动两端 pnpm dev # 2. 浏览器打开 A 标签页:输入昵称 → "创建房间" → 复制邀请链接 # 3. 浏览器打开 B 标签页(无痕窗口):粘贴邀请链接 → 输入昵称 → "加入房间" # 4. B 看到 A 的玩家列表,B 点 "准备" → A 看到 B 状态变化 # 5. A 在房主设置里改"总轮数=5" → B 同步看到 # 6. 关掉 A 标签页 → B 看到 A 是 "离线" → 30 秒内 A 重新打开应该恢复原 playerId # 7. A 点 "离开房间" → B 自动接管为新房主 ``` ## 协议与规则 任何对 **事件名、状态机、计分规则** 的改动都必须先更新 `你画我猜-开发计划.md`, 与第 16 章"执行约束"一致。 ## 阶段 0 → 1 偏差(已记录) - Node 16 上线,Vite 4 / vitest 0.34(原计划 Vite 5 / vitest 1+) - shared 包走 CJS(服务端 require 友好);前端 Vite 仍能消费 - shared 的 `tsc -p` → `tsc -b`,因为 `composite: true` 必须用 build 模式 - 服务端无 `class-validator`,Gateway 全部用 Zod 校验 ## Docker 部署 一条命令在全新环境启动完整服务: ```bash # 开发环境快速启动(前端 Vite 热重载) docker-compose up --build # 生产环境 docker-compose -f docker-compose.yml up --build -d ``` 启动后: - Web UI: http://localhost (端口 80) - Server HTTP/WS: http://localhost:3000 - Health: http://localhost:3000/health ### 前置条件 - Docker Desktop (Windows/Mac) 或 Docker Engine (Linux) - Docker Compose v2 ### 环境变量 服务端支持以下环境变量: | 变量 | 默认值 | 说明 | |------|--------|------| | `NODE_ENV` | `development` | `production` 时关闭 debug 日志 | | `PORT` | `3000` | 服务端口 | | `WEB_ORIGIN` | `http://localhost:5173` | 允许的 Web 源(生产填 Nginx 地址) | | `LOG_LEVEL` | `info` | `debug`/`info`/`warn`/`error` | ### 手动构建 ```bash # 只构建后端 docker build -f apps/server/Dockerfile -t dag-server . # 只构建前端 docker build -f apps/web/Dockerfile -t dag-web . # 单独运行后端(需自行暴露端口) docker run -p 3000:3000 dag-server ``` ## Playwright E2E 测试 > 需要 Node.js >= 18(Node 16 不兼容) ```bash # 1. 安装 Playwright 浏览器(一次性) npx playwright install chromium --with-deps # 2. 确保 pnpm dev 已运行(server :3000 + web :5173) # 3. 运行 E2E pnpm test:e2e:playwright ``` CI 会自动在 Node 20 环境运行 E2E 测试。