# NomadCNA 前端项目分析报告 生成日期:2026-06-06 ## 1. 分析范围与结论 本报告只分析当前仓库中的前端项目现状。仓库内虽然存在 `app/api`、PocketBase、支付、MinIO 等旧接口适配代码,但根据当前开发方向,这部分后端实现已隔离,后续应由 FastAPI + PocketBase 重新设计和实现。因此本文不会把旧 `app/api` 作为未来后端实现依据,只把它们作为“前端当前依赖的接口形状”记录,方便后续替换。 总体判断: - 当前项目是一个 Next.js 16 App Router 前端应用,核心体验已经具备较完整的页面骨架和视觉资产。 - 主要业务数据仍以 TypeScript 静态数据、配置文件和页面内 mock 数据为主。 - 前端已覆盖城市探索、下一站决策、社区加入、会员支付入口、聚会、匹配、讨论、赏金、工具箱、年报、地图、内容页和法律页等模块。 - 后续真实开发重点不是重写 UI,而是抽离接口层、设计 PocketBase 数据模型、用 FastAPI 承接认证、业务规则、支付、上传、AI、统计等后端能力。 - 当前前端和旧后端存在耦合,需要在后续开发中集中替换为统一 API client 和清晰的数据契约。 ## 2. 技术栈概览 ### 2.1 主要依赖 来自 `package.json`: - Next.js:`16.1.6` - React / React DOM:`19.2.3` - TypeScript:`^5` - Tailwind CSS:`^4` - ECharts:`^6.0.0` - PocketBase JS SDK:`^0.26.8` - MinIO SDK:`^8.0.7` - 包管理:`pnpm@10.25.0` ### 2.2 运行脚本 - `pnpm dev`:`next dev -p 3001 -H 0.0.0.0` - `pnpm build`:生产构建 - `pnpm start`:生产启动 - `pnpm lint`:ESLint 注意:`README.md` 中写的是打开 `http://localhost:3000`,但实际 dev 脚本端口是 `3001`,文档需要同步。 ## 3. 目录结构与职责 当前关键目录: ```text app/ [locale]/ 多语言页面路由 components/ 通用前端组件 context/ Locale / Theme Context data/ 静态业务数据 lib/ 前端工具库、旧服务适配、图表组件 api/ 旧 Next API Route,后续不建议作为目标后端保留 config/ 站点、导航、首页、页脚、服务配置 i18n/ 本地化导航封装 messages/ zh / en 文案 public/ 静态资源 ``` ### 3.1 前端核心文件 - `app/layout.tsx`:全局 HTML、主题脚本、ThemeProvider。 - `app/[locale]/layout.tsx`:语言路由布局,加载多语言消息,挂载 Navbar。 - `app/[locale]/page.tsx`:首页,包含 Hero、城市列表、筛选、热门路线、社区动态。 - `app/globals.css`:Tailwind 4 入口、深色模式、全局布局类、城市卡片和表单样式。 - `app/context/LocaleContext.tsx`:自定义 i18n Context 和路由跳转封装。 - `app/context/ThemeContext.tsx`:亮色/暗色主题,使用 localStorage 保存偏好。 ### 3.2 配置文件 - `config/site.config.ts`:站点标题、描述、口号。 - `config/nav.config.ts`:顶部导航入口。 - `config/home.config.ts`:首页成员头像、路线、热门话题、统计数据。 - `config/footer.config.ts`:页脚链接。 - `config/services.config.ts`、`config/domain.config.ts`:旧服务配置。未来后端重写时应重构为前端只保留 `NEXT_PUBLIC_API_BASE_URL` 等必要公开变量。 ## 4. 页面模块梳理 当前 `app/[locale]` 下页面较完整,页面数量约 31 个。 ### 4.1 首页与城市探索 相关文件: - `app/[locale]/page.tsx` - `app/components/HeroSection.tsx` - `app/components/FilterBar.tsx` - `app/components/CityCard.tsx` - `app/components/CityModal.tsx` - `app/data/cities.ts` 能力现状: - 首页展示城市卡片网格,支持按标签筛选和按综合评分、费用、网速、安全、游民数量、温度排序。 - 城市数据来自 `app/data/cities.ts`,共 18 个城市。 - `CityCard` 提供卡片 hover 评分展示。 - `CityModal` 提供接近 Nomad List 风格的城市详情弹窗,但大量 tab 内容仍是占位。 - 首页的成员、路线、热门话题、社区动态来自 `config/home.config.ts`。 后续真实化方向: - 城市、城市指标、标签、封面图、热度、评分、评论、气候、网速、生活成本应迁入 PocketBase。 - 首页统计、热门路线、成员头像、热门话题应改由 FastAPI 聚合返回。 - 筛选逻辑目前在前端内存完成;真实数据量上来后应由后端分页、排序、过滤。 ### 4.2 下一站决策仪表盘 相关文件:`app/[locale]/dashboard/page.tsx` 能力现状: - 用户可设置预算、最低网速、时区、签证偏好、希望认识的人群。 - 实际筛选只使用预算和网速,数据来自本地 `cities`。 - 成本曲线、游民密度热力图、AI 推荐等为占位。 后续真实化方向: - 建立城市推荐 API,根据预算、网速、气候、社区密度、签证、职业偏好等返回排序结果。 - AI 推荐可以由 FastAPI 调用模型服务,结果落库便于复盘。 - 图表数据需要后端提供时间序列、城市指标、用户偏好权重。 ### 4.3 加入社区与会员支付 相关文件: - `app/[locale]/join/page.tsx` - `app/[locale]/join/paid/page.tsx` - `app/components/JoinModal.tsx` - `app/components/AuthModal.tsx` - `app/components/HeroSection.tsx` 能力现状: - 首页 Hero 支持输入邮箱并进入加入/支付流程。 - `/join` 是较完整的报名表单,包含昵称、性别、感情状态、职业、微信、手机、自我介绍、学历、毕业时间、头像/视频上传。 - 当前页面会调用旧接口:`/api/auth/me`、`/api/join`、`/api/join/status`、`/api/vip/check`、`/api/upload-media`、`/api/pay/status`、`/api/meetup/*` 等。 - 支付成功页负责完成订单、同步登录态、设置改密状态等。 后续真实化方向: - FastAPI 统一接管登录、报名、会员状态、订单创建、支付回调、支付状态查询、媒体上传。 - PocketBase 存储用户、资料、报名表、会员权益、订单、支付流水。 - 前端应只调用 FastAPI,不直接处理 PocketBase 管理员逻辑。 - 支付状态和订单状态需要明确状态机,例如 `pending`、`paid`、`failed`、`expired`、`refunded`。 ### 4.4 社区、匹配、聚会、讨论、赏金 相关页面: - `app/[locale]/dating/page.tsx` - `app/[locale]/meetups/page.tsx` - `app/[locale]/meetups/host/page.tsx` - `app/[locale]/discuss/page.tsx` - `app/[locale]/gigs/page.tsx` 能力现状: - 匹配页有 profile card、喜欢/不感兴趣按钮、匹配类型 tab,但使用页面内 mock。 - 聚会页有 upcoming / previous tab,聚会列表全部 hardcode。 - 发起聚会页有表单,文案明确“演示模式,数据不会保存”。 - 讨论页使用 `MOCK_TOPICS`,支持搜索过滤。 - 赏金墙使用 `MOCK_GIGS`。 后续真实化方向: - 聚会:活动创建、审核、发布、报名、取消报名、参与者列表、城市筛选。 - 匹配:个人资料、目标类型、滑动记录、互相喜欢、举报/拉黑、推荐排序。 - 讨论:话题、评论、点赞、浏览数、标签、审核。 - 赏金:任务发布、接单、交付、评价、平台抽成、支付/托管。 ### 4.5 工具箱、AI、年报、地图和数据报告 相关页面: - `app/[locale]/tools/page.tsx` - `app/[locale]/ai/page.tsx` - `app/[locale]/report/page.tsx` - `app/[locale]/report/data/page.tsx` - `app/[locale]/map/page.tsx` - `app/lib/charts/*` 能力现状: - 工具箱包含静态汇率、税务估算、签证倒计时,FIRE 和气候查询为占位。 - AI 页面为即将上线状态。 - 年报页面是静态生成入口和展示样式。 - 地图和数据报告使用 `MAP_CITIES` 静态城市坐标和 ECharts 地图组件。 后续真实化方向: - 汇率、天气、气候、签证政策属于外部数据集成,应由 FastAPI 定时同步或按需代理。 - 年报依赖用户行程、城市停留、消费、活动报名、社区互动等真实数据。 - 地图应聚合匿名化成员城市分布,避免暴露个人精确位置。 - AI 需要用户上下文、城市数据和安全边界。 ### 4.6 内容与静态信息页 相关页面: - `blog`、`careers`、`press`、`help` - `about`、`contact`、`support` - `terms`、`privacy`、`cookies`、`safety`、`guidelines` 能力现状: - 多数内容来自 `app/data/mock.ts`。 - 页面完成度适合 MVP 展示,但没有 CMS 或后台维护能力。 后续真实化方向: - 内容可先继续静态化,后期迁入 PocketBase 作为轻量 CMS。 - 法律、隐私、帮助中心等应有版本号和更新时间。 - 招聘、媒体报道、博客需要 slug、SEO metadata、草稿/发布状态。 ## 5. 数据来源现状 ### 5.1 静态数据 - `app/data/cities.ts`:18 个城市,含成本、网速、安全、温度、标签、封面、经纬度等。 - `app/data/map-cities.ts`:地图城市坐标和成员数。 - `app/data/mock.ts`:博客、招聘、媒体报道、帮助中心、安全指南、社区准则、联系信息、条款、隐私、Cookie。 - `config/home.config.ts`:首页社群头像、旅行中成员、聚会、热门话题、路线、统计。 - 页面内 mock:聚会、匹配、讨论、赏金等。 ### 5.2 多语言数据 - `messages/zh.json` - `messages/en.json` 当前 i18n 是自定义 Context,不依赖 next-intl。优点是简单可控,缺点是类型约束弱,缺少自动 key 检查,也没有格式化复数、日期、变量插值的完整能力。 ### 5.3 外部资源 当前大量图片来自: - `i.pravatar.cc` - `images.unsplash.com` - `api.dicebear.com` - `logo.clearbit.com` 这些适合原型阶段,但生产环境需要明确版权、可用性、缓存策略、头像隐私和图片优化策略。 ## 6. 前端状态与交互方式 当前项目大量使用 client component: - `useState` 管理表单、弹窗、tab、筛选、排序。 - `useMemo` 做城市筛选、聚会分类。 - `localStorage` 保存主题、旧 PocketBase token、用户信息、支付订单。 - `document.cookie` 保存旧支付订单状态和服务端 session。 - `createPortal` 实现 AuthModal、JoinModal、CityModal。 - `window.location.href` / `replace` 用于语言切换、支付回跳和登录同步。 后续建议: - 建立统一 `app/lib/api-client.ts` 或 `app/services/*`,集中处理 API base URL、鉴权、错误码、重试、超时。 - 把旧 PocketBase 前端 SDK 调用逐步移除,前端只通过 FastAPI 访问业务接口。 - 登录态统一为 httpOnly cookie + `/auth/me`,避免前端长期保存敏感 token。 - 表单建议引入 schema 校验,例如 Zod;至少在前后端共享字段约束。 ## 7. 当前主要风险 ### 7.1 敏感信息风险 `.env.example` 和 `.env.local` 中存在 PocketBase 管理员邮箱和密码字段,并且当前样例包含明文值。即使这些只是旧后端配置,也应立即视为泄露风险: - 从仓库中移除真实凭据。 - 轮换 PocketBase 管理员密码。 - `.env.example` 只保留占位符。 - 后续 FastAPI 服务端使用 Secret Manager 或部署平台环境变量。 ### 7.2 前端与旧后端耦合 多个核心前端组件直接调用旧路径: - `Navbar`:`/api/auth/me`、`/api/auth/sync-session` - `HeroSection`:`/api/auth/me`、`/api/meetup/check-user`、`/api/meetup/ensure-user` - `JoinModal`:`/api/meetup/ensure-user` - `join/page.tsx`:`/api/join`、`/api/join/status`、`/api/vip/check`、`/api/upload-media` - `join/paid/page.tsx`:`/api/meetup/complete-order`、`/api/auth/change-password` - payment hooks:`/api/pay`、`/api/pay/status` - charts:`/api/geo/china` 这些路径后续需要迁移到 FastAPI,并通过统一 API client 映射。 ### 7.3 大量业务仍为 mock 当前页面中明确存在“演示模式”“开发中”“即将上线”: - 反馈提交 - 发起聚会 - 成员地图 - 数据报告 - AI - FIRE 计算器 - 气候查询 - 仪表盘图表 这不是坏事,说明前端原型覆盖面广;但后续排期需要明确哪些 mock 优先变成真实闭环。 ### 7.4 日期数据过期 当前日期为 2026-06-06,但聚会页仍把 2026-03 和 2026-04 的活动标记为“即将举办”。后续真实数据必须由后端按当前时间计算活动状态,不能依赖静态 `isUpcoming`。 ### 7.5 文档与实际运行不一致 - README 写 `localhost:3000`,脚本实际是 `3001`。 - README 写 Node.js 18+,但 Next.js 16 / React 19 的实际运行要求需要在开发环境中确认并统一。 ### 7.6 UI 资产和图片生产化不足 - 大量使用第三方随机头像和远程图片。 - 未系统使用 `next/image`。 - 没有图片域名、尺寸、占位、失败回退策略。 ## 8. 后续 FastAPI + PocketBase 目标架构建议 ### 8.1 推荐边界 建议后续边界如下: ```text Next.js 前端 只负责页面、交互、渲染、调用 FastAPI FastAPI 负责业务 API、认证会话、权限、支付、上传、AI、统计聚合、外部服务集成 PocketBase 负责数据存储、基础用户表、文件/记录管理、后台管理界面、必要的 realtime 能力 ``` 关键原则: - 前端不要直接使用 PocketBase 管理员权限。 - 复杂业务规则放在 FastAPI,不散落在前端。 - PocketBase 作为数据和后台管理层,不承担所有业务流程。 - 支付回调、会员开通、退款、上传鉴权、AI 调用必须走 FastAPI。 ### 8.2 建议数据模型 首批 PocketBase collections 可按以下方向设计: - `users`:用户基础账号,可使用 PocketBase auth collection。 - `profiles`:昵称、头像、职业、城市、简介、标签、匹配偏好。 - `member_applications`:加入社区报名表。 - `memberships`:会员等级、有效期、权益、状态。 - `orders`:订单号、用户、金额、渠道、状态、业务类型。 - `payment_events`:支付回调原始事件和处理状态。 - `media_assets`:上传文件、类型、归属用户、用途。 - `cities`:城市基础信息、slug、多语言名称、坐标、封面。 - `city_metrics`:成本、网速、气候、安全、社区密度等指标。 - `city_guides`:城市攻略、共享办公、社区推荐、tips。 - `meetups`:聚会活动。 - `meetup_rsvps`:活动报名关系。 - `discussions`:讨论话题。 - `comments`:评论。 - `gigs`:赏金任务。 - `gig_applications`:接单/投递。 - `swipes`:匹配滑动记录。 - `matches`:互相喜欢记录。 - `feedback`:建议与 Bug 反馈。 - `annual_reports`:年报生成结果和快照。 ## 9. FastAPI API 清单草案 ### 9.1 认证与用户 - `POST /auth/register` - `POST /auth/login` - `POST /auth/logout` - `GET /auth/me` - `POST /auth/change-password` - `GET /users/me/profile` - `PATCH /users/me/profile` ### 9.2 加入社区与会员 - `GET /join/status` - `POST /join/applications` - `GET /memberships/me` - `POST /payments/checkout` - `GET /payments/{order_id}/status` - `POST /payments/webhooks/{provider}` ### 9.3 媒体上传 - `POST /media/uploads` - `GET /media/{id}` - `DELETE /media/{id}` ### 9.4 城市与推荐 - `GET /cities` - `GET /cities/{slug}` - `GET /cities/{slug}/metrics` - `GET /cities/{slug}/guide` - `POST /recommendations/next-stop` - `GET /routes/hot` ### 9.5 社区模块 - `GET /meetups` - `POST /meetups` - `GET /meetups/{id}` - `POST /meetups/{id}/rsvp` - `DELETE /meetups/{id}/rsvp` - `GET /discussions` - `POST /discussions` - `GET /discussions/{id}/comments` - `POST /discussions/{id}/comments` ### 9.6 匹配模块 - `GET /matches/candidates` - `POST /matches/swipes` - `GET /matches/me` - `POST /reports/profile` - `POST /blocks/profile` ### 9.7 赏金与反馈 - `GET /gigs` - `POST /gigs` - `POST /gigs/{id}/apply` - `POST /feedback` ### 9.8 数据报告与 AI - `GET /stats/member-map` - `GET /stats/city-ranking` - `POST /reports/annual/generate` - `GET /reports/annual/{id}` - `POST /ai/assistant` ## 10. 前端改造路线 ### 阶段 0:清理与契约冻结 - 移除仓库中的真实密钥,轮换泄露风险凭据。 - 明确旧 `app/api` 全部为 legacy,不继续扩展。 - 建立 `NEXT_PUBLIC_API_BASE_URL`。 - 梳理当前前端调用接口,写成接口契约文档。 - 修正 README 端口和环境说明。 ### 阶段 1:统一 API client - 新增统一 API client,集中处理: - base URL - credentials - JSON 解析 - 错误响应 - 登录失效 - loading / retry 策略 - 替换 `fetch("/api/...")` 为领域服务函数,例如 `authApi.me()`、`joinApi.submit()`。 - 前端保留 mock fallback,方便后端未完成时继续开发 UI。 ### 阶段 2:认证、报名、支付闭环 优先原因:这是转化和会员收入核心链路。 - FastAPI 实现注册、登录、会话、改密。 - FastAPI 实现报名表提交。 - 实现支付下单、支付状态、支付回调、会员开通。 - 实现上传鉴权和媒体资产记录。 - 前端替换 Hero、JoinModal、JoinPage、JoinPaidPage、Navbar 的旧接口调用。 ### 阶段 3:城市数据真实化 - 将 `cities.ts` 迁入 PocketBase。 - 前端首页和仪表盘改为调用 `/cities`。 - 城市详情弹窗拆分真实字段和占位字段。 - 建立城市 slug,避免只用中文城市名作为业务 key。 ### 阶段 4:社区功能真实化 - 聚会列表和发起聚会落库。 - 讨论和评论落库。 - 匹配候选人、滑动、match 记录落库。 - 赏金墙发布和接单落库。 ### 阶段 5:AI、年报、统计 - 接入 AI 助手。 - 根据真实用户行为生成年度报告。 - 地图、城市排名、增长趋势改由后端聚合。 ### 阶段 6:运营后台与权限 - 使用 PocketBase Admin 作为轻量后台。 - 增加内容审核、聚会审核、举报处理、会员管理、订单查询。 - FastAPI 增加管理员 API 或管理脚本。 ## 11. 建议优先级 P0: - 凭据清理与轮换。 - 统一 API base URL 和 API client。 - 认证、报名、支付、会员状态真实闭环。 - 上传链路真实化。 P1: - 城市数据迁移 PocketBase。 - 首页、城市详情、仪表盘接入真实城市 API。 - 聚会列表和报名真实化。 - 反馈提交真实化。 P2: - 匹配、讨论、赏金墙真实化。 - 地图和数据报告真实化。 - AI 助手上线。 P3: - 内容 CMS 化。 - SEO metadata 完善。 - 图片优化和 CDN 策略。 - 自动化测试和监控。 ## 12. 测试与验收建议 前端: - `pnpm lint` - `pnpm build` - 首页、加入表单、登录弹窗、支付回跳、城市筛选、语言切换、暗色模式的 Playwright E2E。 - 移动端视口检查,尤其是首页网格、Join 表单、CityModal。 后端: - FastAPI 单元测试:认证、报名、支付状态机、权限。 - 支付 webhook 幂等测试。 - PocketBase collection rule 测试。 - 媒体上传大小、类型、权限测试。 契约: - OpenAPI 自动生成。 - 前端类型从 OpenAPI 生成或至少共享 DTO schema。 - mock server 保持和 OpenAPI 一致。 ## 13. 总结 当前项目的价值主要在前端产品原型和页面覆盖度:导航、首页、城市探索、会员加入、社区、工具、内容页都已经成型。短板集中在数据真实性、后端契约、认证支付安全、mock 数据和旧接口耦合。 后续开发不建议在旧 `app/api` 上继续补功能。更稳妥的路线是保留当前 Next.js 前端体验,新增 FastAPI 后端,PocketBase 作为数据和后台管理层,然后按“认证/报名/支付 -> 城市数据 -> 社区互动 -> AI/统计”的顺序逐步替换 mock 和旧接口。