---
name: 伙伴泡泡三端项目搭建
overview: 在 paopao 目录下新建 server（Node.js 后台）、big-screen（大屏展示页）、admin（后台管理系统）三个项目，与现有 minigame-1 并列，实现小游戏画面实时投屏到大屏、游戏数据持久化存储、后台管理控制等完整功能链路。
todos:
  - id: server-init
    content: "Phase 1.1: 初始化 server 项目（Express + Socket.io + 基础中间件 + 项目结构）"
    status: completed
  - id: server-prisma
    content: "Phase 1.2: 配置 Prisma + MySQL 5.7，定义 Room / GameSession / ScreenConfig 数据模型，执行迁移"
    status: completed
  - id: server-socket
    content: "Phase 1.3: 实现 Socket.io 事件处理（room:join / room:state 转发 / screen:bindRoom 等）"
    status: completed
  - id: server-api
    content: "Phase 1.4: 实现 REST API（rooms / sessions / screens / stats 四组路由）"
    status: completed
  - id: bigscreen-init
    content: "Phase 2.1: 初始化 big-screen 项目（Vite + 基础 HTML/Canvas 结构）"
    status: completed
  - id: bigscreen-renderer
    content: "Phase 2.2: 移植 minigame-1 渲染逻辑到浏览器端（背景、泡泡、爆炸、射击器、得分），去除 wx.* 依赖"
    status: completed
  - id: bigscreen-socket
    content: "Phase 2.3: 对接 Socket.io，接收游戏状态帧数据，驱动 Canvas 渲染循环"
    status: completed
  - id: bigscreen-scaler
    content: "Phase 2.4: 实现大屏自适应缩放 + 等待画面 + 游戏结束展示"
    status: completed
  - id: minigame-socket
    content: "Phase 3.1: minigame-1 新增 WebSocket 连接模块（wx.connectSocket），实现房间加入和状态上报"
    status: completed
  - id: minigame-serialize
    content: "Phase 3.2: DataBus 添加 serialize() 方法，Main.loop() 中每 2 帧发送一次状态"
    status: completed
  - id: admin-init
    content: "Phase 4.1: 初始化 admin 项目（Vue 3 + Vite + Element Plus + Vue Router + Pinia + Axios）"
    status: completed
  - id: admin-layout
    content: "Phase 4.2: 实现管理后台布局（侧边栏导航 + 顶栏 + 内容区）"
    status: completed
  - id: admin-dashboard
    content: "Phase 4.3: 实现 Dashboard 总览页（统计卡片 + 实时房间列表）"
    status: completed
  - id: admin-rooms
    content: "Phase 4.4: 实现房间管理页 + 房间详情页"
    status: completed
  - id: admin-sessions
    content: "Phase 4.5: 实现游戏记录页（分页列表、筛选）"
    status: completed
  - id: admin-screens
    content: "Phase 4.6: 实现大屏控制页（绑定/解绑房间投屏）"
    status: completed
  - id: integration-test
    content: "Phase 5: 全链路联调测试（小游戏→服务器→大屏 实时投屏通路）"
    status: pending
isProject: false
---

# 伙伴泡泡三端项目搭建规划

## 整体目录结构

```
paopao/
├── minigame-1/       # [已有] 微信小游戏端
├── server/           # [新建] Node.js 后台服务（Express + Socket.io + Prisma + MySQL 5.7）
├── big-screen/       # [新建] 大屏展示页（Vite + Canvas 2D 纯渲染）
└── admin/            # [新建] 后台管理系统（Vue 3 + Vite + Element Plus）
```

## 整体数据流架构

```mermaid
flowchart LR
    subgraph phone [微信小游戏]
        MiniGame["minigame-1"]
    end
    subgraph backend [Node.js 后台]
        API["REST API"]
        WS["Socket.io"]
        DB["MySQL 5.7 / Prisma"]
    end
    subgraph screens [展示端]
        BigScreen["大屏 Web"]
        Admin["管理后台"]
    end

    MiniGame -->|"WebSocket 实时状态"| WS
    MiniGame -->|"HTTP 提交分数"| API
    WS -->|"转发游戏状态"| BigScreen
    API <-->|"数据增删改查"| DB
    Admin <-->|"REST API"| API
    Admin -->|"指定投屏房间"| WS
    WS -->|"通知大屏切换房间"| BigScreen
```



---

## 一、server — Node.js 后台服务

### 技术选型

- **框架**: Express（成熟稳定，社区生态好，后期扩展方便）
- **WebSocket**: Socket.io（内置房间机制、自动重连、心跳检测）
- **ORM**: Prisma（类型安全、迁移管理、开发体验好）
- **数据库**: MySQL 5.7（生产级关系型数据库，稳定可靠）
- **驱动**: mysql2（Prisma 连接 MySQL 的底层驱动）
- **其他**: cors、dotenv、nodemon

### 数据库模型设计

- **Room（房间表）**: id, roomId(6位数字), status(playing/finished/waiting), createdAt, updatedAt
- **GameSession（游戏局表）**: id, roomId(FK), score, duration(秒), startedAt, endedAt, status(playing/finished)
- **ScreenConfig（大屏配置表）**: id, screenName, currentRoomId(当前投屏的房间ID), createdAt, updatedAt

