16 KiB
手机端前端设计文档
日期:2026-06-15 仓库:gamegroup2(http://jiulu-gameplay.com.cn:13001/congsh/gamegroup2.git) 状态:已确认,待实施
1. 目标
为现有 Game Group V2(游戏组队管理平台)增加完整的手机端前端,使移动设备用户通过手机浏览器即可使用全部功能。手机端与桌面端共存于同一项目、同一域名、同一后端,访问时根据设备自动分流。
成功标准:手机浏览器打开 http://192.168.1.14:7033(Dev)/ 7034(UAT),自动进入手机版界面,可完成登录、群组管理、组队、投票、竞猜、账本、资产、黑名单、回忆、游戏库等全部现有功能,交互符合移动端操作习惯。
2. 技术决策
2.1 方案:单项目双视图层 + 路由分流
在现有 frontend 项目内新增手机端视图层,与桌面端共存:
- 共享层(零改动,手机端直接复用):
api/(PocketBase 封装)、stores/(Pinia)、types/(接口定义)、composables/(useRealtime 等)、assets/design.css(设计系统变量) - 桌面层(不动):现有
views/、components/保持原样 - 手机层(全新):
views-mobile/、components-mobile/、mobile/(布局与设备检测)
理由:业务逻辑全在前端、API 为标准 PocketBase SDK,共享层与 UI 无关;分成独立项目会导致 api/stores/types/composables 要么复制要么抽包,维护成本翻倍。单项目共享核心 + 双视图层是最低成本、最高复用的方案。
2.2 手机端组件库:Vant 4
引入 Vant 4(Vue 3 移动端组件库)作为手机端 UI 组件库。
- 现有 Element Plus 面向桌面(弹窗、表格、复杂表单),手机端的 Tabbar、ActionSheet、PullRefresh、Toast、SwipeCell、NavBar 等交互它不擅长
- Vant 专注移动端,与 Vite / Vue 3 / TypeScript 无缝集成
- 桌面端继续用 Element Plus,两套通过路由分流隔离,互不干扰
新增依赖:vant@^4 + @vant/auto-import-resolver(Vant 按需引入插件,确保未使用的组件不打包进桌面端产物)
2.3 主题一致性
将 Vant 的 CSS 变量覆盖为现有 design.css 的 --gg-* 值,保证手机端与桌面端视觉统一:
- 主色
--van-primary-color: var(--gg-primary)(#059669) - 背景色、文字色、圆角、阴影等全部映射到
--gg-*对应变量
2.4 语音能力
手机端 VoiceRoom 做完整 UI(成员网格、控制条、房间布局),实际 WebRTC 连接与麦克风采集暂不接入。原因:非 HTTPS / 部分手机浏览器(如微信内置)限制 mediaDevices,桌面 Electron 端已遇到同类问题。
手机端语音房显示明确占位提示:"语音功能请在 App 中使用"。完整语音能力待后续打包为原生 App(Capacitor / Tauri Mobile)时再接入。
3. 目录结构
frontend/src/
├─ api/ # 共享(PocketBase 封装,零改动)
├─ stores/ # 共享(Pinia,零改动)
├─ types/ # 共享(接口定义,零改动)
├─ composables/ # 共享(useRealtime 等,零改动)
├─ assets/
│ ├─ design.css # 共享设计系统(桌面+手机)
│ └─ mobile.css # 手机端主题覆盖(Vant 变量映射)
├─ views/ # 桌面端页面(现有,不动)
├─ components/ # 桌面端组件(现有,不动)
├─ views-mobile/ # 手机端页面(全新)
├─ components-mobile/ # 手机端组件(全新)
├─ mobile/ # 手机端专用
│ ├─ MobileLayout.vue # 底部 Tab + 顶部栏 主布局
│ ├─ useDevice.ts # 设备检测 composable
│ └─ DeviceGuard.ts # 路由级设备分流
├─ router/
│ └─ index.ts # 改造:设备检测 + 分流
└─ main.ts # 改造:按需注册 Vant
4. 设备检测与路由分流
4.1 检测策略
- 主判据:
navigator.userAgent匹配移动设备关键字(iPhone/Android/Windows Phone 等) - 辅助判据:
window.innerWidth <= 768(覆盖平板竖屏) - 检测结果在应用启动时执行一次,存入
localStorage(device_mode)避免重复检测 - 提供手动切换入口(设置页:"切换到桌面版"),少数平板/桌面用户可能需要
4.2 路由结构
每个业务路由定义 desktop 和 mobile 两个组件,路由守卫根据设备模式返回对应组件:
// 示例:路由记录
{
path: '/group/:id',
name: 'GroupView',
meta: { requiresAuth: true },
component: () => isMobile()
? import('@/views-mobile/GroupViewMobile.vue')
: import('@/views/GroupView.vue')
}
- 登录态校验(
requiresAuth/requiresGuest)逻辑不变 - 所有路由 URL 与桌面端完全一致(同一
/group/:id),只是加载的视图不同 - 切换设备模式后整页刷新以重新走路由解析
5. 手机端布局与导航
5.1 整体框架
┌──────────────────────────┐
│ ← 群组名 🔔(3) │ 顶部栏:返回 / 标题 / 通知
├──────────────────────────┤
│ │
│ 页面内容区 │
│ (下拉刷新、滚动) │
│ │
├──────────────────────────┤
│🏠首页 👥群组 🎮游戏 🔔通知 👤我│ 底部 5 Tab
└──────────────────────────┘
- 顶部栏(NavBar):左侧返回按钮(次级页面显示)、中间页面标题、右侧通知铃铛(带未读数徽标)
- 底部 Tab(Tabbar):5 个固定入口,单手拇指可达
- 内容区:占满中间空间,支持下拉刷新(列表页)、无限滚动加载
5.2 底部 Tab 定义
| Tab | 图标 | 页面 | 说明 |
|---|---|---|---|
| 首页 | home-o | HomeMobile | 状态 + 当前组队 + 我的群组 + 热门游戏 |
| 群组 | friends-o | GroupsMobile | 群组列表 + 创建/加入入口 |
| 游戏 | game-o | GamesLibraryMobile | 游戏库浏览 + 搜索 |
| 通知 | bell | NotificationsMobile | 全部站内通知(邀请/组队/入群) |
| 我的 | user-o | ProfileMobile | 个人信息 + 状态 + 设置 |
投票、竞猜、账本、资产、黑名单、回忆、统计 不占底部位置,通过群组详情内的标签栏进入(见 5.3)。
5.3 群组详情的子页面组织
群组详情(GroupViewMobile)承载桌面端 GroupView 的全部 Tab 内容,手机端用可横滑的顶部标签栏组织:
┌──────────────────────────┐
│ ← 群组名 [12人] [⚙] │
├──────────────────────────┤
│ 动态 投票 竞猜 回忆 → │ 可横滑标签(横向滚动)
├──────────────────────────┤
│ │
│ [当前标签内容] │
│ │
└──────────────────────────┘
(其余标签:成员 账本 资产 黑名单 统计)
- 9 个标签:动态 / 投票 / 竞猜 / 回忆 / 成员 / 账本 / 资产 / 黑名单 / 统计
- 首次进入默认「动态」Tab
- 横向可滑动,超出屏幕的标签左右滑出
- 群组级独立页面(账本
/group/:id/ledger、资产/group/:id/assets、黑名单/group/:id/blacklist)也可从标签进入,URL 保持一致以支持直接跳转和返回
6. 全部页面设计
6.1 认证
| 页面 | 文件 | 设计要点 |
|---|---|---|
| 登录 | views-mobile/LoginMobile.vue |
全屏卡片式,顶部 Logo + 标语,大号输入框(昵称/邮箱/用户名 + 密码),主按钮全宽,底部"去注册"链接。键盘弹出时内容上推不遮挡。 |
| 注册 | views-mobile/RegisterMobile.vue |
步骤化表单:昵称 → 密码 → 确认密码。复用桌面端自动生成 username 的逻辑('u' + Date.now().toString(36) + random)。 |
6.2 主功能
| 页面 | 文件 | 设计要点 |
|---|---|---|
| 首页 | views-mobile/HomeMobile.vue |
顶部:当前用户状态卡片(在线/忙碌/离开 + 一键切换 + 状态备注)。中部:当前临时小组卡片(如有,显示成员头像 + 进入语音房按钮)。下方:我的群组横滑卡片列表(点击进群组详情)。底部:热门游戏横滑封面。无群组时显示引导卡(创建/加入)。 |
| 群组列表 | views-mobile/GroupsMobile.vue |
群组卡片纵向列表(群名 + 成员数 + 简介 + 未读标记),顶部右侧浮动「+」按钮弹出 ActionSheet(创建群组 / 加入群组)。下拉刷新。 |
| 群组详情 | views-mobile/GroupViewMobile.vue |
顶部群信息条(群名 / 成员数 / 群主 / 容量)+ 快捷操作(账本/资产/黑名单图标入口)+ 可横滑标签栏(见 5.3)。 |
| 语音房 | views-mobile/VoiceRoomMobile.vue |
成员头像大网格(2-3 列,显示麦克风开关状态、说话动效)。底部固定控制条(麦克风开关 / 静音 / 退出)。顶部显示房间名和在线人数。WebRTC 未接入时显示占位提示。 |
6.3 群组内功能(标签栏子页面)
| 功能 | 组件 | 设计要点 |
|---|---|---|
| 动态 | components-mobile/group/ActivityFeed.vue |
当前组队状态卡 + 空闲成员列表 + 所有成员按状态分组列表。 |
| 投票 | components-mobile/poll/PollListMobile.vue + PollDetailMobile.vue |
卡片列表(标题 / 选项数 / 截止时间 / 状态),下拉刷新,点击进详情投票。创建投票走底部弹出表单。 |
| 竞猜 | components-mobile/bet/BetListMobile.vue + BetDetailMobile.vue |
卡片列表(标题 / 下注范围 / 截止时间 / 我的下注),点击进详情下注。结算展示结果。 |
| 回忆 | components-mobile/memory/MemoryGridMobile.vue |
九宫格图片视频缩略图,点击全屏浏览(支持滑动切换、捏合缩放)。上传走底部弹出(拍照/相册选择)。 |
| 成员 | components-mobile/group/MemberListMobile.vue |
按状态分组列表(头像 + 昵称 + 状态备注),群主可管理(踢人/审核入群)。 |
| 账本 | views-mobile/LedgerMobile.vue |
顶部月度汇总卡片(总收入/支出/结余),下方账目列表,右下角浮动「+」添加(弹出表单:金额/类型/备注)。 |
| 资产 | views-mobile/AssetMobile.vue |
资产卡片列表(名称 / 类型 / 当前持有者),点击查看详情 / 转移。 |
| 黑名单 | views-mobile/BlacklistMobile.vue |
顶部 Tab 切换「游戏黑名单 / 玩家黑名单」。游戏:卡片列表(游戏名 + 标签 + 备注)。玩家:列表(昵称 + 标签 + 备注)。 |
| 统计 | components-mobile/stats/StatsPanelMobile.vue |
桌面 GroupStatsPanel 的简化只读版,展示群组活跃度、游戏偏好等核心数据(图表用简化柱状/环形,避免手机端图表过密)。 |
6.4 全局页面
| 页面 | 文件 | 设计要点 |
|---|---|---|
| 游戏库 | views-mobile/GamesLibraryMobile.vue |
顶部搜索栏,下方游戏封面瀑布流(2 列),点击弹出详情底部面板(封面 / 平台 / 标签 / 评论 / 收藏 / 发起组队)。 |
| 通知 | views-mobile/NotificationsMobile.vue |
全部通知列表(类型图标 + 内容 + 时间),按时间倒序,支持标记已读 / 接受 / 拒绝操作。下拉刷新。 |
| 个人中心 | views-mobile/ProfileMobile.vue |
头像 + 昵称 + 用户名,状态切换,积分余额,我的群组数 / 组队次数等数据,设置 / 更新日志 / 退出登录入口。 |
| 设置 | views-mobile/SettingsMobile.vue |
列表式设置项:通知开关、主题(预留)、切换到桌面版、关于。 |
| 更新日志 | views-mobile/ChangelogMobile.vue |
时间线列表展示版本更新记录。 |
7. 共享层改动说明
手机端零改动地复用以下现有代码:
| 层 | 内容 | 说明 |
|---|---|---|
api/pocketbase.ts |
PocketBase 单例、getCurrentUser()、isAuthenticated()、logout() |
手机端直接 import 使用 |
api/* |
users / groups / sessions / invitations / games / polls / bets / points / ledgers / assets / memories / notifications / gameBlacklist / playerBlacklist | 全部领域 API 封装,手机端复用 |
stores/* |
user / group / team / notification / poll / ledger / asset / memory | Pinia stores,组合式 API,手机端复用(UI 状态可按需扩展) |
composables/useRealtime.ts |
PocketBase 实时订阅管理 | 手机端复用,组件卸载自动清理 |
types/index.ts |
全部接口定义 + displayName() + 状态映射常量 |
手机端复用 |
桌面端代码零改动:现有 views/、components/ 保持原样,不影响桌面用户。
8. 构建与部署
- Vite 构建合并:手机端和桌面端在同一份构建产物中,路由层负责分流。Vant 按需引入(
@vant/auto-import-resolver),不使用的组件不打包,避免桌面端访问时加载手机端组件库。 - 部署不变:现有
deploy-dev.sh/deploy-uat.sh流程不变,nginx 配置不变,同一端口同一域名同时服务两端。 - 环境变量:
.env的VITE_PB_URL、VITE_PORT对两端同样生效。
9. 实施顺序
分 9 个阶段,每阶段产出可验证的成果(可在手机浏览器实测):
- 基础设施:安装 Vant、设备检测(
useDevice)、路由分流改造、MobileLayout(底部 Tab + 顶部栏)、mobile.css主题覆盖 - 认证:LoginMobile + RegisterMobile(打通登录注册全流程)
- 首页 + 群组列表:HomeMobile + GroupsMobile(含创建/加入群组弹层)
- 群组详情核心:GroupViewMobile + 动态标签(组队状态 + 成员列表)+ 成员管理
- 组队 + 语音房 UI:发起组队、邀请、接受邀请、状态切换、VoiceRoomMobile(占位)
- 投票 + 竞猜:列表 + 详情 + 创建/下注 + 结算
- 游戏库:GamesLibraryMobile + 详情弹层 + 搜索
- 账本 + 资产 + 黑名单:三个管理类页面(列表 + 增删改 + 资产转移)
- 回忆 + 统计 + 个人/设置/更新日志:收尾页面
10. 不在本次范围内
以下事项明确排除,待后续迭代:
- 语音 WebRTC 实际接入:手机端语音房仅做 UI 和占位提示,实际通话能力待打包为原生 App(Capacitor / Tauri Mobile)时实现
- PWA / 离线支持:本次不做离线缓存和可安装 Web App
- 推送通知(原生):本次仅做站内通知,App 级推送待后续
- 桌面端改动:现有桌面端代码不做任何修改
11. 风险与缓解
| 风险 | 缓解 |
|---|---|
| Vant 与 Element Plus 样式冲突 | 两套组件库通过路由分流隔离,不同时挂载;Vant 主题变量全部覆盖为 --gg-* 值 |
| 手机端浏览器实时订阅稳定性 | 复用现有 useRealtime,组件卸载自动清理;移动端切后台时 PocketBase SSE 断连,回前台后自动重连(现有机制) |
| 构建体积增长 | Vant 按需引入,仅打包手机端实际用到的组件 |
| 微信内置浏览器限制 | 语音功能已有占位;如遇其他 API 限制(如某些路由 history 模式),预留 hash 模式降级方案 |
12. 验收标准
- 手机浏览器访问 Dev/UAT 自动进入手机版界面
- 桌面浏览器访问仍是原桌面版,行为不变
- 登录 / 注册 / 退出全流程正常
- 首页:状态切换、群组入口、当前组队卡片显示正常
- 群组详情:9 个标签全部可访问,数据正确
- 组队流程:发起 / 邀请 / 接受 / 状态流转正常
- 投票 / 竞猜:创建 / 参与 / 结算正常
- 账本 / 资产 / 黑名单:增删改查正常,资产转移正常
- 回忆:浏览 + 上传正常
- 游戏库:浏览 + 搜索 + 详情正常
- 通知:接收 / 标记已读 / 接受拒绝正常
- 个人中心 / 设置:状态切换、切换桌面版正常
- 语音房界面完整,占位提示明确