--- sidebar_position: 9 title: 开发规范与 Sprint 计划 sidebar_label: 开发规范 description: Plaza 开发顺序、编码规范、本地启动方式、Sprint 拆分和出口条件 --- # 开发规范与 Sprint 计划 ## 开发顺序原则 每个功能点按以下顺序完成,不跳步: ``` 1. 数据库迁移(plaza_* 表) 2. 后端 repository 层(纯 SQL,无业务逻辑) 3. 后端 service 层(权限校验、状态机、事务) 4. 后端 API 路由(DTO、OpenAPI 更新) 5. 前端 API 封装(ui/plaza/lib/api.ts) 6. 前端页面和组件 7. 自动化测试(单元 + E2E) 8. 审计日志和指标埋点 9. 手工验收 ``` --- ## 本地启动 ### 前置要求 ```bash source bin/activate-hermit # Rust 工具链(现有要求) node --version # >= 18 pnpm --version # >= 8 redis-server --version # >= 6(新增依赖) ``` ### 启动顺序 ```bash # 1. 后端(现有,不变) cd ui/h5 node server.mjs # 2. MindSpace H5(现有,不变) cd ui/h5 pnpm dev # 3. Plaza Next.js(新增) cd ui/plaza pnpm install pnpm dev # 开发模式,port 3001 # 4. 运营后台(新增,可选) cd ui/ops pnpm install pnpm dev # port 3002 ``` ### 环境变量 `ui/plaza/.env.local`: ```bash NEXT_PUBLIC_API_BASE=http://localhost:18006 NEXT_PUBLIC_PLAZA_BASE=http://localhost:3001 ``` `ui/ops/.env.local`: ```bash VITE_API_BASE=http://localhost:18006 ``` ### Nginx 本地开发替代方案 开发时不需要 Nginx,三个进程各自占用端口,直接访问: - `http://localhost:8080` → MindSpace H5 - `http://localhost:3001` → Plaza - `http://localhost:3002` → 运营后台 - `http://localhost:18006` → 后端 API --- ## 编码规范 ### 后端 ``` - 新模块放在 ui/h5/plaza-*.mjs,与 mindspace-publications.mjs 并列,由 server.mjs 挂载 /api/plaza/v1/* - 路由文件只做:解析请求、鉴权、调用 service、映射响应 - service 文件只做:业务逻辑、事务、权限校验 - repository 文件只做:SQL,不含业务判断 - plaza_posts 快照字段在 service 层写入,repository 层不负责查 h5_users 表 - 错误返回统一格式:{ error: { code: 'XXX', message: '...' } } - 运营写操作写入 ops_audit_log;用户写操作写入 h5_mindspace_audit_logs(如需要) ``` ### 前端(Next.js) ``` - 所有数据获取在 Server Component 中完成,不在 useEffect 里 fetch - 客户端交互(点赞、评论)使用 SWR mutation,乐观更新 - 图片全部用 next/image,不用 - 所有 API 调用封装在 lib/api.ts,组件不直接调用 fetch - 类型定义放在 types/plaza.ts,与后端 DTO 保持一致 - 不引入 Redux / Zustand,组件状态用 useState,跨组件用 React Context ``` ### 通用 ``` - 所有 SQL 迁移:更新 `ui/h5/schema.sql` + `db.mjs` 幂等 ALTER - 不在迁移文件中写业务数据(除 plaza_categories 初始数据) - 新功能分支命名:feature/plaza-{功能名} - commit 消息格式:feat(plaza): 描述 / fix(plaza): 描述 - PR 必须更新对应文档 ``` --- ## Sprint 计划 ### Sprint 1:数据基础 + 发布到广场 **目标**:用户能将 MindSpace 页面发布到广场,广场首页能展示。 **后端任务**: - [x] 创建 `plaza_categories` 表并写入初始 8 个分类 - [x] 创建 `plaza_posts` 表(含索引) - [x] 后端 POST /api/plaza/v1/posts(发布到广场) - [x] 后端 GET /api/plaza/v1/feed(热门/最新列表) - [x] 后端 GET /api/plaza/v1/posts/:id(帖子详情) - [x] 后端 GET /api/plaza/v1/categories(分类列表) - [x] publication 下线时自动 hidden 对应 plaza_posts - [ ] 初始化 Redis 连接,view_count 计数接入(Sprint 3 已实现,Sprint 1 出口不阻塞) - [ ] OpenAPI 同步(S1-B10,见 10-implementation-status P2) **前端任务**: - [x] 初始化 `ui/plaza/` Next.js 项目 - [x] 实现 /plaza 首页(SSR,卡片瀑布流) - [x] 实现 /plaza/cat/:slug 分类页(SSR + fetch 缓存) - [x] 实现 /plaza/p/:id 帖子详情页(含 iframe embed) - [x] 实现 PostCard 组件(含所有状态) - [x] MindSpace 页面详情新增「发布到广场」按钮 - [x] generateMetadata 接入所有 SSR 页面 - [x] MindSpace 发布对话框:封面 URL + 允许评论开关(见 08 流程图) **审核策略(Sprint 1)**: - 帖子创建后默认 `pending_review`,**不出现在**公开 Feed。 - 开发环境:`PLAZA_AUTO_APPROVE=true` 时,内容扫描通过后自动 `published`(便于本地 E2E)。 - 生产环境:Sprint 1 在现有 `/admin` 增加最小审核入口;Sprint 5 再上线完整 `ui/ops/`。 **出口条件**: - 用户能完成「MindSpace 发布页面 → 发布到广场 → **审核通过** → 广场首页出现」完整流程 - 游客可以浏览广场,curl 能拿到完整 HTML(验证 SSR 正常) - 下线 publication 后,对应广场帖子消失 --- ### Sprint 2:互动系统 **目标**:点赞、收藏、评论、关注全部可用。 **后端任务**: - [x] 创建 `plaza_reactions`、`plaza_comments`、`plaza_follows` 表 - [x] POST/DELETE /api/plaza/v1/posts/:id/reactions - [x] GET/POST/DELETE /api/plaza/v1/posts/:id/comments - [x] POST/DELETE /api/plaza/v1/comments/:id/reactions - [x] POST/DELETE /api/plaza/v1/users/:slug/follow - [x] GET /api/plaza/v1/users/:slug(用户主页数据) - [ ] Redis 点赞计数 + 定时同步任务(仍直写 MySQL,见 P3) - [x] users 表新增 plaza_* 计数字段 **前端任务**: - [x] PostActions 组件(点赞/收藏/分享,含登录引导浮层) - [x] CommentSection 组件(列表 + 输入框 + 二级回复展示) - [x] /u/:slug 用户主页(SSR) - [x] 关注按钮组件(含乐观更新) - [x] 数字格式化(1.2k / 1.2万) - [x] 分享时调用 `share` reaction 写入 `share_count` **出口条件**: - 点赞后 hot_score 在下一次计算周期后反映在热门列表 - 二级评论正常展示,不允许三级嵌套 - 关注后用户主页粉丝数 +1(乐观更新) --- ### Sprint 3:热度算法 + 用户主页 **目标**:热度排序正常运转,用户主页作品集完整。 **后端任务**: - [x] 创建 `plaza_algorithm_config` 表 - [x] 热度计算定时任务(每 10 分钟,覆盖 48 小时内帖子) - [x] Feed 缓存接入(Redis TTL 5 分钟) - [x] GET /api/plaza/v1/users/:slug/posts(分页) - [x] 防刷:IP 维度浏览去重(Redis SET NX) - [x] 广场互动数据异步回写 publications **前端任务**: - [x] UserPostGrid 组件(用户主页帖子网格) - [x] FeedTabs 「热门/最新」切换 - [x] 无限滚动加载(IntersectionObserver) - [x] CategoryNav 分类导航 - [x] 移动端底部导航 **出口条件**: - 广场首页热门列表按 hot_score 正确排序 - 同一 IP 对同一帖子 24 小时内只计 1 次浏览 - 移动端 2 列布局正常 --- ### Sprint 4:SEO 完善 + 水印入口 **目标**:所有页面可被搜索引擎收录,病毒增长入口上线。 **后端任务**: - [x] 动态 OG 图生成(无封面图时兜底) - [x] Sitemap 接口(/sitemap.xml) - [x] 新帖发布后主动推送百度索引 - [x] UTM 参数追踪接口(记录广场带来的注册转化) **前端任务**: - [x] 所有 SSR 页面接入完整 meta(JSON-LD:帖子/用户/首页/分类) - [x] robots.txt 正确配置 - [x] Footer 水印「用 MindSpace 制作 →」(带 UTM 参数) - [x] 社交分享功能(复制链接 + 生成分享图 + share_count) - [x] 性能优化:图片懒加载、骨架屏(`PostGridSkeleton` + `loading.tsx`) - [ ] 微信 JS-SDK 内分享(P3) **出口条件**: - Google Search Console 提交 Sitemap 无报错 - 微信内分享帖子能显示封面图和标题 - 广场注册转化率可追踪(UTM 数据进入运营看板) --- ### Sprint 5:运营后台 **目标**:运营人员可以审核内容、管理精选。 **后端任务**: - [x] 创建 `plaza_reports`、`plaza_featured`、`ops_audit_log` 表 - [x] 运营角色中间件(ops_role 校验) - [x] POST /api/ops/v1/review/posts/:id(审核) - [x] POST /api/plaza/v1/posts/:id/reports(帖子举报) - [x] POST /api/plaza/v1/comments/:id/reports(评论举报) - [x] POST /api/ops/v1/featured(设置精选,含 `category_top`) - [x] GET /api/ops/v1/analytics/overview - [x] POST /api/ops/v1/review/batch(批量审核) **前端任务**: - [x] 初始化 `ui/ops/` Vite 项目 - [x] 审核队列页面(待审/已通过/已拒绝 Tab + 批量通过) - [x] 举报处理页面 - [x] 精选管理页面 - [ ] 数据概览看板(图表,当前为列表指标) - [x] Plaza 帖子页举报入口 **出口条件**: - 审核操作全部写入 ops_audit_log - 精选帖子在广场首页正确展示 - Nginx `/ops` 路由只允许内网访问 --- ## 每个 Sprint 的通用出口条件 - [x] 数据库迁移可在空库和现有生产库执行(`schema.sql` + `db.mjs` ALTER) - [x] 后端 API 与 OpenAPI 文档同步(`just check-h5-openapi-schema`) - [ ] 权限拒绝路径有测试(跨用户越权返回 404/403) - [x] 前端有加载、空、错误三种状态(主要页面) - [ ] 移动端主要流程验收通过(手工) - [x] 无 TypeScript 编译错误(`ui/plaza` / `ui/ops` build) - [x] `cargo clippy` 无警告(Plaza 无 Rust 改动时 N/A) > 详细差距见 [实现进度](./10-implementation-status.md#差距追踪p0p3)。 --- ## 发布到广场的用户体验流程图 ```text MindSpace 页面详情 │ ▼ [发布到广场] 按钮 │ ▼ 选择分类(必选) 输入标签(可选,最多 5 个) 确认封面图(可换) 是否允许评论(默认开) │ ▼ POST /api/plaza/v1/posts │ ┌──┴──┐ │ │ 成功 失败 │ │ ▼ ▼ 帖子进入 提示错误原因 待审状态 (publication 未上线 / │ 已发布过 / 无权限) ▼ 审核通过(自动或人工) │ ▼ 广场公开展示 │ ▼ 页面详情显示「广场链接」和互动数 ```