### Socket.io 事件设计


| 事件名                  | 方向              | 说明                |
| -------------------- | --------------- | ----------------- |
| `room:join`          | 小游戏 → 服务器       | 手机端加入房间，携带 roomId |
| `room:state`         | 小游戏 → 服务器 → 大屏  | 实时游戏状态帧数据转发       |
| `room:gameOver`      | 小游戏 → 服务器       | 游戏结束，保存分数到数据库     |
| `screen:bindRoom`    | 管理后台 → 服务器 → 大屏 | 管理后台指定大屏展示某房间     |
| `screen:join`        | 大屏 → 服务器        | 大屏端连接并注册          |
| `screen:roomChanged` | 服务器 → 大屏        | 通知大屏切换展示房间        |


### REST API 设计

- `GET /api/rooms` — 获取所有房间列表（含状态）
- `GET /api/rooms/:roomId` — 获取指定房间详情
- `GET /api/sessions` — 获取游戏局列表（支持分页、按房间筛选）
- `GET /api/sessions/:id` — 获取单局详情
- `GET /api/stats/overview` — 总览统计（总局数、总玩家、平均分等）
- `POST /api/screens/:screenId/bindRoom` — 绑定大屏到指定房间
- `GET /api/screens` — 获取所有大屏及其当前绑定状态

### 项目结构

```
server/
├── src/
│   ├── app.js              # Express 应用入口
│   ├── socket/
│   │   ├── index.js         # Socket.io 初始化
│   │   ├── roomHandler.js   # 房间相关事件处理
│   │   └── screenHandler.js # 大屏相关事件处理
│   ├── routes/
│   │   ├── rooms.js         # 房间 API
│   │   ├── sessions.js      # 游戏局 API
│   │   ├── screens.js       # 大屏配置 API
│   │   └── stats.js         # 统计 API
│   └── prisma/
│       └── schema.prisma    # 数据库模型
├── package.json
├── .env
└── nodemon.json
```

---

## 二、big-screen — 大屏展示页

### 技术选型

- **构建工具**: Vite（快速热更新）
- **渲染方案**: 原生 Canvas 2D（复用 minigame-1 的绘制逻辑，无需 UI 框架）
- **通信**: Socket.io-client

### 核心功能

1. **连接服务器**: 通过 Socket.io 连接后台，监听 `screen:roomChanged` 获取当前应展示的房间
2. **接收游戏状态**: 监听 `room:state` 事件，接收小游戏实时帧数据
3. **Canvas 渲染**: 将 minigame-1 的渲染逻辑（背景、泡泡网格、飞行泡泡、爆炸特效、射击器）移植到浏览器端
4. **自适应布局**: 按大屏分辨率等比缩放，保持竖版游戏画面居中
5. **等待/空闲态**: 无房间绑定或无数据时展示等待画面（房间号、二维码等）
6. **游戏结束态**: 展示得分卡片

### 需要从 minigame-1 移植的渲染模块

以下文件的绘制逻辑需要适配浏览器端（主要是去除 `wx.*` API 依赖）：

- [js/runtime/background.js](minigame-1/js/runtime/background.js) — 紫色星空背景绘制
- [js/bubble/bubble.js](minigame-1/js/bubble/bubble.js) — `drawBubble3D()` 泡泡绘制、`gridToScreen()` 坐标转换、颜色定义
- [js/effects/explosion.js](minigame-1/js/effects/explosion.js) — 爆炸粒子特效
- [js/bubble/shooter.js](minigame-1/js/bubble/shooter.js) — 射击器和瞄准线绘制（仅渲染部分，不含触摸交互）
- [js/runtime/gameinfo.js](minigame-1/js/runtime/gameinfo.js) — 得分显示、游戏结束卡片

关键适配点：

- `wx.createImage()` → `new Image()`
- `wx.createCanvas()` → `document.createElement('canvas')`
- 屏幕尺寸从 `wx.getWindowInfo()` → `window.innerWidth / innerHeight`
- 泡泡精灵图 `images/bubble.png` 需复制到大屏项目的静态资源目录

### 项目结构

```
big-screen/
├── index.html
├── src/
│   ├── main.js              # 入口：初始化 Canvas、Socket 连接
│   ├── socket.js            # Socket.io 客户端封装
│   ├── renderer/
│   │   ├── background.js    # 背景渲染（移植）
│   │   ├── bubbleGrid.js    # 泡泡网格渲染（移植）
│   │   ├── bubble.js        # 单泡泡绘制 + 颜色常量（移植）
│   │   ├── shooter.js       # 射击器渲染（移植，仅绘制）
│   │   ├── explosion.js     # 爆炸特效（移植）
│   │   └── gameinfo.js      # 得分和结束画面（移植）
│   ├── stateManager.js      # 接收并管理游戏状态
│   └── scaler.js            # 屏幕自适应缩放计算
├── public/
│   └── images/
│       └── bubble.png       # 泡泡精灵图（从 minigame-1 复制）
├── package.json
└── vite.config.js
```

