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

19 KiB
Raw Blame History

聚玩前端 缺陷审计报告

审计时间: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_zhangcarry_chen),昵称过于"人设化"(张小明、李大神、王老板、陈Carry、刘甜甜)。真实用户名通常有数字、大小写混搭、随机后缀(如 xm_2003LDShen666甜甜酱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 + gameNameconsumerId + consumerNameplayerId + 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 ChatSessiontype 已区分 order/consultation,但 orderId 仍是 optional,缺少判别联合约束(type 为 order 时 orderId 应必填)
types.ts:117-125 Dispute.resultstatus 无联动,resolved 状态时也可无结果
types.ts:18,29,31 Game.categoryPlayerService.unitavailability 过宽(全是 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:15app/(order)/order/[id]/page.tsx:20app/(dashboard)/dashboard/page.tsx:12
roleLabels(用户角色中文映射) app/(main)/community/page.tsx:9app/(main)/post/[id]/page.tsx:12
侧栏组件结构 components/account-sidebar.tsxcomponents/dashboard-sidebar.tsx 结构高度重复
Layout 壳层 app/(account)/layout.tsxapp/(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.tsxcomponents/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 要求按身份展示不同视图
身份认证审核 不完整 只有"填写→审核中"两个状态,缺少拒绝、补件、重新提交等完整审核状态机
搜索混合展示 未实现 当前只筛选 mockPlayersPLAN 要求"店铺打手+独立打手混合展示"
社区筛选排序 未实现 缺少时间/热度排序、标签/游戏筛选,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. 社区筛选排序(最新/最热/关注、标签/游戏筛选)