Ingen beskrivning

wuzj 0008691de4 scss definition 19 timmar sedan
config 0008691de4 scss definition 19 timmar sedan
src 0008691de4 scss definition 19 timmar sedan
types 11ea639bd0 linejoy init 1 dag sedan
.editorconfig 11ea639bd0 linejoy init 1 dag sedan
.eslintrc 11ea639bd0 linejoy init 1 dag sedan
.gitignore 11ea639bd0 linejoy init 1 dag sedan
README.md 11ea639bd0 linejoy init 1 dag sedan
babel.config.js 11ea639bd0 linejoy init 1 dag sedan
components.d.ts 0008691de4 scss definition 19 timmar sedan
package.json 3aca7a63e4 tabbar 20 timmar sedan
pnpm-lock.yaml 3aca7a63e4 tabbar 20 timmar sedan
project.config.json 11ea639bd0 linejoy init 1 dag sedan
project.tt.json 11ea639bd0 linejoy init 1 dag sedan
tsconfig.json 11ea639bd0 linejoy init 1 dag sedan

README.md

排乐队 LineJoy - PRD & TDD 概要文档

产品需求文档 (PRD)

1. 产品概述

产品名称:基于微信小程序的排队解闷小游戏合集

产品愿景:将排队时的无聊等待转变为社交互动的契机,通过线上小游戏引导线下交流,增进陌生人或团队成员间的互动与了解。

核心价值主张

  • 特定场景解决方案:专为排队场景设计的互动游戏体验
  • 线上引导线下:使用小程序作为媒介促进真实社交
  • 即开即玩:无需复杂注册,扫码即可参与
  • 持续扩展内容:从海龟汤开始,逐步扩展多种游戏类型

2. 目标用户

  • 主要用户:20-35岁年轻人群,在餐厅、景点、医院等场所排队等待的小团体
  • 次要用户:团队建设活动组织者(公司团建、课外活动等)
  • 潜在用户:陌生人社交需求者,希望在公共场合认识新朋友的人群

3. 核心功能模块

3.1 游戏广场

  • 游戏分类展示(推荐、热门、新增)
  • 按游戏时长筛选(5分钟、15分钟、30分钟)
  • 排队场景推荐
  • 搜索功能

3.2 房间系统

  • 创建房间(主持人)

    • 游戏选择
    • 难度设置
    • 人数限制
    • 房间公开性设置
    • 位置标记(可选)
  • 加入房间

    • 通过房间码加入
    • 扫描二维码加入
    • 查看附近的公开房间

3.3 角色系统

  • 主持人(游戏创建者)

    • 控制游戏进程
    • 查看完整游戏信息
    • 管理提示公开
    • 回答玩家问题
    • 公布游戏结果
  • 玩家

    • 提问询问线索
    • 查看已公开信息
    • 参与讨论推理
    • 提交猜测

3.4 游戏内容

  • 海龟汤(首发核心游戏)

    • 谜题展示
    • 问答系统
    • 提示管理
    • 线索整理
    • 解谜流程
  • 其他游戏类型(后续拓展)

    • 谁是卧底
    • 20个问题
    • 微型创意讲故事
    • 附近的谎言家
    • 队列连连看
    • 秘密任务

3.5 社交功能

  • 房间内聊天
  • 游戏结果分享
  • 添加游戏好友
  • 历史游戏记录
  • 游戏战绩统计

4. 用户流程

4.1 主持人流程

  1. 进入游戏广场
  2. 选择游戏类型
  3. 创建房间并设置参数
  4. 分享房间码/二维码邀请他人
  5. 等待玩家加入
  6. 开始游戏并担任主持角色
  7. 游戏结束后查看结果统计

4.2 玩家流程

  1. 通过码/二维码打开小程序
  2. 输入房间码或扫码加入房间
  3. 等待主持人开始游戏
  4. 参与游戏互动
  5. 游戏结束后查看结果
  6. 选择继续游戏或退出房间