---

## 三、admin — 后台管理系统

### 技术选型

- **框架**: Vue 3 + Composition API
- **构建工具**: Vite
- **UI 组件库**: Element Plus（适合管理后台的表格、表单、弹窗等）
- **状态管理**: Pinia
- **路由**: Vue Router 4
- **HTTP 请求**: Axios
- **实时通信**: Socket.io-client（用于监听房间状态变化、控制大屏投屏）

### 页面规划

1. **Dashboard 总览页** (`/`)
  - 当前在线房间数、今日总局数、总玩家数、平均得分
  - 当前进行中的游戏列表（实时刷新）
2. **房间管理页** (`/rooms`)
  - 房间列表（房间号、状态、当前分数、在线时长）
  - 搜索/筛选（按房间号、状态）
  - 查看房间详情（历史游戏局列表）
3. **游戏记录页** (`/sessions`)
  - 所有游戏局列表（分页）
  - 字段：房间号、得分、开始/结束时间、时长
  - 筛选：按日期范围、按房间号、按分数区间
4. **大屏控制页** (`/screens`)
  - 大屏列表（屏幕名称、当前绑定房间、在线状态）
  - **核心功能**：下拉选择房间 → 点击"投屏"按钮 → 调用 API 绑定房间，大屏实时切换
  - 支持"取消投屏"回到等待画面

### 项目结构

```
admin/
├── index.html
├── src/
│   ├── main.js
│   ├── App.vue
│   ├── router/
│   │   └── index.js
│   ├── stores/
│   │   ├── rooms.js
│   │   ├── sessions.js
│   │   └── screens.js
│   ├── api/
│   │   ├── index.js         # Axios 实例配置
│   │   ├── rooms.js
│   │   ├── sessions.js
│   │   └── screens.js
│   ├── views/
│   │   ├── Dashboard.vue
│   │   ├── Rooms.vue
│   │   ├── RoomDetail.vue
│   │   ├── Sessions.vue
│   │   └── Screens.vue
│   ├── components/
│   │   ├── layout/
│   │   │   ├── AppLayout.vue
│   │   │   └── Sidebar.vue
│   │   └── common/
│   │       └── StatusTag.vue
│   └── socket/
│       └── index.js          # Socket.io 实时监听
├── package.json
└── vite.config.js
```

---

## 四、minigame-1 改造 — 小游戏端对接

需要在现有小游戏中添加 WebSocket 连接和状态上报能力，改动集中在以下文件：

### 改动点

1. **新增 `js/network/socket.js**` — Socket.io 客户端封装
  - 连接服务器，加入房间（携带 roomId）
  - 暴露 `sendState(data)` 方法
2. **修改 [js/main.js**](minigame-1/js/main.js) — 游戏主循环
  - `start()` 中初始化 WebSocket 连接
  - `loop()` 中每 2 帧调用一次状态序列化并发送（`frame % 2 === 0`）
  - `collisionDetection()` 中游戏结束时发送 `room:gameOver` 事件
3. **修改 [js/databus.js**](minigame-1/js/databus.js) — 添加序列化方法
  - 新增 `serialize()` 方法，将 grid、score、fireBubbles、explosions 等压缩为紧凑 JSON

### 状态序列化格式

```javascript
{
  frame: 120,
  score: 350,
  isGameOver: false,
  grid: [[0,1,2,0,3,...], [1,0,2,...], ...],  // 二维数组，值=颜色编号，0=空
  pushAnimOffsetY: -5.2,
  fireBubbles: [{ x: 180, y: 400, color: 2, vx: 5, vy: -15 }],
  explosions: [{ x: 100, y: 50, color: 1, particles: [...] }],
  shooter: { aimAngle: 1.57, isAiming: true, currentColor: 3, nextColor: 1 }
}
```

### 关于 Socket.io 在小游戏端的使用

微信小游戏不支持浏览器原生 WebSocket API，但 Socket.io 提供了 `weapp` 适配方案。需要：

- 使用 `weapp-socket.io` 或 `socket.io-client` 的微信小程序兼容包
- 或者直接使用微信原生 `wx.connectSocket` + 自行实现简单的消息协议（更轻量）

建议：先用 `wx.connectSocket` 原生 API 实现，服务端同时支持原生 WebSocket 和 Socket.io 两种连接（Socket.io 服务端天然支持）。

---

## 五、实施顺序建议

按依赖关系，建议按以下顺序逐步实施：

1. **Phase 1**: 搭建 server 项目骨架（Express + Socket.io + Prisma + MySQL 5.7），实现基础 WebSocket 中继和 REST API
2. **Phase 2**: 搭建 big-screen 项目，移植渲染逻辑，对接 Socket.io 接收状态并渲染
3. **Phase 3**: 改造 minigame-1，添加 WebSocket 连接和状态上报
4. **Phase 4**: 搭建 admin 项目，实现管理页面和大屏投屏控制
5. **Phase 5**: 联调测试，打通 小游戏→服务器→大屏 全链路

