Files
juwan-frontend/AUDIT.md
T
2026-02-20 19:54:14 +08:00

336 lines
19 KiB
Markdown
Raw 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.
# 聚玩前端 缺陷审计报告
> 审计时间:2026-02-20
> 项目:聚玩(JuWan)— 基于 Next.js 16 + shadcn/ui + Tailwind CSS 4 的游戏陪玩平台前端
> 仓库结构:约 100 个源文件,分布在 app/(页面)、components/(共享组件)、lib/(工具/类型/mock 数据)、store/Zustand 状态管理)
> 背景:本项目由 AI 辅助生成,本报告检查脏代码、AI 生成痕迹、劣质 UI 设计、与 PLAN.md 的偏差等问题
> 审计方法:8 个并行审计 Agent 分别负责不同维度(代码卫生、AI 痕迹、UI 设计、文案质量、mock 数据、架构、功能完整性),交叉验证
---
## 一、代码卫生
对全部 .ts/.tsx/.css/.json 文件做了关键词扫描。
**扫描结果:全部为零。**
- `@ts-ignore` / `@ts-expect-error` / `as any`:零
- `biome-ignore` / `eslint-disable` / `prettier-ignore`:零
- `console.log` / `console.warn` / `console.error`:零
- 空 catch 块:零
- 代码注释:整个 app/components/store/lib 目录没有一行注释
- AI 工具签名(Claude / Copilot / Cursor / GPT / Sisyphus / OpenCode):零
- 对话痕迹("根据你的要求" / "as you requested" 等):零
- Git 提交消息:风格统一(Conventional Commits),无 AI 工具提及
唯一残留:`next.config.ts:4` 的脚手架占位注释 `/* config options here */`
结论:代码表面非常干净。AI 痕迹不在注释层面,而在内容和设计层面(见后续章节)。
---
## 二、Emoji 滥用
### 2.1 游戏图标用 emoji 代替 [严重]
`lib/mock-data.ts` 第 71-78 行定义了 8 个游戏,它们的 `icon` 字段全部使用 emoji 字符:
```
🎮(英雄联盟)👑(王者荣耀)🔫(和平精英)⚔️(原神)🌟(永劫无间)🪖(CS2)🛡️(DOTA2)💥(绝地求生)
```
这些 emoji 通过 `{game.icon}` 被渲染到以下 UI 位置:
- `app/(main)/page.tsx:46` — 首页游戏分类卡片
- `app/(main)/search/page.tsx:212` — 搜索页游戏筛选标签
- `app/(dashboard)/dashboard/services/new/page.tsx:73` — 服务发布页游戏选择列表
这是典型的 AI 生成偷懒行为——用 emoji 代替真实图标。应替换为 lucide-react 图标或自定义 SVG 图标映射。
### 2.2 UI 标签中的 emoji [严重]
`app/(main)/community/page.tsx:66` — 社区页帖子中出现 `📋 关联订单秀单`,在 UI 标签/区块标题场景使用 emoji 装饰,是典型 AI 生成风格。
### 2.3 可接受的 emoji [低]
`lib/mock-data.ts:459` — 聊天消息 `"感谢好评!下次继续带飞 💪"`,这是模拟用户聊天行为,emoji 使用合理,可保留。
---
## 三、AI 味文案
项目中没有直接的 AI 工具签名,但大量 UI 文案带有明显的 AI 生成特征——空洞的营销语、模板化表达、过于正式的语气。
### 3.1 首页/搜索页营销腔 [严重]
| 文件:行号 | 文案内容 | 问题 |
|-----------|----------|------|
| `app/(main)/page.tsx:15` | "专业陪玩、代练、上分,覆盖主流游戏,安全可靠" | 空洞的"全都好"营销句,任何平台都能用 |
| `app/(main)/search/page.tsx:383` | "找到最适合你的游戏伙伴,一起畅玩游戏世界" | 泛化 AI 文案,无具体信息 |
| `app/(main)/search/page.tsx:407` | "调整筛选条件以找到更匹配的陪玩" | 说明书口吻,不像产品在和用户说话 |
| `components/footer.tsx:14` | "专业游戏陪玩服务平台" | 通用 slogan,品牌辨识度为零 |
### 3.2 Mock 数据中的模板化文案 [中等]
`lib/mock-data.ts` 中的文本内容几乎全部带有 AI 生成特征:
**服务描述**(第 87-135 行):标题和描述高度模板化——"上分陪玩"、"代练上星"、"带飞"、"安全高效"、"保证胜率60%+"。这些像是 AI 批量生成的电商文案,缺少真实卖家会写的个性化表达。
**用户简介**(第 37、56、65 行):营销腔明显——"全国百强"、"全球精英"、"专业工作室"。真实用户简介通常更随意。
**店铺介绍**(第 188 行):"专业电竞陪玩工作室,拥有50+签约打手,覆盖主流游戏"——万能介绍模板。
**评价内容**(第 280、292、304 行):语句太完整、太"好文案",缺少真实评价中常见的口语化表达、碎句、停顿词。
**聊天消息**(第 382、402 行):偏客服话术("请问什么时候方便开始"),真实私聊通常更短更随意。
**通知文案**(第 516 行):"聚玩春节活动即将开始,敬请期待!"——"敬请期待"式公告模板化明显。
### 3.3 页面文案细节 [中等]
| 文件:行号 | 文案内容 | 问题 |
|-----------|----------|------|
| `app/(main)/post/new/page.tsx:110` | "分享你的游戏体验..." | 典型 AI 占位句,泛而无指向 |
| `app/(main)/post/[id]/page.tsx:127` | "来抢沙发吧" | 老论坛语感,和当前产品调性不匹配 |
| `app/(order)/review/[id]/page.tsx` | "确保真实性和公正性" | 偏 AI/公文腔 |
| `app/(main)/page.tsx:21` | "搜索打手" | 用词偏硬,和"陪玩"语境不统一 |
### 3.4 术语不统一 [严重]
同一概念在不同位置使用不同称呼,这是 AI 分次生成不同页面时缺乏全局一致性的典型表现:
| 位置 | 对用户的称呼 | 对服务提供者的称呼 |
|------|-------------|-------------------|
| `components/header.tsx:38` | "消费者" | — |
| 社区页 roleLabels | "玩家" | — |
| `components/header.tsx:93` 搜索框 | — | "打手" |
| 首页/其他页面 | — | "陪玩" |
应建立统一的术语体系并全局替换。
---
## 四、Mock 数据 AI 味道
`lib/mock-data.ts` 是全站的模拟数据源,约 550 行。其中的数据分布和内容风格暴露了大量 AI 批量生成的特征。
### 4.1 用户名/昵称过于规整 [中等]
第 22-62 行定义了 5 个用户。用户名模式过于规整(全是英文词+下划线+拼音姓,如 `pro_zhang``carry_chen`),昵称过于"人设化"(张小明、李大神、王老板、陈Carry、刘甜甜)。真实用户名通常有数字、大小写混搭、随机后缀(如 `xm_2003``LDShen666``甜甜酱w`)。
### 4.2 数值分布过于理想化 [中等]
- **价格**:全是整数且多为 5 的倍数(30、40、50),缺少真实定价噪声(如 23、29、33、58)
- **评分**:集中在 4.7-4.9,完单率 0.97-0.99,区间极窄,分布过于理想化
- **订单总价**:都刚好是服务单价×3(90/120/60),模式过齐
### 4.3 数据关联不匹配 [严重]
- 打手累计订单数很高(645/832/1256),但全局评论只有 3 条——一个接了 1256 单的打手只有 1 条评价,严重不合理
- 店铺写了 12 名打手、5600 单,但当前只挂了 2 名店内打手,样本关系断裂
### 4.4 数据结构冗余 [中等]
第 85-86、214-217 行:同一实体重复存储 id+name(如 `gameId` + `gameName``consumerId` + `consumerName``playerId` + `playerName`)。这种冗余容易导致数据漂移,是 AI "先堆字段再补逻辑"的常见写法。
---
## 五、类型建模问题
`lib/types.ts` 定义了全站的 TypeScript 类型。主要问题是约束过松——AI 倾向于用 optional 字段"兜住"所有情况,而不是用联合类型精确建模。
### 5.1 Order 状态机松散 [严重]
第 76-101 行:`Order` 类型用大量 optional 字段承载状态机(`acceptedAt?``closedAt?``completedAt?``cancelledAt?`),但没有按 `status` 区分的联合类型。例如,一个 `status: "pending"` 的订单在类型层面也允许有 `completedAt`,这在逻辑上是矛盾的。应改为按状态区分的判别联合类型。
### 5.2 其他类型问题 [中等]
| 位置 | 问题 |
|------|------|
| `types.ts:129-132` | `ChatSession``type` 已区分 `order`/`consultation`,但 `orderId` 仍是 optional,缺少判别联合约束(type 为 order 时 orderId 应必填) |
| `types.ts:117-125` | `Dispute.result``status` 无联动,`resolved` 状态时也可无结果 |
| `types.ts:18,29,31` | `Game.category``PlayerService.unit``availability` 过宽(全是 `string`),应使用字面量联合类型 |
| `types.ts:112-113` | `Review.content?` + `sealed` 缺语义关系,允许"无内容且未密封"等不自然组合 |
| 全局 | 时间字段全部裸 `string`,无 ISO 8601 / epoch 约束 |
---
## 六、代码架构问题
### 6.1 Auth 系统设计缺陷 [严重]
当前的认证系统是一个极简的 Zustand store,存在多个设计问题:
| 文件 | 问题 |
|------|------|
| `store/auth.ts` | `login()` 函数不接收任何参数(用户信息、token),直接硬编码设置登录状态 |
| `store/auth.ts` | `switchRole()` 无权限校验,任何人可切换到任何角色 |
| `store/login-dialog.ts` | 状态过窄,只有 open/close,无法携带"登录后继续动作"的上下文(如用户点了收藏→弹登录→登录后应自动收藏) |
| `lib/use-require-auth.ts` | 登录成功后不会自动续执被中断的操作 |
| `components/header.tsx` | 用户信息来自 mock 常量而非 auth store,导致状态源分裂 |
### 6.2 重复代码 [中等]
以下常量/组件在多处重复定义,应提取到共享模块:
| 重复内容 | 出现位置 |
|----------|----------|
| `statusLabels`(订单状态中文映射) | `app/(order)/orders/page.tsx:15``app/(order)/order/[id]/page.tsx:20``app/(dashboard)/dashboard/page.tsx:12` |
| `roleLabels`(用户角色中文映射) | `app/(main)/community/page.tsx:9``app/(main)/post/[id]/page.tsx:12` |
| 侧栏组件结构 | `components/account-sidebar.tsx``components/dashboard-sidebar.tsx` 结构高度重复 |
| Layout 壳层 | `app/(account)/layout.tsx``app/(dashboard)/layout.tsx` 完全相同的侧栏+内容布局 |
### 6.3 过度工程 [低-中等]
| 位置 | 问题 |
|------|------|
| `app/(main)/search/page.tsx:77,82` | 对轻量计算(取最小价格、取单位)做了不必要的 `useMemo` |
| `app/(main)/search/page.tsx:335,354,355` | 对类型中已标记为必填的 `services` 字段做防御式 `?.` + `\|\| [0]` |
| `app/(order)/orders/page.tsx:105` | JSX 内使用 IIFE(立即执行函数)做条件渲染,降低可读性 |
| `store/player-status.ts:9,22` | `getStatus` 是单行包装函数(`get().statuses[playerId]`),抽象价值很低 |
### 6.4 响应式缺失 [中等]
- `components/account-sidebar.tsx``components/dashboard-sidebar.tsx` 固定 `w-56`,无移动端断点
- 对应的 layout 文件直接常驻侧栏,未做 `md:` 以上的条件显示
- 移动端用户会看到被侧栏挤压的内容区
### 6.5 假异步模式 [中等]
以下 5 处使用 `await new Promise((r) => setTimeout(r, 500))` 模拟表单提交,是 AI 生成 demo 的典型模式:
- `app/(auth)/login/page.tsx:31`
- `app/(auth)/register/page.tsx:38`
- `components/login-dialog.tsx:41`
- `app/(dashboard)/dashboard/services/new/page.tsx:44`
- `app/(main)/post/new/page.tsx:52`
### 6.6 硬编码问题 [中等]
多处将用户 ID、数据索引等写死,导致页面只能展示特定 mock 数据:
| 位置 | 硬编码内容 |
|------|-----------|
| `app/(main)/player/[id]/page.tsx:34` | 收藏判断写死 `userId === "u1"` |
| `app/(main)/shop/[id]/page.tsx:29` | 收藏用户写死 `u1` |
| `app/(order)/chat/[id]/page.tsx:29` | 当前用户写死 `participants[0]` |
| `app/(dashboard)/dashboard/page.tsx:27-28` | 直接取第一个 player/shop |
| `app/(dashboard)/dashboard/shop/page.tsx:13` | 固定 `mockShops[0]` |
| `app/(dashboard)/dashboard/shop/employees/page.tsx:23` | 写死 `shop1` |
### 6.7 占位渲染 [严重]
以下位置有图片/上传等功能的数据结构,但 UI 只渲染了占位文字,是明显的原型态残留:
| 位置 | 占位内容 |
|------|----------|
| `app/(main)/post/[id]/page.tsx:70` | 有图片数据却只渲染「图片」二字 |
| `app/(order)/dispute/[id]/page.tsx:81` | 证据图只渲染「截图」二字 |
| `app/(account)/verify/page.tsx:102` | 身份证上传是静态卡片 |
| `app/(dashboard)/dashboard/shop/templates/page.tsx:88` | 直接写死"原型演示中暂不支持拖拽" |
---
## 七、UI 设计质量
整体评价:项目功能上是完整的 Draft,但视觉上患有"shadcn 默认主题综合征"——看起来像 B2B SaaS 后台管理系统,而不是面向消费者的游戏平台。
### 7.1 各页面成熟度评级
| 页面 | 评级 | 核心问题 |
|------|------|----------|
| 首页 `app/(main)/page.tsx` | Prototype | Hero 区只是居中文字+两个按钮,零视觉冲击力;三段区块都用"标题+查看全部+卡片列表"重复模板 |
| 搜索页 `app/(main)/search/page.tsx` | Draft(功能好) | 筛选/排序/移动端适配做得不错,但卡片信息过密缺视觉层次;整卡可点同时又有「查看详情」按钮,交互语义重复 |
| 打手详情 `app/(main)/player/[id]/page.tsx` | Draft | 最通用的 profile 布局(头像左+信息右+Tabs 下),无个性;bio 区是纯灰色盒子 |
| 店铺详情 `app/(main)/shop/[id]/page.tsx` | Draft | 不像店铺,像组件列表;banner 文字叠加用最基础的 `bg-black/40` |
| 登录/注册 `app/(auth)/` | Prototype | 最简表单(图标+标题+输入框+按钮),无背景图/分屏布局/社交登录 |
| 订单管理 `app/(order)/` | Production-ready | 状态步骤指示器和上下文操作按钮做得不错 |
| 仪表盘 `app/(dashboard)/` | Production-ready(通用) | 零定制,和 shadcn/ui 官方示例一模一样;缺图表/趋势可视化 |
| 社区 `app/(main)/community/page.tsx` | Draft | 通用论坛外观,帖子类型无视觉区分;缺最新/最热/关注切换和标签筛选 |
| Header `components/header.tsx` | Production-ready | 功能完整(sticky、backdrop-blur、移动端 Sheet),但缺品牌感 |
| Footer `components/footer.tsx` | Draft | 标准 4 列布局;支持区链接是纯 `<span>` 不可点击,用户预期会落空 |
### 7.2 系统性设计问题
**品牌感缺失**`app/globals.css` 整套 CSS 变量接近黑白灰中性色,没有明确主色和游戏化氛围。作为游戏陪玩平台,视觉上应该有活力和沉浸感,而不是企业后台的冷淡风格。
**Card 过度使用**:几乎所有内容都装在 `<Card>` 组件里,1px 边框+白色背景,缺少视觉变化。应该用留白、背景色渐变、字体层级来分隔内容,而不是全靠卡片边框。
**微交互缺失**:当前 hover 效果只有 `hover:shadow-md`,缺少 scale 变化、颜色过渡、focus 指示器等。游戏平台用户期望更丰富的交互反馈。
**暗色模式未考虑**:游戏平台通常偏暗色主题,当前项目完全没有暗色模式的设计考虑。
**字体配置不完整**`app/layout.tsx` 中只配了 Geist 字体的 latin subset,中文站点缺少中文字体配置,中文内容会 fallback 到系统默认字体。
**导航设计问题**:主导航是「首页/社区/订单/消息」,缺少核心业务入口"找陪玩"或"找店铺",新用户不知道从哪里开始。移动端抽屉里没有通知入口,和桌面端信息架构不对齐。
---
## 八、功能完整性(对照 PLAN.md)
PLAN.md 是本项目的需求规格文档。以下列出当前实现与 PLAN 之间的偏差。
### 8.1 未实现 / 不完整的功能
| 功能 | 当前状态 | 与 PLAN 的偏差 |
|------|----------|---------------|
| 订单状态流转 | 不完整 | 只展示状态标签和步骤条,缺少接单、发起结单、确认结单、超时自动流转等可执行动作 |
| 争议仲裁 | 不完整 | 只有发起争议+静态详情展示,缺少双方举证、平台处理节点、申诉动作闭环 |
| 密封评价 | 未实现 | 只有文案提示"评价将在双方都提交后公开",但展示逻辑直接显示评价内容,未实现双方同时揭晓机制 |
| 聊天会话 | 部分实现 | 有咨询/订单会话标签和只读状态,但缺少咨询转订单、时效关闭、争议期特殊规则 |
| 店铺规则设置 | 未实现 | 派单模式、多店挂靠、独立接单等规则是只读 Badge 展示,不可配置 |
| 钱包分流 | 未实现 | 消费者充值和打手/店主提现混在同一界面,PLAN 要求按身份展示不同视图 |
| 身份认证审核 | 不完整 | 只有"填写→审核中"两个状态,缺少拒绝、补件、重新提交等完整审核状态机 |
| 搜索混合展示 | 未实现 | 当前只筛选 `mockPlayers`PLAN 要求"店铺打手+独立打手混合展示" |
| 社区筛选排序 | 未实现 | 缺少时间/热度排序、标签/游戏筛选,PLAN 中有明确要求 |
### 8.2 违反 PLAN 的设计 [严重]
| 位置 | 问题 | PLAN 要求 |
|------|------|-----------|
| `app/(main)/shop/[id]/page.tsx:67-71` | 店铺公开页直接展示抽成比例(如"平台抽成 10%") | PLAN 明确规定消费者不可见抽成比例和打手实收金额 |
| `app/(account)/settings/page.tsx:74` | 设置页可直接切换到 owner/player 角色,无需认证 | PLAN 要求打手/店主身份需通过认证申请和审核后才能启用 |
---
## 九、优先级建议
### P0 — 必须修(违反 PLAN 或严重 AI 痕迹)
1. 删除 emoji 游戏图标,替换为 lucide-react 图标或自定义 SVG 映射
2. 重写首页 hero 和搜索页的 AI 营销文案,使用具体、有人味的表达
3. 统一术语体系(确定"陪玩"还是"打手""消费者"还是"玩家"
4. 修复店铺页泄露抽成比例(违反 PLAN)
5. 修复设置页可绕过认证直接切角色(违反 PLAN)
6. 删除占位渲染和"原型演示"文案
### P1 — 应该修(代码质量和数据真实性)
1. 重写 mock 数据使其更真实(用户名加噪声、价格不规整、评分分布拉宽、评价口语化)
2. 收敛重复常量(statusLabels、roleLabels)到 `lib/constants.ts` 共享模块
3. 加强类型建模(Order 按状态区分的联合类型、ChatSession 判别联合)
4. 修复 auth store 设计(login 接收参数、switchRole 权限校验、登录后续执)
5. 侧栏移动端适配(md: 断点条件显示)
6. 配置中文字体 subset
7. 修复 Footer 支持区链接不可点击
### P2 — 设计提升(视觉和交互)
1. 建立品牌色系,替换黑白灰中性色,体现游戏平台氛围
2. 首页 hero 重设计(动态背景、品牌色、视觉冲击力)
3. 减少 Card 过度使用,用留白和字体层级分隔内容
4. 添加微交互(hover scale/color transition、loading skeleton
5. 暗色模式支持
6. 登录页分屏设计(一侧表单、一侧品牌视觉)
7. 仪表盘添加图表/趋势可视化
### P3 — 功能补全(对照 PLAN.md
1. 订单状态机完整实现(接单→进行中→结单确认→完成,含超时机制)
2. 密封评价双方揭晓机制
3. 争议仲裁完整流程(双方举证→平台处理→结果→申诉)
4. 聊天持久化和实时通信(WebSocket 或轮询)
5. 钱包按身份分流视图
6. 身份认证完整状态机(提交→审核→通过/拒绝→补件→重新提交)
7. 搜索混合展示(店铺打手+独立打手)
8. 社区筛选排序(最新/最热/关注、标签/游戏筛选)