5. 特色功能

  • 线下互动提示:定期弹出"看看周围的人"等提示,引导线上到线下的转化
  • 时间感知:根据用户输入的排队预计时间,推荐适合的游戏
  • 位置标记:标记当前排队地点,方便附近用户发现并加入
  • 破冰话题:在游戏过程中提供话题建议,促进陌生人交流
  • 合影留念:游戏结束后提供拍照记录功能,保存互动回忆

6. 性能与体验需求

  • 启动速度:冷启动时间不超过3秒
  • 响应时间:交互响应时间不超过300ms
  • 离线能力:基本游戏内容在网络不稳定时仍可使用
  • 单手操作:界面设计适配单手操作场景
  • 低电量优化:提供省电模式,延长排队中的使用时间

7. 发布计划

第一阶段

  • 完成核心海龟汤游戏
  • 实现基础房间系统
  • 构建游戏广场
  • 支持扫码和房间码加入

第二阶段

  • 增加2-3个新游戏类型
  • 完善社交功能
  • 优化用户体验
  • 增加位置服务

第三阶段

  • 开放用户贡献内容
  • 增加成就系统
  • 推出更多游戏类型
  • 增强数据分析能力

技术设计文档 (TDD)

1. 技术选型

  • 前端框架:Taro4.x + Vue3 + TypeScript + pnpm + Sass
  • 状态管理:Pinia
  • UI组件库:NutUI Vue
  • 后端服务:微信云开发
  • 数据库:云开发数据库
  • 编译:webpack5

2. 系统架构

客户端 (Taro)
    ↑↓
云开发 API
    ↑↓
云函数 (业务逻辑)
    ↑↓
云数据库 (数据存储)

3. 数据模型设计

3.1 用户模型

interface User {
  id: string;            // 用户唯一ID
  openId: string;        // 微信OpenID
  nickname: string;      // 昵称
  avatarUrl: string;     // 头像
  createdAt: Date;       // 注册时间
  stats: {               // 统计数据
    gamesPlayed: number;
    gamesHosted: number;
    solvedRate: number;  // 解谜成功率
  };
}

3.2 房间模型

interface Room {
  id: string;            // 房间ID
  roomCode: string;      // 6位房间码
  gameType: string;      // 游戏类型
  gameId: string;        // 游戏内容ID
  hostId: string;        // 主持人ID
  createdAt: Date;       // 创建时间
  status: RoomStatus;    // 等待中/进行中/已结束
  settings: {            // 房间设置
    maxPlayers: number;
    isPublic: boolean;
    difficulty: string;
    hintRevealMode: string; // 自动/手动
  };
  location?: {           // 可选位置信息
    latitude: number;
    longitude: number;
    name?: string;       // 位置名称
  };
  players: RoomMember[]; // 玩家列表
}

interface RoomMember {
  id: string;            // 用户ID
  role: RoomRole;        // 主持人/玩家
  nickname: string;      // 昵称
  avatarUrl: string;     // 头像
  joinTime: Date;        // 加入时间
  isReady: boolean;      // 准备状态
}

enum RoomRole {
  HOST = 'host',         // 主持人
  PLAYER = 'player'      // 玩家
}

enum RoomStatus {
  WAITING = 'waiting',   // 等待中
  PLAYING = 'playing',   // 游戏中
  ENDED = 'ended'        // 已结束
}

3.3 游戏模型 (海龟汤)

interface TurtleSoupGame {
  id: string;            // 游戏ID
  roomId: string;        // 关联房间ID
  title: string;         // 标题
  initialStory: string;  // 初始故事
  hints: string[];       // 提示列表
  solution: string;      // 解答
  revealedHints: number[]; // 已公开提示索引
  questions: Question[]; // 问题列表
  startTime: Date;       // 开始时间
  endTime?: Date;        // 结束时间
  status: GameStatus;    // 游戏状态
}

interface Question {
  id: string;            // 问题ID
  playerId: string;      // 提问玩家ID
  playerName: string;    // 提问玩家名称
  content: string;       // 问题内容
  answer?: string;       // 回答 (是/否/不相关)
  createdAt: Date;       // 创建时间
  answeredAt?: Date;     // 回答时间
}

