Files
gitlab-instance-0a899031_cn…/PROJECT_ANALYSIS_REPORT.md
2026-06-06 04:29:46 -05:00

549 lines
19 KiB
Markdown
Raw Permalink 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.
# 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 记录落库。
- 赏金墙发布和接单落库。
### 阶段 5AI、年报、统计
- 接入 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 和旧接口。