Files
soul-yongping/开发文档/4、前端/当前小程序开发细则.md

161 lines
11 KiB
Markdown
Raw Normal View History

2026-02-05 11:35:57 +08:00
# 当前小程序开发细则
> 汇总当前 Soul 创业派对小程序的架构、经验与规划,便于新人上手与后续迭代。
> 最后整理2026-02
---
## 一、概述与定位
- **产品**Soul 创业派对 — 微信小程序,内容为《一场 SOUL 的创业实验场》章节阅读 + 找伙伴 + 分销。
- **技术**:原生微信小程序(非 uni-app / Taro与 Next.js 后端同仓,接口统一走 `apiBase`(如 `https://soul.quwanzhi.com`)。
- **核心能力**:章节阅读(免费/付费)、单章/全书支付、邀请码分销、找伙伴(匹配次数购买)、推广中心、我的订单/设置。
---
## 二、目录与页面结构
### 2.1 目录结构miniprogram/
```
miniprogram/
├── app.js / app.json / app.wxss # 入口、全局配置、样式
├── custom-tab-bar/ # 自定义底部 tabBar
├── pages/
│ ├── index/ # 首页(推荐章节、已读统计)
│ ├── chapters/ # 目录(全书章节列表)
│ ├── read/ # 阅读页(核心:权限、支付、分享)
│ ├── match/ # 找伙伴(匹配 + 购买次数)
│ ├── my/ # 我的(入口:订单、推广、设置)
│ ├── referral/ # 推广中心(邀请码、收益、海报)
│ ├── purchases/ # 我的订单(当前为本地已购章节列表)
│ ├── settings/ # 设置(提现、绑定账号等)
│ ├── search/ # 搜索
│ ├── about/ # 关于
│ └── addresses/ # 地址(若启用)
├── utils/
│ ├── chapterAccessManager.js # 章节权限与状态
│ ├── readingTracker.js # 阅读进度追踪
│ ├── payment.js # 旧支付封装(部分场景仍用)
│ └── util.js
└── assets/ # 图标等静态资源
```
### 2.2 TabBar 与主要页面
| Tab | 页面 | 说明 |
|-----|------|------|
| 首页 | pages/index/index | 推荐章节、已读/待读、入口到阅读 |
| 目录 | pages/chapters/chapters | 全书章节列表 |
| 找伙伴 | pages/match/match | 匹配 + 购买匹配次数 |
| 我的 | pages/my/my | 已读/已购、推广中心、订单、设置 |
非 Tab 页:阅读页 read、推广中心 referral、订单 purchases、设置 settings、搜索 search、关于 about。
### 2.3 全局状态app.js globalData
- `userInfo`登录后用户信息id、openId、nickname、purchasedSections、hasFullBook、referralCode、referralCount 等)。
- `openId` / `isLoggedIn`:微信登录态。
- `readSectionIds`:已读章节 ID 列表(有权限打开全文时打点)。
- `pendingReferralCode`:待绑定推荐码(带 ref 进入时写入,登录后绑定)。
- `apiBase`:后端 API 根地址。
---
## 三、核心流程与经验
### 3.1 阅读与章节权限
- **权威数据源**:章节是否可读以**服务端**为准(`/api/user/check-purchased``/api/user/purchase-status`),不依赖前端缓存做最终判断。
- **权限状态**:设计上支持 `unknown / free / locked_not_login / locked_not_purchased / unlocked_purchased / error`(见《章节阅读付费标准流程设计》);阅读页通过 `chapterAccessManager``determineAccessState` 等做状态判断。
- **免费章节**:来自后端配置(如 `/api/db/config` 的 freeChapters页面 onLoad 时拉取最新免费列表再判断;首帧可用本地默认 freeIds拉取完成后需能刷新当前章状态避免竞态误判。
- **已读 vs 已购**
- **已读**:仅统计“有权限打开并看到全文”的章节(`canAccess=true``app.markSectionAsRead(sectionId)`),存 `readSectionIds`
- **已购**:来自服务端 `userInfo.purchasedSections``hasFullBook` 及 orders 表,用于付费墙与购买按钮展示。
- **登录后防误解锁**:登录成功(含支付流程中登录)后必须 `refreshPurchaseFromServer()`,再对当前章节做 `recheckCurrentSectionAndRefresh()`(先拉最新免费列表,再请求 check-purchased避免“刚登录”时误用旧缓存解锁付费章。
- **内容接口**:当前 `GET /api/book/chapter/[id]` 不校验登录与购买,前端按 `canAccess` 控制展示全文或预览;若未来开放 Web/API建议章节接口侧做鉴权。
详见:`开发文档/8、部署/章节阅读付费标准流程设计.md`
2026-02-05 11:35:57 +08:00
### 3.2 支付流程(章节 + 找伙伴)
- **统一入口**:章节支付 `pages/read/read.js``POST /api/miniprogram/pay`;找伙伴支付 `pages/match/match.js` 同样调该接口,传 `productType: 'match'`
- **订单先行**:支付前**必须先创建订单**并插入 `orders`status=`created`),再调微信统一下单;即使插库失败也继续支付流程,避免用户卡在“创建订单失败”。
- **请求体约定**`openId``userId``productType`section/fullbook/match`productId``amount``description`**必须带 `referralCode`**(见下节)。
- **支付成功**:依赖微信回调 `POST /api/miniprogram/pay/notify` 更新订单为 `paid`、解锁用户权限、分佣、清理同产品未支付订单;前端支付成功后调用 `refreshUserPurchaseStatus()``initSection()` 刷新当前页。
- **兜底**:若回调丢失,依赖**订单状态同步定时任务**(如每 5 分钟调 `GET /api/cron/sync-orders`)查询微信侧状态并同步到本地 orders保证最终一致。详见 `开发文档/8、部署/宝塔面板配置订单同步定时任务.md`
2026-02-05 11:35:57 +08:00
### 3.3 邀请码与分销(必传、必记)
- **绑定逻辑**:带 `ref``referralCode` 的链接进入 → `app.js``handleReferralCode` 写入 `pendingReferralCode` 并**同步写入 `referral_code`**`wx.setStorageSync('referral_code', refCode)`);登录后调用 `/api/referral/bind` 完成绑定30 天有效、可续期/抢夺)。
- **支付必带邀请码**:章节支付、找伙伴支付创建订单时都要传 `referralCode`,来源为 `wx.getStorageSync('referral_code')`;后端据此(或先查 referral_bindings写入订单的 `referrer_id`**`referral_code`**(下单时使用的邀请码,便于对账与后台展示)。
- **订单表字段**`orders.referrer_id`推荐人用户ID`orders.referral_code`(下单时邀请码)。若表尚未加字段,需执行 `scripts/add_orders_referrer_id.py``scripts/add_orders_referral_code.py`
- **推荐人 vs 邀请码**:全局只认「推荐人 = 用户ID」邀请码仅用于解析出 referrer_id不会混用。分佣以 `referral_bindings` 为准,不依赖订单上的 referrer_id。详见 `开发文档/8、部署/邀请码分销规则说明.md`
### 3.4 分享与落地
- 阅读页分享:`onShareAppMessage` / `onShareTimeline``id=章节ID&ref=当前用户邀请码`,落地后 ref 写入 storage绑定与订单归属同上。
- 文章/章节分销与全局同一套不按“哪篇文章带来”单独分成或统计仅按“谁发的链接ref=谁)”归属。
---
## 四、数据与接口约定
### 4.1 关键接口
| 接口 | 用途 |
|------|------|
| POST /api/miniprogram/login | 微信登录,返回 userInfo含 purchasedSections、referralCode 等) |
| GET /api/user/purchase-status | 拉取购买状态(已购章节、全书) |
| GET /api/user/check-purchased | 校验指定章节/全书是否已购买 |
| POST /api/miniprogram/pay | 创建订单 + 微信预支付,**需传 referralCode** |
| POST /api/miniprogram/pay/notify | 微信支付回调(服务端) |
| GET /api/cron/sync-orders | 订单状态同步(定时任务,需 secret |
| POST /api/referral/bind | 绑定推荐关系 |
| GET /api/db/config | 免费章节等配置 |
### 4.2 Storage 约定
- `referral_code`:落地 ref 或 app 检测到 ref 时写入;支付时读取并传后端。
- `pendingReferralCode` / `boundReferralCode`:待绑定/已绑定推荐码app 层)。
- `readSectionIds`:已读章节 ID 列表。
- `openId`、用户信息等由 app 与登录逻辑维护。
---
## 五、已知问题与修复要点
- **免费章节配置竞态**onLoad 时若未 await 免费列表再 initSection首帧可能用默认 freeIds 误判;建议先拉配置再判断当前章,或拉取完成后对当前页再刷一次权限。
- **check-purchased 失败降级**:失败时应**保守**设为无权限(不信任本地缓存),避免误解锁。
- **支付回调丢失**:必须部署订单同步定时任务(如宝塔 crontab 调 `/api/cron/sync-orders`),否则会出现“已扣款但订单仍 created、内容未解锁”。
- **订单表缺字段**:新环境或老库需执行 `add_orders_referrer_id.py``add_orders_referral_code.py`,否则下单可能 fallback 成不写这两列(功能仍可用,但订单无推荐人/邀请码记录)。
---
## 六、部署与运维
- **后端**Next.js 部署至 soul.quwanzhi.com小程序 `app.globalData.apiBase` 指向该域名。
- **订单同步**:生产环境配置 crontab 每 5 分钟请求 `GET /api/cron/sync-orders?secret=YOUR_SECRET`(如宝塔定时任务),保证回调丢失时仍能同步为 paid 并解锁。见 `开发文档/8、部署/宝塔面板配置订单同步定时任务.md`
2026-02-05 11:35:57 +08:00
- **数据库**orders 表需含 `referrer_id``referral_code`;若为已有表,执行上述两个 Python 迁移脚本。
- **小程序发布**:按微信后台流程上传代码、提交审核;注意域名白名单、支付商户号与回调 URL 配置。
---
## 七、规划与待办(可选)
- **我的订单页**:当前 `purchases` 页为本地已购章节列表;若需“真实订单列表+邀请码展示”,可对接 `GET /api/orders?userId=xxx` 并展示订单维度数据。
- **阅读进度**:已设计阅读进度状态与 `readingTracker`、可上报服务端;是否全量接入与埋点可按产品需求推进。
- **章节接口鉴权**:若开放 Web 或对外 API建议在章节内容接口侧按用户与购买记录返回全文/预览,防止直连拿全文。
- **按文章/章节维度的分销统计**:当前未实现;若需要“某章节带来的访问/订单数”,需在访问或订单上增加来源章节等字段并在报表中汇总。
---
## 八、相关文档索引
| 文档 | 说明 |
|------|------|
| 开发文档/8、部署/邀请码分销规则说明.md | 分销规则、订单 referrer_id/referral_code、推荐人 vs 邀请码 |
| 开发文档/8、部署/章节阅读付费标准流程设计.md | 阅读状态机、权限判断、阅读进度设计 |
| 开发文档/4、前端/ui/06-分销系统说明.md | 分销规则与推广方式 |
| 开发文档/4、前端/ui/08-支付系统说明.md | 支付方式与价格体系 |