enum GameStatus {
  PREPARING = 'preparing', // 准备中
  ONGOING = 'ongoing',     // 进行中
  SOLVED = 'solved',       // 已解决
  EXPIRED = 'expired'      // 已过期
}

4. API 设计

4.1 房间管理 API

接口名称 功能描述 参数 返回值
createRoom 创建游戏房间 gameType, settings roomId, roomCode
joinRoom 加入游戏房间 roomCode roomDetail
getRoomDetail 获取房间详情 roomId roomDetail
startGame 开始游戏 roomId gameId
leaveRoom 离开房间 roomId success

4.2 游戏逻辑 API

接口名称 功能描述 参数 返回值
getGameData 获取游戏数据 gameId, role filteredGameData
submitQuestion 提交问题 gameId, content questionId
answerQuestion 回答问题 questionId, answer success
revealHint 公开提示 gameId, hintIndex success
endGame 结束游戏 gameId, result gameResult

5. 组件设计

5.1 角色分离组件

HostOnly组件:仅主持人可见内容

<template>
  <slot v-if="isHost"></slot>
</template>

<script setup lang="ts">
import { useRoomRole } from '@/hooks/useRoomRole';

const props = defineProps<{
  roomId: string
}>();

const { isHost } = useRoomRole(props.roomId);
</script>

PlayerOnly组件:仅玩家可见内容

<template>
  <slot v-if="isPlayer"></slot>
</template>

<script setup lang="ts">
import { useRoomRole } from '@/hooks/useRoomRole';

const props = defineProps<{
  roomId: string
}>();

const { isPlayer } = useRoomRole(props.roomId);
</script>

5.2 核心业务组件

  • GameRoom:游戏房间容器,负责数据流和状态管理
  • RoomSettings:房间设置面板(主持人使用)
  • PlayerList:房间玩家列表
  • GameStory:游戏故事展示
  • QuestionPanel:问题面板(提问和回答)
  • HintManager:提示管理器(主持人使用)
  • HintDisplay:提示展示(玩家使用)
  • ChatRoom:房间内聊天功能

6. 页面结构和路由设计

/pages/
  /index/                       # 游戏广场
  /game-detail/                 # 游戏详情
  /room/
    /create/                    # 创建房间(主持人专用)
    /join/                      # 加入房间(玩家专用)
    /waiting/                   # 等待室(带角色参数)
    /play/                      # 游戏进行中(带角色参数)
  /profile/                     # 个人中心
  /history/                     # 游戏历史

6.1 工程目录结构

src/ ├── app.config.ts # 小程序全局配置 ├── app.scss # 全局样式 ├── app.ts # 应用入口 ├── assets/ # 静态资源 │ ├── images/ # 图片资源 │ └── styles/ # 样式资源 │ ├── variables.scss # 样式变量 │ └── mixins.scss # 样式混合 ├── components/ # 全局组件 │ ├── HostOnly/ │ └── PlayerOnly/ ├── composables/ # 可组合式函数 │ └── useRoomRole.ts ├── pages/ # 页面 │ ├── index/ # 游戏广场 │ ├── game-detail/ # 游戏详情 │ ├── room/ # 房间相关页面 │ │ ├── create/ # 创建房间 │ │ ├── join/ # 加入房间 │ │ ├── waiting/ # 等待室 │ │ └── play/ # 游戏进行中 │ ├── profile/ # 个人中心 │ └── history/ # 游戏历史 ├── services/ # API服务 │ ├── api/ # API定义 │ ├── request.ts # 请求封装 │ └── cloud.ts # 云函数封装 ├── stores/ # Pinia状态管理 │ ├── modules/ # 状态模块 │ │ ├── user.ts # 用户状态 │ │ ├── room.ts # 房间状态 │ │ └── game.ts # 游戏状态 │ └── index.ts # 状态入口 ├── types/ # TypeScript类型 │ ├── room.ts # 房间相关类型 │ ├── game.ts # 游戏相关类型 │ └── user.ts # 用户相关类型 └── utils/ # 工具函数

├── common.ts       # 通用工具
├── format.ts       # 格式化工具
└── storage.ts      # 存储工具

7. 权限控制机制

7.1 前端权限控制

  • 使用 useRoomRole 组合式API获取和验证用户角色
  • 基于角色条件渲染不同UI组件
  • 页面级权限检查,防止直接访问无权限页面

7.2 后端权限控制

  • 云函数中验证用户身份和权限
  • 数据访问权限过滤
  • 主持人专属操作权限验证

7.3 数据过滤策略

// 根据角色过滤游戏数据
function filterGameDataByRole(gameData, role: RoomRole) {
  if (role === RoomRole.HOST) {
    // 主持人可以看到所有数据
    return gameData;
  } else {
    // 玩家只能看到部分数据
    return {
      ...gameData,
      initialStory: gameData.initialStory,
      revealedHints: gameData.revealedHints,
      // 隐藏未公开信息
      solution: undefined,
      unreveaedHints: undefined,
      secretNotes: undefined
    };
  }
}

8. 实时数据同步

  • 使用云开发实时数据库监听房间状态变化
  • 使用 WebSocket 实现聊天功能
  • 定义数据更新策略,避免频繁刷新

9. 关键技术实现

9.1 角色分离实现

// hooks/useRoomRole.ts
import { ref, onMounted, computed } from 'vue';
import Taro from '@tarojs/taro';
import { RoomRole } from '@/types';

export function useRoomRole(roomId: string) {
  const role = ref<RoomRole | null>(null);
  
  onMounted(() => {
    // 从路由参数获取角色
    const params = Taro.getCurrentInstance().router?.params;
    let roleFromParams = params?.role as RoomRole;
    
    // 如果没有,从服务器获取
    if (!roleFromParams && roomId) {
      Taro.cloud.callFunction({
        name: 'getRoomMemberRole',
        data: { roomId }
      }).then(res => {
        role.value = res.result.role;
      });
    } else {
      role.value = roleFromParams;
    }
  });
  
  const isHost = computed(() => role.value === RoomRole.HOST);
  const isPlayer = computed(() => role.value === RoomRole.PLAYER);
  
  return { 
    role, 
    isHost,
    isPlayer
  };
}

9.2 实时数据同步

// composables/useRoomData.ts
import { ref, onMounted, onUnmounted } from 'vue';
import Taro from '@tarojs/taro';
import type { Room } from '@/types';

export function useRoomData(roomId: string) {
  const roomData = ref<Room | null>(null);
  let watcher = null;
  
  // 设置房间数据监听
  onMounted(() => {
    const db = Taro.cloud.database();
    watcher = db.collection('rooms')
      .doc(roomId)
      .watch({
        onChange: function(snapshot) {
          roomData.value = snapshot.docs[0];
        },
        onError: function(err) {
          console.error('监听房间失败', err);
        }
      });
  });
  
  // 组件卸载时关闭监听
  onUnmounted(() => {
    if (watcher) {
      watcher.close();
    }
  });
  
  return {
    roomData
  };
}

10. 性能优化策略

  • 数据缓存:缓存游戏静态资源和配置
  • 按需加载:按需加载游戏资源
  • 防抖节流:对频繁操作(如聊天输入)进行防抖处理
  • 延迟加载:非关键组件延迟加载
  • 状态局部化:将状态尽可能局部化,避免全局状态过多

11. 安全考虑

  • 数据校验:前后端同时校验数据有效性
  • 角色验证:每次操作前验证用户角色权限
  • 数据脱敏:敏感游戏数据(如解答)仅发送给有权限的用户
  • 请求频率限制:防止恶意请求攻击

12. 测试策略

  • 单元测试:核心业务逻辑单元测试
  • 组件测试:UI组件渲染测试
  • 集成测试:页面流程测试
  • 真机测试:不同设备兼容性测试
  • 性能测试:启动时间、响应时间测试

13. 部署与发布

  • 环境配置:开发、测试、生产环境配置
  • CI/CD:持续集成与部署流程
  • 版本控制:语义化版本控制
  • 灰度发布:新功能灰度发布策略
  • 监控告警:线上问题监控与告警机制