删除过时的部署管理端触发词文档,并更新相关索引以反映新的触发词约定,确保文档一致性和准确性。

This commit is contained in:
Alex-larget
2026-03-20 14:38:51 +08:00
parent 385e47bc55
commit d34d209b37
84 changed files with 1127 additions and 4241 deletions

View File

@@ -0,0 +1,26 @@
# 管理端部署触发词约定
**日期**2026-03-20
## 场景
用户说「管理端帮我部署到xx环境」时安全工程师应语义化解析 xx直接执行对应部署脚本。
## 解决方案
- **触发词**管理端帮我部署到xx环境语义化理解意图即可
- **脚本映射**
- 含「正式」「线上」「生产」→ `cd soul-admin && python master.py`(正式环境,/www/wwwroot/self/soul-admin
- 含「测试」「dev」→ `cd soul-admin && python deploy.py`(测试环境,/www/wwwroot/self/soul-admin-dev
## soul-admin 部署脚本
| 脚本 | 环境 | 目标目录 | 构建命令 |
|------|------|----------|----------|
| master.py | 正式 | soul-admin | pnpm build |
| deploy.py | 测试 | soul-admin-dev | pnpm run build:dev |
## 已升级 Skills
1. **security-server-ops**何时使用表、2.2 soul-admin 脚本索引、4.4/4.5 常用操作
2. **soul-project-boundary**:按场景触发词表新增

View File

@@ -0,0 +1,18 @@
# 部署 API 触发词约定
**日期**2026-03-20
## 场景
用户说「帮我部署api到线上」时安全工程师应直接执行部署脚本无需再询问或选择。
## 解决方案
- **触发词**帮我部署api到线上
- **动作**:直接执行 `cd soul-api && python master.py`
- **脚本**`soul-api/master.py`soul-api 正式环境部署)
## 已升级 Skills
1. **security-server-ops**:何时使用表新增该触发词,明确直接执行命令
2. **soul-project-boundary**:按场景触发词表新增,加载 security-server-ops 后执行

View File

@@ -1,24 +0,0 @@
# 部署管理端触发词约定
**日期**2026-03-20
## 场景
用户说「帮我部署管理端到线上」时,安全工程师应直接执行部署脚本,无需再询问或选择。
## 解决方案
- **触发词**:帮我部署管理端到线上
- **动作**:直接执行 `cd soul-api && python master.py`
- **脚本**`soul-api/master.py`soul-api 正式环境部署)
## 已升级 Skills
1. **security-server-ops**:何时使用表新增该触发词,明确直接执行命令
2. **soul-project-boundary**:按场景触发词表新增,加载 security-server-ops 后执行
## 说明
- `master.py` 部署的是 soul-apiGo 后端),非 soul-admin 前端
- 若需部署 soul-admin 前端,应使用 `soul-admin/deploy.py`
- 用户明确指定「管理端」对应 master.py按约定执行

View File

@@ -5,4 +5,5 @@
| 日期 | 摘要 | 文件 |
|------|------|------|
| 2026-03-20 | 挖矿病毒排查经验转化为 Skills服务器操作 Skill 创建 | 2026-03-20-挖矿与服务器Skills.md |
| 2026-03-20 | 「帮我部署管理端到线上」→ 执行 soul-api/master.py | 2026-03-20-部署管理端触发词.md |
| 2026-03-20 | 「帮我部署api到线上」→ 执行 soul-api/master.py | 2026-03-20-部署API触发词.md |
| 2026-03-20 | 「管理端帮我部署到xx环境」→ 语义化解析正式→master.py测试→deploy.py | 2026-03-20-管理端部署触发词.md |

View File

@@ -0,0 +1,39 @@
# 手机号一键登录与登录弹窗公用组件
> 日期2026-03-20 | 角色:小程序开发工程师
## 问题与场景
1. **getPhoneNumber 不弹窗**:点击手机号登录按钮时,无法弹出手机号选择界面,也无法获取手机号
2. **登录弹窗重复**read、my、gift-pay/detail 三处各自维护一套登录弹窗,逻辑重复、维护成本高
3. **登录后手机号未同步**:手机号登录后若响应中 user.phone 为空,本地 userInfo 未更新
## 解决方案
### 1. getPhoneNumber 必须与隐私协议耦合
- **open-type**`open-type="getPhoneNumber|agreePrivacyAuthorization"`(基础库 2.32.3+
- **onNeedPrivacyAuthorization**app.js 中需将使用 getPhoneNumber 的页面加入支持列表,否则会 `resolve({ event: 'disagree' })` 导致获取失败
- **支持页面**avatar-nickname、profile-edit、read、my、gift-pay/detail、index、settings
- **隐私弹窗**:当 onNeedPrivacyAuthorization 触发时,页面需有 `showPrivacyModal` + `<button open-type="agreePrivacyAuthorization">` 供用户同意
### 2. 登录弹窗公用组件
- **组件路径**`components/login-modal/`
- **使用方式**`<login-modal show="{{showLoginModal}}" desc="..." showPrivacyModal="{{showPrivacyModal}}" showCancel="{{true}}" bind:close="..." bind:success="..." bind:privacyagree="..." />`
- **适用页面**read、my、gift-pay/detail
- **app.json**:全局注册 `"login-modal": "/components/login-modal/login-modal"`
### 3. 登录后手机号同步
- **loginWithPhone 后**:若 `user.phone` 为空,调用 `_syncPhoneFromProfileAfterLogin(userId)` 从 profile 拉取最新
- **checkLoginStatus 恢复缓存时**:若 `userInfo.phone` 为空,调用 `_refreshUserInfoIfPhoneEmpty()` 静默刷新
## 管理后台配置
- **隐私保护指引**:小程序管理后台 → 设置 → 用户隐私保护指引,必须声明「收集你选择的手机号」
- **主体限制**:个人主体小程序无法使用 getPhoneNumber
## 升级 Skill
- miniprogram-dev SKILL §8 补充 getPhoneNumber 耦合与 onNeedPrivacyAuthorization 页面支持

View File

@@ -14,3 +14,4 @@
| 2026-03-16 | 编辑资料页分享名片:转发/朋友圈特殊处理Canvas 绘制封面,标题「昵称+为您分享名片」 | [2026-03-16.md](./2026-03-16.md) |
| 2026-03-17 | 代付美团式:读页→代付页→分享;详情页双态(发起人/好友);目录 loading、最新新增 5 条折叠 | [2026-03-17.md](./2026-03-17.md) |
| 2026-03-19 | 原生按钮覆盖定位chooseAvatar 等用绝对定位 overlay 覆盖,禁止 button 包裹,避免原生样式影响 | [2026-03-19-原生按钮覆盖定位.md](./2026-03-19-原生按钮覆盖定位.md) |
| 2026-03-20 | 手机号一键登录与公用组件getPhoneNumber 耦合 agreePrivacyAuthorizationlogin-modal 组件;登录后手机号同步 | [2026-03-20-手机号登录与公用组件.md](./2026-03-20-手机号登录与公用组件.md) |

View File

@@ -54,7 +54,9 @@
| 2026-03-18 | 小程序、团队 | 业务规则/最佳实践 | - | 分享链路兼容好友/朋友圈 singlePage单页模式能力降级不支付/不自动领取),引导点击底部“前往小程序”进入完整版 |
| 2026-03-18 | 产品、后端、管理端、测试 | 文档归档/需求口径 | - | 文档归档整理:以《以界面定需求》为基准,各角色重整“功能需求+验收口径+风险点”并写入各自经验库;补齐《项目落地推进表》 |
| 2026-03-19 | 小程序 | 最佳实践 | miniprogram-dev SKILL §11 | 原生按钮覆盖定位chooseAvatar 等用绝对定位 overlay 覆盖,禁止 button 包裹,避免原生样式影响(灰色矩形等) |
| 2026-03-20 | 安全工程师 | 触发词约定 | security-server-ops、soul-project-boundary | 「帮我部署管理端到线上」→ 直接执行 soul-api/master.py |
| 2026-03-20 | 安全工程师 | 触发词约定 | security-server-ops、soul-project-boundary | 「帮我部署api到线上」→ 直接执行 soul-api/master.py |
| 2026-03-20 | 安全工程师 | 触发词约定 | security-server-ops、soul-project-boundary | 「管理端帮我部署到xx环境」→ 语义化解析正式→master.py测试→deploy.py |
| 2026-03-20 | 小程序 | 最佳实践 | miniprogram-dev SKILL §8 | 手机号登录getPhoneNumber 需耦合 agreePrivacyAuthorizationonNeedPrivacyAuthorization 支持页面;登录弹窗公用组件 login-modal |
---

View File

@@ -6,7 +6,7 @@
## 项目总结
Soul 创业派对产品定位:面向创业者的社区/工具型小程序。核心需求文档在 `开发文档/1、需求/需求汇总.md`,项目推进表在 `开发文档/10、项目管理/项目落地推进表.md`,临时需求/分析在 `临时需求池/`
Soul 创业派对产品定位:面向创业者的社区/工具型小程序。核心需求文档在 `开发文档/1、需求/`(按日期命名,以最新为主;见 `1、需求/索引.md`,项目推进表在 `开发文档/10、项目管理/项目落地推进表.md`,临时需求/分析在 `临时需求池/`
---

View File

@@ -31,7 +31,8 @@ Soul 创业派对全项目架构与约定路由隔离miniprogram/admin/db
| 2026-03-17 | 性能优化与 Redis 缓存方案落地Redis 容灾回退 DB、OSS 上传容灾;/health 返回 database/redis 状态 | 已完成 |
| 2026-03-18 | 吸收经验:分享进入链路需兼容朋友圈 singlePage单页模式不执行支付/自动领取等强动作并引导“前往小程序” | 已完成 |
| 2026-03-18 | 会议:超级个体开通后自动创建@人统一走 Person幂等键绑定 userId默认资料 flags 后端输出 | 已完成 |
| 2026-03-20 | 「帮我部署管理端到线上」→ 安全工程师执行 soul-api/master.pysecurity-server-ops、soul-project-boundary 触发词升级 | 已完成 |
| 2026-03-20 | 「帮我部署api到线上」→ 安全工程师执行 soul-api/master.pysecurity-server-ops、soul-project-boundary 触发词升级 | 已完成 |
| 2026-03-20 | 「管理端帮我部署到xx环境」→ 语义化解析:正式/线上/生产→master.py测试/dev→deploy.pysoul-admin 部署脚本索引 | 已完成 |
> **格式说明**:每次架构级讨论后在此追加一行,日期格式 YYYY-MM-DD

View File

@@ -42,9 +42,10 @@
| 2026-03-18 | 吸收经验:分享链路需兼容好友/朋友圈 singlePage单页模式能力降级并引导“前往小程序”进入完整版 | 已完成 |
| 2026-03-18 | 会议:支付超级个体前/开通后资料默认校验,跳转 avatar-nickname 引导页(仅头像+昵称) | 已完成 |
| 2026-03-19 | 吸收经验原生按钮覆盖定位chooseAvatar 用绝对定位 overlay 覆盖头像,禁止 button 包裹,已升级 SKILL §11 | 已完成 |
| 2026-03-20 | 手机号一键登录getPhoneNumber 耦合 agreePrivacyAuthorizationonNeedPrivacyAuthorization 支持 read/my/gift-pay/index/settings登录弹窗公用组件 components/login-modal登录后手机号同步 _syncPhoneFromProfileAfterLogin | 已完成 |
> **格式说明**:每次开发后在此追加一行,日期格式 YYYY-MM-DD状态用已完成 / 进行中 / 待续 / 搁置
---
**最后更新**2026-03-19
**最后更新**2026-03-20

View File

@@ -12,5 +12,5 @@ alwaysApply: false
### 行为摘要(供模型快速理解,完整流程以 SKILL 文件为准)
1. **文档同步**:从对话中提炼结论/待办/变更 → 写入 `开发文档/1、需求/需求汇总.md`、`开发文档/10、项目管理/运营与变更.md`、`临时需求池/` 等对应文档
1. **文档同步**:从对话中提炼结论/待办/变更 → 写入 `开发文档/1、需求/YYYY-MM-DD-需求.md`(当日文件,以日期最新为主)、`开发文档/10、项目管理/运营与变更.md`、`临时需求池/` 等对应文档
2. **经验入库**:提炼经验 → 写入 `agent/{角色}/evolution/YYYY-MM-DD.md` → 更新 `agent/开发助理/项目索引/{索引名}.md`(写日期)→ 更新 `agent/开发助理/经验清单.md` → 升级对应 SKILL

View File

@@ -20,6 +20,13 @@ alwaysApply: true
| 预览/参考 | next-project/ | 仅预览,非线上 | 不依赖 |
| **新版管理端** | **new-soul/soul-admin/** | 新版参考实现,迁移时对照 | soul-api |
## 需求目录与命名约定
- **需求目录**`开发文档/1、需求/`
- **命名**`YYYY-MM-DD-需求.md` 或 `YYYY-MM-DD-简短描述.md`
- **主需求**:以日期最新的需求文件为主;同步需求时新建/更新当日文件,并更新 `1、需求/索引.md`
- **基准**`以界面定需求.md` 为界面级需求基准,新增/改版界面或业务规则时先更新该文档
## 核心原则
- 小程序只调 `/api/miniprogram/*`;管理端只调 `/api/admin/*`、`/api/db/*`;禁止混用。
@@ -64,6 +71,7 @@ alwaysApply: true
| 会议结束、散会、会开完了 | `e:\Gongsi\Mycontent\.cursor\skills\assistant-doc-sync\SKILL.md`(会议收尾) |
| **加个需求**、加个需求xxx | `e:\Gongsi\Mycontent\.cursor\skills\product-manager\SKILL.md`(产品经理三端分析 → 功能规划 → 指派) |
| **新版分析**、版本对比、迁移分析、甲方代码分析、快速分析新版、抽取需求 | `e:\Gongsi\Mycontent\.cursor\skills\new-version-analyze\SKILL.md`(新版快速分析 → 差异清单 → 接口冲突 → 迁移迭代) |
| **帮我部署管理端到线上** | `e:\Gongsi\Mycontent\.cursor\skills\security-server-ops\SKILL.md`(安全工程师 → 执行 soul-api/master.py |
| **帮我部署api到线上** | `e:\Gongsi\Mycontent\.cursor\skills\security-server-ops\SKILL.md`(安全工程师 → 执行 soul-api/master.py |
| **管理端帮我部署到xx环境** | `e:\Gongsi\Mycontent\.cursor\skills\security-server-ops\SKILL.md`(安全工程师 → 语义化解析 xx正式/线上/生产→master.py测试/dev→deploy.py |
**注意**:「必须 Read」= 使用 Read 工具读取**绝对路径**的完整文件内容后执行,不可跳过或仅凭记忆。

View File

@@ -30,7 +30,7 @@ description: 开发团队文档同步与经验升级。小橙、橙子、讨论
| 要点类型 | 写入位置 | 示例 |
|----------|----------|------|
| 需求清单项 | `开发文档/1、需求/需求汇总.md` 需求清单表 | 会员分润差异化、VIP 手动设置 |
| 需求清单项 | `开发文档/1、需求/YYYY-MM-DD-需求.md`(当日文件,以日期最新为主) | 会员分润差异化、VIP 手动设置;同步后更新 `1、需求/索引.md` |
| 近期讨论 | `开发文档/10、项目管理/运营与变更.md` | 第五部分或新增节 |
| 技术分析 | `临时需求池/``开发文档/8、部署/` | 分润需求-技术分析.md |
| 项目推进 | `开发文档/10、项目管理/项目落地推进表.md` | 第十二节永平落地表 |
@@ -130,7 +130,10 @@ description: 开发团队文档同步与经验升级。小橙、橙子、讨论
```
开发文档/
├── 1、需求/需求汇总.md # 需求清单、业务需求
├── 1、需求/
│ ├── 索引.md # 主需求 = 日期最新的需求文件
│ ├── YYYY-MM-DD-需求.md # 需求文件按日期命名,以最新为主
│ └── 以界面定需求.md # 界面级需求基准
├── 8、部署/ # 技术方案、部署说明
├── 10、项目管理/
│ ├── 项目落地推进表.md # 里程碑、永平落地
@@ -153,7 +156,7 @@ description: 开发团队文档同步与经验升级。小橙、橙子、讨论
**小橙**执行:
1. 提炼VIP 手动设置已完成;会员分润差异化待实现;好友优惠仅针对文章
2. 更新 `需求汇总.md`:新增「需求清单」行
2. 更新 `1、需求/YYYY-MM-DD-需求.md`(当日文件):新增「需求清单」行;同步后更新 `1、需求/索引.md`
3. 更新 `运营与变更.md`:第五部分追加近期讨论
4. 回复:已记录并更新开发文档,详见 xxx

View File

@@ -79,6 +79,8 @@ description: Soul 创业派对小程序开发规范。在 miniprogram/ 下编辑
## 8. 平台合规与能力检测2025 起)
- **隐私按需授权**:涉及用户信息的接口(登录、手机号、位置等)必须在用户**实际触发功能时**再请求授权,禁止在 `app.onLaunch` 中集中请求。需配置《小程序用户隐私保护指引》,使用 `<button open-type="agreePrivacyAuthorization">` 获取同意。
- **getPhoneNumber 必须耦合**`open-type="getPhoneNumber|agreePrivacyAuthorization"`(基础库 2.32.3+),否则无法弹窗获取手机号。同时需在 app.js 的 `onNeedPrivacyAuthorization` 中将该页面加入支持列表,并提供 `showPrivacyModal` + 同意按钮,否则会 resolve(disagree) 导致失败。
- **登录弹窗**:使用公用组件 `components/login-modal`read/my/gift-pay 等页面引入,避免重复实现。
- **能力检测**:使用新 API 前用 `wx.canIUse('api.xxx')` 检测,低版本做降级。
- **Skyline可选**:性能敏感页面可在 `page.json` 中配置 `"renderer": "skyline"`,仍使用 WXML/WXSS。

View File

@@ -192,10 +192,10 @@ description: 新版快速分析 Skill。甲方/第三方 AI 写的新版本,
2. 排除:技术债、规则不清、与稳定版冲突的部分
3. 按**最小功能**拆分,保证每个任务迁移后能完整运行
4. 排期顺序:**界面修改优先** → 大逻辑排后P0逻辑不通→ P1功能缺失→ P2优化
5. 写入需求汇总,形成迁移任务清单
5. 写入需求清单(当日需求文件),形成迁移任务清单
**产出**
- `开发文档/1、需求/需求汇总.md` 追加需求
- `开发文档/1、需求/YYYY-MM-DD-需求.md` 追加需求(当日文件,以日期最新为主;同步后更新 `1、需求/索引.md`
- `开发文档/新版迁移-开发方案与清单.md` 或等价迁移清单
---
@@ -259,7 +259,7 @@ description: 新版快速分析 Skill。甲方/第三方 AI 写的新版本,
4. **逻辑分层**:每个功能过三层(界面/接口/数据)
5. **体验评估**:补充空态、错误态、边界处理
6. **接口规范与冲突**:产出接口规范与冲突清单
7. **抽取需求**:写入需求汇总,形成迁移任务清单
7. **抽取需求**:写入需求清单(当日需求文件),形成迁移任务清单
8. **需求评审(迁移前必做)**:列出功能点 + 样式变更,逐一确认,产出评审清单
9. **回复用户**:给出分析摘要 + 文档路径 + 建议执行顺序;**迁移须在需求评审通过后开始**
@@ -273,7 +273,7 @@ description: 新版快速分析 Skill。甲方/第三方 AI 写的新版本,
| 接口规范与冲突 | `开发文档/新版迁移-接口规范与冲突清单.md` |
| 迁移方案/清单 | `开发文档/新版迁移-开发方案与清单.md``新版功能迁移到稳定版方案.md` |
| **需求评审清单** | `开发文档/新版迁移-需求评审清单.md`(功能点 + 样式变更,含确认状态) |
| 需求汇总 | `开发文档/1、需求/需求汇总.md` |
| 需求清单 | `开发文档/1、需求/YYYY-MM-DD-需求.md`(以日期最新为主) |
若已有同名文档,在其基础上**追加或更新**,不重复创建。

View File

@@ -42,7 +42,7 @@ description: Soul 创业派对产品经理需求与验收。需求分析、需
### 0.3 功能规划与协调变更
1. **输出需求分析**:写入 `临时需求池/YYYY-MM-DD-需求简述.md` 或追加到 `需求汇总.md` 需求清单
1. **输出需求分析**:写入 `临时需求池/YYYY-MM-DD-需求简述.md` 或追加到 `开发文档/1、需求/YYYY-MM-DD-需求.md` 需求清单(以日期最新为主,同步后更新 `1、需求/索引.md`
2. **三端任务拆分**:按上表列出「小程序任务」「管理端任务」「后端任务」
3. **协调变更**:若需更新《以界面定需求》,同步更新界面清单与业务逻辑
4. **指派**:明确各任务对应角色(小程序开发工程师、管理端开发工程师、后端工程师),并给出执行顺序建议(通常:后端 → 小程序;管理端视依赖可并行或后置)
@@ -73,7 +73,7 @@ description: Soul 创业派对产品经理需求与验收。需求分析、需
| 职责 | 说明 | 产出 |
|------|------|------|
| 需求分析 | 业务需求拆解、优先级、技术可行性 | 需求分析文档、临时需求池 |
| 需求文档 | 需求清单、业务规则、验收标准 | 需求汇总.md、运营与变更.md |
| 需求文档 | 需求清单、业务规则、验收标准 | 1、需求/YYYY-MM-DD-需求.md以最新为主、运营与变更.md |
| 验收 | 功能验收、回归检查 | 验收清单、项目推进表 |
| 协调 | 与开发沟通、排期、变更 | 运营与变更、项目落地推进表 |
@@ -83,7 +83,7 @@ description: Soul 创业派对产品经理需求与验收。需求分析、需
| 文档 | 说明 |
|------|------|
| `开发文档/1、需求/需求汇总.md` | 需求清单、业务需求 |
| `开发文档/1、需求/` | 需求清单(按日期命名,以最新为主)、业务需求;见 `1、需求/索引.md` |
| `临时需求池/` | 需求分析、技术分析 |
| `开发文档/10、项目管理/项目落地推进表.md` | 里程碑、永平落地 |
| `开发文档/10、项目管理/运营与变更.md` | 近期讨论、变更记录 |

View File

@@ -9,7 +9,8 @@ description: Soul 服务器操作与部署。部署脚本、SSH、宝塔、环
| 触发词 | 动作 |
|--------|------|
| **帮我部署管理端到线上** | **直接执行 `cd soul-api && python master.py`** |
| **帮我部署api到线上** | **直接执行 `cd soul-api && python master.py`** |
| **管理端帮我部署到xx环境** | **语义化解析 xx直接执行**:含「正式」「线上」「生产」→ `cd soul-admin && python master.py`含「测试」「dev」→ `cd soul-admin && python deploy.py` |
| 部署、服务器操作、SSH | 按本 Skill 选择对应脚本 |
| 宝塔、devloy、master | 查阅部署配置与命令 |
| Cunkebao 部署 | 使用 Cunkebao 专用脚本 |
@@ -32,7 +33,8 @@ description: Soul 服务器操作与部署。部署脚本、SSH、宝塔、环
|------|------|------|------|----------|
| soul-api 正式 | 43.139.27.93 | 22022 | root | master.py / 环境变量 |
| soul-api 测试 | 43.139.27.93 | 22022 | root | devloy.py / 环境变量 |
| soul-admin | 43.139.27.93 | 22022 | root | soul-admin/deploy.py / 环境变量 |
| soul-admin 正式 | 43.139.27.93 | 22022 | root | soul-admin/master.py / 环境变量 |
| soul-admin 测试 | 43.139.27.93 | 22022 | root | soul-admin/deploy.py / 环境变量 |
| Cunkebao | 42.194.245.239 | 6523 | yongpxu | Cunkebao/miner_guard_install.py 内嵌 |
**密码**:从 `DEPLOY_PASSWORD` 或各脚本 `get_cfg()` 默认值读取,**不在此文档记录**。
@@ -61,7 +63,8 @@ description: Soul 服务器操作与部署。部署脚本、SSH、宝塔、环
| 脚本 | 用途 | 命令示例 |
|------|------|----------|
| `soul-admin/deploy.py` | 静态站点部署dist → dist2 互换 | `python deploy.py` |
| `soul-admin/master.py` | 正式环境部署soul-adminpnpm build | `python master.py` |
| `soul-admin/deploy.py` | 测试环境部署soul-admin-devpnpm build:dev | `python deploy.py` |
### 2.3 挖矿防护
@@ -114,14 +117,21 @@ cd e:\Gongsi\Mycontent\soul-api
python master.py
```
### 4.4 部署 soul-admin
### 4.4 部署 soul-admin 正式环境
```powershell
cd e:\Gongsi\Mycontent\soul-admin
python master.py
```
### 4.5 部署 soul-admin 测试环境
```powershell
cd e:\Gongsi\Mycontent\soul-admin
python deploy.py
```
### 4.5 检查挖矿守护
### 4.6 检查挖矿守护
```powershell
cd e:\Gongsi\Mycontent\soul-api

View File

@@ -1,6 +1,7 @@
{
"usingComponents": {
"icon": "/components/icon/icon"
"icon": "/components/icon/icon",
"login-modal": "/components/login-modal/login-modal"
},
"pages": [
"pages/chapters/chapters",

View File

@@ -0,0 +1,79 @@
/**
* Soul 创业派对 - 公用登录弹窗
* 手机号一键登录 + 隐私协议
*/
Component({
properties: {
show: { type: Boolean, value: false },
desc: { type: String, value: '登录后可购买章节、解锁更多内容' },
showPrivacyModal: { type: Boolean, value: false },
showCancel: { type: Boolean, value: false }
},
data: {
agreeProtocol: false,
isLoggingIn: false
},
observers: {
show(v) {
if (!v) this.setData({ agreeProtocol: false, isLoggingIn: false })
}
},
methods: {
stopPropagation() {},
onClose() {
this.triggerEvent('close')
},
onToggleAgree() {
this.setData({ agreeProtocol: !this.data.agreeProtocol })
},
onOpenUserProtocol() {
wx.navigateTo({ url: '/pages/agreement/agreement' })
},
onOpenPrivacy() {
wx.navigateTo({ url: '/pages/privacy/privacy' })
},
onAgreePrivacy() {
const app = getApp()
if (app._privacyResolve) {
app._privacyResolve({ buttonId: 'agree-privacy-btn', event: 'agree' })
app._privacyResolve = null
}
this.triggerEvent('privacyagree')
},
async onPhoneLogin(e) {
if (!e.detail.code) {
return this._fallbackWechatLogin()
}
const app = getApp()
this.setData({ isLoggingIn: true })
try {
const result = await app.loginWithPhone(e.detail.code)
this.setData({ isLoggingIn: false })
if (result) {
this.triggerEvent('success')
} else {
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
} catch (err) {
this.setData({ isLoggingIn: false })
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
},
async _fallbackWechatLogin() {
const app = getApp()
this.setData({ isLoggingIn: true })
try {
const result = await app.login()
this.setData({ isLoggingIn: false })
if (result) {
this.triggerEvent('success')
} else {
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
} catch (err) {
this.setData({ isLoggingIn: false })
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
}
}
})

View File

@@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"icon": "/components/icon/icon"
}
}

View File

@@ -0,0 +1,27 @@
<!-- Soul 创业派对 - 公用登录弹窗 -->
<view class="modal-overlay" wx:if="{{show}}" bindtap="onClose">
<view class="modal-content login-modal" catchtap="stopPropagation">
<view class="modal-close" bindtap="onClose"><icon name="x" size="36" color="#8e8e93"></icon></view>
<view class="login-icon"><icon name="lock" size="80" color="#00CED1"></icon></view>
<text class="login-title">登录 卡若创业派对</text>
<text class="login-desc">{{desc}}</text>
<button id="agree-phone-btn" class="btn-wechat {{agreeProtocol ? '' : 'btn-wechat-disabled'}}" open-type="getPhoneNumber|agreePrivacyAuthorization" bindgetphonenumber="onPhoneLogin" bindagreeprivacyauthorization="onAgreePrivacy" disabled="{{isLoggingIn || !agreeProtocol}}">
<text class="btn-wechat-icon">微</text>
<text>{{isLoggingIn ? '登录中...' : '手机号一键登录'}}</text>
</button>
<view class="privacy-wechat-row" wx:if="{{showPrivacyModal}}">
<text class="privacy-wechat-desc">为获取手机号,请先同意《用户隐私保护指引》</text>
<button id="agree-privacy-btn" class="privacy-agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="onAgreePrivacy">同意</button>
</view>
<view class="login-modal-cancel" wx:if="{{showCancel}}" bindtap="onClose">取消</view>
<view class="login-agree-row" catchtap="onToggleAgree">
<view class="agree-checkbox {{agreeProtocol ? 'agree-checked' : ''}}"><icon wx:if="{{agreeProtocol}}" name="check" size="24" color="#34C759"></icon></view>
<text class="agree-text">我已阅读并同意</text>
<text class="agree-link" catchtap="onOpenUserProtocol">《用户协议》</text>
<text class="agree-text">和</text>
<text class="agree-link" catchtap="onOpenPrivacy">《隐私政策》</text>
</view>
</view>
</view>

View File

@@ -0,0 +1,136 @@
/* Soul 创业派对 - 公用登录弹窗 */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
padding: 48rpx;
}
.modal-content {
width: 100%;
max-width: 600rpx;
background: #1c1c1e;
border-radius: 32rpx;
overflow: hidden;
}
.modal-close {
position: absolute;
top: 24rpx;
right: 24rpx;
z-index: 1;
padding: 16rpx;
}
.login-modal {
padding: 48rpx 32rpx;
text-align: center;
}
.login-icon {
font-size: 80rpx;
display: block;
margin-bottom: 24rpx;
}
.login-title {
font-size: 36rpx;
font-weight: 700;
color: #ffffff;
display: block;
margin-bottom: 16rpx;
}
.login-desc {
font-size: 26rpx;
color: rgba(255, 255, 255, 0.5);
display: block;
margin-bottom: 48rpx;
}
.btn-wechat {
display: flex;
align-items: center;
justify-content: center;
gap: 16rpx;
padding: 28rpx;
background: #07C160;
color: #ffffff;
font-size: 30rpx;
font-weight: 600;
border-radius: 24rpx;
margin-bottom: 20rpx;
border: none;
}
.btn-wechat::after { border: none; }
.btn-wechat-icon {
width: 40rpx;
height: 40rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 8rpx;
font-size: 24rpx;
display: flex;
align-items: center;
justify-content: center;
}
.btn-wechat-disabled { opacity: 0.6; }
.login-modal-cancel {
margin-top: 24rpx;
padding: 24rpx;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.5);
text-align: center;
}
.privacy-wechat-row {
margin: 24rpx 0;
padding: 24rpx;
background: rgba(0, 206, 209, 0.1);
border-radius: 16rpx;
}
.privacy-wechat-desc {
display: block;
font-size: 26rpx;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 16rpx;
}
.privacy-agree-btn {
width: 100%;
padding: 20rpx;
background: #07C160;
color: #fff;
font-size: 28rpx;
border-radius: 16rpx;
border: none;
}
.privacy-agree-btn::after { border: none; }
.login-agree-row {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
margin-top: 32rpx;
font-size: 22rpx;
color: rgba(255, 255, 255, 0.5);
}
.agree-checkbox {
width: 32rpx;
height: 32rpx;
border: 2rpx solid rgba(255, 255, 255, 0.5);
border-radius: 6rpx;
margin-right: 12rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 22rpx;
flex-shrink: 0;
}
.agree-checked {
background: #00CED1;
border-color: #00CED1;
}
.agree-text { color: rgba(255, 255, 255, 0.6); }
.agree-link {
color: #00CED1;
text-decoration: underline;
padding: 0 4rpx;
}

View File

@@ -18,7 +18,6 @@ Page({
amountDisplay: '0.00',
isSinglePageMode: false,
showLoginModal: false,
agreeProtocol: false,
showPrivacyModal: false,
// 创建态
isCreateMode: false,
@@ -227,7 +226,7 @@ Page({
}
const userId = app.globalData.userInfo?.id
if (!userId) {
this.setData({ showLoginModal: true, agreeProtocol: false })
this.setData({ showLoginModal: true })
return
}
await this._doRedeem()
@@ -265,51 +264,15 @@ Page({
}
},
closeLoginModal() {
onLoginModalClose() {
this.setData({ showLoginModal: false, showPrivacyModal: false })
},
toggleAgree() {
this.setData({ agreeProtocol: !this.data.agreeProtocol })
},
async handleWechatLogin() {
if (!this.data.agreeProtocol) {
wx.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
return
}
try {
const result = await app.login()
if (!result) return
this.setData({ showLoginModal: false, agreeProtocol: false })
await this._doRedeem()
} catch (e) {
wx.showToast({ title: '登录失败', icon: 'none' })
}
},
handleAgreePrivacyForPhone() {
if (app._privacyResolve) {
app._privacyResolve({ buttonId: 'agree-privacy-btn', event: 'agree' })
app._privacyResolve = null
}
onLoginModalPrivacyAgree() {
this.setData({ showPrivacyModal: false })
},
async handlePhoneLogin(e) {
if (!e.detail.code) return this.handleWechatLogin()
try {
const result = await app.loginWithPhone(e.detail.code)
if (!result) return
this.setData({ showLoginModal: false })
await this._doRedeem()
} catch (e) {
wx.showToast({ title: '登录失败', icon: 'none' })
}
},
stopPropagation() {},
openUserProtocol() {
wx.navigateTo({ url: '/pages/agreement/agreement' })
},
openPrivacy() {
wx.navigateTo({ url: '/pages/privacy/privacy' })
async onLoginModalSuccess() {
this.setData({ showLoginModal: false })
await this._doRedeem()
},
goBack() {

View File

@@ -145,30 +145,15 @@
</view>
</view>
<!-- 登录弹窗(好友领取时未登录 -->
<view class="modal-overlay" wx:if="{{showLoginModal}}" bindtap="closeLoginModal">
<view class="modal-content login-modal" catchtap="stopPropagation">
<view class="modal-close" bindtap="closeLoginModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
<view class="login-icon"><icon name="lock" size="80" color="#00CED1"></icon></view>
<text class="login-title">登录 卡若创业派对</text>
<text class="login-desc">登录后可免费领取并阅读</text>
<button id="agree-phone-btn" class="btn-wechat {{agreeProtocol ? '' : 'btn-wechat-disabled'}}" open-type="getPhoneNumber|agreePrivacyAuthorization" bindgetphonenumber="handlePhoneLogin" bindagreeprivacyauthorization="handleAgreePrivacyForPhone" disabled="{{!agreeProtocol}}">
<text class="btn-wechat-icon">微</text>
<text>手机号一键登录</text>
</button>
<view class="privacy-wechat-row" wx:if="{{showPrivacyModal}}">
<text class="privacy-wechat-desc">为获取手机号,请先同意《用户隐私保护指引》</text>
<button id="agree-privacy-btn" class="privacy-agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyForPhone">同意</button>
</view>
<view class="login-agree-row" catchtap="toggleAgree">
<view class="agree-checkbox {{agreeProtocol ? 'agree-checked' : ''}}"><icon wx:if="{{agreeProtocol}}" name="check" size="24" color="#34C759"></icon></view>
<text class="agree-text">我已阅读并同意</text>
<text class="agree-link" bindtap="openUserProtocol">《用户协议》</text>
<text class="agree-text">和</text>
<text class="agree-link" bindtap="openPrivacy">《隐私政策》</text>
</view>
</view>
</view>
<!-- 登录弹窗(公用组件 -->
<login-modal
show="{{showLoginModal}}"
desc="登录后可免费领取并阅读"
showPrivacyModal="{{showPrivacyModal}}"
bind:close="onLoginModalClose"
bind:success="onLoginModalSuccess"
bind:privacyagree="onLoginModalPrivacyAgree"
/>
<!-- 背景光效 -->
<view class="bg-effects">

View File

@@ -60,9 +60,6 @@ Page({
// 登录弹窗
showLoginModal: false,
isLoggingIn: false,
// 用户须主动勾选同意协议(审核要求:不得默认同意)
agreeProtocol: false,
showPrivacyModal: false,
// 修改昵称弹窗
@@ -691,93 +688,23 @@ Page({
console.warn('[My] 检测单页模式失败,回退为正常登录弹窗:', e)
}
try {
this.setData({ showLoginModal: true, agreeProtocol: false })
this.setData({ showLoginModal: true })
} catch (e) {
console.error('[My] showLogin error:', e)
this.setData({ showLoginModal: true })
}
},
// 切换协议勾选(用户主动勾选,非默认同意)
toggleAgree() {
this.setData({ agreeProtocol: !this.data.agreeProtocol })
},
// 打开用户协议页(审核要求:点击《用户协议》需有响应)
openUserProtocol() {
wx.navigateTo({ url: '/pages/agreement/agreement' })
},
// 打开隐私政策页(审核要求:点击《隐私政策》需有响应)
openPrivacy() {
wx.navigateTo({ url: '/pages/privacy/privacy' })
},
// 关闭登录弹窗
closeLoginModal() {
if (this.data.isLoggingIn) return
onLoginModalClose() {
this.setData({ showLoginModal: false, showPrivacyModal: false })
},
// 微信登录(须已勾选同意协议,且做好错误处理避免审核报错)
async handleWechatLogin() {
if (!this.data.agreeProtocol) {
wx.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
return
}
this.setData({ isLoggingIn: true })
try {
const result = await app.login()
if (result) {
this.initUserStatus()
this.setData({ showLoginModal: false, agreeProtocol: false })
wx.showToast({ title: '登录成功', icon: 'success' })
} else {
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
} catch (e) {
console.error('[My] 微信登录错误:', e)
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
} finally {
this.setData({ isLoggingIn: false })
}
},
// 微信隐私协议同意getPhoneNumber 需先同意)
handleAgreePrivacyForPhone() {
if (app._privacyResolve) {
app._privacyResolve({ buttonId: 'agree-privacy-btn', event: 'agree' })
app._privacyResolve = null
}
onLoginModalPrivacyAgree() {
this.setData({ showPrivacyModal: false })
},
// 手机号登录(需要用户授权)
async handlePhoneLogin(e) {
// 检查是否有授权code
if (!e.detail.code) {
// 用户拒绝授权或获取失败,尝试使用微信登录
console.log('手机号授权失败,尝试微信登录')
return this.handleWechatLogin()
}
this.setData({ isLoggingIn: true })
try {
const result = await app.loginWithPhone(e.detail.code)
if (result) {
this.initUserStatus()
this.setData({ showLoginModal: false })
wx.showToast({ title: '登录成功', icon: 'success' })
} else {
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
} catch (e) {
console.error('手机号登录错误:', e)
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
} finally {
this.setData({ isLoggingIn: false })
}
onLoginModalSuccess() {
this.initUserStatus()
this.setData({ showLoginModal: false })
wx.showToast({ title: '登录成功', icon: 'success' })
},
// 点击菜单

View File

@@ -171,31 +171,16 @@
</view>
</view>
<!-- 登录弹窗 -->
<view class="modal-overlay" wx:if="{{showLoginModal}}" bindtap="closeLoginModal">
<view class="modal-content login-modal-content" catchtap="stopPropagation">
<view class="modal-close" bindtap="closeLoginModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
<view class="login-icon"><icon name="lock" size="80" color="#00CED1"></icon></view>
<text class="login-title">登录 卡若创业派对</text>
<text class="login-desc">登录后可购买章节、解锁更多内容</text>
<button id="agree-phone-btn" class="btn-wechat {{agreeProtocol ? '' : 'btn-wechat-disabled'}}" open-type="getPhoneNumber|agreePrivacyAuthorization" bindgetphonenumber="handlePhoneLogin" bindagreeprivacyauthorization="handleAgreePrivacyForPhone" disabled="{{isLoggingIn || !agreeProtocol}}">
<text class="btn-wechat-icon">微</text>
<text>{{isLoggingIn ? '登录中...' : '手机号一键登录'}}</text>
</button>
<view class="privacy-wechat-row" wx:if="{{showPrivacyModal}}">
<text class="privacy-wechat-desc">为获取手机号,请先同意《用户隐私保护指引》</text>
<button id="agree-privacy-btn" class="privacy-agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyForPhone">同意</button>
</view>
<view class="login-modal-cancel" bindtap="closeLoginModal">取消</view>
<view class="login-agree-row" catchtap="toggleAgree">
<view class="agree-checkbox {{agreeProtocol ? 'agree-checked' : ''}}"><icon wx:if="{{agreeProtocol}}" name="check" size="24" color="#34C759"></icon></view>
<text class="agree-text">我已阅读并同意</text>
<text class="agree-link" catchtap="openUserProtocol">《用户协议》</text>
<text class="agree-text">和</text>
<text class="agree-link" catchtap="openPrivacy">《隐私政策》</text>
</view>
</view>
</view>
<!-- 登录弹窗(公用组件) -->
<login-modal
show="{{showLoginModal}}"
desc="登录后可购买章节、解锁更多内容"
showPrivacyModal="{{showPrivacyModal}}"
showCancel="{{true}}"
bind:close="onLoginModalClose"
bind:success="onLoginModalSuccess"
bind:privacyagree="onLoginModalPrivacyAgree"
/>
<!-- 手机/微信号弹窗 -->
<view class="modal-overlay contact-modal-overlay" wx:if="{{showContactModal}}" bindtap="closeContactModal">

View File

@@ -74,7 +74,6 @@ Page({
giftPaid: false,
giftRequestSn: '',
showLoginModal: false,
agreeProtocol: false,
showPrivacyModal: false,
showPosterModal: false,
isPaying: false,
@@ -975,78 +974,23 @@ Page({
console.warn('[Read] 检测单页模式失败,回退为正常登录流程:', e)
}
try {
this.setData({ showLoginModal: true, agreeProtocol: false })
this.setData({ showLoginModal: true })
} catch (e) {
console.error('[Read] showLoginModal error:', e)
this.setData({ showLoginModal: true })
}
},
closeLoginModal() {
onLoginModalClose() {
this.setData({ showLoginModal: false, showPrivacyModal: false })
},
toggleAgree() {
this.setData({ agreeProtocol: !this.data.agreeProtocol })
},
openUserProtocol() {
wx.navigateTo({ url: '/pages/agreement/agreement' })
},
openPrivacy() {
wx.navigateTo({ url: '/pages/privacy/privacy' })
},
// 从服务端刷新购买状态,避免登录后误用旧数据导致误解锁
// 【重构】微信登录(须先勾选同意协议,符合审核要求)
async handleWechatLogin() {
if (!this.data.agreeProtocol) {
wx.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
return
}
try {
const result = await app.login()
if (!result) return
this.setData({ showLoginModal: false, agreeProtocol: false })
await this.onLoginSuccess()
wx.showToast({ title: '登录成功', icon: 'success' })
} catch (e) {
console.error('[Read] 登录失败:', e)
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
},
// 微信隐私协议同意getPhoneNumber 需先同意)
handleAgreePrivacyForPhone() {
const app = getApp()
if (app._privacyResolve) {
app._privacyResolve({ buttonId: 'agree-privacy-btn', event: 'agree' })
app._privacyResolve = null
}
onLoginModalPrivacyAgree() {
this.setData({ showPrivacyModal: false })
},
// 【重构】手机号登录(标准流程)
async handlePhoneLogin(e) {
if (!e.detail.code) {
return this.handleWechatLogin()
}
try {
const result = await app.loginWithPhone(e.detail.code)
if (!result) return
this.setData({ showLoginModal: false })
await this.onLoginSuccess()
wx.showToast({ title: '登录成功', icon: 'success' })
} catch (e) {
console.error('[Read] 手机号登录失败:', e)
wx.showToast({ title: '登录失败', icon: 'none' })
}
async onLoginModalSuccess() {
this.setData({ showLoginModal: false })
await this.onLoginSuccess()
wx.showToast({ title: '登录成功', icon: 'success' })
},
// 【新增】登录成功后的标准处理流程

View File

@@ -333,32 +333,15 @@
</view>
</view>
<!-- 登录弹窗 - 须勾选同意协议,《用户协议》《隐私政策》可点击查看 -->
<view class="modal-overlay" wx:if="{{showLoginModal}}" bindtap="closeLoginModal">
<view class="modal-content login-modal" catchtap="stopPropagation">
<view class="modal-close" bindtap="closeLoginModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
<view class="login-icon"><icon name="lock" size="80" color="#00CED1"></icon></view>
<text class="login-title">登录 卡若创业派对</text>
<text class="login-desc">登录后可购买章节、解锁更多内容</text>
<button id="agree-phone-btn" class="btn-wechat {{agreeProtocol ? '' : 'btn-wechat-disabled'}}" open-type="getPhoneNumber|agreePrivacyAuthorization" bindgetphonenumber="handlePhoneLogin" bindagreeprivacyauthorization="handleAgreePrivacyForPhone" disabled="{{!agreeProtocol}}">
<text class="btn-wechat-icon">微</text>
<text>手机号一键登录</text>
</button>
<view class="privacy-wechat-row" wx:if="{{showPrivacyModal}}">
<text class="privacy-wechat-desc">为获取手机号,请先同意《用户隐私保护指引》</text>
<button id="agree-privacy-btn" class="privacy-agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyForPhone">同意</button>
</view>
<view class="login-agree-row" catchtap="toggleAgree">
<view class="agree-checkbox {{agreeProtocol ? 'agree-checked' : ''}}"><icon wx:if="{{agreeProtocol}}" name="check" size="24" color="#34C759"></icon></view>
<text class="agree-text">我已阅读并同意</text>
<text class="agree-link" catchtap="openUserProtocol">《用户协议》</text>
<text class="agree-text">和</text>
<text class="agree-link" catchtap="openPrivacy">《隐私政策》</text>
</view>
</view>
</view>
<!-- 登录弹窗(公用组件) -->
<login-modal
show="{{showLoginModal}}"
desc="登录后可购买章节、解锁更多内容"
showPrivacyModal="{{showPrivacyModal}}"
bind:close="onLoginModalClose"
bind:success="onLoginModalSuccess"
bind:privacyagree="onLoginModalPrivacyAgree"
/>
<!-- 支付中提示 -->
<view class="modal-overlay" wx:if="{{isPaying}}" catchtap="">

View File

@@ -16,7 +16,14 @@
* 浏览导师页 → browse_mentor
*/
const app = getApp()
function getAppInstance() {
try {
const a = getApp()
return a && a.globalData ? a : null
} catch (e) {
return null
}
}
const RULE_COOLDOWN_KEY = 'rule_engine_cooldown'
const COOLDOWN_MS = 60 * 1000
@@ -60,11 +67,14 @@ function setCooldown(ruleId) {
}
function getUserInfo() {
return app.globalData.userInfo || {}
const app = getAppInstance()
return app ? (app.globalData.userInfo || {}) : {}
}
async function loadRules() {
if (_cachedRules && Date.now() - _cacheTs < CACHE_TTL) return _cachedRules
const app = getAppInstance()
if (!app) return _cachedRules || []
try {
const res = await app.request({ url: '/api/miniprogram/user-rules', method: 'GET', silent: true })
if (res && res.success && res.rules) {
@@ -90,7 +100,8 @@ function getRuleInfo(rules, triggerName) {
// VIP 用户不触发:统一由 checkVipContactRequiredAndGuide 引导到 profile-edit避免与主流程冲突
function checkRule_FillAvatar(rules) {
if (!isRuleEnabled(rules, '注册')) return null
if (app.globalData.isVip) return null
const app = getAppInstance()
if (app && app.globalData.isVip) return null
const user = getUserInfo()
if (!user.id) return null
const avatar = user.avatar || user.avatarUrl || ''
@@ -147,7 +158,8 @@ function checkRule_ShareAfter5Chapters(rules) {
if (!isRuleEnabled(rules, '累计浏览5章节')) return null
const user = getUserInfo()
if (!user.id) return null
const readCount = (typeof app.getReadCount === 'function' ? app.getReadCount() : (app.globalData.readCount || 0))
const app = getAppInstance()
const readCount = app ? (typeof app.getReadCount === 'function' ? app.getReadCount() : (app.globalData.readCount || 0)) : 0
if (readCount < 5) return null
if (isInCooldown('share_after_5')) return null
setCooldown('share_after_5')
@@ -166,7 +178,8 @@ function checkRule_FillVipInfo(rules) {
if (!isRuleEnabled(rules, '完成付款')) return null
const user = getUserInfo()
if (!user.id) return null
if (!(app.globalData.hasFullBook || app.globalData.hasPurchasedFull)) return null
const app = getAppInstance()
if (!app || !(app.globalData.hasFullBook || app.globalData.hasPurchasedFull)) return null
if (user.wechatId && user.address) return null
if (isInCooldown('fill_vip_info')) return null
setCooldown('fill_vip_info')
@@ -218,7 +231,8 @@ function checkRule_Withdraw(rules) {
if (!isRuleEnabled(rules, '收益满50元')) return null
const user = getUserInfo()
if (!user.id) return null
const earnings = app.globalData.totalEarnings || 0
const app = getAppInstance()
const earnings = app ? (app.globalData.totalEarnings || 0) : 0
if (earnings < 50) return null
if (isInCooldown('withdraw_50')) return null
setCooldown('withdraw_50')
@@ -280,6 +294,8 @@ function executeRule(rule, pageInstance) {
function _trackRuleAction(ruleId, action) {
const userId = getUserInfo().id
if (!userId) return
const app = getAppInstance()
if (!app) return
app.request({
url: '/api/miniprogram/track',
method: 'POST',

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,8 +4,8 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>管理后台 - Soul创业派对</title>
<script type="module" crossorigin src="/assets/index-uFsIOb55.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BHvHUv2T.css">
<script type="module" crossorigin src="/assets/index-DCoaVA6V.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DGXqHqcA.css">
</head>
<body>
<div id="root"></div>

View File

@@ -775,7 +775,7 @@ def deploy_runner_container(cfg):
sftp.close()
cmd = (
"mkdir -p %s && cd %s && gunzip -c soul_runner_image.tar.gz | docker load && "
"docker compose -f docker-compose.runner.standalone.yml up -d && "
"docker-compose -f docker-compose.runner.standalone.yml up -d && "
"rm -f soul_runner_image.tar.gz && echo OK"
) % (deploy_path, deploy_path)
stdin, stdout, stderr = client.exec_command(cmd, timeout=300)

View File

@@ -74,3 +74,11 @@
{"level":"debug","timestamp":"2026-03-20T13:35:34+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 250\r\nCache-Control: no-cache, must-revalidate\r\nConnection: keep-alive\r\nContent-Language: zh-CN\r\nContent-Type: application/json; charset=utf-8\r\nDate: Fri, 20 Mar 2026 05:35:33 GMT\r\nKeep-Alive: timeout=8\r\nRequest-Id: 08A5B9F3CD0610D00118C3B9F8AF012098C81228AAF801-0\r\nServer: nginx\r\nWechatpay-Nonce: 3ac56a1aba0043f64f699ffe371ebabe\r\nWechatpay-Serial: 5F2543BF58239A4EB68FA4433DF1438A88B34B16\r\nWechatpay-Signature: tJsbXVjsXPLgAzH1ETyBrZ+xsrwmgOnT+sH8JmcqlyxUkFGCFkiqm+5DiKhE07f60dHXGeOSS4qrBzR37HzZitTeqodR7E2JB0Ut5xFbBKQL39nMDvB314u3CmklcjRrrUuSayXNUHrINYYwizfaj3GQMWlytWiS/IuC8rKhOSD1LxKQRUZvs9YD/v2EtjJrU8rXqIJdtdpAggMdIxl88oGR9/cPqBE+fSrngtqJtS+8HXfClPhrDOka1ah/faeHsQxYnb9Izglix057mv7W6vUBIjlbPsTxL1dREPQyyZ9UumcbPgnXXHkJ4iufXD61KPDPHtJjMQRaoLyZMCKR7A==\r\nWechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048\r\nWechatpay-Timestamp: 1773984933\r\nX-Content-Type-Options: nosniff\r\n\r\n{\"amount\":{\"payer_currency\":\"CNY\",\"total\":1000},\"appid\":\"wxb8bbb2b10dec74aa\",\"mchid\":\"1318592501\",\"out_trade_no\":\"MP20260320130728781800\",\"promotion_detail\":[],\"scene_info\":{\"device_id\":\"\"},\"trade_state\":\"NOTPAY\",\"trade_state_desc\":\"订单未支付\"}"}
{"level":"debug","timestamp":"2026-03-20T13:35:34+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/MP20260320130734906900?mchid=1318592501 request header: { Authorization:WECHATPAY2-SHA256-RSA2048 mchid=\"1318592501\",nonce_str=\"F4jAe1o38Lshn82q3fXtEKVPM1DONLof\",timestamp=\"1773984934\",serial_no=\"4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5\",signature=\"TIlP8QQWNG3f+RHfZefrC7CIaovaFw6JW0V8O5r6bbPu37/aKwItYZcWKlfIkv/oxQDc1hYEx/u3EU+Wwj51DemXo4ct2phaBjLH7bc2KVM5lJEOFSODme9AKlrWiu8etlYESCjSZ01TXwrD1VFoIO3Ga16TNa7xV9Y4V9MXnkcvd2v1OUHpIwB1VjjrKvpoC31959mQfXOKvJ8aLTdru+IjYuCYlMIlz7hIy6tNTpzfHA0biVsHSU8Y4ap301GeuyRp4GQdS0px8pJR0wN7BXuuXuUA3GO6vNqVCREveYcEAaFOgz0GDyCAqYiVk5MMXNNueLqGmUXBz9mvj9d/Mw==\"Accept:*/*Content-Type:application/json} request body:"}
{"level":"debug","timestamp":"2026-03-20T13:35:34+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 250\r\nCache-Control: no-cache, must-revalidate\r\nConnection: keep-alive\r\nContent-Language: zh-CN\r\nContent-Type: application/json; charset=utf-8\r\nDate: Fri, 20 Mar 2026 05:35:33 GMT\r\nKeep-Alive: timeout=8\r\nRequest-Id: 08A5B9F3CD0610A60318FACDC0552094913028E68402-0\r\nServer: nginx\r\nWechatpay-Nonce: c8cd238aa151bc5b3562d983525c9a10\r\nWechatpay-Serial: 5F2543BF58239A4EB68FA4433DF1438A88B34B16\r\nWechatpay-Signature: cU4LnoqphDCn40rM/L3JSxkg6E3H9TZXBZ2xFed9nrEt885jzrXhZACABPs+o9Pw6yyIoPDbzTukJlAZNQTZT/6zliHHuP4Wp+XF1HnWm/AxbDQwK6t23GtzY8L60ZgCJQN7xbnjqHmwKL2cX86ZB9lWGvoAcMXRhLKN3McoicwTC4268Z7xwSvUGBbIv3zmawbXZkqiYKckowym8kEHP9KXzV/7SEwwvW3CIGmloTukwcpaYOtJSRuit6/A3uz25ryxrgHT2gIudNRpW/SRKV/+M5uCd8gsJgQX27IE+KW58BnUu7oP0JC0PZXtvBHheSXo/9PmfBQVRt4Bgsbqtg==\r\nWechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048\r\nWechatpay-Timestamp: 1773984933\r\nX-Content-Type-Options: nosniff\r\n\r\n{\"amount\":{\"payer_currency\":\"CNY\",\"total\":1000},\"appid\":\"wxb8bbb2b10dec74aa\",\"mchid\":\"1318592501\",\"out_trade_no\":\"MP20260320130734906900\",\"promotion_detail\":[],\"scene_info\":{\"device_id\":\"\"},\"trade_state\":\"NOTPAY\",\"trade_state_desc\":\"订单未支付\"}"}
{"level":"debug","timestamp":"2026-03-20T13:40:34+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/MP20260320130728781800?mchid=1318592501 request header: { Content-Type:application/jsonAuthorization:WECHATPAY2-SHA256-RSA2048 mchid=\"1318592501\",nonce_str=\"J1pqkGs4r9ufJmtmovx3Cmohp0AVzD1p\",timestamp=\"1773985233\",serial_no=\"4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5\",signature=\"YcC2AmHsM/4iEuchlI60nv43aVTuEiCEKHCsJgxy0Ai0PhYuJJpyUoJJJegjcGSKqWPqGBuQxhNO93dVdWVSoYWpxUgX0DFpWfgSwSJyA7ORL5Zih1tQ9Y+bRZNR2SUrH4/a3IHDgKB5pEBg9JqeRXZSSzIjFda/mBFRMvHEZqGNWZaXc2YUxTtGIQJcTOYvz/69PgsiT8KwyzrWndgi/Kl77L1NtGpHQMvijCsNfrMDd7OgF8GPt6kiR+c94pQPRLl1yNJJ1bOkYTA5o5gOwgOnKLz+AgzVFTW1mHBnOnKFWp16tE1ppu2nBd/BV3RDs7A/riV+WteSkfRSyfN6kw==\"Accept:*/*} request body:"}
{"level":"debug","timestamp":"2026-03-20T13:40:34+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 250\r\nCache-Control: no-cache, must-revalidate\r\nConnection: keep-alive\r\nContent-Language: zh-CN\r\nContent-Type: application/json; charset=utf-8\r\nDate: Fri, 20 Mar 2026 05:40:33 GMT\r\nKeep-Alive: timeout=8\r\nRequest-Id: 08D1BBF3CD0610F30118B9B4F8AF0120CC933228B19E05-0\r\nServer: nginx\r\nWechatpay-Nonce: b9df57e2e45c6e3daaf7587ae548dae7\r\nWechatpay-Serial: 5F2543BF58239A4EB68FA4433DF1438A88B34B16\r\nWechatpay-Signature: a6eIinFWYfNr7C2vNL+oxWVo8gKXwg5/l5+pmFHnQFB23ziIBzAYmOdCmbY93Wyy9iPoqJoltohjpGAwHno61Zdz/PVAxEtuQ3bU23nr6h3YhRa4wYJxGqNlrQg+Mx6WP3uaYcRzF0x7BMo0OQDCNiJs9oaaswQlSnZPrSZJhDfYuhhR5GXWqRkvfHh6efayvosWung+91KoYDRKVnZEuxYNwwZhRMNcQcBhwb+gGw8qirzTrv4tCsgqOT8mOQYiG+z+P6dKcym0VMnWoJIeuPR68C+5Sx7K8C0g/3F8/YJqQZPnWPNN3icFIgEY+stS6tJ0/6O0gHv49PCdetZyKA==\r\nWechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048\r\nWechatpay-Timestamp: 1773985233\r\nX-Content-Type-Options: nosniff\r\n\r\n{\"amount\":{\"payer_currency\":\"CNY\",\"total\":1000},\"appid\":\"wxb8bbb2b10dec74aa\",\"mchid\":\"1318592501\",\"out_trade_no\":\"MP20260320130728781800\",\"promotion_detail\":[],\"scene_info\":{\"device_id\":\"\"},\"trade_state\":\"NOTPAY\",\"trade_state_desc\":\"订单未支付\"}"}
{"level":"debug","timestamp":"2026-03-20T13:40:34+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/MP20260320130734906900?mchid=1318592501 request header: { Content-Type:application/jsonAuthorization:WECHATPAY2-SHA256-RSA2048 mchid=\"1318592501\",nonce_str=\"AC0lRpeh3hYl39CPzGGmTPIS2JAdf7kx\",timestamp=\"1773985234\",serial_no=\"4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5\",signature=\"Gzk8hxM6I8DpDa/YYrSEqBXKVxMAfswSmY9fA4BiwGwCftGZzISk1ywGO+2RGvr7qR+7rjH36vTum/j3fb90WUopAtW2yJt42uFpuXyoHL3dw4aO6GAeNMT1BAsixXR82w+KwyYnHOMD29qgmZMzQScn+o6ID6zhCT0TusQY885R9YQN7XmnyxsNJhYchlWN5N3pBJSeDVFrlwy8RR2+ZvyRYtHy69m2Vm8rnL44cRNX0jhYyOph5ofeOYcxAL2nHRYHfuOxpjszPA1BWBHHwTm/G1Ql9VW1ZVM41N0+tfsSuAGncYfkEIkqHmEXosHvJMLle1utod879SFF5R3vXw==\"Accept:*/*} request body:"}
{"level":"debug","timestamp":"2026-03-20T13:40:34+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 250\r\nCache-Control: no-cache, must-revalidate\r\nConnection: keep-alive\r\nContent-Language: zh-CN\r\nContent-Type: application/json; charset=utf-8\r\nDate: Fri, 20 Mar 2026 05:40:33 GMT\r\nKeep-Alive: timeout=8\r\nRequest-Id: 08D1BBF3CD0610C804188EC8C05520CEB40728EEC304-0\r\nServer: nginx\r\nWechatpay-Nonce: 40782685ba30351314483606d380e1b0\r\nWechatpay-Serial: 5F2543BF58239A4EB68FA4433DF1438A88B34B16\r\nWechatpay-Signature: lCv+RTz7EyD7pg/TCP+EOS+iPm5ks3uYPZ0CHeL9U8JvW/jSo5IziNC5HAHrRoA/2kgusr/PF1/0JbogjvLpJj1dNjQhlQrhu2qvtDwV5aafkPPkRIEnE6GwKxK0qYUbk/Kf4Q3yPpodSsluOioLzRAE9fDabcaIBt0ier+r2dpQZ6ObEx+jkVoyxf07FMSFNiROClJKmFaITP+DtdjmARpEc4uzZpeVLgk6o18nHe/r/1r+7TO+jo1LgZF6vj9pUXkoWP5gjQjFUNCbGJMLbDLQgkOhn0JbQjIpN82Woi8FOhFdRUCQfCASBbSFpDcBfydi6FNqaZcpB2bX5Msh5A==\r\nWechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048\r\nWechatpay-Timestamp: 1773985233\r\nX-Content-Type-Options: nosniff\r\n\r\n{\"amount\":{\"payer_currency\":\"CNY\",\"total\":1000},\"appid\":\"wxb8bbb2b10dec74aa\",\"mchid\":\"1318592501\",\"out_trade_no\":\"MP20260320130734906900\",\"promotion_detail\":[],\"scene_info\":{\"device_id\":\"\"},\"trade_state\":\"NOTPAY\",\"trade_state_desc\":\"订单未支付\"}"}
{"level":"debug","timestamp":"2026-03-20T13:51:02+08:00","caller":"kernel/accessToken.go:381","content":"GET https://api.weixin.qq.com/cgi-bin/token?appid=wxb8bbb2b10dec74aa&grant_type=client_credential&neededText=&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
{"level":"debug","timestamp":"2026-03-20T13:51:02+08:00","caller":"kernel/accessToken.go:383","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 174\r\nConnection: keep-alive\r\nContent-Type: application/json; encoding=utf-8\r\nDate: Fri, 20 Mar 2026 05:51:01 GMT\r\n\r\n{\"access_token\":\"102_q0Pwcij9HevkF1S3emEoJBECS3UyMRcGqUkz5ot41QOeP_Qo-AaeayA2e9WuJh3mebufTiBJEu7eXwXThAgAbR9LYsn0QFMXVrVg9Q1WR4_Xdwy9xdHbiO5JhpICBAeAHAPON\",\"expires_in\":7200}"}
{"level":"debug","timestamp":"2026-03-20T13:51:02+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=102_q0Pwcij9HevkF1S3emEoJBECS3UyMRcGqUkz5ot41QOeP_Qo-AaeayA2e9WuJh3mebufTiBJEu7eXwXThAgAbR9LYsn0QFMXVrVg9Q1WR4_Xdwy9xdHbiO5JhpICBAeAHAPON&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0b3jvdGa1Q6VoL0cTlHa1BJvuq3jvdGA&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
{"level":"debug","timestamp":"2026-03-20T13:51:02+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Fri, 20 Mar 2026 05:51:01 GMT\r\n\r\n{\"session_key\":\"R/QHH5/k9JfJYETxk2lLDQ==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"}

View File

@@ -2,12 +2,14 @@
> 相关文档已统一移至 **开发文档**。
- [6、后端/管理端鉴权设计](../开发文档/6、后端/管理端鉴权设计.md)
- [6、后端/miniprogram接口补全说明](../开发文档/6、后端/miniprogram接口补全说明.md)
- [8、部署/宝塔反向代理说明](../开发文档/8、部署/宝塔反向代理说明.md)
- [8、部署/部署总览](../开发文档/8、部署/部署总览.md) — 部署入口
- [8、部署/DOCKER部署说明](../开发文档/8、部署/DOCKER部署说明.md)
- [8、部署/宝塔-Docker首次配置指南](../开发文档/8、部署/宝塔-Docker首次配置指南.md)
- [8、部署/宝塔反向代理说明](../开发文档/8、部署/宝塔反向代理说明.md)
- [8、部署/提现功能完整技术文档](../开发文档/8、部署/提现功能完整技术文档.md)
- [8、部署/订阅消息](../开发文档/8、部署/订阅消息.md)
- [8、部署/商家转账](../开发文档/8、部署/商家转账.md)
- [6、后端/管理端鉴权设计](../开发文档/6、后端/管理端鉴权设计.md)
- [6、后端/miniprogram接口补全说明](../开发文档/6、后端/miniprogram接口补全说明.md)
详见 [开发文档 README](../开发文档/README.md)。
详见 [开发文档索引](../开发文档/索引.md)。

View File

@@ -0,0 +1,8 @@
# 10、项目管理
> 里程碑、运营与变更
| 文件 | 用途 |
|------|------|
| [项目落地推进表](项目落地推进表.md) | 当前阶段、里程碑、风险与阻塞、永平落地 |
| [运营与变更](运营与变更.md) | 运营数据、soul-admin 变更、近期讨论、技术决策 |

View File

@@ -171,6 +171,29 @@ VIP 接口、章节推荐逻辑、数据库依赖
---
## 小程序登录改为手机号一键登录2026-03-20 橙子同步)
### 变更摘要
| 项目 | 说明 |
|------|------|
| **登录方式** | 主登录改为「手机号一键登录」,按钮文案统一;用户拒绝手机号时回退微信静默登录 |
| **公用组件** | 新增 `components/login-modal`read、my、gift-pay/detail 引入,去除三处重复实现 |
| **隐私协议** | getPhoneNumber 必须 `open-type="getPhoneNumber\|agreePrivacyAuthorization"`onNeedPrivacyAuthorization 支持 read/my/gift-pay/index/settings |
| **手机号同步** | 登录后若 user.phone 为空,从 profile 拉取并更新本地 userInfo |
### 管理后台配置
- 小程序管理后台 → 设置 → 用户隐私保护指引,必须声明「收集你选择的手机号」
- 个人主体小程序无法使用 getPhoneNumber
### 经验入库
- `agent/小程序开发工程师/evolution/2026-03-20-手机号登录与公用组件.md`
- miniprogram-dev SKILL §8 已补充 getPhoneNumber 耦合与 login-modal 约定
---
# 第七部分开发进度同步2026-02-27 橙子)
## 三端开发进度汇报
@@ -509,3 +532,31 @@ Mycontent-temp/miniprogram 为样式预览分支miniprogram 为线上主线
- `开发文档/代付-业务线框图.md`流程、角色映射、领取记录、UI 规则
- `开发文档/代付-简化流程设计.md`:改动清单全部标记已完成
- `开发文档/代付-需求分析与待完善.md`:已实现项与待确认项
---
# 第二十一部分提现功能完善2026-03-20 橙子同步)
## 变更摘要
| 项 | 说明 |
|------|------|
| **审批逻辑修复** | 批准时校验「累计佣金-已提现>=待审核」,避免本笔在 pending 中导致误拒;使用 -0.01 浮点容差 |
| **我的收益字段** | 小程序我的页「我的收益」取 availableEarnings可提现金额不再显示累计佣金 |
| **提现手续费** | 推广设置「提现规则」增加「提现手续费(%)」可配置;批准时按比例扣除后打款 |
| **自动审批开关** | 推广中心-提现审核列表与搜索框同行增加「自动审批」开关;与推广设置 enableAutoWithdraw 同源 |
| **备注列** | 提现列表增加「备注」列:失败时显示 fail_reason/error_message否则显示用户 remark |
| **失败记录** | 打款失败/拒绝时落库 fail_reason、error_messageWithdrawal 模型增加 ErrorMessage 字段 |
## 提现规则配置referral_config使用情况
| 配置项 | 使用位置 |
|--------|----------|
| minWithdrawAmount | 后端申请校验;小程序推广中心「满 X 元可提现」 |
| withdrawFee | 后端批准时扣除;管理端推广设置可配置 |
| enableAutoWithdraw | 后端 WithdrawPost 后自动审批;管理端推广设置 + 提现审核开关 |
## 相关文档
- `开发文档/1、需求/三端需求整理.md`:按小程序/管理端/后端分类的需求整理
- `开发文档/1、需求/需求汇总.md`:需求清单已追加 2026-03-20 提现相关条目

View File

@@ -0,0 +1,63 @@
# Soul 创业派对 - 需求汇总
> **主需求文件**(日期最新)。基准:《[以界面定需求](以界面定需求.md)》
---
## 需求基准
- 需求以《以界面定需求》为准,以界面定需求
- 需求文件命名:`YYYY-MM-DD-需求.md`**日期最新的为主需求文件**
- 同步需求时:新建或更新当日需求文件,并更新本目录 `索引.md`
---
## 需求清单
| 日期 | 描述 | 状态 | 备注 |
|------|------|------|------|
| 2026-02 | 内容管理页仅保留「API 接口」按钮 | 已完成 | soul-admin ContentPage |
| 2026-02 | 侧栏与分销页「交易中心」→「推广中心」 | 已完成 | AdminLayout、DistributionPage |
| 2026-02 | 推广中心/我的收益:绑定中、已付款、已过期清晰展示 | 已有 | referral 页 |
| 2026-02 | 海报小程序码带用户 IDscene ref=userId | 已完成 | referral.js generatePoster |
| 2026-02 | 复制朋友圈文案去掉「专属邀请码」展示 | 已完成 | 海报 |
| 2026-02 | 我的页:待领收益→我的收益、头像/昵称/ID 一键获取 | 已有 | my.wxml |
| 2026-02 | 设置页:手机/微信号一键获取、自动提现默认开启 | 已有 | settings.js |
| 2026-02 | 后台与前台参数一致(绑定有效期、自动提现、免费章节等) | 已检查 | 推广设置 |
| 2026-02 | 找伙伴匹配后台用户库、资源对接两步 | 已有 | match 页 |
| 2026-02 | VIP 手动设置 + 支付设置 + 日志 | 已完成 | 用户详情弹窗、支付回调 |
| 2026-02 | 管理端设置 VIP 必填到期日 | 已完成 | 前后端校验 |
| 2026-02 | 会员订单分润差异化(会员 20% / 非会员 10% | 已完成 | computeOrderCommission |
| 2026-02 | VIP 设置入口拆分、SetVipModal、VIP 角色管理 | 已完成 | UserDetailModal、SetVipModal |
| 2026-02 | VIP 排序vip_activated_at、vip_sort | 已完成 | VipMembers |
| 2026-02 | VIP 角色:可选择 + 可手动填写 | 已完成 | vip_roles 表 |
| 2026-03-08 | 文章阅读付费规则:免费章节以 free_chapters 为准VIP 全章免费 | 已完成 | soul-api book.go |
| 2026-03-10 | 我的页阅读统计改为后端接口(真实数据) | 已完成 | loadDashboardStats |
| 2026-03-10 | 富文本渲染升级TipTap HTML → rich-text保留 @mention | 待实施 | 确认 DB 格式 |
| 2026-03-16 | 文章编辑 @某人/#标签 自动创建并同步存客宝 | 已完成 | ParseAutoLinkContent |
| 2026-03-16 | 编辑资料页分享名片Canvas 封面、标题「昵称+为您分享名片」 | 已完成 | profile-edit.js |
| 2026-03-16 | 链接人与事列表table、planId/apiKey 列、删除 Dialog | 已完成 | ContentPage.tsx |
| 2026-03-16 | 存客宝创建计划参数planType=1、sceneId=9、status=1 | 已完成 | db_person.go |
| 2026-03-16 | @mention 存储格式span 必须含 data-label | 已完成 | ParseAutoLinkContent |
| 2026-03-17 | 代付统一到代付页 | 已完成 | read.js onLoad |
| 2026-03-18 | 代付流程:阅读页弹窗选择名额→支付→分享;好友自动领取 | 已完成 | read 页、singlePage 引导 |
| 2026-03-18 | 代付退款后禁用status=refunded | 已完成 | gift_pay_requests |
| 2026-03-20 | 提现审批逻辑修复:批准时校验「累计-已提现>=待审核」 | 已完成 | doApproveWithdrawal |
| 2026-03-20 | 我的页「我的收益」取 availableEarnings | 已完成 | my.wxml pendingEarnings |
| 2026-03-20 | 推广设置:提现手续费、自动提现开关 | 已完成 | ReferralSettingsPage |
| 2026-03-20 | 提现审核列表:自动审批开关、备注列 | 已完成 | DistributionPage |
| 2026-03-20 | 提现失败记录fail_reason/error_message 落库 | 已完成 | admin_withdrawals |
---
## 三端需求速查
| 端 | 主需求 |
|----|--------|
| 小程序 | 我的收益、推广中心、代付、阅读统计、VIP |
| 管理端 | 推广设置、提现审核、VIP 设置、链接人与事 |
| 后端 | 提现审批、referral_config、代付、分润 |
---
**最后更新**2026-03-20

View File

@@ -0,0 +1,11 @@
# 1、需求 - 归档
专项需求、技术分析、已合并或过时文档,保留供追溯。
| 文件 | 说明 |
|------|------|
| 链接人与事-实现方案.md | 实现方案 |
| 链接人与事-存客宝同步-需求规划.md | 存客宝同步需求规划 |
| 链接人与事-所有同步需求.md | 链接人与事所有同步需求 |
| 链接人与事-置顶功能-技术分析.md | 置顶功能技术分析 |
| 文章详情-阅读页线框图.md | 阅读页线框图 |

View File

@@ -29,6 +29,7 @@
| **pages/my/my** | 我的配置、阅读统计、待确认提现、收益、VIP 状态、提现入口 | `GET /api/miniprogram/config``GET /api/miniprogram/user/dashboard-stats``GET /api/miniprogram/withdraw/pending-confirm``GET /api/miniprogram/earnings``GET /api/miniprogram/vip/status``POST /api/miniprogram/user/update``POST /api/miniprogram/withdraw` |
| **pages/referral/referral** | 推广中心:推广数据、海报与小程序码、复制文案、申请提现 | `GET /api/miniprogram/referral/data``POST /api/miniprogram/qrcode``POST /api/miniprogram/withdraw` |
| **pages/settings/settings** | 设置:头像/昵称/手机/微信号、用户资料编辑、一键获取 | `GET /api/miniprogram/user/profile``POST /api/miniprogram/user/update``POST /api/miniprogram/phone` |
| **components/login-modal** | 公用登录弹窗手机号一键登录、隐私协议、协议勾选read/my/gift-pay 等页面引入 | 无独立接口,内部调 `app.loginWithPhone``app.login` |
| **pages/vip/vip** | VIP状态查询、开通支付 | `GET /api/miniprogram/vip/status``POST /api/miniprogram/pay`productType=vip |
| **pages/purchases/purchases** | 购买记录 | `GET /api/miniprogram/orders` |
| **pages/withdraw-records/withdraw-records** | 提现记录、确认收款 | `GET /api/miniprogram/withdraw/records``GET /api/miniprogram/withdraw/confirm-info` |
@@ -115,7 +116,7 @@
| 文档 | 关系 |
|------|------|
| **本文档(以界面定需求)** | 界面级需求基准;新增/改版界面或业务规则时先更新本文档。 |
| **需求汇总.md** | 需求清单、历史与待办;需求描述与验收标准应与本文档界面及§四业务逻辑一致。 |
| **1、需求/索引.md** | 需求 = 日期最新的需求文件(如 2026-03-20-需求.md;需求描述与验收标准应与本文档界面及§四业务逻辑一致。 |
| **运营与变更.md** | 近期变更、讨论结论、技术决策;涉及界面或规则时同步引用本文档。 |
---
@@ -126,3 +127,4 @@
|------|----------|
| 2026-03-11 | 初版小程序与管理端界面清单、业务逻辑对齐VIP 资料以用户资料为准、三端路由、免费章与 VIP、分销提现与需求汇总、README、运营与变更同步。 |
| 2026-03-17 | 管理端清单补充:用户规则、用户余额、订单支付方式;详见《管理端迁移分析-基于小程序功能.md》。 |
| 2026-03-20 | 小程序:登录改为手机号一键登录;新增公用组件 login-modalread/my/gift-pay 引入getPhoneNumber 需耦合 agreePrivacyAuthorization。 |

View File

@@ -0,0 +1,25 @@
# 1、需求 - 索引
## 命名规则
| 规则 | 说明 |
|------|------|
| **文件名** | `YYYY-MM-DD-需求.md``YYYY-MM-DD-简短描述.md` |
| **主需求文件** | **日期最新的**需求文件为主,作为当前需求基准 |
| **同步需求时** | 新建当日 `YYYY-MM-DD-需求.md` 或更新已有;更新本索引 |
## 当前主需求文件
**2026-03-20-需求.md**(日期最新)
## 基准文档(常驻)
| 文件 | 说明 |
|------|------|
| [以界面定需求](以界面定需求.md) | 界面级需求基准:小程序/管理端界面清单、主要接口、业务逻辑对齐 |
## 归档
| 目录 | 说明 |
|------|------|
| [archive/](archive/) | 专项需求、技术分析、已合并或过时文档 |

View File

@@ -1,60 +0,0 @@
# 需求汇总(合并自 业务需求、技术需求、需求方案汇总、需求日志、卡若角色设定)
## 需求基准(必读)
**需求以《[以界面定需求](以界面定需求.md)》为准,以界面定需求。**
- 小程序、管理端各界面及主要接口见该文档第二、三节。
- 业务逻辑对齐(用户/VIP 资料展示、三端 API 边界、免费章与 VIP、分销提现等见该文档第四节。
- 新增或变更功能时,先对齐界面与接口,再在本文档需求清单中补充或更新条目。
---
## 业务需求
项目目标、成本、技术要求(见原业务需求、技术需求)。
## 需求方案
Soul 创业派对整体定位、闭环、用户画像;小程序改造与迭代、已修复问题、已完成功能、配置与上线检查。详见原需求方案汇总。
## 需求日志
日常需求变更记录(见原需求日志)。
## 卡若角色设定
IP 设定、风格、输出规范(见原卡若角色设定)。
---
## 需求清单(来自 cursor_1_14 与永平落地)
| 日期 | 描述 | 状态 | 备注 |
|------|------|------|------|
| 2026-02 | 内容管理页仅保留「API 接口」按钮 | 已完成 | soul-admin ContentPage 源码改造 |
| 2026-02 | 侧栏与分销页「交易中心」→「推广中心」 | 已完成 | AdminLayout、DistributionPage |
| 2026-02 | 推广中心/我的收益:绑定中、已付款、已过期清晰展示 | 已有 | referral 页数据结构支持 |
| 2026-02 | 海报小程序码带用户 IDscene ref=userId | 已完成 | referral.js generatePoster |
| 2026-02 | 复制朋友圈文案去掉「专属邀请码」展示 | 已完成 | 海报上去掉邀请码文案 |
| 2026-02 | 我的页:待领收益→我的收益、头像/昵称/ID 一键获取 | 已有/已完成 | my.wxml 文案统一 |
| 2026-02 | 设置页:手机/微信号一键获取、自动提现默认开启 | 已有 | settings.js |
| 2026-02 | 后台与前台参数一致(绑定有效期、自动提现、免费章节等) | 已检查 | 推广设置、系统设置已对齐 |
| 2026-02 | 找伙伴匹配后台用户库、资源对接两步(能帮什么/需要什么) | 已有 | match 页与后端 /api/match |
| 2026-02 | VIP 手动设置 + 支付设置 + 日志(区分来源、订单号) | 已完成 | 用户详情弹窗、支付回调、db/miniprogram handler |
| 2026-02 | 管理端设置 VIP 必填到期日 | 已完成 | 前后端校验 |
| 2026-02 | 会员订单分润差异化(会员 20% / 非会员 10% | 已完成 | 技术分析见 临时需求池/分润需求-技术分析.mdcomputeOrderCommission推广设置页增加会员分润配置 |
| 2026-02 | VIP 设置入口拆分:用户列表「设置 VIP」按钮 + 独立弹窗 | 已完成 | UserDetailModal 移除 VIP 区块SetVipModal 独立 |
| 2026-02 | VIP 排序:后付款/后设置在前;支持手动排序 | 已完成 | vip_activated_at、vip_sortVipMembers 排序逻辑 |
| 2026-02 | VIP 角色:可选择 + 可手动填写 | 已完成 | vip_roles 表VIP 角色管理页SetVipModal 角色下拉 |
| 2026-03-08 | 文章阅读付费规则:免费章节以 free_chapters 为准VIP 全章免费 | 已完成 | soul-api book.go 合并 free_chapterscheck-purchased 已支持 VIP |
| 2026-03-10 | 小程序「我的」页阅读统计改为后端接口(真实数据) | 已完成 | my.js loadDashboardStatssoul-api GET /api/miniprogram/user/dashboard-stats |
| 2026-03-10 | 富文本渲染升级TipTap HTML → rich-text 组件,保留 @mention 交互) | 待实施 | 确认 DB 内容格式后实施;当前 contentParser.js 为纯文本剥除 |
| 2026-03-16 | 文章编辑时 @某人/#标签 自动创建:不存在则自动新增到链接人与事/链接标签并同步存客宝 | 已完成 | 临时需求池/2026-03-16-文章编辑自动创建@和#.md |
| 2026-03-16 | 编辑资料页分享名片:转发/朋友圈特殊处理Canvas 封面(头像+昵称+四栏信息),标题「昵称+为您分享名片」 | 已完成 | profile-edit.js generateShareCard |
| 2026-03-16 | 链接人与事列表table 布局、planId/apiKey 列、apiKey 复制图标、删除 Dialog 二次确认 | 已完成 | ContentPage.tsx |
| 2026-03-16 | 存客宝创建计划参数planType=1、sceneId=9、status=1 | 已完成 | db_person.go |
| 2026-03-16 | @mention 存储格式span 必须含 data-label否则 TipTap 显示 token | 已完成 | ParseAutoLinkContent、autolink.go |
| 2026-03-17 | 代付统一到代付页gift=1&ref 打开 read 页时 redirectTo 代付页,禁止在阅读页代付;代付页显示部分文章信息 | 已完成 | read.js onLoad代付页已有 description |
| 2026-03-18 | 代付流程调整:阅读页内居中弹窗选择名额→支付成功直接分享;好友打开阅读页自动领取并解锁(含朋友圈 singlePage 降级引导) | 已完成 | read 页代付弹窗+自动领取singlePage 引导规则入库 |
| 2026-03-18 | 代付退款后禁用:订单退款后代付请求标记 refunded小程序/管理端均展示“已退款”,不可再分享/领取 | 已完成 | 后端退款同步 gift_pay_requests.status=refunded |
| - | 链接人与事所有同步需求汇总 | - | 链接人与事-所有同步需求.md |

View File

@@ -0,0 +1,9 @@
# 6、后端
> soul-api 相关技术文档
| 文件 | 用途 |
|------|------|
| [管理端鉴权设计](管理端鉴权设计.md) | JWT 鉴权、路由分层、AdminAuth 中间件 |
| [miniprogram接口补全说明](miniprogram接口补全说明.md) | VIP/users 接口迁移至 /api/miniprogram/* |
| [soul-admin与Mycontent-temp内容页对比](soul-admin与Mycontent-temp内容页对比.md) | 内容管理页功能对比soul-admin 为基准 |

View File

@@ -1,285 +1,84 @@
# soul-api Docker 部署说明
## 一、前置要求
- 服务器已安装 **Docker****Docker Compose**
- 已有 **MySQL** 数据库(如腾讯云 CDB
- 准备 **微信支付证书**`apiclient_cert.pem``apiclient_key.pem`(放在 `certs/` 目录)
> 当前实际部署以 **master.py正式** 和 **devloy.py测试** 为主。Docker 用于测试环境的 Runner 模式。详见 [部署总览](部署总览.md)。
---
## 二、部署步骤
## 一、测试环境 Runner 模式(推荐)
### 1. 准备配置
容器内红蓝切换,宝塔 Nginx 固定 `proxy_pass http://127.0.0.1:9001`,无需改配置
### 1. 首次准备(服务器)
```bash
cd soul-api
# 复制生产配置为 .env不要直接修改 .env.production避免敏感信息进 git
cp .env.production .env
# 编辑 .env重点确认
# - DB_DSNMySQL 连接串(腾讯云 CDB 等)
# - API_BASE_URL你的 API 域名
# - 其他微信、存客宝等配置
#
# REDIS_URL 由 docker-compose 自动注入,无需在 .env 中配置。
# Docker 自建 Redis与宝塔已有 Redis 完全隔离,互不影响。
bash deploy/runner-init.sh
```
### 2. 准备证书
会构建 `soul-api-runner:latest` 并启动容器,使用 `network_mode: host`,容器内监听 9001。
确保 `certs/` 目录下有:
### 2. 部署新版本(本地)
- `apiclient_cert.pem`
- `apiclient_key.pem`
Docker 启动时会挂载 `./certs` 到容器内的 `/app/certs`
### 3. 构建并启动
```bash
# 构建镜像并启动
docker compose -f docker-compose.production.yml up -d --build
# 查看日志
docker compose -f docker-compose.production.yml logs -f soul-api
```
### 4. 验证
```bash
# 健康检查
curl http://localhost:8080/health
# 应返回类似:{"success":true,"version":"0.0.0",...}
```
---
## 三、常用命令
| 操作 | 命令 |
|------------|------------------------------------------------------------|
| 启动 | `docker compose -f docker-compose.production.yml up -d` |
| 停止 | `docker compose -f docker-compose.production.yml down` |
| 查看日志 | `docker compose -f docker-compose.production.yml logs -f` |
| 重启 API | `docker compose -f docker-compose.production.yml restart soul-api` |
| 仅重新构建 | `docker compose -f docker-compose.production.yml build --no-cache` |
---
## 四、端口与数据
| 服务 | 端口映射 | 说明 |
|-----------|-------------|--------------------------|
| soul-api | 8080:8080 | API 服务 |
| redis | 6379:6379 | 可按需不暴露到公网 |
**持久化卷**
- `soul_uploads`:上传文件(头像、书籍封面等)
- `redis_data`Redis 数据
---
## 五、Nginx 反向代理示例
```nginx
server {
listen 443 ssl;
server_name soulapi.quwanzhi.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
---
## 六、从宝塔部署迁移到 Docker
原先通过 `master.py` 部署到宝塔的流程,可改为:
1. 在服务器创建目录,如 `/opt/soul-api`
2. 上传项目代码(或 git clone
3. 按上述步骤配置 `.env``certs/`
4. 执行 `docker compose -f docker-compose.production.yml up -d --build`
5. 在 Nginx/宝塔中配置反向代理到 `127.0.0.1:8080`
数据库、Redis 可继续使用原有实例,只需在 `.env` 中正确配置连接串即可。
---
## 七、蓝绿无缝部署deploy.py --mode docker
运行 `deploy.py --mode docker` 后,可**本地构建镜像 → 上传宝塔 → 自动蓝绿切换、零停机**。
### 原理
- **blue** 实例:端口 8081
- **green** 实例:端口 8082
- 部署时:先启动新实例 → 健康检查通过 → 切换 Nginx 到新端口 → 停止旧实例
### 首次服务器准备
1. 创建目录:`mkdir -p /www/wwwroot/self/soul-dev`
2. 放入 `.env``certs/`(与普通 Docker 部署相同)
3. 配置环境变量(本地执行 deploy.py 前):
```bash
export DEPLOY_DOCKER_PATH=/www/wwwroot/self/soul-dev
export DEPLOY_NGINX_CONF=/www/server/panel/vhost/nginx/soulapi.quwanzhi.com.conf
```
### 使用方式
```bash
```powershell
cd soul-api
python deploy.py --mode docker
python devloy.py --mode runner
```
脚本会:构建镜像 → 导出 tar.gz → 上传 → 服务器执行蓝绿切换。Nginx 由脚本自动修改 `proxy_pass` 端口并重载
流程:本地 go build → 打包二进制 + .env.development + certs → 上传 → 容器内红蓝切换
### 3. 前置要求
- 服务器已安装 Docker、Docker Compose
- soul-api 目录有 `.env.development``certs/`apiclient_cert.pem、apiclient_key.pem
- 宝塔站点 souldev.quwanzhi.com 的 `location /` 已配置 `proxy_pass http://127.0.0.1:9001`
---
## 七、蓝绿无缝部署deploy.py --mode docker
## 二、测试环境 Docker 蓝绿模式(宿主机
本地运行 `python deploy.py --mode docker` 可一键打包镜像、上传到宝塔、自动蓝绿切换,**零停机**
宿主机双实例 8081/8082 轮流对外,需脚本自动修改 Nginx `proxy_pass` 端口
### 原理
### 1. 环境变量
- **双实例**blue8081、green8082轮流对外服务
- **部署流程**:先启动新实例 → 健康检查通过 → Nginx 切到新端口 → 停止旧实例
- **无缝切换**:切换过程中始终有实例在服务,用户无感知
### 首次部署准备(服务器)
```bash
# 1. 创建目录
mkdir -p /www/wwwroot/self/soul-dev
cd /www/wwwroot/self/soul-dev
# 2. 准备 .env、certs/
cp soul-api/.env.production .env
# 将微信证书放到 certs/
# 3. 设置 Nginx 配置路径(宝塔常用路径)
export DEPLOY_NGINX_CONF=/www/server/panel/vhost/nginx/soulapi.quwanzhi.com.conf
```powershell
$env:DEPLOY_DOCKER_PATH="/www/wwwroot/self/soul-dev"
$env:DEPLOY_NGINX_CONF="/www/server/panel/vhost/nginx/souldev.quwanzhi.com.conf"
```
### 本地执行
### 2. 执行
```bash
```powershell
cd soul-api
# 环境变量(或写入 .env
export DEPLOY_HOST=43.139.27.93
export DEPLOY_USER=root
export DEPLOY_PASSWORD=你的密码
export DEPLOY_DOCKER_PATH=/www/wwwroot/self/soul-dev
export DEPLOY_NGINX_CONF=/www/server/panel/vhost/nginx/soulapi.quwanzhi.com.conf
# 执行(需本地安装 Docker
python deploy.py --mode docker
python devloy.py --mode docker
```
### 参数说明
流程:本地 go build → Dockerfile.local 打镜像 → 导出 tar.gz → 上传 → 服务器加载 → 蓝绿切换 → 修改 Nginx 并重载。
| 参数 | 说明 |
---
## 三、Docker 相关文件
| 文件 | 用途 |
|------|------|
| `--mode docker` | 使用 Docker 蓝绿部署(默认 binary |
| `--no-build` | 跳过镜像构建(使用已有 soul-api:latest |
| `--no-env` | 不上传 .env保留服务器现有配置 |
| deploy/Dockerfile.runner | Runner 容器镜像Alpine + nginx + redis |
| deploy/docker-compose.runner.yml | Runner 容器编排 |
| deploy/runner-init.sh | 首次构建并启动 Runner 容器 |
| deploy/runner/entrypoint.sh | 容器入口,启动 nginx + 红蓝切换逻辑 |
| deploy/runner/deploy.sh | 容器内部署脚本 |
---
## 七、蓝绿部署无缝切换deploy.py --mode docker
## 四、正式环境(非 Docker
通过 `deploy.py` 一键打包镜像、上传并自动蓝绿切换,实现 **零停机部署**
### 原理
- 双实例blue8081、green8082交替使用
- 部署时:启动新实例 → 健康检查通过 → 切换 Nginx → 停旧实例
- 请求始终有实例在服务,实现无缝切换
### 首次准备(服务器端)
```bash
# 在服务器创建目录
mkdir -p /www/wwwroot/self/soul-dev
cd /www/wwwroot/self/soul-dev
# 从本地上传或创建 .env、certs/
# .env 同第二节
# certs/ 下放 apiclient_cert.pem、apiclient_key.pem
```
### 配置环境变量(本地)
```bash
# .env 或 系统环境变量
DEPLOY_HOST=43.139.27.93
DEPLOY_USER=root
DEPLOY_PASSWORD=你的密码
DEPLOY_SSH_PORT=22022
DEPLOY_DOCKER_PATH=/www/wwwroot/self/soul-dev
# 宝塔 Nginx 配置路径(必填,用于自动切换端口)
DEPLOY_NGINX_CONF=/www/server/panel/vhost/nginx/soulapi.quwanzhi.com.conf
```
### 一键部署
```bash
cd soul-api
python deploy.py --mode docker
```
流程:本地 `docker build` → 导出 tar.gz → 上传 → 服务器 `docker load` → 蓝绿切换 → 完成。
### 首次部署
若 Nginx 当前指向 8080原二进制首次执行后会自动改为 8081 或 8082。请先停用宝塔里的 soulApi Go 项目,避免端口冲突。
正式环境使用 **master.py** 部署 Go 二进制到宝塔,不走 Docker。详见 [部署总览](部署总览.md) 第三节
---
## 七、deploy.py 蓝绿无缝部署(零停机)
本地运行 `deploy.py --mode docker` 可一键完成:构建镜像 → 上传服务器 → 蓝绿切换。
### 7.1 流程说明
| 步骤 | 操作 |
|------|------|
| 1 | 本地 `docker build` 构建 soul-api:latest |
| 2 | `docker save` 导出为 tar.gz |
| 3 | SFTP 上传镜像、docker-compose.bluegreen.yml、deploy 脚本 |
| 4 | 服务器加载镜像,启动**未活跃**实例blue 或 green |
| 5 | 等待健康检查通过 |
| 6 | Nginx `proxy_pass` 切换到新实例端口 |
| 7 | 停止旧实例 |
### 7.2 使用前准备
1. **服务器**创建目录 `/www/wwwroot/self/soul-dev`,放入 `.env``certs/`
2. **环境变量**(或 `.env`
- `DEPLOY_HOST` / `DEPLOY_USER` / `DEPLOY_PASSWORD`SSH
- `DEPLOY_DOCKER_PATH=/www/wwwroot/self/soul-dev`
- `DEPLOY_NGINX_CONF=/www/server/panel/vhost/nginx/soulapi.quwanzhi.com.conf`
### 7.3 执行
## 五、健康检查
```bash
cd soul-api
python deploy.py --mode docker
# 或跳过构建使用已有镜像python deploy.py --mode docker --no-build
curl -s http://127.0.0.1:9001/health # Runner 模式
curl -s http://127.0.0.1:8080/health # 正式环境
```
应返回 `{"status":"ok"}``{"success":true,...}`

View File

@@ -0,0 +1,13 @@
# 8、部署
> soul-api 部署、提现、订阅消息相关
| 文件 | 用途 |
|------|------|
| [部署总览](部署总览.md) | **入口**:正式/测试/管理端部署脚本、环境、命令 |
| [DOCKER部署说明](DOCKER部署说明.md) | 测试环境 Runner/Docker 模式、Docker 相关文件 |
| [宝塔-Docker首次配置指南](宝塔-Docker首次配置指南.md) | 测试环境 Runner 首次配置 |
| [宝塔反向代理说明](宝塔反向代理说明.md) | 域名 404 排查、Nginx 反向代理 |
| [提现功能完整技术文档](提现功能完整技术文档.md) | 微信支付商家转账到零钱 API 集成 |
| [订阅消息](订阅消息.md) | 提现成功订阅消息PowerWeChat |
| [商家转账](商家转账.md) | PowerWeChat 商家转账示例 |

View File

@@ -1,24 +1,24 @@
# soul-api 测试环境 - 宝塔 Docker 首次配置指南
> deploy.py 部署的是**测试环境**。运行 `python deploy.py` 前,在宝塔服务器上完成本指南的一次性配置。
> 运行 `python devloy.py --mode runner` 前,在宝塔服务器上完成本指南的一次性配置。
---
## 一、运行 deploy.py 会做什么(测试环境
## 一、devloy.py 会做什么(Runner 模式
在 soul-api 目录执行:
```bash
python deploy.py
```powershell
python devloy.py --mode runner
```
会自动完成:
1. 本地构建 Docker 镜像(含 certs、.env.development
2. 导出为 tar.gz
3. 通过 SSH 上传到宝塔测试环境服务器
4. 服务器加载镜像并执行蓝绿部署
5. 自动切换 Nginx 到新实例
1. 本地 go build 交叉编译 Linux 二进制
2. 打包二进制 + .env.development + certs 为 tar.gz
3. 通过 SSH 上传到服务器
4. 上传到 Runner 容器内,执行红蓝切换
5. 宝塔 Nginx 固定 `proxy_pass http://127.0.0.1:9001`,无需改配置
---
@@ -29,34 +29,35 @@ python deploy.py
在宝塔终端或 SSH 执行:
```bash
# 安装 Docker若未安装
curl -fsSL https://get.docker.com | sh
systemctl enable docker
systemctl start docker
# 安装 Docker Compose
# Docker Compose
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
```
### 2. 创建部署目录
### 2. 首次启动 Runner 容器
在服务器上(或通过 SSH 上传 soul-api 后):
```bash
mkdir -p /www/wwwroot/self/soul-dev
cd /www/wwwroot/self/soul-dev
cd /path/to/soul-api
bash deploy/runner-init.sh
```
本目录用于存放 `docker-compose.bluegreen.yml``docker-deploy-remote.sh`deploy.py 每次部署会覆盖),以及持久化数据卷
会构建 `soul-api-runner:latest` 并启动容器,监听 9001
### 3. 配置 Nginx 站点
在宝塔:**网站** → 找到 `soulapi.quwanzhi.com`(若没有则新建站点)
在宝塔:**网站** → 找到 `souldev.quwanzhi.com`(若没有则新建站点)
**设置****配置文件**,确保 `location /` 为反向代理:
```nginx
location / {
proxy_pass http://127.0.0.1:8081;
proxy_pass http://127.0.0.1:9001;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
@@ -65,35 +66,22 @@ location / {
}
```
- 首次可用 `8081``8082`deploy.py 部署时会自动切换
- Runner 模式固定 9001无需 8081/8082
- 删除或注释掉原来的 `root``index` 等静态配置,否则会 404
保存后点击 **重载配置**
### 4. 确认 Nginx 配置文件路径
宝塔 Nginx 配置通常在:
```
/www/server/panel/vhost/nginx/soulapi.quwanzhi.com.conf
```
若域名不同,请在宝塔 **网站** → 该站点 → **设置****配置文件** 查看实际路径。
---
## 三、本地环境变量(执行 deploy.py 前)
在本地设置以下环境变量(或写入 soul-api 同级的 `.env`
## 三、本地环境变量(执行 devloy.py 前)
| 变量 | 示例 | 说明 |
|------|------|------|
| DEPLOY_HOST | 43.139.27.93 | 宝塔服务器 IP |
| DEPLOY_USER | root | SSH 用户名 |
| DEPLOY_PASSWORD | xxx | SSH 密码 |
| DEPLOY_SSH_PORT | 22022 | SSH 端口(默认 22022 |
| DEPLOY_DOCKER_PATH | /www/wwwroot/self/soul-dev | 测试环境部署目录 |
| DEPLOY_NGINX_CONF | /www/server/panel/vhost/nginx/soulapi.quwanzhi.com.conf | Nginx 配置路径 |
| DEPLOY_SSH_PORT | 22022 | SSH 端口 |
| DEPLOY_DOCKER_PATH | /www/wwwroot/self/soul-dev | 测试环境部署目录Runner 模式也会用到) |
PowerShell 示例:
@@ -102,41 +90,47 @@ $env:DEPLOY_HOST="43.139.27.93"
$env:DEPLOY_USER="root"
$env:DEPLOY_PASSWORD="你的密码"
$env:DEPLOY_DOCKER_PATH="/www/wwwroot/self/soul-dev"
$env:DEPLOY_NGINX_CONF="/www/server/panel/vhost/nginx/soulapi.quwanzhi.com.conf"
```
**注意**Runner 模式不需要 `DEPLOY_NGINX_CONF`Nginx 固定 9001。若用 `--mode docker` 蓝绿模式才需要。
---
## 四、首次部署前检查
1. **soul-api 目录**:已有 `.env.development`deploy.py 固定用测试环境配置)
1. **soul-api 目录**:已有 `.env.development`devloy 固定用测试环境配置)
2. **certs/**:包含 `apiclient_cert.pem``apiclient_key.pem`
3. **本地 Docker**:已安装并运行
4. **宝塔 Go 项目**:若之前用 soulApi 二进制,建议先在宝塔里**停止** soulApi避免 8080 冲突Docker 用 8081/8082
3. **服务器**:已执行 `deploy/runner-init.sh`Runner 容器在跑
4. **宝塔**souldev.quwanzhi.com 的 Nginx 已配置 `proxy_pass http://127.0.0.1:9001`
---
## 五、执行部署
```bash
```powershell
cd soul-api
python deploy.py
python devloy.py --mode runner
```
首次会构建镜像并上传,之后每次有代码变更再执行即可,会自动蓝绿切换、零停机。
首次会构建并上传,之后每次有代码变更再执行即可,容器内红蓝切换、零停机。
---
## 六、常见问题
### Nginx 配置路径不对
### Nginx 404
`DEPLOY_NGINX_CONF` 填错,部署脚本会提示「未配置 DEPLOY_NGINX_CONF」。请在宝塔中确认实际配置文件路径并修正环境变量
### 原 soulApi 还在跑导致冲突
Docker 使用 8081、8082与宝塔 Go 项目的 8080 不冲突。若 Nginx 仍指向 8080请改为指向 8081 或 8082或先停止宝塔里的 soulApi。
确认 `location /` 已改为 `proxy_pass http://127.0.0.1:9001`,且删除了 `root``index` 等静态配置。详见 [宝塔反向代理说明](宝塔反向代理说明.md)
### 健康检查超时
检查服务器防火墙、MySQL/Redis 等是否可访问,以及 `.env` 中 DB_DSN、REDIS 等配置是否正确。
```bash
curl -s http://127.0.0.1:9001/health
```
若失败,检查 Runner 容器是否在跑:`docker ps | grep soul-api-runner`,以及 `.env` 中 DB_DSN、REDIS 等配置。
### 正式与测试域名区分
- **正式**soulapi.quwanzhi.com → master.py → 8080
- **测试**souldev.quwanzhi.com → devloy.py --mode runner → 9001

View File

@@ -1,18 +1,35 @@
# soul-api 域名 404 原因与解决
## 原因
域名请求先到 Nginx若没有把请求转发到本机 8080 的 Go,或站点用了 root/静态目录,就会 404。
域名请求先到 Nginx若没有把请求转发到本机对应端口,或站点用了 root/静态目录,就会 404。
---
## 一、先确认 Go 是否在跑(必做)
## 端口对照
| 环境 | 域名 | 端口 | 部署方式 |
|------|------|------|----------|
| 正式 | soulapi.quwanzhi.com | 8080 | master.py宝塔 soulApi |
| 测试 | souldev.quwanzhi.com | 9001 | devloy.py --mode runner |
---
## 一、先确认服务是否在跑(必做)
在宝塔终端或 SSH 里执行:
curl -s http://127.0.0.1:8080/health
```bash
# 正式环境
curl -s http://127.0.0.1:8080/health
- 若返回 {"status":"ok"}:说明 Go 正常,问题在 Nginx看下面第二步。
- 若连接被拒绝或超时:说明 8080 没在监听。去 宝塔 → Go项目管理 → soulApi → 服务状态,看是否“运行中”;看“项目日志”是否有报错。
# 测试环境Runner 模式)
curl -s http://127.0.0.1:9001/health
```
- 若返回 `{"status":"ok"}``{"success":true,...}`:说明服务正常,问题在 Nginx看下面第二步。
- 若连接被拒绝或超时:
- **正式**:宝塔 → Go项目管理 → soulApi → 服务状态,看是否“运行中”
- **测试**`docker ps | grep soul-api-runner` 看容器是否在跑
---
@@ -23,16 +40,16 @@
- 站点默认有 location / { root ...; index ...; },请求被当成静态文件处理,/health 找不到就 404
- 或反向代理只绑在了子路径(如 /api/ 和 /health 没被代理。
做法:让 soulapi.quwanzhi.com 的**所有路径**都走 8080,不要用 root。
做法:让站点的**所有路径**都走对应端口,不要用 root。端口:正式 8080测试 9001。
在宝塔:网站 → soulapi.quwanzhi.com → 设置 → 配置文件,找到该站点的 server { ... },按下面两种方式之一改。
在宝塔:网站 → 对应站点 → 设置 → 配置文件,找到该站点的 server { ... },按下面两种方式之一改。
### 方式 A只保留一个 location /(推荐)
把 server 里**原来的** location / { ... }(含 root、index 的那段)**删掉或注释掉**,只保留下面这一段:
把 server 里**原来的** location / { ... }(含 root、index 的那段)**删掉或注释掉**,只保留下面这一段(端口按环境改)
location / {
proxy_pass http://127.0.0.1:8080;
proxy_pass http://127.0.0.1:8080; # 正式用 8080测试用 9001
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;

View File

@@ -0,0 +1,144 @@
# Soul 创业派对 - 部署总览
> 基于当前实际部署脚本整理。最后更新2026-03-20
---
## 一、环境与域名
| 环境 | 域名 | 服务器 | 部署目录 | 说明 |
|------|------|--------|----------|------|
| **正式** | soulapi.quwanzhi.com | 43.139.27.93:22022 | /www/wwwroot/self/soul-api | Go 二进制 + 宝塔 soulApi |
| **测试** | souldev.quwanzhi.com | 43.139.27.93:22022 | /www/wwwroot/self/soul-dev | Runner/Docker/Binary 三选一 |
| **管理端** | (同服务器) | 43.139.27.93:22022 | /www/wwwroot/self/soul-admin-dev | 静态站点 dist/dist2 互换 |
---
## 二、部署脚本索引
| 项目 | 脚本 | 用途 | 命令 |
|------|------|------|------|
| **soul-api 正式** | soul-api/master.py | 交叉编译 → 打包 .env.production → 上传 → 重启 | `cd soul-api && python master.py` |
| **soul-api 测试** | soul-api/devloy.py | 三种模式runner / docker / binary | `cd soul-api && python devloy.py --mode runner` |
| **soul-admin** | soul-admin/deploy.py | pnpm build:dev → zip → dist/dist2 互换 | `cd soul-admin && python deploy.py` |
---
## 三、soul-api 正式环境master.py
### 流程
1. 本地交叉编译 Go 二进制Linux amd64
2. 打包 `.env.production``.env`,设置 `PORT=8080``WECHAT_MINI_PROGRAM_STATE=formal`
3. 上传 tar.gz 到 `/www/wwwroot/self/soul-api`
4. 解压、chmod +x重启优先宝塔 API否则 SSH nohup
### 命令
```powershell
cd soul-api
python master.py
```
### 参数
| 参数 | 说明 |
|------|------|
| --no-build | 跳过编译,使用已有 soul-api 二进制 |
| --no-env | 不打包 .env保留服务器现有配置 |
| --no-restart | 上传后不重启 |
| --restart-method auto/btapi/ssh | 重启方式,默认 auto |
### 环境变量
| 变量 | 默认 | 说明 |
|------|------|------|
| DEPLOY_HOST | 43.139.27.93 | SSH 主机 |
| DEPLOY_USER | root | SSH 用户 |
| DEPLOY_PASSWORD | (需设置) | SSH 密码 |
| DEPLOY_SSH_PORT | 22022 | SSH 端口 |
| BT_PANEL_URL | https://{host}:9988 | 宝塔面板 |
| BT_API_KEY | (脚本内默认) | 宝塔 API 密钥 |
| BT_GO_PROJECT_NAME | soulApi | 宝塔 Go 项目名 |
### Nginx
宝塔站点 soulapi.quwanzhi.com → `proxy_pass http://127.0.0.1:8080`
---
## 四、soul-api 测试环境devloy.py
### 三种模式
| 模式 | 说明 | Nginx | 推荐 |
|------|------|-------|------|
| **runner** | 容器内红蓝切换,固定 9001 | proxy_pass 127.0.0.1:9001 | ✅ |
| **docker** | 宿主机蓝绿 8081/8082 | 脚本自动切换 proxy_pass | 需改 Nginx |
| **binary** | Go 二进制 + 宝塔 soulDev | 8080 | 与正式类似 |
### Runner 模式(推荐)
**首次**(服务器执行):
```bash
cd soul-api
bash deploy/runner-init.sh
```
**部署**(本地执行):
```powershell
cd soul-api
python devloy.py --mode runner
```
- 打包Go 二进制 + .env.development + certsPORT=18081REDIS 容器内
- 上传到容器内 /app红蓝目录切换Nginx 固定 9001
### 环境变量(测试)
| 变量 | 默认 | 说明 |
|------|------|------|
| DEPLOY_HOST | 43.139.27.93 | 同正式 |
| DEPLOY_DOCKER_PATH | /www/wwwroot/self/soul-dev | 测试部署目录 |
| DEPLOY_NGINX_CONF | docker 模式必填) | 如 /www/server/panel/vhost/nginx/souldev.quwanzhi.com.conf |
---
## 五、soul-admin 部署
### 流程
1. 本地 `pnpm run build:dev`.env.development
2. 打包 dist 为 zip
3. 上传到 /www/wwwroot/self/soul-admin-dev
4. 解压到 dist2与 dist 互换,实现无缝切换
### 命令
```powershell
cd soul-admin
python deploy.py
```
### 环境变量
| 变量 | 默认 | 说明 |
|------|------|------|
| DEPLOY_HOST | 43.139.27.93 | 同 soul-api |
| DEPLOY_BASE_PATH | /www/wwwroot/self/soul-admin-dev | 站点根目录 |
| DEPLOY_WWW_USER | www:www | chown 属主 |
---
## 六、相关文档
| 文档 | 用途 |
|------|------|
| [宝塔反向代理说明](宝塔反向代理说明.md) | 域名 404 排查、Nginx 配置 |
| [宝塔-Docker首次配置指南](宝塔-Docker首次配置指南.md) | 测试环境 Runner 首次配置 |
| [DOCKER部署说明](DOCKER部署说明.md) | Docker 构建、Runner 模式 |
| [提现功能完整技术文档](提现功能完整技术文档.md) | 微信支付商家转账 API |
| [订阅消息](订阅消息.md) | 提现成功订阅消息PowerWeChat |
| [商家转账](商家转账.md) | PowerWeChat 商家转账示例 |

View File

@@ -1,6 +1,8 @@
# Soul 创业派对 - 开发文档索引
# Soul 创业派对 - 开发文档
> 小橙整理 · 2026-02-26
> 入口索引:[**索引.md**](索引.md) — 按目录与文件标注用途,便于快速定位
---
## 当前项目架构
@@ -13,83 +15,41 @@
---
## 文档导航
## 文档导航(按目录)
### 需求与项目管理
| 文档 | 说明 |
| 目录 | 说明 |
|------|------|
| [1、需求/以界面定需求](1、需求/以界面定需求.md) | **界面级需求基准**以界面定需求小程序与管理端界面清单、主要接口、业务逻辑对齐三端路由、VIP 资料以用户资料为准等) |
| [1、需求/需求汇总](1、需求/需求汇总.md) | 需求清单、业务需求 |
| [10、项目管理/项目落地推进表](10、项目管理/项目落地推进表.md) | 里程碑、永平落地 |
| [10、项目管理/运营与变更](10、项目管理/运营与变更.md) | 近期讨论、变更记录 |
| [迁移完成度与待办清单](迁移完成度与待办清单.md) | 迁移完成度、剩余待办、搁置项 |
| [代付-业务线框图](代付-业务线框图.md) | 代付主流程(发起人支付、好友领取) |
| [代付-简化流程设计](代付-简化流程设计.md) | 代付页面态与操作 |
| [代付-需求分析与待完善](代付-需求分析与待完善.md) | 已实现项与待确认 |
| [新版与稳定版-管理端功能样式差异分析](新版与稳定版-管理端功能样式差异分析.md) | 管理端两版功能/样式对比、文章内容弹窗差异 |
| [功能测试流程](../scripts/test/功能测试流程.md) | 功能测试流程、测试报告模板、自动化用例 |
### 架构与规范
| 文档 | 说明 |
|------|------|
| [2、架构/系统与技术](2、架构/系统与技术.md) | 系统与技术栈 |
| [2、架构/soul-api技术栈](2、架构/soul-api技术栈.md) | soul-api Go 技术栈Gin、GORM、PowerWeChat、JWT |
| [2、架构/链路与变现](2、架构/链路与变现.md) | 业务链路 |
| [4、前端/前端开发规范](4、前端/前端开发规范.md) | 前端规范 |
| [6、后端/后端开发规范](6、后端/后端开发规范.md) | 后端规范 |
### 接口与部署
| 文档 | 说明 |
|------|------|
| [5、接口/API接口完整文档](5、接口/API接口完整文档.md) | API 完整文档 |
| [Cunkebao接口文档](Cunkebao接口文档/README.md) | **存客宝Cunkebao** 前端项目接口清单、入参出参结构 |
| [6、后端/管理端鉴权设计](6、后端/管理端鉴权设计.md) | soul-api 管理端 JWT 鉴权、路由分层 |
| [8、部署/部署总览](8、部署/部署总览.md) | 部署入口、分销与流程 |
| [8、部署/宝塔反向代理说明](8、部署/宝塔反向代理说明.md) | soul-api 域名 404 排查、Nginx 反向代理配置 |
| [8、部署/DOCKER部署说明](8、部署/DOCKER部署说明.md) | soul-api Docker 构建与生产环境部署 |
| [8、部署/提现功能完整技术文档](8、部署/提现功能完整技术文档.md) | 微信支付商家转账到零钱 API 集成 |
| [8、部署/分销提现流程图](8、部署/分销提现流程图.md) | 提现业务流程图 |
| [8、部署/订阅消息](8、部署/订阅消息.md) | 提现成功订阅消息PowerWeChat |
| [8、部署/商家转账](8、部署/商家转账.md) | PowerWeChat 商家转账示例 |
### 临时需求池
| 文档 | 说明 |
|------|------|
| 临时需求池/需求分析-产品经理视角 | 需求分析 |
| 临时需求池/分润需求-技术分析 | 会员分润差异化技术方案 |
| [1、需求/](1、需求/) | 需求基准、主需求文件(按日期命名)、归档 |
| [6、后端/](6、后端/) | 鉴权设计、接口补全、迁移对比 |
| [8、部署/](8、部署/) | Docker、宝塔、提现、订阅消息 |
| [10、项目管理/](10、项目管理/) | 里程碑、运营与变更 |
| [Cunkebao接口文档/](Cunkebao接口文档/) | 存客宝前端项目接口清单 |
---
## 已移除文档2026-02-26
## 常用文档
- Prisma ORM 迁移相关3 份)— 项目已迁至 Go/GORM
- Next.js 宝塔部署方案、Standalone 模式 — next-project 仅预览
- 拆解计划 — 已完成soul-admin 与 soul-api 已落地
- 近3天更新文档5 份)— 已合并至 运营与变更 第六部分
- 8、部署 历史修复说明(约 35 份)— 一次性修复记录,已无参考价值
| 文档 | 用途 |
|------|------|
| [1、需求/以界面定需求](1、需求/以界面定需求.md) | **界面级需求基准**:小程序/管理端界面清单、业务逻辑对齐 |
| [1、需求/索引](1、需求/索引.md) | 主需求 = 日期最新的需求文件 |
| [10、项目管理/项目落地推进表](10、项目管理/项目落地推进表.md) | 里程碑、永平落地 |
| [10、项目管理/运营与变更](10、项目管理/运营与变更.md) | 近期讨论、变更记录 |
| [8、部署/部署总览](8、部署/部署总览.md) | **部署入口**:正式/测试/管理端脚本与命令 |
| [8、部署/提现功能完整技术文档](8、部署/提现功能完整技术文档.md) | 微信支付商家转账 API 集成 |
| [6、后端/管理端鉴权设计](6、后端/管理端鉴权设计.md) | soul-api 管理端 JWT 鉴权 |
| [scripts/test/功能测试流程](../scripts/test/功能测试流程.md) | 功能测试流程、自动化用例 |
## 已移除文件2026-02-27 橙子清理)
---
- `.DS_Store`4 处)— macOS 系统缓存
- `1、需求/修改/1.doc` — 空文件
- `SKILL.md`(根目录)— 技术栈已过期(写的是 Next.js以 README 与 .cursor/skills 为准
- `小程序管理/scripts/__pycache__/*.pyc` — Python 缓存
- `小程序管理/scripts/reports/*.json`4 份)— 脚本生成的一次性报告
## 已移除/归档(历史记录)
## 已移除文件2026-03-10 橙子清理)
<details>
<summary>点击展开</summary>
- `api_v1.md` — 存客宝对外获客 API 文档,项目已明确搁置对接,文档无继续维护价值
- `小程序功能与管理端配置补齐分析.md` — 2026-02-25 一次性补齐分析,全部项目已标注 ✅ 已完成,分析目的达成
- 2026-03-20需求汇总、三端需求整理 → 合并至 2026-03-20-需求.md链接人与事等 → archive/
- 2026-03-17代付逻辑旧文档 → 已合并至代付-业务线框图等
- 2026-03-10api_v1、小程序功能补齐分析
- 2026-02-26Prisma 迁移、Next 部署、拆解计划等
## 已移除文件2026-03-17 橙子清理)
- `代付功能-美团式方案与场景清单.md` — 描述「好友代付」旧逻辑,已由「发起人支付、好友领取」替代
- `找朋友代付-流程与配置.md` — 描述「好友帮他付款」旧流程,已过时
- `代付逻辑-正确需求与改造方案.md` — 需求已落地,内容已合并至 代付-业务线框图、代付-简化流程设计
- `代付逻辑-开发排期与任务清单.md` — 排期已执行完毕
- `代付逻辑-开发任务指派.md` — 任务指派已执行完毕
- `代付逻辑-设计评审与跑通验证.md` — 评审结论已落地
</details>

View File

@@ -1,163 +0,0 @@
# Config 接口优化分析
## 一、现状
### 1.1 当前 config 接口
- **路径**`GET /api/miniprogram/config`
- **Handler**`GetPublicDBConfig`soul-api/internal/handler/db.go
- **缓存**Redis 10min配置变更时 `InvalidateConfig()` 失效
### 1.2 返回内容buildMiniprogramConfig
| 字段 | 来源 | 小程序使用场景 | 使用频率 |
|-----|------|----------------|----------|
| **prices** | chapter_config | 阅读页解锁价格、chapterAccessManager | 中 |
| **features** | chapter_config + feature_config | 首页/目录/我的/TabBarsearchEnabled、matchEnabled、referralEnabled | 高 |
| **mpConfig** | mp_config | auditMode、appId、mchId、withdrawSubscribeTmplId、supportWechat | 高auditMode/ 低(支付) |
| **linkTags** | link_tags 表 | 阅读页 onLinkTagTap、contentParser | 低(仅阅读页) |
| **linkedMiniprograms** | system_config | 阅读页跳转关联小程序 | 低(仅阅读页) |
| **userDiscount** | referral_config | 阅读页优惠价展示 | 低 |
| **configs** | 原始配置 | 备用格式 | 低 |
### 1.3 管理端与审核模式
- 管理端 SettingsPage 通过 `/api/admin/settings` 读写 `mp_config`,其中 `auditMode` 由管理端开关控制
- 审核模式开启时小程序隐藏支付、提现、VIP 等 UI
- 小程序从后台切回时需刷新 auditModeonShow 节流 30s
---
## 二、优化目标
1. **审核模式独立**:管理端控制,需单独接口,不影响线上 config
2. **config 保留**:向后兼容,不破坏现有小程序
3. **拆分按需加载**:提升首屏/预览速度,减少单次请求体积
4. **废弃标记**:对后续计划废弃的接口在代码中标记
---
## 三、拆分方案
### 3.1 新增接口
| 接口 | 用途 | 返回内容 | 缓存 | 调用时机 |
|-----|------|----------|------|----------|
| **GET /api/miniprogram/config/audit-mode** | 审核模式(独立) | `{ auditMode: boolean }` | 1min可更短 | onShow、阅读页 onLoad、支付前 |
| **GET /api/miniprogram/config/core** | 核心配置(精简) | prices、features、userDiscount | 10min | 首屏、Tab 切换、getConfig 主入口 |
| **GET /api/miniprogram/config/read-extras** | 阅读页扩展 | linkTags、linkedMiniprograms | 10min | 阅读页 onLoad 懒加载 |
### 3.2 保留接口(加废弃标记)
| 接口 | 标记 | 说明 |
|-----|------|------|
| **GET /api/miniprogram/config** | `@deprecated` | 保留至小程序全部迁移到 core + audit-mode + read-extras 后废弃 |
### 3.3 数据流示意
```
首屏 / Tab 切换
→ app.getConfig() 优先请求 /config/core轻量
→ 并行或单独请求 /config/audit-mode从后台切回时必拉
阅读页 onLoad
→ 若已有 config 缓存,用 linkTags/linkedMiniprograms
→ 若无,懒加载 /config/read-extras
支付 / 提现前
→ 拉取 audit-mode 确认非审核态
→ mpConfigappId、mchId 等)可从 core 或保留在 config 中,按需
```
---
## 四、实施步骤建议
### 阶段一:新增接口(不破坏现有)
1. **后端**:新增 `GetAuditMode``GetCoreConfig``GetReadExtras` 三个 handler
2. **缓存**audit-mode 单独 key、短 TTLcore、read-extras 复用或新建 key
3. **管理端**:保存 mp_config 时,除 `InvalidateConfig()` 外,增加 `InvalidateAuditMode()`(若 audit-mode 单独缓存)
### 阶段二:小程序迁移
1. **app.getConfig()**:改为请求 `/config/core`,内部合并 audit-mode可并行请求
2. **app.getAuditMode()**:新增,单独拉取 audit-mode用于 onShow 刷新
3. **阅读页**:优先用 `app.globalData.linkTagsConfig`,无则请求 `/config/read-extras`
### 阶段三:废弃标记
1. **db.go**`GetPublicDBConfig` 注释加 `@deprecated 计划迁移至 /config/core + /config/audit-mode + /config/read-extras`
2. **router.go**`miniprogram.GET("/config", ...)` 上方加废弃说明
3. **小程序**:保留对 `/config` 的兼容逻辑,逐步移除
---
## 五、接口详细设计
### 5.1 GET /api/miniprogram/config/audit-mode
**响应**
```json
{ "auditMode": false }
```
**缓存**`soul:config:audit-mode`TTL 60s审核开关后需较快生效
**失效**:管理端保存 mp_config 时调用 `InvalidateAuditMode()`
### 5.2 GET /api/miniprogram/config/core
**响应**
```json
{
"success": true,
"prices": { "section": 1, "fullbook": 9.9 },
"features": { "matchEnabled": true, "referralEnabled": true, "searchEnabled": true },
"userDiscount": 5
}
```
**缓存**`soul:config:core`TTL 10min与现有 config 变更联动
### 5.3 GET /api/miniprogram/config/read-extras
**响应**
```json
{
"linkTags": [...],
"linkedMiniprograms": [...]
}
```
**缓存**`soul:config:read-extras`TTL 10minlink_tags / linked_miniprograms 变更时失效
---
## 六、性能与兼容
| 指标 | 当前 config | 拆分后(首屏) |
|------|-------------|----------------|
| 首请求体量 | 全量(含 linkTags、linkedMiniprograms、configs | core + audit-mode体积约 1/3 |
| 阅读页 | 依赖全量 config | 无 linkTags 时再请求 read-extras |
| 审核模式刷新 | 拉全量 config | 仅拉 audit-mode |
| 兼容性 | - | 保留 /config@deprecated |
---
## 七、废弃标记清单(代码位置)
| 文件 | 位置 | 状态 |
|------|------|------|
| soul-api/internal/handler/db.go | GetPublicDBConfig 函数注释 | ✅ 已加 Deprecated |
| soul-api/internal/router/router.go | miniprogram.GET("/config", ...) 上方 | ✅ 已加 Deprecated |
| miniprogram/app.js | getConfig 已迁移至 core+audit-mode | ✅ 已实现 |
---
## 八、总结
- **审核模式**:独立接口 `/config/audit-mode`,管理端开关后快速生效,不依赖全量 config
- **config 保留**:继续可用,加废弃标记,便于后续统一下线
- **拆分策略**core首屏必需、audit-mode独立、read-extras阅读页懒加载
- **迁移节奏**:先上新接口,小程序逐步切到 core + audit-mode + read-extras最后废弃 /config

View File

@@ -1,296 +0,0 @@
# 代付分享 - 业务线框图ASCII
> 改造后发起人支付好友免费领取。更新日期2026-03-17橙子整理
---
## 〇、业务说明(与卡券系统类比)
代付与**卡券系统**类似:
| 环节 | 代付 | 卡券类比 |
|------|------|----------|
| 购买 | 用户输入数量,按文章单价计算总金额,发起微信支付 | 购买多张卡券 |
| 录入 | 支付成功后,在卡片系统录入代付记录 | 卡券入库 |
| 分享 | 用户分享链接给其他人 | 转赠/发放卡券 |
| 领取 | 他人进入页面后领取文章(当前:点击「领取并阅读」) | 核销/兑换卡券 |
| 权益 | 领取后相当于已购买该文章,可正常阅读 | 获得权益 |
| 分佣 | **领取不参与分佣**,发起人支付时已完成分销 | 分佣在购买端 |
| 记录 | **发起人可查看领取记录**:谁领取了、何时领取 | 核销记录 |
---
## 一、主流程总览
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ 发起人(购买者) │
└─────────────────────────────────────────────────────────────────────────────┘
┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 阅读章节 │────>│ 点击代付分享 │────>│ 跳转detail │────>│ 输入份数 │
└──────────┘ └──────────────┘ │ sectionId │ │ 去支付→create│
└──────────────┘ └──────┬───────┘
v
┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 分享链接 │<────│ 支付成功 │<────│ 微信支付 │<────│ initiator-pay│
│ 给好友 │ └──────────────┘ └──────┬───────┘ └──────────────┘
└────┬─────┘ │
│ 分享
v
┌─────────────────────────────────────────────────────────────────────────────┐
│ 好友(领取者) │
└─────────────────────────────────────────────────────────────────────────────┘
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 收到分享链接 │────>│ 打开detail │────>│ 已登录? │
└──────────────┘ └──────────────┘ └──────┬───────┘
┌──────────────────────┼──────────────────────┐
│ 否 │ 是 │
v v │
┌──────────────┐ ┌──────────────┐ │
│ 弹窗登录 │────────>│ 领取并阅读 │<──────────────┘
└──────────────┘ └──────┬───────┘
v
┌──────────────┐ ┌──────────────┐
│ 调用redeem │────>│ 跳转read阅读 │
└──────────────┘ └──────────────┘
```
---
## 二、发起人流程(详细)
```
┌─ read 页 ─────────────────────────────────────────────────────────────────┐
│ │
│ 阅读章节 ──> 代付分享入口 ──> 直接跳转 gift-pay/detail?sectionId=xxx │
│ │
└────────────────────────────────────────┬───────────────────────────────────┘
v
┌─ API create ──────────────────────────────────────────────────────────────┐
│ │
│ 校验登录/章节 ──> amount=单价×quantity ──> 创建 gift_pay_request │
│ │ │
│ v │
│ status=pending_pay ──> 返回 requestSn, path │
│ │
└────────────────────────────────────────┬───────────────────────────────────┘
v
┌─ gift-pay/detail 页 ──────────────────────────────────────────────────────┐
│ │
│ 创建态:输入份数 ──> 去支付 ──> create(quantity) ──> initiator-pay │
│ │ │
│ v │
│ 微信支付 ──> 支付成功 ──> 显示「发送给好友」 │
│ │
│ 发起人视角:隐藏发起人信息卡片、安全徽章、右侧箭头 │
│ 创建态提示:创建后无法退款 │
│ │
└────────────────────────────────────────────────────────────────────────────┘
```
---
## 三、好友领取流程(详细)
```
┌─ 进入详情页 ───────────────────────────────────────────────────────────────┐
│ │
│ 打开链接/扫码 ──> GET /gift-pay/detail ──> isInitiator? │
│ │ │
│ ┌─────────────────────────┼─────────────────────────┐ │
│ │ 是 │ 否 │ │
│ v v │ │
│ 发起人:显示支付/分享 好友:显示「领取并阅读」 │
│ │
└────────────────────────────────────────┬───────────────────────────────────┘
v
┌─ 领取流程 ─────────────────────────────────────────────────────────────────┐
│ │
│ 已登录? │
│ │ │
│ ├── 否 ──> 弹窗:微信/手机号登录 ──> 登录成功 ──┐ │
│ │ │ │
│ └── 是 ──────────────────────────────────────────┼──> 点击「领取并阅读」 │
│ │ │
│ v │
│ POST /gift-pay/redeem
│ │ │
│ v │
│ 创建好友订单 │
│ section+paid │
│ │ │
│ v │
│ redeemed_count+1 │
│ │ │
│ v │
│ 跳转 read 页 │
│ │
│ 单页模式 ──> 提示「前往小程序」 │
│ │
└────────────────────────────────────────────────────────────────────────────┘
```
---
## 四、状态流转
```
create 创建
┌─────────────> ┌──────────────┐
│ │ pending_pay │
│ │ 待发起人支付 │
│ └──────┬───────┘
│ │
│ │ 发起人支付成功
│ v
│ ┌──────────────┐
│ │ paid │
│ │ 已支付 │
│ └──────┬───────┘
│ │
│ │ 好友领取完毕或过期
│ v
│ ┌──────────────┐
│ │ [结束] │
│ └──────────────┘
│ 24h 过期
└──────────────> ┌──────────────┐
│ expired │
│ 已过期 │
└──────┬───────┘
v
┌──────────────┐
│ [结束] │
└──────────────┘
```
---
## 五、接口调用时序
```
发起人 小程序 后端 微信支付
│ │ │ │
│ 1. 创建代付请求
│ │ │ │
│ 输入份数确认 │ │ │
│────────────>│ │ │
│ │ POST create │ │
│ │────────────>│ │
│ │ │ 创建gift_pay_request
│ │ │ │
│ │ requestSn │ │
│ │<────────────│ │
│ 跳转detail │ │ │
│<────────────│ │ │
│ │ │ │
│ 2. 发起人支付
│ │ │ │
│ 点击立即支付 │ │ │
│────────────>│ │ │
│ │ POST initiator-pay │
│ │────────────>│ │
│ │ │ 统一下单 │
│ │ │────────────>│
│ │ │ prepay_id │
│ │ │<────────────│
│ │ payParams │ │
│ │<────────────│ │
│ │ │ │
│ │ wx.requestPayment │
│ │─────────────────────────>│
│ 支付成功 │<─────────────────────────│
│<────────────│ │ │
│ │ │ PayNotify │
│ │ │<────────────│
│ │ │ status=paid │
│ │ │ │
│ 3. 好友领取
│ │ │ │
│ 分享链接 │ │ │
│────────────>│ │ │
│ │ GET detail │ │
│ │────────────>│ │
│ │ action=redeem │
│ │<────────────│ │
│ │ │ │
│ 点击领取 │ │ │
│────────────>│ │ │
│ │ POST redeem │ │
│ │────────────>│ │
│ │ │ 创建好友订单 │
│ │ sectionId │ │
│ │<────────────│ │
│ 跳转read │ │ │
│<────────────│ │ │
│ │ │ │
```
---
## 六、角色与页面映射
| 角色 | 入口 | 页面 | 主要操作 |
|------|------|------|----------|
| 发起人 | read 页「代付分享」 | gift-pay/detail | 创建态输入份数→去支付 → 分享态发送给好友 |
| 发起人 | 我的代付列表 | gift-pay/redemption-detail | 查看文章信息、领取人明细、剩余份数 |
| 好友 | 分享链接/扫码 | gift-pay/detail | 领取并阅读 |
| 好友(单页) | 朋友圈分享 | gift-pay/detail | 引导「前往小程序」 |
---
## 七、关键业务规则
| 规则 | 说明 |
|------|------|
| 份数 | 前端不限制,发起支付时校验正整数;后端校验 ≥1 |
| 金额 | amount = 单价 × quantity支持推荐人折扣 |
| 过期 | 24 小时未支付则 expired |
| 领取 | 好友需登录,每人限领 1 份 |
| 领取不分佣 | 分佣在发起人支付时完成,好友领取不触发分销 |
| 领取记录 | 发起人可查看该代付的领取人列表my-requests 已返回 redeemList |
| attach | 微信支付 attach 最大 128 字节,发起人付用 `{"ip":1}` |
---
## 八、领取记录与列表(发起人视角)
```
┌─ 我发起的代付 ─────────────────────────────────────────────────────────────┐
│ │
│ 代付列表gift-pay/list
│ │ 待支付:仅显示「取消」;已支付:仅显示「分享」 │
│ │ 取消后自动从列表移除my-requests 不返回 status=cancelled 的项 │
│ │ │
│ v 点击卡片 │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 领取详情页gift-pay/redemption-detail │ │
│ │ ├─ 文章信息:标题、内容预览、总份数、剩余份数 │ │
│ │ ├─ 领取人明细:头像、昵称、领取时间 │ │
│ │ └─ 操作:去阅读、去分享/去支付 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ 数据来源detail 接口返回 redeemList含 avatar、nickname、redeemAt
│ │
└────────────────────────────────────────────────────────────────────────────┘
```
## 九、UI 与体验规则
| 规则 | 说明 |
|------|------|
| 发起人视角 | 发起人信息卡片、安全徽章、右侧箭头在 detail 页不展示 |
| 创建态提示 | 创建后无法退款 |
| 分享带 ref | 分享 path 含 `&ref=发起人推荐码`,用于拉新 |

View File

@@ -1,157 +0,0 @@
# 代付分享 - 简化流程设计
> 目标更简单、简洁、方便。领取时未登录先弹窗登录。更新日期2026-03-17橙子整理
---
## 一、简化后的主流程
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ 发起人 │
└─────────────────────────────────────────────────────────────────────────────┘
read 页「代付分享」
v
gift-pay/detail?sectionId=xxx ← 无 requestSn进入「创建态」
├─ 展示:文章标题、单价、数量输入框(无上限,支付时校验正整数)
├─ 点击「去支付」
│ │
│ v
│ create(quantity) + initiator-pay连续调用用户无感知
│ │
│ v
│ 微信支付
v
支付成功 → 刷新为「分享态」
├─ 显示「分享给好友」按钮
└─ 分享 pathdetail?requestSn=xxx&ref=发起人推荐码
┌─────────────────────────────────────────────────────────────────────────────┐
│ 好友 │
└─────────────────────────────────────────────────────────────────────────────┘
打开链接 detail?requestSn=xxx&ref=xxx
v
展示:发起人头像、昵称、文章信息
v
点击「领取」
├─ 未登录 ──> 弹窗「请先登录」──> 登录成功 ──> 自动继续领取
├─ 未领取 ──> 领取成功 ──> 跳转 read 阅读
└─ 已领取 ──> 提示「已领取」──> 自动跳转 read或显示「去阅读」
```
---
## 二、页面状态与路由
### gift-pay/detail统一承载
| 入参 | 身份 | 页面态 | 主要操作 |
|------|------|--------|----------|
| sectionId无 requestSn | 发起人 | 创建态 | 输入数量 → 去支付(创建后无法退款) |
| requestSnisInitiatorstatus=paid | 发起人 | 分享态 | 分享给好友 |
| requestSn!isInitiator未领取 | 好友 | 领取态 | 领取(未登录先弹窗) |
| requestSn!isInitiator已领取 | 好友 | 已领态 | 去阅读 |
### gift-pay/redemption-detail领取详情新建
| 入口 | 展示内容 |
|------|----------|
| 列表点击「我发起的代付」卡片 | 文章信息、领取人明细(头像、昵称、领取时间)、剩余份数 |
---
## 三、关键简化点
### 3.1 入口统一,一步到位
- **旧**read 弹窗输入份数 → 确认 → create → 跳转 detail → 支付
- **新**read 点击「代付分享」→ 直接跳转 detail带 sectionId→ 在 detail 输入数量并支付
减少一次弹窗、一次确认,流程更顺。
### 3.2 创建+支付一气呵成
- 用户点击「去支付」→ 后端先 create(quantity),再 initiator-pay
- 前端可封装为一次「去支付」操作create 成功拿到 requestSn 后,立即调 initiator-pay用户只看到一次支付弹窗
### 3.3 领取前登录(已实现,需确认)
- 点击「领取」时若无 userId → `showLoginModal = true`
- 登录成功后 `handleWechatLogin` 内调用 `_doRedeem()`
- 弹窗文案:「登录后可免费领取并阅读」
### 3.4 已领取自动解锁
- detail 接口增加:好友已领取时返回 `alreadyRedeemed: true``sectionId``sectionMid`
- 前端:展示「已领取」+ 自动跳转 read或提供「去阅读」按钮
### 3.5 分享带 ref
- 分享 path`/pages/gift-pay/detail?requestSn=${requestSn}&ref=${发起人referralCode}`
---
## 四、接口与前端改动清单(已完成)
| 序号 | 改动 | 状态 |
|------|------|------|
| 1 | read 页「代付分享」 | ✅ 直接跳转 detail?sectionId=xxx |
| 2 | detail 支持 sectionId 入参 | ✅ |
| 3 | detail 创建态 UI | ✅ 数量输入框 +「去支付」+「创建后无法退款」 |
| 4 | 去支付逻辑 | ✅ create(quantity) → initiator-pay |
| 5 | GiftPayDetail | ✅ 支持 sectionId已领取返回 action=alreadyRedeemedredeemList 含 avatar |
| 6 | 分享 path | ✅ 含 `&ref=${发起人referralCode}` |
| 7 | 已领取态 | ✅ 按钮「已领取,去阅读」 |
| 8 | 领取详情页 | ✅ redemption-detail文章信息、领取人明细、剩余份数 |
| 9 | 列表 | ✅ 点击→领取详情;待支付仅取消、已支付仅分享;取消后自动删除 |
| 10 | 发起人视角 | ✅ 隐藏发起人信息、安全徽章、右侧箭头 |
| 11 | 份数 | ✅ 前端不限制,支付时校验正整数;后端校验 ≥1 |
---
## 五、登录弹窗流程(已有,保持不变)
```
好友点击「领取」
v
userId 存在?
├─ 是 ──> 直接 _doRedeem()
└─ 否 ──> setData({ showLoginModal: true })
v
用户点击「微信快捷登录」/ 手机号登录
v
登录成功 ──> closeLoginModal ──> _doRedeem()
```
---
## 六、read 页改动(极简)
**旧**
```javascript
showGiftShareModal() 弹窗输入份数 confirmGiftShare() create 跳转 detail
```
**新**
```javascript
showGiftShareModal() 直接 wx.navigateTo(`/pages/gift-pay/detail?sectionId=${sectionId}`)
```
移除:`showGiftModal``giftQuantity``onGiftQuantityInput``confirmGiftShare`、弹窗 wxml。

View File

@@ -1,91 +0,0 @@
# 代付分享 - 需求分析与待完善
> 基于用户描述整理,含 ref=发起人推荐码 说明。更新日期2026-03-17橙子整理
---
## 一、您描述的逻辑梳理
### 1. 流程总览
```
read 页「代付分享」
v
代付页面gift-pay/detail 或新建入口页)
├─ 输入发放数量
├─ 支付(单价×数量)
v
支付完成 → 点击「分享给好友」
v
分享链接:路径 + 代付码(requestSn) + 推荐码(ref=发起人referralCode)
v
好友打开领取页
├─ 变更推荐人逻辑ref 绑定到发起人,给发起人拉新)
├─ 根据代付码显示:发起人头像、昵称、文章信息
v
点击「领取」
├─ 未领取 → 领取 → 创建订单(不参与分佣)→ 解锁文章
└─ 已领取 → 提示「已领取」→ 自动解锁文章(跳转 read
```
### 2. ref 的含义
| 字段 | 含义 | 用途 |
|------|------|------|
| ref | 发起人的推荐码 | 好友从带 ref 的链接进入时,绑定为发起人推荐的用户,给发起人拉新 |
---
## 二、与当前实现的差异(已对齐)
| 环节 | 当前实现 | 状态 |
|------|----------|------|
| 输入数量 | detail 页输入数量 → 去支付create + initiator-pay | ✅ 已实现 |
| 分享链接 | `detail?requestSn=xxx&ref=发起人推荐码` | ✅ 已实现 |
| 已领取处理 | action=alreadyRedeemed按钮「已领取去阅读」 | ✅ 已实现 |
| 文章解锁 | 依赖 orders 表,领取订单不参与分佣 | ✅ 已实现 |
| 领取记录 | 领取详情页展示头像、昵称、领取时间 | ✅ 已实现 |
---
## 三、已实现项
| 项 | 说明 |
|------|------|
| 输入数量 | detail 页输入create + initiator-pay 连续调用 |
| 分享带 ref | 使用 `app.getMyReferralCode()` |
| 已领取态 | 后端返回 action=alreadyRedeemed前端「已领取去阅读」 |
| 领取详情页 | redemption-detail文章信息、领取人明细头像、昵称、剩余份数 |
| 列表逻辑 | 待支付仅取消、已支付仅分享;取消后自动删除 |
| 发起人视角 | 隐藏发起人信息、安全徽章、右侧箭头 |
| 创建态提示 | 创建后无法退款 |
| 份数校验 | 前端支付时校验正整数;后端校验 ≥1 |
| 退款后禁用 | 订单退款后,同步将 gift_pay_requests 标记为 refunded小程序端不可再分享/领取,展示「已退款」 | ✅ 已实现2026-03-18 |
---
## 四、待确认
| 项 | 说明 |
|------|------|
| ref 解析 | app 对分享 path 中 ref 的解析,与 bindReferralCode 规则是否一致 |
---
## 五、状态机补充(用于验收)
| gift_pay_requests.status | 含义 | 发起人可操作 | 好友可操作 |
|---|---|---|---|
| pending_pay | 待发起人支付 | 支付 / 取消 | 等待 |
| paid | 已支付待领取 | 分享 | 领取/已领取 |
| refunded | 已退款 | 不可分享(仅展示已退款) | 不可领取 |
| cancelled | 已取消 | 不可操作 | 不可操作 |
| expired | 已过期 | 不可操作 | 不可操作 |

View File

@@ -1,63 +0,0 @@
# 代付逻辑改造 - 检查与修复记录
> 变更完成检查。更新日期2026-03-17
---
## 一、流程漏洞(已修复)
### 1. 发起人「已拥有」校验错误
**问题**:新逻辑为「发起人帮别人买」,发起人自己可已拥有该章节/全书/VIP但后端仍校验「您已拥有该章节」并拒绝创建。
**修复**:移除 GiftPayCreate 中的 section/fullbook/vip 的「发起人已拥有」校验。
**文件**`soul-api/internal/handler/gift_pay.go`
### 2. gift-pay/detail 缺少 stopPropagation
**问题**:登录弹窗使用 `catchtap="stopPropagation"`,但 detail.js 未定义该方法,可能导致点击弹窗内部时冒泡异常。
**修复**:在 detail.js 中添加 `stopPropagation() {}`
**文件**`miniprogram/pages/gift-pay/detail.js`
---
## 二、样式修复(已修复)
### 1. 登录弹窗 modal-close 定位
**问题**modal-close 使用 `position: absolute`,父级缺少 `position: relative`,关闭按钮可能定位异常。
**修复**:为 `.modal-content.login-modal` 添加 `position: relative`
**文件**`miniprogram/pages/gift-pay/detail.wxss`
### 2. redeem 按钮图标颜色
**问题**redeem-btn 的 btn-icon 未应用 `filter: brightness(0)`,图标颜色可能与 pay/share 按钮不一致。
**修复**:将 redeem-btn 的 btn-icon 加入 filter 规则。
**文件**`miniprogram/pages/gift-pay/detail.wxss`
---
## 三、已确认无问题的项
| 项 | 说明 |
|------|------|
| read 页 gift modal | modal-header、modal-title 等样式在 read.wxss 中已有 |
| onGiftQuantityInput | 空输入、0、超范围均已处理 |
| redeem 跳转 | sectionMid 为 0 时用 id逻辑正确 |
| 后端 detail 错误处理 | cancelled/expired 返回 error前端显示 empty |
| 单页模式 footer | footer-summary 与 footer-tip-single 并排,可接受 |
---
## 四、建议联调验证
1. **发起人已拥有章节**:发起人已购买某章节 → 点击代付分享 → 应能正常创建并支付
2. **登录弹窗**:好友未登录点击领取 → 弹窗打开 → 点击弹窗内部不关闭 → 点击遮罩关闭
3. **redeem 按钮**:图标与 pay 按钮风格一致

View File

@@ -1,121 +0,0 @@
# 存客宝对接逻辑图
## 一、概念区分
| 字段 | 含义 | 来源 | 用途 |
|------|------|------|------|
| **token** | 32 位唯一标识 | 我们 `genPersonToken()` 生成 | 存在文章 `data-id`,小程序传 `targetUserId` |
| **ckb_api_key** | 存客宝计划级密钥 | 存客宝 `plan/detail` 接口返回 | 调 scenarios 内部 API 时作为 `apiKey` 鉴权 |
**token ≠ apiKey**。scenarios 内部 API 需要的是 `ckb_api_key`,不是 token。
---
## 二、Person 创建流程(含存客宝计划)
```
管理端添加 / 文章 @新人物 保存
┌─────────────────────────────────────────────────────────────┐
│ DBPersonSave / createPersonMinimal │
├─────────────────────────────────────────────────────────────┤
│ 1. genPersonToken() → 生成 token32 位) │
│ 2. ckbOpenGetToken() → 获取开放 API JWT │
│ 3. ckbOpenCreatePlan(JWT, payload) → 创建计划,返回 planId │
│ 4. ckbOpenGetPlanDetail(JWT, planId) → 获取 plan 的 apiKey │
│ 5. 落库 Person: │
│ - token = 我们生成的 token │
│ - ckb_api_key = 存客宝返回的 apiKey │
│ - ckb_plan_id = planId │
└─────────────────────────────────────────────────────────────┘
```
---
## 三、文章 @ 到留资提交流程
```
文章 content 解析
<span data-type="mention" data-id="TOKEN" data-label="远志">@远志</span>
小程序 contentParser → seg.userId = TOKEN
用户点击 @远志 → onMentionTap → targetUserId = TOKEN
POST /api/miniprogram/ckb/lead
{ targetUserId: TOKEN, phone, wechatId, ... }
┌─────────────────────────────────────────────────────────────┐
│ CKBLead │
├─────────────────────────────────────────────────────────────┤
│ 1. targetUserId 有值 → 用 token 查 Person │
│ 2. leadKey = Person.CkbApiKey存客宝计划级 apiKey
│ 3. 若 CkbApiKey 为空 → 报错,不 fallback .env │
│ 4. 调 scenarios: GET ckbAPIURL?apiKey=leadKey&...&sign=... │
└─────────────────────────────────────────────────────────────┘
存客宝 scenarios 内部 API 按 apiKey 路由到对应计划,收线索
```
---
## 四、首页「链接卡若」流程
```
首页留资(无 targetUserId
POST /api/miniprogram/ckb/lead
{ phone, wechatId, ... } // 无 targetUserId
┌─────────────────────────────────────────────────────────────┐
│ CKBLead / CKBIndexLead │
├─────────────────────────────────────────────────────────────┤
│ leadKey = getCkbLeadApiKey() │
│ → system_config.site_settings.ckbLeadApiKey │
│ → .env CKB_LEAD_API_KEY │
│ → 代码内置 ckbAPIKey │
└─────────────────────────────────────────────────────────────┘
```
---
## 五、数据流总览
```
┌──────────────┐ token ┌──────────────┐ ckb_api_key ┌──────────────┐
│ 文章 content │ ──────────────▶│ persons 表 │ ─────────────────▶│ scenarios │
│ data-id │ │ token │ │ 内部 API │
└──────────────┘ │ ckb_api_key │ └──────────────┘
▲ │ ckb_plan_id │
│ └──────────────┘
│ ▲
│ │ 创建时
│ ┌──────┴──────┐
│ │ 开放 API │
│ │ createPlan │
│ │ getPlanDetail│
│ └─────────────┘
┌──────┴──────┐
│ 管理端/autolink │
│ 添加/编辑 Person │
└──────────────┘
```
---
## 六、关键结论
1. **apiKey 已存储**:创建计划时 `ckbOpenGetPlanDetail` 返回的 apiKey 会写入 `persons.ckb_api_key`
2. **CKBLead 应用 CkbApiKey**:文章 @ 场景下,用 token 查 Person`CkbApiKey` 作为 scenarios 的 apiKey**不能用 token 代替**。
3. **CkbApiKey 为空时**:应返回明确错误,提示该人物尚未配置存客宝密钥,**不要 fallback 到 .env**.env 是卡若的,会路由到错误计划)。
4. **创建计划参数**`planType=1``sceneId=9``scenario=9``status=1`2026-03-16 修正,否则 401 无效 apiKey
5. **mention span 需 data-label**TipTap 仅从 `data-label` 解析显示名,缺则显示 tokenParseAutoLinkContent 输出必须含 `data-label`

View File

@@ -1,147 +0,0 @@
# Soul 创业派对 - 小程序图标清单(阿里云 iconfont 采购用)
> 用于在 [iconfont.cn](https://www.iconfont.cn) 或阿里云设计资源中搜索、下载。建议统一风格(线性/描边),尺寸 24×24 或 48×48。
---
## 一、icon 组件内联 SVG需对应 name
当前 `components/icon/icon.js` 使用 Lucide 风格,若改为阿里云图标,需按以下 name 一一对应:
| 序号 | name | 中文名 | 用途/场景 |
|-----|------|--------|----------|
| 1 | share | 分享 | 分享到好友/朋友圈 |
| 2 | chevron-left | 左箭头 | 返回、导航 |
| 3 | chevron-right | 右箭头 | 进入、下一步 |
| 4 | chevron-down | 下箭头 | 展开、下拉 |
| 5 | search | 搜索 | 搜索框、目录搜索 |
| 6 | user | 用户 | 个人中心、头像占位 |
| 7 | users | 用户组 | 找伙伴、资源对接 |
| 8 | home | 首页 | 首页入口 |
| 9 | star | 星星 | 找伙伴、收藏 |
| 10 | heart | 心形 | 导师顾问、喜欢 |
| 11 | message-circle | 消息/对话 | 微信、联系方式 |
| 12 | smartphone | 手机 | 手机号、绑定 |
| 13 | map-pin | 地图定位 | 地区、地址 |
| 14 | book-open | 打开的书 | 书籍、阅读、目录 |
| 15 | lightbulb | 灯泡 | 想法、亮点 |
| 16 | handshake | 握手 | 合作、我能帮到你 |
| 17 | rocket | 火箭 | 成长、我能帮到你 |
| 18 | trophy | 奖杯 | 最赚钱的一个月 |
| 19 | star | 星星 | 最有成就感的一件事 |
| 20 | refresh-cw | 刷新 | 人生的转折点 |
| 21 | shield | 盾牌 | 安全、代付保障 |
| 22 | wallet | 钱包 | 余额、支付、提现 |
| 23 | camera | 相机 | 头像上传 |
| 24 | lock | 锁 | 登录、付费墙 |
| 25 | gift | 礼物 | 代付、礼包 |
| 26 | megaphone | 喇叭 | 分享到朋友圈 |
| 27 | image | 图片 | 生成海报 |
| 28 | clipboard | 剪贴板 | 复制联系方式 |
| 29 | check | 勾选 | 同意协议、已绑定 |
| 30 | trash-2 | 删除 | 删除地址 |
| 31 | plus | 加号 | 新增 |
| 32 | pencil | 编辑 | 编辑资料、编辑地址 |
| 33 | zap | 闪电 | 购买次数、解锁 |
| 34 | info | 信息 | 温馨提示 |
| 35 | x | 关闭 | 弹窗关闭 |
| 36 | gamepad | 手柄 | 团队招募 |
| 37 | briefcase | 公文包 | 对私域运营感兴趣 |
| 38 | target | 靶心 | 相似的创业方向 |
| 39 | save | 保存 | 保存海报 |
| 40 | globe | 地球 | 朋友圈 |
| 41 | package | 包裹 | 空状态、订单 |
| 42 | clock | 时钟 | 时间、过期 |
| 43 | corner-down-left | 退款 | 退款类型 |
| 44 | folder | 文件夹 | 目录 |
---
## 二、assets/icons 独立文件image 引用)
当前 `miniprogram/assets/icons/` 下已有,若需阿里云统一风格可替换:
| 文件名 | 用途 |
|--------|------|
| home.svg | 底部 Tab 首页 |
| list.svg | 底部 Tab 目录 |
| user.svg | 底部 Tab 我的 |
| partners.svg | 底部 Tab 找伙伴(中间突出) |
| edit-gray.svg | 我的页编辑、设置入口 |
| wallet.svg | 我的余额、提现 |
| eye-teal.svg | 阅读统计 |
| book-open-teal.svg | 阅读统计 |
| clock-teal.svg | 阅读统计 |
| users-teal.svg | 阅读统计 |
| book-arrow-teal.svg | 阅读统计 |
| folder-teal.svg | 目录入口 |
| gift.svg | 代付入口 |
| settings-gray.svg | 设置入口 |
| chevron-left.svg | 返回 |
| arrow-right.svg | 右箭头 |
| bell.svg | 消息提醒 |
| alert-circle.svg | 警告提示 |
| users.svg | 绑定用户 |
| image.svg | 分享 |
| share.svg | 分享 |
| message-circle.svg | 微信分享 |
| user.svg | 用户占位 |
| gift.svg | 礼包空状态 |
| info.svg | 礼包页说明 |
| eye-off.svg | 未解锁(联系方式/微信号) |
| user-edit-gray.svg | (备用) |
| info-blue.svg | (备用) |
| book.svg | (备用) |
| book-arrow.svg | (备用) |
| clock.svg | (备用) |
| eye.svg | (备用) |
| folder.svg | (备用) |
| settings.svg | (备用) |
**PNGTab 激活态,可考虑改为 SVG**
- home.png / home-active.png
- my.png / my-active.png
- match.png / match-active.png
---
## 三、iconfont 搜索关键词建议
| 图标 | 搜索词 |
|------|--------|
| 分享 | 分享、share |
| 返回 | 左箭头、返回、chevron |
| 箭头 | 右箭头、arrow、chevron |
| 搜索 | 搜索、search、放大镜 |
| 用户 | 用户、user、person |
| 用户组 | 用户组、users、people |
| 首页 | 首页、home、房子 |
| 星星 | 星星、star |
| 心形 | 心、heart、喜欢 |
| 消息 | 消息、对话、message、微信 |
| 手机 | 手机、smartphone |
| 定位 | 定位、地图、map、pin |
| 书本 | 书本、book、阅读 |
| 灯泡 | 灯泡、lightbulb、想法 |
| 握手 | 握手、handshake |
| 火箭 | 火箭、rocket |
| 奖杯 | 奖杯、trophy |
| 盾牌 | 盾牌、shield |
| 钱包 | 钱包、wallet |
| 相机 | 相机、camera |
| 锁 | 锁、lock |
| 礼物 | 礼物、gift |
| 勾选 | 勾选、check、对勾 |
| 删除 | 删除、trash |
| 编辑 | 编辑、pencil、铅笔 |
| 闪电 | 闪电、zap |
| 信息 | 信息、info |
---
## 四、规格建议
- **格式**SVG优先可缩放或 PNG
- **尺寸**24×24、32×32、48×48多尺寸备选
- **风格**线性描边stroke与 Lucide 风格一致
- **颜色**:单色或透明底,便于在代码中动态设置 `color`

View File

@@ -1,67 +0,0 @@
# 小程序变更影响分析2026-03-18
## 一、近期变更汇总
| 变更项 | 影响 |
|--------|------|
| config 拆分 | core + audit-mode + read-extras已迁移 |
| all-chapters 废弃 | 改用 book/parts、chapters-by-part、book/stats |
| idMidMap/getSectionMid 移除 | 列表/接口均带 mid跳转用 mid 或 id |
| 章节接口 | by-mid、by-id移除 /chapter/:id |
| 文章详情 | 响应含 prev/next无需单独请求 |
---
## 二、各页面检查结果
### ✅ 无影响
| 页面 | 说明 |
|------|------|
| **index** | recommended/hot/latest 均带 midgoToRead 用 dataset |
| **chapters** | book/parts + chapters-by-partsection 有 midfixedSections 有 mid |
| **search** | 搜索结果带 id+mid |
| **my** | recentChapters 来自 dashboard-stats后端返回 id+mid |
| **read** | _getChapterUrl 支持 by-mid/by-idprev/next 在详情内 |
| **gift-pay** | detail 含 productMid+productIdgoToRead 优先 mid |
| **purchases** | 订单列表无跳转阅读sectionMid 兜底为 0 |
### ✅ 已优化
| 位置 | 变更 |
|------|------|
| **read 海报 scene** | 有 sectionMid 时用 mid与分享一致 |
### 可选优化(低优先级)
| 位置 | 现状 | 说明 |
|------|------|------|
| **read copyLink** | `soul.quwanzhi.com/read/${sectionId}` | H5 若仅支持 id保持即可 |
| **index bookData** | data 中仍有 bookData: [] | 未在 wxml 展示,可后续清理 |
### 📋 数据流确认
| 数据源 | id | mid | 说明 |
|--------|----|-----|------|
| recommended | ✓ | ✓ | toSection 映射 |
| latest-chapters | ✓ | ✓ | 直接使用 |
| hot | ✓ | ✓ | 直接使用 |
| chapters-by-part | ✓ | ✓ | section 含 mid |
| book/parts fixedSections | id | mid | fixedSectionsMap |
| dashboard-stats recentChapters | ✓ | ✓ | 后端查 chapters 表 |
| gift-pay detail | productId | productMid | 后端查 chapters 表 |
---
## 三、潜在风险点
1. **序言/尾声**fixedSectionsMap 来自 book/parts 的 fixedSections若后端未返回 middata-mid 为空goToRead 会传 id。需确认 book/parts 的 fixedSections 是否含 mid。
2. **orders API**purchases 从 /api/miniprogram/orders 取数,有 section_mid 时正常fallback 到 purchasedSections 时 sectionMid=0当前无跳转阅读无影响。
3. **H5 链接**copyLink 的 soul.quwanzhi.com 若仅支持 id保持现状即可。
---
## 四、结论
- **核心流程**:首页、目录、搜索、我的、阅读、代付、分享均正常。
- **建议**:海报 scene 改为优先 midindex bookData 可清理。

View File

@@ -1,142 +0,0 @@
# Soul 创业派对 - 小程序性能分析2026-03-18
## 一、整体架构
| 层级 | 策略 | 说明 |
|------|------|------|
| **前端** | 并行请求、懒加载、GET 去重 | app.request 同 URL 并发共享 promise |
| **前端** | 配置缓存 5min | getConfig 减少重复请求 |
| **后端** | Redis + 内存双层缓存 | 启动预热,冷启动 502 已规避 |
| **后端** | 按需加载 | book/parts、chapters-by-part 懒加载,无全量 all-chapters |
---
## 二、启动与首屏
### 2.1 App onLaunch
| 任务 | 接口 | 并行 | 说明 |
|------|------|------|------|
| loadBookData | book/parts | ✓ | 仅取 totalSections |
| loadMpConfig | config/core + audit-mode | ✓ | Promise.all 并行 |
| checkUpdate | wx.getUpdateManager | ✓ | 系统 API |
| handleReferralCode | 本地/可选请求 | ✓ | 推荐码绑定 |
**结论**启动阶段请求少config 已拆分,体积小。
### 2.2 首页 index initData
| 任务 | 接口 | 并行 | 说明 |
|------|------|------|------|
| loadBookData | book/parts | ✓ | 与 app 同 URLGET 去重 |
| loadFeaturedFromServer | recommended + latest-chapters | ✓ | Promise.all |
| loadSuperMembers | vip/members → users | 串行 | 不足 4 人时补 users |
| loadLatestChapters | latest-chapters | ✓ | 与 loadFeatured 同 URL去重 |
**首屏请求汇总**(去重后):
- book/parts × 1
- config/core + audit-mode × 1app 已拉)
- book/recommended × 1
- book/latest-chapters × 1
- vip/members × 1
- users条件 × 1
**优化点**
- loadFeaturedFromServer 与 loadLatestChapters 都请求 latest-chapters并发时会被去重但逻辑重复可合并为一次请求、两处使用。
---
## 三、核心页面
### 3.1 目录页 chapters
| 阶段 | 接口 | 说明 |
|------|------|------|
| onLoad | book/parts | 仅篇章列表 + totalSections + fixedSections |
| 展开篇章 | chapters-by-part | 按需懒加载,每篇章一次 |
**潜在问题**`loadChaptersByPart` 每次展开都会 `wx.setStorageSync('bookData', bookDataFlat)`,章节多时可能阻塞主线程,可考虑节流或异步写入。
### 3.2 阅读页 read
| 阶段 | 接口 | 说明 |
|------|------|------|
| onLoad 预加载 | getConfig + getReadExtras | Promise.allread-extras 懒加载 |
| mid 解析 | chapter/by-mid/:mid | 仅 mid 有值且无 id 时 |
| 主流程 | chapter/by-mid 或 by-id | 单次请求 |
| 权限 | check-purchased | 非免费章节且已登录时 |
| 内容 | 复用 chapterRes | 无二次请求 |
**结论**章节数据一次拉取、复用prev/next 在详情内返回,无额外接口。
### 3.3 阅读追踪 readingTracker
| 行为 | 频率 | 说明 |
|------|------|------|
| 初始化 | 立即上报 1 次 | 打开即记录点击 |
| 定期上报 | 每 30 秒 | 增量 duration不重复累加 |
| 读完 | 立即上报 | progress≥90% 且停留 3 秒 |
**结论**:上报策略合理,对性能影响小。
---
## 四、后端缓存
| 接口 | Redis TTL | 内存 TTL | 预热 |
|------|-----------|----------|------|
| config/core | 10min | - | ✓ |
| config/audit-mode | 1min | - | ✓ |
| config/read-extras | 10min | - | ✓ |
| book/parts | 10min | 30s | ✓ |
| chapters-by-part | 10min | 30s | - |
| chapter 正文 | 30min | - | - |
| hot/recommended/stats | 5min | - | ✓ |
| latest-chapters | 5min | - | ✓ |
**结论**Redis + 内存 + 启动预热,冷启动已优化。
---
## 五、优化建议(按优先级)
### 高优先级
| 项 | 现状 | 建议 |
|----|------|------|
| index latest-chapters 重复 | loadFeatured + loadLatestChapters 各请求一次 | 合并为一次请求,两处共用数据 |
### 中优先级
| 项 | 现状 | 建议 |
|----|------|------|
| loadSuperMembers 串行 | vip/members 完成后再请求 users | 可并行发起,按需合并结果 |
| chapters setStorage | 每次展开都同步写入 bookData | 节流或改为异步,避免大对象阻塞 |
### 低优先级
| 项 | 现状 | 说明 |
|----|------|------|
| read-extras | 阅读页 onLoad 即拉 | 可延到首次需要 linkTags 时再拉 |
| GET 去重窗口 | 请求完成即删除 | 可考虑短时(如 200ms窗口覆盖快速重复点击 |
---
## 六、性能风险点
1. **Storage 同步写入**`wx.setStorageSync` 在章节多时可能卡顿,建议监控或改为异步。
2. **read 页 setData**:约 41 处 setData单次更新数据量需控制避免大对象。
3. **长列表**latestChapters 最多 20 条,当前规模可接受;若扩展需考虑虚拟列表。
---
## 七、总结
| 维度 | 评分 | 说明 |
|------|------|------|
| 网络请求 | 良好 | 并行、去重、懒加载、缓存完善 |
| 首屏速度 | 良好 | 请求少,后端有预热 |
| 阅读体验 | 良好 | 单次拉取、复用、追踪合理 |
| 存储与渲染 | 一般 | setStorage 同步、setData 次数可优化 |
**整体**当前性能可接受优先落地「index 合并 latest-chapters」即可带来明显收益。

View File

@@ -1,34 +0,0 @@
# Soul 创业派对 - 废弃接口清单
> 以下接口已标记 Deprecated保留以兼容旧版/管理端/next-project计划后续下线。新开发请使用替代接口。
## 一、小程序组 `/api/miniprogram/*`
| 废弃接口 | 替代接口 | 说明 |
|----------|----------|------|
| `GET /api/miniprogram/config` | `GET /config/core` + `GET /config/audit-mode` + `GET /config/read-extras` | 小程序已迁移至拆分接口 |
| `GET /api/miniprogram/book/all-chapters` | `GET /book/parts` + `GET /book/chapters-by-part` + `GET /book/stats` | 小程序已迁移至按需加载 |
## 二、API 组 `/api/*`next-project / 管理端)
| 废弃接口 | 替代接口 | 说明 |
|----------|----------|------|
| `GET /api/book/all-chapters` | 同上 | 小程序已迁移至 miniprogram 组 |
| `GET /api/db/config` | 小程序用 `/miniprogram/config/core` 等 | 公开配置,小程序已迁移 |
## 三、代码标记位置
| 文件 | 位置 |
|------|------|
| soul-api/internal/handler/db.go | `GetPublicDBConfig` 函数注释 |
| soul-api/internal/handler/book.go | `BookAllChapters` 函数注释 |
| soul-api/internal/router/router.go | miniprogram `/config``/book/all-chapters` 路由上方 |
| soul-api/internal/router/router.go | api `/book/all-chapters``/db/config` 路由上方 |
## 四、迁移状态
| 端 | config | all-chapters |
|----|--------|--------------|
| 小程序 | ✅ 已迁移 core + audit-mode + read-extras | ✅ 已迁移 book/parts + chapters-by-part |
| 管理端 | 使用 /api/db/config、config/full | 不直接调用 all-chapters |
| next-project | 可能仍用 /api/db/config | 可能仍用 /api/book/all-chapters |

View File

@@ -1,124 +0,0 @@
# Soul 创业派对 - 小程序与 API 性能优化综合分析
**分析时间**: 2026-03-18
**范围**: 小程序miniprogram+ 后端 APIsoul-api
---
## 一、当前已完成的优化
### 1.1 API 端soul-api
| 优化项 | 说明 | 效果 |
|--------|------|------|
| **Redis 缓存** | config、book/parts、all-chapters、chapters-by-part、latest-chapters、free_chapters、chapter content、hot、recommended、stats | 命中时免 DB响应 <50ms |
| **启动预热** | WarmConfigCacheWarmAllChaptersCacheWarmBookPartsCacheWarmLatestChaptersCache | 首请求无冷启动 |
| **Gzip 压缩** | gin-contrib/gzip 中间件 | 响应体缩小 6080% |
| **内存兜底** | partsall-chapterschapters-by-part 30s 内存缓存 | Redis 不可用时仍快 |
### 1.2 小程序端miniprogram
| 优化项 | 说明 | 效果 |
|--------|------|------|
| **骨架屏** | 阅读页目录页代付详情搜索页 | 加载过程有占位减少白屏 |
| **bookData 本地缓存** | app.loadBookData 先读 wx.getStorageSync('bookData') | 二次打开可先展示缓存 |
| **config 节流** | onShow loadMpConfig 30 秒节流 | 避免频繁请求 |
| **静默请求** | 统计推荐访问等用 silent: true | 不阻塞 UI |
### 1.3 实测数据(正式环境 2026-03-18
| 接口 | 平均(ms) | 最小(ms) | 最大(ms) |
|------|----------|----------|----------|
| config | 390 | 378 | 406 |
| book/parts | 396 | 387 | 403 |
| book/all-chapters | 390 | 376 | 407 |
| book/chapters-by-part | 420 | 416 | 424 |
| book/chapter/:id | 420 | 401 | 425 |
| book/chapter/by-mid/:mid | 424 | 419 | 431 |
**说明** 390430ms 主要为网络 RTT用户服务器Redis 命中时服务端处理通常 <20ms
---
## 二、待优化项(按优先级)
### 2.1 高优先级:减少重复请求
| 问题 | 现状 | 建议 |
|------|------|------|
| **config 多端重复** | app.loadMpConfigindex.loadFeatureConfigread TabBar 各自拉 config | 统一用 `app.globalData` 缓存首次拉取后 510min 内复用各页优先读缓存过期再拉 |
| **all-chapters 重复** | app.loadBookData + index.loadBookData 都调 all-chapters | index 优先用 `app.globalData.bookData`仅当为空或需刷新时再请求 |
| **loadFeaturedFromServer 串行** | recommended 失败再 hot latest-chapters | 可并行请求 recommended + latest-chapters失败再兜底 |
### 2.2 中优先级:请求策略
| 问题 | 现状 | 建议 |
|------|------|------|
| **首页请求过多** | initData 触发 loadBookDataloadFeaturedFromServerloadSuperMembersloadLatestChapters 4+ 请求 | 合并或分阶段首屏只拉 latestSection + featured 3超级个体最新新增可延迟加载 |
| **阅读页 config** | app.loadMpConfig 可能重复 | 优先用 `app.globalData` 中的 config无缓存再请求 |
| **request 无请求去重** | 同一接口并发多次会发多次请求 | 对相同 url 做短时 200ms去重避免重复请求 |
### 2.3 低优先级:体验与资源
| 问题 | 现状 | 建议 |
|------|------|------|
| **图片未优化** | 头像海报等直接原图 | 使用 CDN 或后端缩略图`<image>` `lazy-load` |
| **setData 频率** | 部分页面多次 setData 更新列表 | 合并更新减少 setData 调用次数 |
| **分包** | 未使用分包 | 非首屏页面设置代付导师等可放入分包降低主包体积 |
---
## 三、API 端可进一步优化
| 方向 | 说明 |
|------|------|
| **HTTP/2** | 若部署支持启用 HTTP/2 多路复用减少连接开销 |
| **Redis 连接池** | 检查 go-redis 默认 PoolSize高并发时可适当调大 |
| **book/search 缓存** | 搜索接口无缓存热门关键词可加短 TTL 12min缓存 |
| **CDN 静态资源** | uploads 图片走 CDN减轻 API 带宽压力 |
---
## 四、实施建议(分阶段)
### 阶段一快速见效12 天)
1. **config 统一缓存** app.js 维护 `configCache` + 过期时间各页优先读缓存
2. **index 复用 bookData**`app.globalData.bookData` 有值时index 不再单独请求 all-chapters
3. **loadFeaturedFromServer 并行**`Promise.all([recommended, latest-chapters])` 并行请求
### 阶段二结构优化35 天)
1. **首页分阶段加载**首屏只拉 latestSection + featured超级个体最新新增 onShow 后延迟拉取
2. **request 去重**对相同 url 200ms 内只发一次请求后续调用复用同一 Promise
3. **图片 lazy-load**列表头像等加 `lazy-load`
### 阶段三:长期(按需)
1. **分包加载**非核心页面放入分包
2. **CDN**静态资源迁移到 CDN
3. **监控**接入性能监控持续观察首屏接口耗时
---
## 五、关键代码位置索引
| 功能 | 文件路径 |
|------|----------|
| 请求封装 | miniprogram/app.js `request()` |
| 启动加载 | miniprogram/app.js `onLaunch` loadBookDataloadMpConfig |
| 首页数据 | miniprogram/pages/index/index.js `initData`loadFeaturedFromServer |
| 阅读页加载 | miniprogram/pages/read/read.js `onLoad` |
| API 缓存 | soul-api/internal/cache/cache.go |
| 预热逻辑 | soul-api/cmd/server/main.go |
---
## 六、总结
- **已做**Redis 多级缓存启动预热Gzip骨架屏本地缓存节流等接口平均 390430ms主要受网络 RTT 影响
- **优先做**减少 configall-chapters 等重复请求统一缓存策略
- **中期**首页分阶段加载request 去重图片懒加载
- **长期**分包CDN性能监控
按上述阶段推进可在不大改架构的前提下明显减少请求数和首屏等待时间

View File

@@ -1,112 +0,0 @@
# Soul 提现流程图
## 一、整体流程Mermaid
```mermaid
flowchart TB
subgraph 小程序["小程序端"]
A1[用户进入推广中心/我的]
A2[输入提现金额]
A3[POST /api/miniprogram/withdraw]
end
subgraph 后端校验["后端校验"]
B1{参数校验}
B2{金额 > 0?}
B3{金额 ≤ 可提现?}
B4{金额 ≥ 最低门槛?}
B5{用户存在且已绑定微信?}
end
subgraph 落库["落库"]
C1[写入 withdrawals 表<br/>status = pending]
end
subgraph 管理端["管理端"]
D1[管理员查看提现列表<br/>GET /api/admin/withdrawals]
D2{审核决策}
D3[拒绝 → status = failed]
D4[批准 → 调用微信转账]
end
subgraph 微信["微信支付"]
E1[商家转账到零钱]
E2{微信返回 state}
E3[processing<br/>处理中]
E4[pending_confirm<br/>待用户确认收款]
end
subgraph 用户确认["用户确认"]
F1[获取待确认列表<br/>GET /api/miniprogram/withdraw/pending-confirm]
F2[领取零钱<br/>wx.requestMerchantTransfer]
F3[确认收款<br/>POST /api/miniprogram/withdraw/confirm-received]
end
subgraph 终态["终态"]
G1[success<br/>已到账]
G2[failed<br/>已拒绝/打款失败]
end
A1 --> A2 --> A3 --> B1
B1 --> B2 --> B3 --> B4 --> B5
B5 -->|通过| C1
C1 --> D1 --> D2
D2 -->|拒绝| D3 --> G2
D2 -->|批准| D4 --> E1 --> E2
E2 --> E3
E2 --> E4 --> F1 --> F2 --> F3 --> G1
E3 -->|回调/同步| G1
E3 -->|失败| G2
```
## 二、可提现金额计算逻辑
```mermaid
flowchart LR
subgraph 公式["可提现 = 累计佣金 - 已提现 - 待审核"]
A[累计佣金<br/>paid 订单佣金求和]
B[已提现<br/>status=success 的 sum]
C[待审核<br/>pending+processing+pending_confirm 的 sum]
end
A --> D[可提现]
B --> D
C --> D
```
## 三、状态流转
```mermaid
stateDiagram-v2
[*] --> pending: 用户申请
pending --> failed: 管理员拒绝
pending --> processing: 批准且微信直接处理
pending --> pending_confirm: 批准且需用户确认收款
processing --> success: 微信回调/主动同步
processing --> failed: 打款失败
pending_confirm --> success: 用户点击确认收款
success --> [*]
failed --> [*]
```
## 四、关键接口一览
| 端 | 接口 | 用途 |
|---|---|---|
| 小程序 | POST /api/miniprogram/withdraw | 申请提现 |
| 小程序 | GET /api/miniprogram/withdraw/records | 提现记录 |
| 小程序 | GET /api/miniprogram/withdraw/pending-confirm | 待确认收款列表 |
| 小程序 | GET /api/miniprogram/withdraw/confirm-info | 领取零钱参数 |
| 小程序 | POST /api/miniprogram/withdraw/confirm-received | 确认收款 |
| 管理端 | GET /api/admin/withdrawals | 提现列表 |
| 管理端 | PUT /api/admin/withdrawals | 审核/打款approve/reject |
| 管理端 | POST /api/admin/withdrawals/sync | 主动同步微信转账结果 |
## 五、校验规则(申请时)
1. **金额 > 0**
2. **金额 ≤ 可提现余额**(累计佣金 - 已提现 - 待审核)
3. **金额 ≥ 最低提现门槛**(默认 10 元,来自 referral_config.minWithdrawAmount
4. **用户存在**
5. **用户已绑定微信**openid 不为空)
批准时二次校验可提现金额,防止退款/冲正后超额打款。

View File

@@ -1,115 +0,0 @@
# 新版与稳定版 - 小程序界面差异清单
> 乘风检测:`new-soul/miniprogram`(新版) vs `miniprogram`(稳定版)
> 更新日期2026-03-17
---
## 一、检测结论摘要
| 维度 | 结论 |
|------|------|
| **页面结构** | 一致23 个页面4 个 Tab首页、目录、找伙伴、我的 |
| **app.json** | 完全一致 |
| **WXML 结构** | 核心页面index、my、read、chapters、vip、wallet、referral、search、match结构高度一致 |
| **WXSS 样式** | 无显著差异 |
| **自定义组件** | 均仅有 `components/icon` |
---
## 二、页面级差异(逐页对比)
### 2.1 首页 index
| 差异项 | 稳定版 miniprogram | 新版 new-soul | 说明 |
|--------|-------------------|---------------|------|
| 搜索栏 | 有 | 有 | 一致 |
| 搜索开关 | 可能有 `wx:if="{{searchEnabled}}"` | 无 | 若稳定版已迁审核/功能开关,则按配置显隐 |
| Banner 标签 | 「推荐」 | 「推荐」 | 一致 |
| 阅读进度卡 | 可能有 | 无 | 稳定版 P1 迁移项:已读 X/62 进度条 |
| 超级个体 | 有 | 有 | 一致 |
| 超级个体审核隐藏 | 可能有 `wx:if="{{!auditMode}}"` | 无 | 若稳定版已迁审核模式 |
| 精选推荐 | 有,支持展开 | 有,支持展开 | 一致 |
| 最新新增 | 有,支持展开 | 有,支持展开 | 一致 |
| 最新新增价格 | 可能有 `timeline-price` | 可能无 | 待确认 |
| 留资弹窗 | 有 | 有 | 一致 |
| env-switch 组件 | 可能有 | 无 | 稳定版开发环境专用悬浮切换 |
### 2.2 我的页 my
| 差异项 | 稳定版 | 新版 | 说明 |
|--------|--------|------|------|
| 资料编辑入口 | 有 nav-settings + profile-edit-btn | 有 nav-settings | 稳定版有「编辑」入口,新版可能无 |
| 会员/收益/余额 | 有 | 有 | 一致 |
| 审核模式隐藏 | 可能有 `wx:if="{{!auditMode}}"` 控制会员/余额/一键收款 | 无 | 若稳定版已迁 |
| 推荐开关 | 可能有 `wx:if="{{referralEnabled}}"` | 无 | 稳定版可配置显隐推荐/收益 |
| 阅读统计 | readCountText、totalReadTimeText、matchHistoryText | readCount、totalReadTime、matchHistory | 格式可能不同 |
| 钱包余额 | walletBalanceText | walletBalance | 显示格式可能不同 |
| 我的代付 | gift-card | gift-card | 一致(代付链接列表) |
| 代付入口 | 可能有 giftPay 菜单项 | 可能有 | 代付美团式后可能改为「我的代付」 |
| 设置入口 | 有 | 有 | 一致 |
### 2.3 阅读页 read
| 差异项 | 稳定版 | 新版 | 说明 |
|--------|--------|------|------|
| 审核模式 | 可能有 `paywall-audit-tip``wx:if="{{auditMode}}"` | 无 | 若稳定版已迁 |
| 分享区 | 代付分享、海报、朋友圈 | 同 | 一致 |
| share-tip-inline | 可能有「分享后好友购买,你可获得 90% 收益」 | 可能无 | 稳定版 P2 可选迁移 |
| 购买按钮 | 有 | 有 | 一致 |
| 余额支付 | 有 | 有 | 一致 |
### 2.4 目录页 chapters
| 差异项 | 稳定版 | 新版 | 说明 |
|--------|--------|------|------|
| 篇章结构 | 序言、篇章、尾声、附录 | 同 | 一致 |
| 每日新增 | 可能有 | 可能无 | 按需求可选 |
| 免费/NEW/¥1 标签 | 有 | 有 | 一致 |
### 2.5 钱包 / VIP / 推广 / 搜索 / 匹配
| 页面 | 差异说明 |
|------|----------|
| wallet | 稳定版可能有 auditMode 隐藏充值入口;结构一致 |
| vip | 结构一致 |
| referral | 结构一致 |
| search | 结构一致 |
| match | 结构一致 |
---
## 三、功能差异(逻辑层,非纯界面)
| 功能 | 稳定版 | 新版 | 说明 |
|------|--------|------|------|
| 审核模式 auditMode | 有index/my/wallet/read 按配置隐藏支付) | 无 | 提审必备 |
| 运行时配置 | getRuntimeBootstrapConfig、envVersion 区分 develop/trial/release | 简单 extConfig+storage | 稳定版按环境区分 baseUrl |
| loadMpConfig | 有,支持 auditMode、apiDomain、supportWechat | 可能无或简化 | 稳定版从 config 接口拉取 |
| 规则引擎 ruleEngine | 有 | 无 | 稳定版 after_login、after_match 等 |
| 埋点 trackClick | 有index/my/match/vip/search/referral 等) | 可能有 | 稳定版已补齐 |
| 代付流程 | 读页→代付页→分享(美团式) | 读页弹窗分享gift-link | 稳定版有独立 gift-pay 页则不同 |
| 开发环境 env-switch | 有 | 无 | 稳定版 develop/trial 显示悬浮切换 |
---
## 四、页面与路由差异
| 项目 | 稳定版 | 新版 |
|------|--------|------|
| gift-pay 独立页 | 若有gift-pay/detail、gift-pay/list | 无app.json 未配置) |
| 代付入口 | 可能有「我的代付」菜单 | 「我的代付链接」gift-card |
---
## 五、建议与结论
1. **界面层面**:两版 WXML/WXSS 高度一致,无明显布局差异。
2. **功能层面**:稳定版在审核模式、运行时配置、规则引擎、埋点、代付流程上更完善。
3. **迁移建议**:以 `miniprogram/` 为主开发目录;新版可作参考,但稳定版已吸收并增强。
4. **后续验证**:建议在真机/模拟器并排对比 index、my、read 三页,确认 auditMode、searchEnabled、阅读进度卡、env-switch 等是否在稳定版中正确展示。
---
**生成时间**2026-03-17
**对比范围**WXML、WXSS、app.json、app.js、pages、components

View File

@@ -1,113 +0,0 @@
# 新版与稳定版管理端 - 功能与样式差异分析
> 橙子整理。基于现有文档与代码分析。更新日期2026-03-17
**目录说明**`new-soul/soul-admin` = **稳定版**(生产主用);`soul-admin/`(根目录)= 另一版/迁移对照
---
## 一、全站功能与样式差异总表
| 模块 | 功能/样式项 | 稳定版 new-soul/soul-admin | 根目录 soul-admin | 说明 |
|------|-------------|---------------------------|-------------------|------|
| **Settings** | 审核模式 auditMode | ✅ 独立 Card + Switch | ❌ 无 | 稳定版有 |
| **Settings** | 关于页面 aboutEnabled | ✅ | ❌ 无 | 稳定版有 |
| **Settings** | 功能开关保存 | 独立 saveFeatureConfigOnly | 与站点设置一起 | 稳定版更细粒度 |
| **Settings** | API 文档 Tab | ✅ 内嵌 ApiDocsPage | 无或简单 | 稳定版有 |
| **Settings** | OSS 配置 | ✅ 完整(含 region | ✅ 有 | 一致或稳定版更完整 |
| **Dashboard** | 代付金额 giftedTotal | ✅ 含 sub「含代付 ¥xx」 | ❌ 无 | 稳定版有 |
| **Dashboard** | 最近订单条数 | 默认 4 条,可展开至 10 条 | 固定 5 条 | 稳定版可展开 |
| **Dashboard** | 订单类型展示 | ✅ balance_recharge、gift_pay | 无 balance_recharge | 稳定版更全 |
| **Dashboard** | 埋点统计 track/stats | ✅ period=week/day | ❌ 无 | 稳定版有,依赖后端 |
| **用户编辑** | 编辑时手机号 | 禁用 | 可编辑 | 稳定版更安全 |
| **Layout** | 鉴权逻辑 | 先检查 token 再请求 | 基础 | 稳定版优化 |
| **Content** | 内容管理整体 | chapters/ranking/search/link-person/link-tag/linkedmp | 同 | 一致 |
| **根目录版独有** | 搜索功能文案 | 「首页搜索栏」 | 「首页、目录页搜索栏」 | 根目录版更完整 |
| **根目录版独有** | 用户详情余额 | ❌ 或无 | ✅ | 根目录版有 |
| **根目录版独有** | 订单支付方式/代付 | 可能简化 | ✅ 微信/余额/代付 | 根目录版更全 |
| **根目录版独有** | RechargeAlert | ❌ 或无 | ✅ | 根目录版有 |
| **根目录版独有** | LinkedMp 关联小程序 | ❌ 或无 | ✅ | 根目录版有 |
---
## 二、文章内容弹窗(新建/编辑章节)— 除富文本外的差异
> 迁移策略:**内容管理以稳定版new-soul/soul-admin为基准**。以下为稳定版实现,供对比参考。
### 2.1 弹窗结构
| 项目 | 稳定版 new-soul/soul-admin | 根目录 soul-admin | 备注 |
|------|-------------------|---------------|------|
| 弹窗尺寸 | 全屏w-screen h-screen | 待确认 | 稳定版新建、编辑均为全屏 |
| 布局 | flex flex-col内容区 overflow-y-auto | 待确认 | 底部按钮始终可见 |
| 关闭方式 | showCloseButton | 待确认 | - |
### 2.2 表单字段(非富文本)
| 字段 | 新建章节 | 编辑章节 | 说明 |
|------|:--------:|:--------:|------|
| 章节ID | ✅ | ✅ | 新建必填,编辑可改 |
| 价格 (元) | ✅ | ✅ | 免费时禁用输入 |
| 免费 | ✅ 复选框 | ✅ 复选框 | 设为免费 |
| 最新新增 | ✅ 标记 NEW | ✅ | - |
| 小程序直推 | ✅ 强制置顶首页 | ✅ | amber 色复选框 |
| 文章类型 | ✅ 普通版/增值版 | ✅ | 单选 |
| 热度分 | ✅ number | ✅ | step=0.1, min=0 |
| 章节标题 | ✅ | ✅ | - |
| 所属篇 | ✅ Select | - | 新建时选 |
| 所属章 | ✅ Select | - | 新建时选 |
| 文件路径 | - | ✅ 只读 | 编辑时若有则展示 |
| 付款记录 | - | ✅ 按钮 | 编辑时底部左侧 |
### 2.3 富文本相关(仅列差异方向,不展开)
| 项 | 稳定版 | 说明 |
|------|--------|------|
| 编辑器 | RichEditor (TipTap) | 支持 @人物#标签、图片上传 |
| 人物/标签 | persons、linkTags 传入 | 输入 @ 可链接 AI 人物,工具栏可插入 # 标签 |
| 图片上传 | onImageUpload → /api/upload | folder=book-images |
### 2.4 文章内容弹窗 — 可能存在的样式差异(待根目录版对照确认)
| 项目 | 稳定版 new-soul/soul-admin | 根目录 soul-admin 可能差异 |
|------|--------|----------------|
| 表单 grid 布局 | grid-cols-3 gap-4 | 可能为 grid-cols-2 或不同 gap |
| 输入框样式 | bg-[#0a1628] border-gray-700 | 可能色值、圆角不同 |
| 主色 | #38bdac(青绿) | 可能主题色不同 |
| Label 样式 | text-gray-300 | 可能字重、字号不同 |
| 底部按钮顺序 | 取消 | 创建/保存 | 可能「付款记录」位置不同(仅编辑) |
| 弹窗背景 | bg-[#0f2137] | 可能背景色不同 |
### 2.5 其他弹窗(内容管理相关)
| 弹窗 | 稳定版 | 说明 |
|------|--------|------|
| 编辑篇名 | Dialog max-w-md | 简单表单 |
| 编辑章节名称 | Dialog | 单字段 |
| 批量移动 | Dialog | 选择目标目录 |
| 付款记录 | Dialog | 展示订单列表 |
| 文章排名算法 | Dialog | 权重配置 |
| 新建篇 | Dialog | 篇名输入 |
| 链接人与事 | PersonAddEditModal | 添加/编辑人物 |
---
## 三、迁移建议(内容管理)
| 策略 | 说明 |
|------|------|
| **以稳定版为准** | 内容管理(含文章内容弹窗)不采纳新版,保持稳定版实现 |
| **富文本** | 稳定版 RichEditor 已支持 @人物#标签、图片上传,无需从新版迁移 |
| **表单字段** | 稳定版新建/编辑字段已对齐,若新版有缺失则勿回退 |
| **样式** | 稳定版深色主题(#0f2137#0a1628#38bdac)已落地,迁移时保持 |
---
## 四、待根目录 soul-admin 对照时的补充项
当需与根目录 `soul-admin` 逐项对比时,建议补充核对:
1. **新建章节弹窗**字段是否完全一致章节ID、价格、免费、最新新增、小程序直推、文章类型、热度分、所属篇/章、内容区)
2. **编辑章节弹窗**:是否多「付款记录」按钮、文件路径展示
3. **表单校验**:必填项、数字范围是否一致
4. **错误提示**:保存失败、加载失败时的 toast/文案是否一致

View File

@@ -1,154 +0,0 @@
# 新版管理端迁移到稳定版 - 需求评估
> 乘风整理。更新日期2026-03-17
**目录说明**`new-soul/soul-admin` = **稳定版**(生产主用);`soul-admin/`(根目录)= 根目录版。迁移时以稳定版为基准,从根目录版带入缺失能力。
---
## 一、评估基准
| 基准 | 说明 |
|------|------|
| **稳定版小程序** | 已梳理完毕,定义 C 端能力余额、代付、VIP、规则引擎、埋点、找伙伴、推广等 |
| **稳定版管理端** | `new-soul/soul-admin`,需支撑上述小程序的运营与管理 |
| **以界面定需求** | 管理端界面清单见《以界面定需求》§三;业务逻辑对齐见§四 |
---
## 二、稳定版管理端必须保留的能力(不可丢)
以下能力对应小程序功能,迁移时**必须保留**,新版若缺失则需从稳定版补齐。
| 能力 | 对应小程序 | 稳定版现状 | 迁移时动作 |
|------|------------|------------|------------|
| 用户详情 - 当前余额 | wallet、read/vip 余额支付 | ✅ 有 | **保留**,新版无则从稳定版代码带入 |
| 订单 - 支付方式(微信/余额/支付宝) | 余额购买、代付 | ✅ 有 | **保留**,新版无则从稳定版代码带入 |
| 订单 - 代付标识、代付人 | gift-pay | ✅ 有 | **保留** |
| 用户规则 CRUD | ruleEngine | ✅ 有 | **保留** |
| 超级个体/VIP 管理 | vip、member-detail | ✅ 有 | **保留** |
| 提现审核、分销、找伙伴、导师 | 对应小程序页 | ✅ 有 | **保留** |
| **内容管理(文章内容)** | chapters、read | ✅ 有 | **以稳定版为主**,不采纳新版 |
| RechargeAlert | 商户号余额不足提示 | ✅ 有 | **保留**,运营需及时感知 |
| LinkedMp关联小程序 | 多小程序场景 | ✅ 有 | **保留**,若业务使用 |
---
## 三、稳定版可选能力(依赖后端,当前 404
以下能力稳定版 UI 已有,但 soul-api **router 未注册**,会 404。迁移时需决策**修后端** 或 **暂隐 UI**
| 能力 | 接口 | 调用位置 | 建议 |
|------|------|----------|------|
| 用户列表 RFM 排序 | `GET /api/db/users/rfm` | UsersPage | 若运营需要 RFM 分析 → 补 router否则迁移时可隐 |
| 用户旅程总览 | `GET /api/db/users/journey-stats` | UsersPage | 若运营需要 → 补 router否则迁移时可隐 |
| 神射手(用户资料完善) | `GET/POST /api/admin/shensheshou/*` | UserDetailModal | 若使用神射手 → 补 router否则迁移时可隐 |
---
## 四、新版独有、稳定版可吸纳的能力
以下为新版有、稳定版无,迁移时**可选择性吸纳**到稳定版。
| 能力 | 说明 | 需求评估 | 建议 |
|------|------|----------|------|
| **OSS 配置** | 阿里云对象存储 endpoint、bucket、accessKey 等 | 新版有 → 迁移 | **吸纳**2026-03-17 会议决议) |
| **API 文档 Tab** | 系统设置内嵌 ApiDocsPage | 新版有 → 迁移 | **吸纳** |
| **api-docs 独立页** | `/api-docs` 路由 | 新版有 → 迁移 | **吸纳** |
| **编辑时手机号禁用** | 编辑用户时手机号不可改 | 新版有 → 迁移 | **吸纳** |
| **鉴权逻辑优化** | 先检查 token 再请求 | 新版有 → 迁移 | **吸纳** |
---
## 五、迁移策略(按模块)
### 5.1 内容管理(文章内容)— 以稳定版为主
| 策略 | 说明 |
|------|------|
| **ContentPage** | 完全以稳定版为准,不采纳新版 |
| **章节树、内容编辑、LinkTag、Person、LinkedMp** | 稳定版实现为准 |
| **富文本、排序、预览、免费章节配置** | 稳定版为准 |
迁移时:内容管理相关代码**不覆盖**,保持稳定版实现。
---
### 5.2 其他模块迁移策略
| 模块 | 策略 | 说明 |
|------|------|------|
| **用户管理** | 以稳定版为主 | 用户详情余额、RFM、旅程、规则、超级个体均保留稳定版可吸纳新版「编辑时手机号禁用」 |
| **订单** | 以稳定版为主 | 支付方式、代付、导出格式不覆盖 |
| **推广中心** | 以稳定版为主 | 保持稳定版实现 |
| **提现** | 以稳定版为主 | 保持稳定版实现 |
| **找伙伴** | 以稳定版为主 | CKB、匹配池、导师、资源对接等保持稳定版 |
| **系统设置** | 稳定版为主 + 吸纳 | 保持稳定版结构;可吸纳新版 API 文档 Tab、OSS 配置 |
| **Layout** | 以稳定版为主 | RechargeAlert、菜单结构保留可吸纳新版鉴权逻辑 |
| **Dashboard** | 以稳定版为主 | 保持稳定版 |
| **支付/站点/小程序码/导师/API 文档** | 以稳定版为主 | 保持稳定版API 文档可吸纳新版 ApiDocsPage |
---
### 5.3 需调整的项
| 项 | 调整说明 |
|----|----------|
| **后端 router** | 若保留 RFM、journey-stats、神射手需 soul-api 补 5 个路由 |
| **OSS** | 若吸纳,需 soul-api 支持 ossConfig/api/admin/settings 需确认) |
| **ApiDocsPage** | 新版有独立实现,可复制到稳定版并接入设置 Tab 或独立路由 |
---
### 5.4 不采纳的项
| 项 | 说明 |
|----|------|
| 新版 ContentPage | 内容管理以稳定版为准 |
| 新版 Layout 结构差异 | 系统设置分区等保持稳定版 |
| 新版部分 UI 细节 | grid-cols、间距等以稳定版为准 |
---
## 六、需求优先级与实施顺序
| 阶段 | 内容 | 优先级 |
|------|------|:------:|
| **1. 必须保留** | 确保迁移后稳定版不丢失:用户详情余额、订单支付方式/代付、RechargeAlert、LinkedMp | P0 |
| **2. 后端补齐** | 若保留 RFM/journey/神射手soul-api router 注册 5 个路由 | P1 |
| **3. 吸纳优化** | 编辑时手机号禁用、鉴权逻辑、API 文档 Tab | P2 |
| **4. 按需吸纳** | OSS 配置、api-docs 独立页 | P3 |
---
## 七、验收标准(迁移完成后)
| 验收项 | 标准 |
|--------|------|
| 用户详情 | 基础信息 Tab 有「当前余额」卡,数据来自 `/api/admin/users/:id/balance` |
| 订单页 | 支付方式列含微信/余额/支付宝,代付订单展示代付人 |
| 用户规则 | 规则配置 Tab 可 CRUD与小程序 ruleEngine 联动 |
| RechargeAlert | 余额不足等错误时顶部红条可展示 |
| 内容管理 | 章节树、文章编辑、LinkTag、Person、LinkedMp 等以稳定版为准 |
| 其他 | 提现、分销、找伙伴、设置等页面功能正常 |
---
## 八、迁移策略汇总
| 原则 | 模块 |
|------|------|
| **以稳定版为主(不覆盖)** | 内容管理、用户管理、订单、推广、提现、找伙伴、Layout、Dashboard |
| **吸纳新版** | 编辑时手机号禁用、鉴权逻辑、API 文档 Tab、OSS 配置(按需) |
| **内容管理** | **明确以稳定版为主**章节树、文章编辑、LinkTag、Person、LinkedMp 等均不采纳新版 |
---
## 九、总结
| 类型 | 说明 |
|------|------|
| **必须保留** | 余额、代付、规则、VIP、RechargeAlert、LinkedMp、**内容管理** |
| **可选(依赖后端)** | RFM、journey-stats、神射手 |
| **可吸纳** | OSS、API 文档、编辑禁用、鉴权优化 |
| **结论** | 内容管理以稳定版为主;其他模块以稳定版为主,选择性吸纳新版优化;后端按需补 router。 |

View File

@@ -1,185 +0,0 @@
# 新版迁移 - 小程序功能差异清单(稳定版 vs 体验版)
> 乘风分析稳定版miniprogram与体验版new-soul/miniprogram的差异。
> 更新日期2026-03-17
**目录说明**`miniprogram` = 稳定版(生产);`new-soul/miniprogram` = 体验版(新版参考)
---
## 一、差异摘要(按页面/模块)
| 页面/模块 | 稳定版 miniprogram | 体验版 new-soul/miniprogram | 迁移建议 |
|-----------|-------------------|-----------------------------|----------|
| **app.js** | 硬编码 baseUrl、无 auditMode | loadRuntimeConfig、auditMode、timeout | 迁运行时配置 |
| **index** | 无 auditMode | auditMode 控制超级个体按钮 | 迁 auditMode |
| **gift-pay/detail** | hero-card、requester-card、完整支付流程 | 简单 card | **勿回退**,稳定版更完善 |
| **read** | 无 auditMode、无 showShareTip | auditMode、personsConfig、showShareTip | 迁 auditMode |
| **my** | profile-name-actions编辑、referralEnabled | auditMode 控制支付 UI | **保留**稳定版编辑入口 |
| **wallet** | 无 auditMode | auditMode | 迁 auditMode |
| **chapters** | 每日新增已删除 | 每日新增区块 | 按需求 |
| **about** | ✅ | ✅ | 一致 |
| **utils** | ruleEngine | 无 | **保留**稳定版 |
---
## 二、需迁移的细节(体验版有、稳定版缺)
### 2.1 app.js - 运行时配置与审核模式
| 功能项 | 稳定版 | 体验版 | 迁移建议 |
|--------|--------|--------|----------|
| **baseUrl 配置** | 硬编码 localhost | getRuntimeBootstrapConfigextConfig/Storage/默认生产 | **P0** |
| **loadRuntimeConfig** | 仅 appId/mchId 等 | 含 apiDomain、auditMode、supportWechat | **P0** |
| **globalData** | 无 auditMode | auditMode、supportWechat | **P0** |
| **request timeout** | 无 | 15000ms | **P2** |
| **loadBookData** | 已类似 | 同 | 已对齐 |
**新版关键代码getRuntimeBootstrapConfig**
```javascript
function getRuntimeBootstrapConfig() {
try {
const extCfg = wx.getExtConfigSync ? (wx.getExtConfigSync() || {}) : {}
return {
baseUrl: extCfg.apiBaseUrl || wx.getStorageSync('apiBaseUrl') || DEFAULT_BASE_URL,
appId: extCfg.appId || DEFAULT_APP_ID,
mchId: extCfg.mchId || DEFAULT_MCH_ID,
withdrawSubscribeTmplId: extCfg.withdrawSubscribeTmplId || DEFAULT_WITHDRAW_TMPL_ID
}
} catch (_) {
return { baseUrl: DEFAULT_BASE_URL, appId: DEFAULT_APP_ID, mchId: DEFAULT_MCH_ID, withdrawSubscribeTmplId: DEFAULT_WITHDRAW_TMPL_ID }
}
}
```
**soul-api 支持**`GET /api/miniprogram/config` 已存在,返回 mpConfig含 apiDomain、appId、mchId 等)。需在 mp_config 或 defaultMp 中增加 `auditMode``supportWechat` 字段,供管理端配置。
---
### 2.2 index 页面 - 审核模式
| 功能项 | 稳定版 | 体验版 | 迁移建议 |
|--------|--------|--------|----------|
| **超级个体空态按钮** | 始终显示 | 按 auditMode 隐藏 | **P1** |
| **data** | 无 auditMode | auditMode: false | - |
| **onShow** | 无 | 同步 app.globalData.auditMode | - |
---
### 2.3 my 页面 - 审核模式
| 功能项 | 稳定版 | 体验版 | 迁移建议 |
|--------|--------|--------|----------|
| **become-member-btn** | 无 auditMode | wx:if="{{!auditMode}}" | **P1** |
| **vip-tags** | 无 | wx:if="{{!auditMode}}" | **P1** |
| **profile-stat 推荐/收益** | referralEnabled | auditMode | **保留**稳定版 referralEnabled |
| **profile-stat 余额** | 无 | wx:if="{{!auditMode}}" | **P1** |
| **receive-card** | 无 auditMode | wx:if="{{... && !auditMode}}" | **P1** |
| **profile-name-actions** | ✅ 有编辑按钮 | ❌ 无 | **勿回退** |
---
### 2.4 wallet 页面 - 审核模式
| 功能项 | 稳定版 | 体验版 | 迁移建议 |
|--------|--------|--------|----------|
| **data** | 无 auditMode | auditMode: false | **P1** |
| **onLoad** | 无 | 同步 app.globalData.auditMode | **P1** |
---
### 2.5 read 页面 - 分享功能与图标
| 功能项 | 稳定版 | 体验版 | 迁移建议 |
|--------|--------|--------|----------|
| **操作区分享** | 朋友圈→海报→代付 | 分享→代付→海报 | 按产品需求 |
| **share-tip-inline** | 无 | 有「分享后好友购买,你可获得 90% 收益」 | 可选 |
| **右下角悬浮按钮** | share.svg + open-type="share" | 🌐 emoji + shareToMoments | 已迁为体验版 |
---
### 2.6 read 页面 - 审核模式与配置
| 功能项 | 稳定版 | 体验版 | 迁移建议 |
|--------|--------|--------|----------|
| **config 预加载** | linkTags、linkedMiniprograms | 含 personsConfig | **P3** |
| **data** | walletBalance、totalSections | auditMode、showShareTip | **P2** auditMode |
| **wx.showShareMenu** | menus: ['shareAppMessage','shareTimeline'] | withShareTimeline: true | 均可 |
---
## 三、稳定版有、体验版无(勿回退)
### 3.1 gift-pay/detail
| 功能项 | 稳定版 | 体验版 | 说明 |
|--------|--------|--------|------|
| **UI 结构** | hero-card、requester-card、footer-bar、bg-effects | 简单 card | **勿回退** |
| **发起人信息** | 可点击头像跳 member-detail | 无 | **勿回退** |
| **跳转文章** | goToArticle 跳 read | 无 | **勿回退** |
| **doPay 登录** | 静默 getOpenId失败再弹 modal | 直接 toast | **勿回退** |
| **支付失败** | 识别 prepay 错误并重试 | 简单 toast | **勿回退** |
### 3.2 my 页面 - 编辑入口
| 功能项 | 稳定版 | 体验版 | 说明 |
|--------|--------|--------|------|
| **profile-name-actions** | ✅ 有编辑按钮 | ❌ 无 | **保留**稳定版 |
### 3.3 utils - ruleEngine
| 功能项 | 稳定版 | 体验版 | 说明 |
|--------|--------|--------|------|
| **ruleEngine** | ✅ app.js 引用 | ❌ 无 | **保留**稳定版 |
---
## 四、迁移优先级建议
| 优先级 | 迁移项 | 稳定版→体验版 |
|--------|--------|---------------|
| **P0** | app.js 运行时配置 | 稳定版缺,体验版有 |
| **P0** | app.js loadMpConfig 扩展 | 稳定版缺 auditMode体验版有 |
| **P0** | soul-api mp_config | 增加 auditMode、supportWechat |
| **P1** | index/my/wallet auditMode | 稳定版缺,体验版有 |
| **P2** | app.js request timeout | 稳定版缺,体验版有 |
| **P2** | read auditMode | 稳定版缺,体验版有 |
| **P3** | read personsConfig、showShareTip | 可选 |
---
## 五、不迁移项(维持现状)
| 项 | 说明 |
|----|------|
| gift-pay/detail 从新版迁 | 稳定版 UI 与逻辑更完善,无需回退 |
| 稳定版 ruleEngine | 已迁移,保留 |
| 稳定版 profile-name-actions | 保留,新版无 |
---
## 六、功能闭环 Checklist每功能必过
```
□ 界面:页面、交互、数据绑定
□ 接口API 存在、参数正确、响应格式规范
□ 数据DB/事务/幂等(若涉及)
□ 边界:未登录、余额不足、网络失败
□ 三端:小程序+后端+管理端(如需)是否都改到
□ 保护区域:未动 @/#、分销、支付 核心逻辑
```
---
## 七、文档产出
| 文档 | 路径 |
|------|------|
| **需求采纳清单** | `开发文档/新版迁移-需求采纳清单.md`(勾选是否采纳) |
| 功能差异清单 | `开发文档/新版迁移-功能差异清单.md`(本文档) |
| 迁移方案/清单 | `开发文档/新版迁移-开发方案与清单.md` |
---
**迁移前必做需求评审**:列出功能点 + 样式变更,逐一确认后再迁。先做功能对齐与取舍,评审通过后按最小功能迁移;界面修改先迁、大逻辑排后。

View File

@@ -1,107 +0,0 @@
# 新版迁移 - 开发方案与清单
> 从 new-soul 迁移到稳定版 miniprogram 的完整开发方案,整合需求、经营、技术、运营视角。
> 更新日期2026-03-16
---
## 一、迁移范围总览
| 需求 | 说明 | 优先级 |
|------|------|--------|
| R1R4 | 余额体系:充值、消费、交易记录、退款 | P0 |
| R5 | 我的页「我的余额」入口 | P0 |
| R2 | 阅读页余额购买(章节/全书) | P0 |
| R6R8 | 首页精选/最新展开、按热度 | P1 |
| R9R10 | 代付(我的代付链接 + 阅读页代付分享) | P2 |
| R11 | 埋点 trackClick | P0 |
| VIP 余额 | VIP 页支持余额购买 | P1 |
| 管理端 | 订单支付方式、用户详情余额 | P0 |
---
## 二、技术实现要点
### 2.1 余额消费必须写 orders
同一事务内:扣 user_balances → 写 balance_transactions → 写 ordersproduct_type、status=paid、payment_method=balance。否则 check-purchased、purchase-status 失效。
### 2.2 分销 + 余额消费
consume 入参增加 referralCode创建订单时与 pay 一致解析 referrer_id、计算佣金。
### 2.3 充值流程
1. POST balance/recharge → 创建 ordersproduct_type=balance_recharge, status=created→ 返回 orderSn
2. POST payproductType=balance_recharge, productId=orderSn→ 后端从 orders 查 amount
3. 支付成功 → 前端调 recharge/confirmPayNotify 也触发加余额(幂等)
### 2.4 consume 价格校验
后端必须用 getStandardPrice 校验 amount禁止仅信前端。
---
## 三、实现清单(可执行)
### soul-api
| # | 任务 | 接口/表 | 状态 |
|---|------|---------|:----:|
| 1 | 埋点 | POST /api/miniprogram/track | ✅ |
| 2 | 余额表 | user_balances、balance_transactions | ✅ |
| 3 | 余额接口 | GET balance、GET transactions、POST recharge、POST recharge/confirm、POST refund、POST consume | ✅ |
| 4 | pay 扩展 | productType=balance_recharge从 orders 取 amount | ✅ |
| 5 | PayNotify | balance_recharge 分支,加余额幂等 | ✅ |
| 6 | BookHot | 支持 ?limit=,最大 50 | ✅ |
| 7 | orders | 增加 payment_method 字段 | ✅ |
| 8 | 管理端 | GET /api/admin/users/:id/balance | ✅ |
### miniprogram
| # | 任务 | 文件 | 状态 |
|---|------|------|:----:|
| 1 | trackClick | utils/trackClick.js | ✅ |
| 2 | wallet 页 | pages/wallet/* | ✅ |
| 3 | 我的页 | 余额入口、handleMenuTap wallet、loadWalletBalance | ✅ |
| 4 | read 页 | 余额支付、walletBalance 拉取 | ✅ |
| 5 | 首页 | featuredExpanded、latestExpanded、book/hot?limit=50 | ✅ |
| 6 | VIP 页 | 余额支付分支 | ✅ |
### soul-admin
| # | 任务 | 说明 | 状态 |
|---|------|------|:----:|
| 1 | 订单支付方式 | balance → 余额支付 | ✅ |
| 2 | 余额订单 | 不展示退款按钮 | ✅ |
| 3 | 用户详情 | 余额 + 最近交易 | ✅ |
---
## 四、开发顺序
```
1. soul-api: 余额表 + 接口 + pay 扩展 + PayNotify + track + BookHot limit + payment_method
2. soul-api: 管理端用户余额接口
3. miniprogram: trackClick + wallet + 我的页 + read 页余额
4. miniprogram: 首页展开 + VIP 余额
5. soul-admin: 订单展示 + 用户详情余额
```
---
## 五、不迁移项
ruleEngine、user-rules、loadRuntimeConfig。avatar-nickname 保留迁移(稳定版已有,继续使用)。
---
## 六、数据库迁移
执行 `soul-api/scripts/add-balance-tables.sql` 创建 user_balances、balance_transactions并为 orders 增加 payment_method 列。GORM AutoMigrate 也会自动同步。
---
## 七、实现说明2026-03-16
已完成:余额体系(充值/消费/退款、埋点、我的页余额入口、阅读页余额支付、VIP 页余额支付、管理端订单展示与用户详情余额、首页精选/最新展开、搜索页 book/hot?limit=50。代付链接后端 GET /api/miniprogram/gift/link + gift-link 页对接。阅读页代付分享为后续迭代项。

View File

@@ -1,129 +0,0 @@
# 新版迁移 - 管理端功能差异清单new-soul vs soul-admin
> 更新日期2026-03-18
**目录说明**
- `new-soul/soul-admin`new-soul 版本(对照)
- `soul-admin/`:当前稳定版(根目录,线上部署)
> **保护区(强约束)**:文章详情富文本编辑与保存解析 @/# 标签等逻辑(如 `RichEditor` 相关)**不要动**,本清单不包含对该区域的任何改造建议。
---
## 一、差异摘要(按页面/模块)
### 1.1 页面/路由集合结论
-**两边页面文件集合一致**`src/pages/**/*.tsx` 差集为 0only_new=0、only_old=0
-**路由结构一致**`App.tsx` 两边路由项一致dashboard/orders/users/distribution/withdrawals/content/settings 等)。
因此,“未迁移”主要不是缺页面,而是**同页面内部的功能点实现深度不同**。
### 1.2 功能点差异表(按模块)
| 页面/模块 | new-soul/soul-admin | soul-admin | 结论(以谁为准) |
|-----------|---------------------------|-------------------|----------|
| **Settings** | aboutEnabled无 auditMode | aboutEnabled✅ auditMode审核模式开关 | 以 soul-admin 为准new-soul 可补齐) |
| **Dashboard** | ✅ giftedTotal、✅ track/stats订单列表固定 5formatOrderProduct 分支较少 | ✅ giftedTotal、✅ track/stats、✅ ordersExpanded(4→10)、✅ balance_recharge/gift_pay_batch 等格式化 | 以 soul-admin 为准new-soul 可补齐) |
| **DistributiongiftPay tab** | 有 giftPay 列表与筛选(未核对 refunded 展示) | 已补齐 refunded 筛选与徽章 | 以 soul-admin 为准 |
| **Content/Users/Orders/Withdrawals…** | 文件存在 | 文件存在 | 需按功能点逐项复核(本次优先聚焦 Settings/Dashboard |
---
## 二、Settings 页对比(结论)
### 2.1 auditMode小程序审核模式
| 项 | new-soul/soul-admin | soul-admin | 建议 |
|---|---|---|---|
| 字段与保存 | ❌ mpConfig 无 auditMode | ✅ mpConfig.auditMode + 单独保存逻辑 | new-soul 补齐到与 soul-admin 一致 |
| UI | - | ✅ 审核模式卡片/提示文案 | new-soul 复用 soul-admin 的 UI 与交互 |
### 2.2 aboutEnabled关于页面开关
两边都已有 `featureConfig.aboutEnabled` 开关与保存逻辑,差异不大。
---
## 三、Dashboard 页面对比
### 3.1 统计卡片giftedTotal 子文案)
两边都已有 giftedTotal并在收入卡片显示「含代付 ¥xx」子文案。
---
### 3.2 最近订单(是否可展开 4→10
| 项 | new-soul/soul-admin | soul-admin | 建议 |
|---|---|---|---|
| 显示条数 | 固定 5 条 | ✅ 默认 4 条,可展开至 10 条 | new-soul 补齐 ordersExpanded同 soul-admin |
| recent-orders limit | 未传 limit 参数 | ✅ `/recent-orders?limit=10` | new-soul 对齐 limit=10 |
---
### 3.3 埋点统计track/stats
两边均已调用 `/api/admin/track/stats?period=...`,差异不大。
---
## 四、Dashboard 商品类型展示formatOrderProduct
| 项 | new-soul/soul-admin | soul-admin | 建议 |
|---|---|---|---|
| balance_recharge | ❌ 未特殊处理 | ✅ 特殊处理为「余额充值 ¥xx」 | new-soul 补齐 |
| gift_pay_batch | ❌ 未特殊处理 | ✅ 特殊处理为「代付分享」等 | new-soul 补齐 |
| 代付领取 | 部分处理 | ✅ 处理更完整(含 desc 文案) | new-soul 参考 soul-admin 对齐 |
---
## 五、迁移优先级建议(如果目标是对齐两端)
> 注意:本仓库当前状态下,**soul-admin 的实现更完整**;若要统一体验,应把差异从 soul-admin 同步到 new-soul。
| 优先级 | 迁移项soul-admin → new-soul | 原因 |
|--------|-------------------------------|------|
| **P0** | SettingsauditMode 开关与保存 | 影响小程序审核隐藏支付入口 |
| **P1** | DashboardordersExpanded4→10与 recent-orders limit=10 | 体验更好、信息密度更高 |
| **P1** | DashboardformatOrderProduct 补齐 balance_recharge/gift_pay_batch/代付领取 | 订单类型展示更准确 |
---
## 六、接口与数据层检查
| 接口 | 稳定版 | 体验版 | soul-api 支持 |
|------|--------|--------|---------------|
| GET /api/admin/settings | ✅ | ✅ | ✅ |
| POST /api/admin/settings | ✅ mpConfig/featureConfig/siteSettings/ossConfig | ✅ mpConfig/featureConfig/siteSettings/ossConfig | ✅camelCase |
| GET /api/admin/track/stats | ❌ 未用 | ✅ period=week/day | 需确认 |
| GET /api/admin/dashboard/stats | ✅ | ✅ | ✅ |
| GET /api/admin/dashboard/overview | ✅ | ✅ | ✅ |
---
## 七、功能闭环 Checklist每功能必过
```
□ 界面:页面、交互、数据绑定
□ 接口API 存在、参数正确、响应格式规范
□ 数据DB/配置存储system_config 表)
□ 边界:保存失败、加载失败
□ 三端:管理端 + soul-apimp_config 需供小程序 config 读取)
□ 保护区域:未动分销、支付核心逻辑
```
---
## 八、文档产出
| 文档 | 路径 |
|------|------|
| **需求采纳清单** | `开发文档/新版迁移-需求采纳清单.md`(勾选是否采纳) |
| 管理端功能差异清单 | `开发文档/新版迁移-管理端功能差异清单.md`(本文档) |
| 小程序功能差异清单 | `开发文档/新版迁移-功能差异清单.md` |
| 迁移完成度 | `开发文档/迁移完成度与待办清单.md` |
---
**迁移前必做需求评审**:列出功能点 + 样式变更,逐一确认后再迁。

View File

@@ -1,61 +0,0 @@
# 新版迁移 - 需求采纳清单
> 推荐迁移项汇总,供选择是否采纳。勾选 ☐ 表示采纳,☑ 表示已确认采纳。
> 更新日期2026-03-17
**标签说明**
- **🔴 必选**:提审/生产必备,建议优先
- **🟠 推荐**:有明显价值,建议采纳
- **🟡 可选**:按需采纳
- **⚪ 不迁**:明确不迁移
**乘风建议2026-03-17**X1/X2/X7 与审核模式配套必迁X8/X9 低成本建议采纳M6 因 soul-api 暂无 track/stats 接口待接口就绪后再迁X10 保持不迁。
---
## 一、管理端soul-admin
| 序号 | 功能项 | 标签 | 简要说明 | 采纳 |
|:----:|--------|------|----------|:----:|
| M1 | 小程序审核模式 | 🔴 必选 | 系统设置 → 审核模式开关,提审前隐藏支付入口 | ☑ |
| M2 | 关于页面开关 aboutEnabled | 🟠 推荐 | 功能开关第 4 项,控制关于页访问 | ☑ |
| M3 | Dashboard 代付金额 giftedTotal | 🟠 推荐 | 总收入下显示「含代付 ¥xx」 | ☑ |
| M4 | Dashboard 订单展开 | 🟠 推荐 | 默认 4 条,可展开至 10 条 | ☑ |
| M5 | 订单类型 balance_recharge | 🟡 可选 | 订单列表正确展示余额充值类型 | ☑ |
| M6 | 埋点统计 track/stats | 🟡 可选 | 依赖 /api/admin/track/statssoul-api 暂无,待接口就绪) | ☐ |
---
## 二、小程序miniprogram
| 序号 | 功能项 | 标签 | 简要说明 | 采纳 |
|:----:|--------|------|----------|:----:|
| X1 | app.js 运行时配置 | 🔴 必选 | getRuntimeBootstrapConfig避免生产用 localhost | ☑ |
| X2 | app.js loadMpConfig 扩展 | 🔴 必选 | 支持 apiDomain、auditMode、supportWechat | ☑ |
| X3 | soul-api mp_config | 🔴 必选 | 增加 auditMode、supportWechat 字段 | ☑ |
| X4 | index 超级个体按 auditMode 隐藏 | 🟠 推荐 | 审核时隐藏超级个体空态按钮 | ☑ |
| X5 | my 页支付相关按 auditMode 隐藏 | 🟠 推荐 | 会员、收益、余额、一键收款 | ☑ |
| X6 | wallet 页 auditMode | 🟠 推荐 | 审核时隐藏或提示 | ☑ |
| X7 | read 页 auditMode | 🟠 推荐 | 购买按钮等按审核隐藏 | ☑ |
| X8 | app.js request timeout | 🟡 可选 | 15s 超时,避免长时间挂起 | ☑ |
| X9 | read share-tip-inline | 🟡 可选 | 「分享后好友购买,你可获得 90% 收益」 | ☑ |
| X10 | read personsConfig、showShareTip | ⚪ 不迁 | 按需,优先级低 | ☐ |
---
## 三、不迁移项(维持现状)
| 项 | 说明 |
|----|------|
| gift-pay/detail 从体验版迁 | 稳定版 UI 与逻辑更完善 |
| 稳定版 ruleEngine | 保留 |
| 稳定版 profile-name-actions | 保留编辑入口 |
| 稳定版 referralEnabled | 保留,与 auditMode 并存 |
---
## 四、采纳后执行
1. 将 ☐ 改为 ☑ 表示确认采纳
2. 按标签优先级排期:🔴 → 🟠 → 🟡
3. 迁移完成后执行 `change-checklist` 三端关联检查

View File

@@ -1,32 +0,0 @@
# 文章阅读与界面预览 GET 接口响应速度测试报告
**测试时间**: 2026-03-18 12:43
**测试环境**: 正式 (https://soulapi.quwanzhi.com)
**每接口请求次数**: 5
## 一、测试范围
| 分类 | 接口 | 说明 |
|------|------|------|
| 界面预览 | GET /api/miniprogram/config | 配置(价格、功能开关等) |
| 界面预览 | GET /api/miniprogram/book/parts | 目录-篇章列表 |
| 界面预览 | GET /api/miniprogram/book/all-chapters | 全书章节列表 |
| 界面预览 | GET /api/miniprogram/book/chapters-by-part | 篇章内章节列表 |
| 文章阅读 | GET /api/miniprogram/book/chapter/:id | 按业务 id 获取章节内容 |
| 文章阅读 | GET /api/miniprogram/book/chapter/by-mid/:mid | 按 mid 获取章节内容 |
## 二、响应速度结果
| 接口 | 状态 | 平均(ms) | 最小(ms) | 最大(ms) |
|------|------|----------|----------|----------|
| GET /api/miniprogram/config | OK | 390 | 378 | 406 |
| GET /api/miniprogram/book/parts | OK | 396 | 387 | 403 |
| GET /api/miniprogram/book/all-chapters | OK | 390 | 376 | 407 |
| GET /api/miniprogram/book/chapters-by-part?partId=part-2026-daily | OK | 420 | 416 | 424 |
| GET /api/miniprogram/book/chapter/:id | OK | 420 | 401 | 425 |
| GET /api/miniprogram/book/chapter/by-mid/:mid | OK | 424 | 419 | 431 |
## 三、汇总
- 通过: 6/6
- 全部接口平均响应: 406ms

View File

@@ -1,269 +0,0 @@
# 稳定版 vs 新版 · 小程序与 API 对比清单
> 稳定版:`miniprogram/`;新版:`new-soul/miniprogram/`
> 生成日期2026-03-16
---
## 一、页面差异
| 页面 | 稳定版 | 新版 | 说明 |
|------|:-----:|:----:|------|
| pages/avatar-nickname | ✓ | ✗ | 新版移除,可能合并到 profile-edit |
| pages/wallet | ✗ | ✓ | **新版新增**:钱包(余额、充值、退款、交易记录) |
| 其它 22 页 | ✓ | ✓ | 一致 |
---
## 二、小程序页面清单(稳定版)
| 页面路径 | 功能 | Tab |
|---------|------|-----|
| pages/index/index | 首页 | ✓ |
| pages/chapters/chapters | 目录 | ✓ |
| pages/match/match | 找伙伴 | ✓ |
| pages/my/my | 我的 | ✓ |
| pages/read/read | 文章阅读 | - |
| pages/link-preview/link-preview | 链接预览 | - |
| pages/about/about | 关于作者 | - |
| pages/agreement/agreement | 用户协议 | - |
| pages/privacy/privacy | 隐私政策 | - |
| pages/referral/referral | 推广中心 | - |
| pages/purchases/purchases | 我的订单 | - |
| pages/settings/settings | 设置 | - |
| pages/search/search | 搜索 | - |
| pages/addresses/addresses | 收货地址列表 | - |
| pages/addresses/edit | 地址编辑 | - |
| pages/withdraw-records/withdraw-records | 提现记录 | - |
| pages/vip/vip | VIP 购买 | - |
| pages/member-detail/member-detail | 会员/用户详情 | - |
| pages/mentors/mentors | 导师列表 | - |
| pages/mentor-detail/mentor-detail | 导师详情 | - |
| pages/profile-show/profile-show | 资料展示 | - |
| pages/profile-edit/profile-edit | 资料编辑 | - |
| pages/avatar-nickname/avatar-nickname | 头像昵称 | - |
---
## 三、小程序调用的 API 清单(稳定版,按模块)
### 3.1 配置与登录
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/config | GET | app.js, my.js, read.js, chapterAccessManager.js, custom-tab-bar | 公开配置persons、linkTags、freeChapters 等) |
| /api/miniprogram/login | POST | app.js | 微信 code 登录 |
| /api/miniprogram/phone-login | POST | app.js | 手机号一键登录 |
| /api/miniprogram/phone | POST | index.js, settings.js | 获取手机号 |
| /api/miniprogram/dev/login-as | POST | settings.js | 开发专用:按 userId 切换账号 |
### 3.2 书籍/章节
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/book/all-chapters | GET | app.js, index.js, read.js | 全量章节树 |
| /api/miniprogram/book/parts | GET | chapters.js | 篇章列表(懒加载) |
| /api/miniprogram/book/chapters-by-part | GET | chapters.js | 按篇章返回章节 |
| /api/miniprogram/book/chapter/:id | GET | read.js | 按 id 获取章节 |
| /api/miniprogram/book/chapter/by-mid/:mid | GET | read.js | 按 mid 解析章节 |
| /api/miniprogram/book/hot | GET | search.js | 热门排行 |
| /api/miniprogram/book/recommended | GET | index.js | 推荐章节 |
| /api/miniprogram/book/latest-chapters | GET | index.js | 最新章节 |
| /api/miniprogram/book/search | GET | search.js | 搜索 |
| /api/miniprogram/book/stats | GET | about.js | 书籍统计 |
### 3.3 用户/资料
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/user/profile | GET/POST | profile-show, profile-edit, member-detail, index, read, match, my, settings, avatar-nickname | 用户资料 |
| /api/miniprogram/user/update | POST | my.js, settings.js | 更新用户(头像、昵称等) |
| /api/miniprogram/user/purchase-status | GET | read.js, chapterAccessManager.js | 购买状态VIP/买断/单章) |
| /api/miniprogram/user/check-purchased | GET | chapterAccessManager.js | 校验是否已购买 |
| /api/miniprogram/user/dashboard-stats | GET | my.js | 阅读统计(我的页) |
| /api/miniprogram/user/reading-progress | GET/POST | readingTracker.js | 阅读进度 |
| /api/miniprogram/user/addresses | GET/POST | addresses.js, addresses/edit.js | 收货地址 CRUD |
| /api/miniprogram/user/addresses/:id | GET/PUT/DELETE | addresses.js, addresses/edit.js | 单条地址 |
### 3.4 VIP
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/vip/status | GET | vip.js, chapters.js, my.js, profile-edit | VIP 状态 |
| /api/miniprogram/vip/members | GET | index.js, member-detail.js | VIP 会员列表/单个 |
| /api/miniprogram/vip/profile | GET/POST | 未直接调用vip 组有) | VIP 资料 |
### 3.5 支付与订单
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/pay | GET/POST | read.js, vip.js, match.js | 创建订单/查询 |
| /api/miniprogram/orders | GET | purchases.js | 订单列表 |
| /api/miniprogram/qrcode | POST | read.js, referral.js | 生成小程序码 |
### 3.6 分销/推广
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/referral/visit | POST | app.js | 访问记录 |
| /api/miniprogram/referral/bind | POST | app.js | 绑定推广关系 |
| /api/miniprogram/referral/data | GET | referral.js | 推广数据 |
| /api/miniprogram/earnings | GET | my.js | 我的收益 |
| /api/miniprogram/withdraw | POST | my.js, referral.js | 申请提现 |
| /api/miniprogram/withdraw/records | GET | withdraw-records.js | 提现记录 |
| /api/miniprogram/withdraw/pending-confirm | GET | my.js | 待确认收款 |
| /api/miniprogram/withdraw/confirm-received | POST | my.js | 确认收款 |
| /api/miniprogram/withdraw/confirm-info | GET | my.js, withdraw-records.js | 领取零钱参数 |
### 3.7 存客宝CKB
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/ckb/index-lead | POST | index.js | 首页「链接卡若」留资 |
| /api/miniprogram/ckb/lead | POST | read.js | 文章 @某人 留资 |
| /api/miniprogram/ckb/match | POST | match.js | 找伙伴留资 |
| /api/miniprogram/ckb/join | POST | match.js | 加入匹配池 |
### 3.8 找伙伴
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/match/config | GET | match.js | 找伙伴配置 |
| /api/miniprogram/match/users | POST | match.js | 匹配用户 |
### 3.9 导师
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/mentors | GET | mentors.js | 导师列表 |
| /api/miniprogram/mentors/:id | GET | mentor-detail.js | 导师详情 |
| /api/miniprogram/mentors/:id/book | POST | mentor-detail.js | 预约导师 |
### 3.10 其它
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/upload | POST | my.js, profile-edit, settings, avatar-nickname | 图片上传 |
| /api/miniprogram/users | GET | index.js, member-detail.js | 用户列表/单个(超级个体、回退) |
| /api/miniprogram/about/author | GET | about.js | 关于作者配置 |
---
## 四、soul-api 已注册的 miniprogram 路由(稳定版)
| 路由 | 方法 | Handler |
|------|------|---------|
| /api/miniprogram/config | GET | GetPublicDBConfig |
| /api/miniprogram/login | POST | MiniprogramLogin |
| /api/miniprogram/phone-login | POST | WechatPhoneLogin |
| /api/miniprogram/dev/login-as | POST | MiniprogramDevLoginAs |
| /api/miniprogram/phone | POST | MiniprogramPhone |
| /api/miniprogram/pay | GET/POST | MiniprogramPay |
| /api/miniprogram/pay/notify | POST | MiniprogramPayNotify |
| /api/miniprogram/qrcode | POST | MiniprogramQrcode |
| /api/miniprogram/qrcode/image | GET | MiniprogramQrcodeImage |
| /api/miniprogram/book/all-chapters | GET | BookAllChapters |
| /api/miniprogram/book/parts | GET | BookParts |
| /api/miniprogram/book/chapters-by-part | GET | BookChaptersByPart |
| /api/miniprogram/book/chapter/:id | GET | BookChapterByID |
| /api/miniprogram/book/chapter/by-mid/:mid | GET | BookChapterByMID |
| /api/miniprogram/book/hot | GET | BookHot |
| /api/miniprogram/book/recommended | GET | BookRecommended |
| /api/miniprogram/book/latest-chapters | GET | BookLatestChapters |
| /api/miniprogram/book/search | GET | BookSearch |
| /api/miniprogram/book/stats | GET | BookStats |
| /api/miniprogram/referral/visit | POST | ReferralVisit |
| /api/miniprogram/referral/bind | POST | ReferralBind |
| /api/miniprogram/referral/data | GET | ReferralData |
| /api/miniprogram/earnings | GET | MyEarnings |
| /api/miniprogram/match/config | GET | MatchConfigGet |
| /api/miniprogram/match/users | POST | MatchUsers |
| /api/miniprogram/ckb/join | POST | CKBJoin |
| /api/miniprogram/ckb/match | POST | CKBMatch |
| /api/miniprogram/ckb/lead | POST | CKBLead |
| /api/miniprogram/ckb/index-lead | POST | CKBIndexLead |
| /api/miniprogram/upload | POST/DELETE | UploadPost / UploadDelete |
| /api/miniprogram/user/addresses | GET/POST | UserAddressesGet/Post |
| /api/miniprogram/user/addresses/:id | GET/PUT/DELETE | UserAddressesByID |
| /api/miniprogram/user/check-purchased | GET | UserCheckPurchased |
| /api/miniprogram/user/dashboard-stats | GET | UserDashboardStats |
| /api/miniprogram/user/profile | GET/POST | UserProfileGet/Post |
| /api/miniprogram/user/purchase-status | GET | UserPurchaseStatus |
| /api/miniprogram/user/reading-progress | GET/POST | UserReadingProgressGet/Post |
| /api/miniprogram/user/update | POST | UserUpdate |
| /api/miniprogram/withdraw | POST | WithdrawPost |
| /api/miniprogram/withdraw/records | GET | WithdrawRecords |
| /api/miniprogram/withdraw/pending-confirm | GET | WithdrawPendingConfirm |
| /api/miniprogram/withdraw/confirm-received | POST | WithdrawConfirmReceived |
| /api/miniprogram/withdraw/confirm-info | GET | WithdrawConfirmInfo |
| /api/miniprogram/vip/status | GET | VipStatus |
| /api/miniprogram/vip/profile | GET/POST | VipProfileGet/Post |
| /api/miniprogram/vip/members | GET | VipMembers |
| /api/miniprogram/users | GET | MiniprogramUsers |
| /api/miniprogram/orders | GET | MiniprogramOrders |
| /api/miniprogram/mentors | GET | MiniprogramMentorsList |
| /api/miniprogram/mentors/:id | GET | MiniprogramMentorsDetail |
| /api/miniprogram/mentors/:id/book | POST | MiniprogramMentorsBook |
| /api/miniprogram/about/author | GET | MiniprogramAboutAuthor |
---
## 五、对齐情况
| 状态 | 说明 |
|------|------|
| ✓ 已对齐 | 小程序调用的所有 `/api/miniprogram/*` 接口均在 soul-api router 中注册 |
| - | 小程序未调用 `/api/miniprogram/vip/profile`,但后端已提供(备用) |
---
## 六、新版new-soul新增 API稳定版 soul-api 暂无)
| 接口 | 方法 | 调用位置 | 用途 |
|------|------|----------|------|
| /api/miniprogram/balance | GET | wallet.js | 查询余额、累计充值/赠送/退款 |
| /api/miniprogram/balance/transactions | GET | wallet.js | 交易记录列表 |
| /api/miniprogram/balance/recharge | POST | wallet.js | 创建充值订单 |
| /api/miniprogram/balance/recharge/confirm | POST | wallet.js | 支付成功后确认充值 |
| /api/miniprogram/balance/refund | POST | wallet.js | 余额退款 |
| /api/miniprogram/user-rules | GET | ruleEngine.js | 规则引擎:按场景触发引导 |
| /api/miniprogram/track | POST | trackClick.js, ruleEngine.js | 埋点上报 |
**说明**:新版 wallet 页的支付流程为:`balance/recharge``pay`productType: 'balance_recharge')→ `balance/recharge/confirm`。稳定版 soul-api 需新增上述路由才能支持新版钱包功能。
---
## 七、新版新增能力(稳定版无)
| 能力 | 说明 |
|------|------|
| **规则引擎** | `utils/ruleEngine.js` + `/api/miniprogram/user-rules`,按 page_show、after_login 等场景触发引导 |
| **埋点上报** | `utils/trackClick.js` + `/api/miniprogram/track` |
| **运行配置** | `loadRuntimeConfig()` 从 config 取 `mpConfig.apiDomain` 等,支持动态覆盖 baseUrl |
| **单页模式** | `ensureFullAppForAuth()` 检测朋友圈单页,引导用户「前往小程序」 |
| **更新检测** | `checkUpdate()` 基于 wx.getUpdateManager |
| **navigateToMiniProgramAppIdList** | 新版 app.json 配置 `wx6489c26045912fe1``wx3d15ed02e98b04e3` |
| **我的页** | 新版有 `loadWalletBalance``loadGiftList`(代付链接) |
---
## 八、config 返回格式差异
| 字段 | 稳定版 | 新版 |
|------|--------|------|
| 主结构 | persons、linkTags、freeChapters、prices 等 | 同上 + `mpConfig``features` |
| mpConfig | - | apiDomain、appId、mchId、withdrawSubscribeTmplId |
| features | - | matchEnabled 等 |
| configs.feature_config | - | 备用格式,含 matchEnabled |
---
## 九、迁移建议
1. **后端**soul-api 需新增 balance、user-rules、track 相关路由,才能完整支持新版。
2. **稳定版→新版**:若稳定版要升级,需补充 wallet 页、ruleEngine、trackClick并调整 config 返回格式。
3. **新版→稳定版**:若新版要回退,需移除 wallet、user-rules、track 依赖,或在后端做空实现。
---
*文档由助理橙子生成 | 基于 miniprogram/、new-soul/miniprogram/ 与 soul-api/internal/router/router.go 扫描*

View File

@@ -1,175 +0,0 @@
# Soul 创业派对稳定版 - 源码质量分析报告
> 分析时间2026-03-17
> 分析人:乘风(老板分身)
---
## 一、高优先级(建议优先处理)
### 1. soul-api敏感配置默认值泄露
**位置**`soul-api/internal/config/config.go` 第 174237 行
**问题**AppSecret、MchKey、APIv3Key、adminPassword、adminSessionSecret、证书序列号等敏感信息有硬编码默认值。若 `.env` 未配置,将使用这些默认值,存在泄露与撞库风险。
**建议**
- 生产环境强制从环境变量读取,缺则 `log.Fatal` 启动失败
- 或使用占位符如 `"MUST_SET_IN_ENV"`,启动时校验并拒绝
---
### 2. soul-api`/api/user/track` 无鉴权
**位置**`soul-api/internal/router/router.go` 第 260261 行;`soul-api/internal/handler/user.go` 第 535 行
**问题**`GET /api/user/track?userId=xxx` 无 AdminAuth任何人可查任意用户行为轨迹。管理端 `UserDetailModal` 调用此接口展示用户行为。
**建议**
- 将接口迁至 `/api/admin/user/track``/api/db/user/track`,并加 `AdminAuth()` 中间件
- 或保留路径,在 handler 内校验管理员 token
---
### 3. miniprogram`payment.js` 使用未定义变量
**位置**`miniprogram/utils/payment.js` 第 25 行
**问题**:使用 `app.globalData.apiBase`,而 app 中仅有 `baseUrl`,会导致 `undefined + '/payment/create'`,请求失败。
**说明**:当前支付流程在 `read.js` 中直接调用 `/api/miniprogram/pay`,未使用 `payment.js`,该文件疑似废弃。若确认废弃,建议删除;若保留,需改为 `baseUrl` 并统一走 miniprogram 支付接口。
---
## 二、中优先级
### 4. miniprogram`goToMatch()` 重复定义
**位置**`miniprogram/pages/my/my.js` 第 801、816 行
**问题**:两个完全相同的 `goToMatch()`,后者覆盖前者,易造成维护困惑。
**建议**:删除其中一个。
---
### 5. miniprogram敏感信息硬编码
**位置**`miniprogram/app.js` 第 1825 行
**问题**appId、mchId、withdrawSubscribeTmplId 写死在代码中,与后端 config 重复。
**建议**:优先从 `/api/miniprogram/config``mpConfig` 读取,代码中仅保留开发兜底。
---
### 6. miniprogram开发接口暴露
**位置**`miniprogram/pages/settings/settings.js` 第 416 行
**问题**`dev/login-as` 在开发/体验版可见,生产需确保后端关闭或鉴权。
**建议**:后端对该接口做环境或 IP 白名单限制。
---
### 7. soul-adminRichEditor innerHTML 潜在 XSS
**位置**`soul-admin/src/components/RichEditor.tsx` 第 177 行
**问题**`popup.innerHTML = items.map(...)` 直接拼接 `item.name``item.label`,若含 HTML 可能 XSS。
**建议**:对 `name``label` 做 HTML 转义,或使用 `textContent` 渲染。
---
### 8. miniprogram`totalSections: 62` 多处硬编码
**位置**`app.js``index.js``my.js``chapters.js`
**问题**:章节总数写死为 62与真实数据可能不一致。
**建议**:从 `book/stats``all-chapters` 动态获取,或统一从 config 读取。
---
### 9. miniprogram废弃/备份文件
**位置**
- `miniprogram/pages/read/read.js.backup`
- `miniprogram/pages/referral/referral.wxss.backup`
**问题**:备份文件混入源码,增加噪音。
**建议**:若无需保留,可删除或移出版本库。
---
### 10. soul-admin`/api/user/track` 三端边界
**位置**`soul-admin/src/components/modules/user/UserDetailModal.tsx` 第 192 行
**问题**:管理端调用 `/api/user/track`(非 admin/db 路径),与「管理端只调 admin/db」约定不符。
**建议**:后端将 track 查询迁至 `/api/admin/user/track``/api/db/user/track`,管理端同步改路径。
---
## 三、低优先级
### 11. soul-api`DBUsersList` 函数过长
**位置**`soul-api/internal/handler/db.go`
**建议**:拆分为统计、过滤、分页等子函数,提升可读性。
---
### 12. soul-api`AdminWithdrawTest` 默认值
**位置**`soul-api/internal/handler/withdraw.go` 第 137138 行
**问题**:测试接口默认 userId、amount 写死,易误用。
**建议**:仅开发环境启用,或强制从请求体传入。
---
### 13. miniprogram错误处理不统一
**问题**:部分 `app.request``try/catch` 并提示用户,部分 `catch (e) {}` 静默吞错。
**建议**:统一约定:用户可见操作需提示,静默请求可吞错但需 `console.warn`
---
### 14. soul-admin上传逻辑重复
**位置**`ContentPage.tsx``MentorsPage.tsx`
**建议**:抽取公共 `uploadFile(apiUrl, file)` 方法复用。
---
### 15. 性能config / book 请求缓存
**问题**`/api/miniprogram/config``book/all-chapters` 等频繁请求,无本地缓存。
**建议**:对 config 做短期缓存(如 5 分钟),减少重复请求。
---
## 四、已确认无问题
- **三端路由边界**:小程序统一走 `/api/miniprogram/*`,管理端走 `/api/admin/*``/api/db/*`,主体符合约定
- **支付流程**`read.js` 正确使用 `/api/miniprogram/pay`,未依赖有问题的 `payment.js`
- **read.js.backup**:未在业务中引用,可安全清理
---
## 五、建议处理顺序
1. **立即**soul-api 敏感默认值、`/api/user/track` 鉴权
2. **短期**`payment.js` 废弃或修复、`goToMatch` 去重、`totalSections` 动态化
3. **中期**:管理端 track 路径迁移、RichEditor XSS 修复、配置与缓存优化
4. **长期**:代码结构优化、备份文件清理、错误处理统一

View File

@@ -1,123 +0,0 @@
# 稳定版:管理端与小程序功能对接分析
> 分析时间2026-03-17
> 分析人:乘风(老板分身)
> 更新2026-03-17 已完成 referralEnabled、searchEnabled 对接,删除 aboutEnabled 及关于作者页
## 一、结论概览
| 类型 | 数量 | 说明 |
|-----|------|------|
| ✅ 已对接 | 3 | matchEnabled、referralEnabled、searchEnabled |
| 🗑️ 已删除 | 1 | aboutEnabled、关于作者页 |
| ⚠️ 需确认 | 1 | site_settings 与 chapter_config 价格同步 |
---
## 二、功能开关feature_config对接情况
### 管理端配置项SettingsPage 系统设置)
| 开关 | 管理端 | 后端 config 返回 | 小程序使用 |
|-----|--------|------------------|------------|
| **matchEnabled** | ✅ 有 | ✅ features.matchEnabled | ✅ **已用**custom-tab-bar 控制找伙伴 tabmy 页根据此隐藏/显示找伙伴入口 |
| **referralEnabled** | ✅ 有 | ✅ features.referralEnabled | ✅ **已用**my 页推荐好友/我的收益入口 `wx:if`goToReferral 二次校验 |
| **searchEnabled** | ✅ 有 | ✅ features.searchEnabled | ✅ **已用**:首页搜索栏、目录页搜索按钮 `wx:if` |
| ~~aboutEnabled~~ | 🗑️ 已删除 | - | 关于作者页已移除 |
### 小程序实际使用(对接后)
- **custom-tab-bar**:读取 `matchEnabled`,控制找伙伴 tab
- **my.js**`loadFeatureConfig()` 取 matchEnabled、referralEnabled、searchEnabled存 globalData.features
- **my.wxml**:推荐好友/我的收益 `wx:if="{{referralEnabled}}"`;已删除关于作者菜单
- **index**`loadFeatureConfig()` 取 searchEnabled搜索栏 `wx:if="{{searchEnabled}}"`
- **chapters**`loadFeatureConfig()` 取 searchEnabled搜索按钮 `wx:if="{{searchEnabled}}"`
---
## 三、其他配置对接情况
### 已对接
| 配置项 | 来源 | 小程序使用位置 |
|--------|------|----------------|
| prices (section/fullbook) | chapter_config | read.js 展示价格、chapterAccessManager |
| userDiscount | referral_config | referral 页展示好友优惠 |
| linkTags | link_tag 表 | read.js onLinkTagTap |
| linkedMiniprograms | system_config | read.js 跳转关联小程序 |
| mpConfig | mp_config | 支付、提现等 |
### 需确认
| 配置项 | 说明 |
|--------|------|
| site_settings (sectionPrice, baseBookPrice) | 管理端保存到 `site_settings`,小程序 config 的 prices 来自 `chapter_config`。需确认两处是否同步,或是否有单独维护 chapter_config 的流程。 |
---
## 四、建议改造(补齐未用开关)
### 1. 推广开关 referralEnabled
**影响入口**我的页「推荐好友」「我的收益」统计、goToReferral 跳转
**改造建议**
- my.js`loadFeatureConfig()` 增加 `referralEnabled`
- my.wxml`profile-stat`(推荐好友、我的收益)加 `wx:if="{{referralEnabled}}"`
- 若有单独推广入口(如菜单项),也加 `wx:if="{{referralEnabled}}"`
### 2. 搜索开关 searchEnabled
**影响入口**:首页搜索栏、目录页搜索按钮
**改造建议**
- app.js 或各页:从 config 拉取 `searchEnabled` 存 globalData
- index.wxml搜索栏加 `wx:if="{{searchEnabled}}"`
- chapters.wxml搜索按钮加 `wx:if="{{searchEnabled}}"`
### 3. 关于作者开关 aboutEnabled
**影响入口**:我的页「关于作者」菜单项
**改造建议**
- my.js`loadFeatureConfig()` 增加 `aboutEnabled`
- my.wxml关于作者 menu-item 加 `wx:if="{{aboutEnabled}}"`
---
## 五、数据流说明
```
管理端 SettingsPage
→ POST /api/admin/settings { featureConfig }
→ 写入 system_config.feature_config
小程序
→ GET /api/miniprogram/config
→ GetPublicDBConfig 读取 feature_config合并到 features
→ 返回 { features: { matchEnabled, referralEnabled, searchEnabled, aboutEnabled } }
当前:仅 matchEnabled 被小程序使用
```
---
## 六、附录config 接口返回结构GetPublicDBConfig
```json
{
"success": true,
"prices": { "section": 1, "fullbook": 9.9 },
"features": {
"matchEnabled": true,
"referralEnabled": true,
"searchEnabled": true,
"aboutEnabled": true
},
"mpConfig": { "appId", "apiDomain", "buyerDiscount", ... },
"userDiscount": 5,
"linkTags": [...],
"linkedMiniprograms": [...],
"configs": { "chapter_config", "feature_config", "mp_config" }
}
```

View File

@@ -1,87 +0,0 @@
# 稳定版适配新界面 - 调整清单
> 基于 stitch_soul 设计稿与迁移方案,梳理稳定版 miniprogram 需调整项及完成路径。
> 更新日期2026-03-16
---
## 一、设计稿与当前状态对照
| 设计稿 | 页面 | 当前状态 | 待调整 |
|--------|------|----------|--------|
| optimized_home_content_feed_v1 | 首页 | 品牌+搜索、最新更新、**阅读进度**、超级个体、精选推荐、最新新增、展开折叠 | ✅ |
| catalog_with_new_additions_v1 | 目录 | 篇章折叠、章节列表 | 基本对齐 |
| premium_membership_landing_v1 | VIP | 权益卡片、¥1980 按钮 | 基本对齐 |
| professional_profile_with_earnings_vip | 我的 | VIP 徽章、收益、阅读统计、最近阅读、订单、代付链接、**编辑→profile-show** | ✅ |
| enhanced_professional_profile | 个人资料展示 | profile-show、member-detail | 基本对齐 |
| comprehensive_profile_editor_v1_2 | 手机/微弹窗 | 提现/找伙伴时弹窗 | 已实现 |
---
## 二、需完成的调整项(按优先级)
### P1首页补充「阅读进度」✅
**设计稿要求**:最新更新 → **阅读进度** → 超级个体 → 精选推荐 → 最新新增
**已完成**:在「最新更新」与「超级个体」之间插入阅读进度卡,已登录时显示,点击跳转目录。
---
### P2我的页增加「编辑」入口 ✅
**设计稿要求**:我的页头像资料卡片增加「编辑」图标,点击进入**个人资料展示页**profile-show
**已完成**:在 profile-name-row 增加「编辑」按钮,点击进入 profile-show展示页内可再进 profile-edit。
---
### P3代付功能闭环 ✅
**已完成**
1. **后端**`GET /api/miniprogram/gift/link?userId=` 返回 path、ref、scene
2. **小程序**gift-link 页 loadGiftLink 对接真实 API
**已完成**
3. **阅读页**:分享操作区「代付分享」按钮 + 付费墙「找好友代付」+ 代付分享弹窗(复制链接/分享给好友path 带 gift=1
---
### P4目录页与设计稿对齐可选
**设计稿**:免费/NEW/¥1 标签、找伙伴图标高亮
**当前**chapters 页已有篇章折叠,标签与找伙伴状态需核对
---
## 三、保护区域(调整时勿动)
| 模块 | 文件 | 说明 |
|------|------|------|
| @/# 标签 | contentParser.js、read.js、read.wxml | mention、linkTag 解析与点击 |
| 分销 | app.js、read.js、vip.js、match.js、referral/* | referralCode、bind、visit |
| 支付 | read.js、vip.js、wallet.js | pay、consume、balance |
---
## 四、建议执行顺序
```
1. 首页补充阅读进度P1仅改 index不动支付/分销)
2. 我的页编辑入口P2仅改 my.wxml + 跳转逻辑)
3. 代付后端接口 + gift-link 对接P3
4. 阅读页代付分享P3可选
```
---
## 五、已完成(无需再改)
- 代付链接:后端 gift/link 接口 + gift-link 对接 + 阅读页代付分享入口
- navigateToMiniProgramAppIdList 配置
- 余额体系、埋点、wallet、VIP 余额支付
- 首页精选/最新展开、搜索 book/hot?limit=50
- 我的页余额入口、代付链接入口(界面)
- 管理端订单、用户详情余额
- 超级个体、精选推荐、最新新增布局

View File

@@ -1,37 +0,0 @@
# 管理端两版界面差异(新需求参考)
> 更新日期2026-03-17
**目录说明**`new-soul/soul-admin` = **稳定版**(生产主用);`soul-admin/`(根目录)= 根目录版
---
## 一、稳定版new-soul有、根目录版无以稳定版为准
| 页面/组件 | 界面差异 | 说明 |
|-----------|----------|------|
| **系统设置** | 审核模式 auditMode、aboutEnabled、API 文档 Tab、OSS 完整 | 稳定版更全 |
| **Dashboard** | 代付金额 giftedTotal、订单可展开 4→10、埋点统计 | 稳定版有 |
| **用户编辑** | 编辑时手机号禁用 | 稳定版更安全 |
| **Layout** | 鉴权逻辑优化 | 稳定版优化 |
---
## 二、根目录版有、稳定版无(迁移时需保留)
迁移时若以稳定版为基准合并,以下能力需从根目录版**带入**,不可丢失。
| 页面/组件 | 界面差异 | 说明 |
|-----------|----------|------|
| **用户详情** | 基础信息 Tab 有「当前余额」卡片 | 对应小程序 wallet、余额支付 |
| **订单页** | 支付方式(微信/余额/支付宝)、代付标识、代付人 | 对应小程序 gift-pay、余额购买 |
| **用户列表** | RFM 排序模式、RFM 分值列 | 运营分析用(依赖后端 users/rfm |
| **用户列表** | 用户旅程总览 Tab | 依赖后端 users/journey-stats |
| **内容管理** | 关联小程序管理LinkedMpPage | 多小程序场景 |
| **全局** | RechargeAlert 充值告警条 | 商户号余额不足提示 |
---
## 三、与需求评估的关系
详见《新版管理端迁移到稳定版-需求评估.md》。迁移时以**稳定版new-soul/soul-admin为基准**从根目录版带入用户余额、订单支付方式、RechargeAlert、LinkedMp 等能力。

View File

@@ -1,89 +0,0 @@
# 管理端迁移分析:基于现有小程序功能
> 乘风整理。以 miniprogram 当前功能为基准,分析稳定版与新版管理端的差异及迁移建议。
> 更新日期2026-03-17
---
## 一、背景与范围
| 项目 | 路径 | 说明 |
|------|------|------|
| **稳定版管理端** | `new-soul/soul-admin/` | 生产主用 |
| **根目录版** | `soul-admin/` | 迁移对照 |
| **分析基准** | miniprogram 当前页面与接口app.json、以界面定需求.md |
**迁移方向**:新版 → 稳定版。分析目标:**以稳定版真实需求为基准,评估新版迁移时的保留项与吸纳项**。详见《新版管理端迁移到稳定版-需求评估.md》。
---
## 二、稳定版 vs 新版 差异对比
| 能力 | 稳定版 soul-admin | 新版 new-soul/soul-admin |
|------|-------------------|---------------------------|
| **用户详情-余额** | ✅ 有 balanceData、余额 Tab、`GET /api/admin/users/:id/balance` | ❌ 无余额展示 |
| **订单-支付方式** | ✅ 展示 wechat/balance/alipay、代付人 payerNickname | ❌ 仅 wechat/alipay无 balance、无代付 |
| **用户规则** | ✅ 规则配置 Tab、user-rules CRUD | ✅ 已有 |
| **超级个体/VIP** | ✅ 有 | ✅ 有 |
| **用户详情-VIP 表单** | ✅ 含 isVip、vipExpireDate、vipRole 等完整字段 | ⚠️ 有 vipForm但 payload 不含 isVip/vipExpireDate 等handleSave 仅保存基础字段handleSaveVip 单独保存 VIP |
| **LinkedMp 页** | 稳定版有 `/linked-mp` | 新版无(需确认是否需迁移) |
| **ApiDocs 页** | 单页 api-doc | 新版多 api-docs 页 |
---
## 三、小程序功能 → 管理端能力对照
以下按 miniprogram 核心能力,逐项对照管理端是否已覆盖(以稳定版为基准)。
| 小程序能力 | 小程序页面/接口 | 管理端需支持 | 稳定版 | 新版 |
|------------|-----------------|--------------|:------:|:----:|
| **余额体系** | wallet、read/vip 余额支付 | 用户余额查看、交易记录 | ✅ | ❌ |
| **代付(美团式)** | gift-pay/detail、list | 订单页展示代付信息 | ✅ | ❌ |
| **规则引擎** | ruleEngine | 用户规则 CRUD | ✅ | ✅ |
| **VIP** | vip、member-detail | VIP 状态、超级个体 | ✅ | ✅ |
| **订单** | purchases、read/vip 支付 | 订单列表、支付方式、退款 | ✅ | ⚠️ 缺余额/代付 |
| **提现、分销、找伙伴、导师、内容** | 对应页面 | 已有 | ✅ | ✅ |
---
## 四、迁移时稳定版必须保留(新版缺失则从稳定版带入)
### 4.1 用户详情 - 余额展示
| 项 | 说明 |
|----|------|
| **目标** | 迁移后稳定版保留「当前余额」卡 |
| **接口** | `GET /api/admin/users/:id/balance` |
| **实现** | 稳定版 UserDetailModal 已有,合并时不可覆盖 |
### 4.2 订单页 - 支付方式与代付
| 项 | 说明 |
|----|------|
| **目标** | 迁移后稳定版保留 balance、代付人展示 |
| **接口** | `GET /api/admin/orders` 已返回 |
| **实现** | 稳定版 OrdersPage 已有,合并时不可覆盖 |
### 4.3 LinkedMp、RechargeAlert
稳定版 ContentPage 嵌入 LinkedMpPage、Layout 有 RechargeAlert合并时保留。
---
## 五、稳定版待补充(两版共用)
| 优先级 | 项 | 说明 |
|:------:|----|------|
| P2 | 用户余额人工调整 | 用户详情增加「调整余额」入口,需 soul-api 新增 `POST /api/admin/users/:id/balance/adjust` |
| P2 | 代付列表页 | 新增代付请求维度管理,需 soul-api 新增 `GET /api/admin/gift-pay-requests` |
| P3 | 埋点看板 | 可选,低优先级 |
---
## 六、总结
| 类型 | 说明 |
|------|------|
| **新版迁移** | 用户详情余额、订单页支付方式(余额/代付——2 项,参考稳定版实现 |
| **稳定版待补充** | 用户余额人工调整、代付列表页——2 项,两版共用后端接口 |
| **结论** | 新版管理端需从稳定版迁移余额与代付相关展示能力,接口已就绪,以 UI 与数据绑定为主。

97
开发文档/索引.md Normal file
View File

@@ -0,0 +1,97 @@
# Soul 创业派对 - 开发文档索引
> 按目录与文件标注用途便于快速定位。最后更新2026-03-20
---
## 一、目录总览
| 目录 | 用途 |
|------|------|
| **1、需求** | 需求基准、主需求文件、归档 |
| **6、后端** | soul-api 鉴权、接口补全、迁移对比 |
| **8、部署** | 部署、提现、订阅消息、宝塔配置 |
| **10、项目管理** | 里程碑、运营与变更记录 |
| **Cunkebao接口文档** | 存客宝Cunkebao前端项目接口清单 |
---
## 二、1、需求
| 文件 | 用途 |
|------|------|
| **索引.md** | 主需求 = 日期最新的需求文件;命名规则 `YYYY-MM-DD-需求.md`;同步需求时更新 |
| **以界面定需求.md** | **界面级需求基准**:小程序/管理端界面清单、主要接口、业务逻辑对齐三端路由、VIP 资料等) |
| **2026-03-20-需求.md** | 当前主需求文件:需求清单、三端需求速查 |
| **archive/** | 专项需求、技术分析、已合并或过时文档 |
| archive/README.md | 归档说明 |
| archive/链接人与事-*.md | 链接人与事相关需求与方案 |
| archive/文章详情-阅读页线框图.md | 阅读页线框图 |
---
## 三、6、后端
| 文件 | 用途 |
|------|------|
| **管理端鉴权设计.md** | soul-api 管理端 JWT 鉴权、路由分层AdminAuth、Cookie/admin_session |
| **miniprogram接口补全说明.md** | VIP/users 接口从 /api/vip 迁移至 /api/miniprogram/* 的说明 |
| **soul-admin与Mycontent-temp内容页对比.md** | 内容管理页新建/编辑弹窗功能对比soul-admin 为基准 |
---
## 四、8、部署
| 文件 | 用途 |
|------|------|
| **部署总览.md** | **入口**:正式/测试/管理端部署脚本、环境、域名、命令 |
| **DOCKER部署说明.md** | 测试环境 Runner/Docker 模式、Docker 相关文件 |
| **宝塔-Docker首次配置指南.md** | 测试环境 Runner 首次配置 |
| **宝塔反向代理说明.md** | 域名 404 排查、Nginx 反向代理8080/9001 |
| **提现功能完整技术文档.md** | 微信支付商家转账到零钱 API 集成、签名、加密、代码实现 |
| **订阅消息.md** | 提现成功订阅消息PowerWeChat 示例) |
| **商家转账.md** | PowerWeChat 商家转账示例代码 |
---
## 五、10、项目管理
| 文件 | 用途 |
|------|------|
| **项目落地推进表.md** | 里程碑、当前阶段目标、风险与阻塞、永平落地 |
| **运营与变更.md** | 运营数据、soul-admin 变更、近期讨论、技术决策 |
---
## 六、Cunkebao接口文档
> 存客宝为前端项目,接口由后端提供。基础 URL 来自 `VITE_API_BASE_URL`。
| 文件 | 用途 |
|------|------|
| **README.md** | 目录说明、公共约定、工作台 type 含义 |
| **API接口清单.md** | 全部接口路径、方法、入参与简要说明 |
| **入参出参结构.md** | 核心模块请求/响应参数结构(含 TypeScript 类型) |
---
## 七、项目根目录相关
| 路径 | 用途 |
|------|------|
| **scripts/test/功能测试流程.md** | 功能测试流程、自动化用例、手工验证、报告模板 |
| **soul-api/文档索引.md** | 指向开发文档的后端相关文档链接 |
| **miniprogram/README.md** | 小程序项目结构、设计特点 |
---
## 八、快速入口
| 场景 | 推荐文档 |
|------|----------|
| 新增/变更功能 | 1、需求/以界面定需求.md → 1、需求/YYYY-MM-DD-需求.md |
| 部署 soul-api | 8、部署/DOCKER部署说明.md、宝塔反向代理说明.md |
| 提现/商家转账 | 8、部署/提现功能完整技术文档.md、商家转账.md |
| 管理端鉴权 | 6、后端/管理端鉴权设计.md |
| 存客宝对接 | Cunkebao接口文档/ |
| 测试验证 | scripts/test/功能测试流程.md |

View File

@@ -1,77 +0,0 @@
# 规则引擎迁移 - 影响分析
> 乘风严格分析确保不破坏现有功能。2026-03-17
---
## 一、现有逻辑梳理
### 1. 完善头像逻辑(将被吸收)
| 调用位置 | 文件 | 行号 | 触发时机 |
|----------|------|------|----------|
| login 成功 | app.js | 525 | 微信 code 登录成功后 |
| getOpenId 登录 | app.js | 587 | getOpenId 时接口返回 user |
| loginWithPhone | app.js | 641 | 手机号登录成功后 |
**逻辑**`_ensureProfileCompletedAfterLogin(user)` → 若头像/昵称未完善 → Toast + `navigateTo` avatar-nickname
### 2. 规则引擎将接管
- **场景**after_login对应 trigger「注册」
- **规则**checkRule_FillAvatar
- **行为**Modal去完善/稍后再说)→ 确认则 navigateTo
- **目标页**:改为 avatar-nickname与稳定版一致
### 3. 破坏性风险点
| 风险 | 条件 | 后果 | 缓解 |
|------|------|------|------|
| 规则 API 404 | 后端未部署 user-rules | loadRules 返回 [],无引导 | 先部署后端 |
| user_rules 表空 | 无「注册」规则 | isRuleEnabled 为 false无引导 | SQL 脚本插入默认规则 |
| globalData 不兼容 | readCount/hasPurchasedFull | 部分规则不触发 | ruleEngine 内做兼容 |
| 目标页错误 | target=profile-edit | 跳错页 | 改为 avatar-nickname |
---
## 二、兼容性修改清单
### ruleEngine.js
| 修改项 | 原值 | 新值 | 原因 |
|--------|------|------|------|
| checkRule_FillAvatar target | profile-edit | avatar-nickname | 稳定版用 avatar-nickname |
| readCount | globalData.readCount | getReadCount() | 稳定版无 readCount |
| hasPurchasedFull | globalData.hasPurchasedFull | globalData.hasFullBook | 稳定版用 hasFullBook |
### 空规则兜底
`rules` 为空时after_login 不触发 → 用户无引导。**方案**SQL 脚本插入默认「注册」规则,部署时执行。
---
## 三、执行顺序(防破坏)
1. **soul-api**:新增 GET /api/miniprogram/user-rules
2. **soul-api**:确保 user_rules 表存在GORM AutoMigrate
3. **SQL**:插入默认「注册」规则(幂等)
4. **miniprogram**:复制 ruleEngine.js 并做兼容
5. **miniprogram**app.js 替换 _ensureProfileCompletedAfterLogin 为 checkAndExecute
6. **miniprogram**match.js 接入 after_match
---
## 四、回滚方案
若规则引擎导致问题:
1. app.js恢复 _ensureProfileCompletedAfterLogin 调用,注释 checkAndExecute
2. match.js移除 checkAndExecute 调用
3. 规则引擎仅新增不删,可随时停用
---
## 五、部署步骤2026-03-17 已执行)
1. **soul-api**:重启后 AutoMigrate 会创建 user_rules 表
2. **数据库**:执行 `soul-api/scripts/add-user-rules-default.sql` 插入默认「注册」规则
3. **miniprogram**:已接入 ruleEngine无需额外配置

View File

@@ -1,127 +0,0 @@
# 迁移完成度与待办清单
> 乘风吸收当前经验与交互后整理。基于 new-soul 迁移方案、稳定版适配清单、agent 经验库。
> 更新日期2026-03-17乘风同步进度
---
## 一、已迁移完成(✅)
### 新版迁移方案R1R11
| 需求 | 说明 | 状态 |
|------|------|:----:|
| R1R4 | 余额体系:充值、消费、交易记录、退款 | ✅ |
| R5 | 我的页「我的余额」入口 | ✅ |
| R2 | 阅读页余额购买(章节/全书) | ✅ |
| R6R8 | 首页精选/最新展开、按热度、book/hot?limit=50 | ✅ |
| R9R10 | 代付(我的代付 + 阅读页代付分享) | ✅ |
| R11 | 埋点 trackClick | ✅ |
| VIP 余额 | VIP 页支持余额购买 | ✅ |
| 管理端 | 订单支付方式、用户详情余额 | ✅ |
### 稳定版适配P1P3
| 项 | 说明 | 状态 |
|----|------|:----:|
| P1 | 首页「阅读进度」卡 | ✅ |
| P2 | 我的页「编辑」入口 → profile-show | ✅ |
| P3 | 代付功能闭环(美团式:读页→代付页→分享) | ✅ |
### 代付美团式2026-03-17
| 项 | 说明 | 状态 |
|----|------|:----:|
| 读页入口 | 创建请求 → 跳转代付详情页 | ✅ |
| 代付详情页 | 发起人「分享给好友」/ 好友「帮他付款」双态 | ✅ |
| PayNotify | beneficiaryUserID 权益归发起人 | ✅ |
| 订单与分佣 | 并入 orders、分销 | ✅ |
### 体验优化2026-03-17
| 项 | 说明 | 状态 |
|----|------|:----:|
| 目录页 | book/parts 加载 loading | ✅ |
| 首页最新新增 | 默认 5 条、折叠,点击展开 | ✅ |
### 代付营销与体验(近期)
| 项 | 说明 | 状态 |
|----|------|:----:|
| 代付页营销 | 章节标题+内容预览20%),吸引代付人 | ✅ |
| 我的代付列表 | 点击卡片进入代付详情页 | ✅ |
| 代付页布局 | 页面协调、间距统一、视觉统一 | ✅ |
---
## 二、未迁移 / 待办
### 明确暂不处理
| 项 | 说明 | 决策 |
|----|------|------|
| 导师预约支付 | mentor-detail 预约成功后调起支付 | 暂不处理,保持与 new-soul 一致,弹「请联系客服」 |
### 边缘场景(可选)
| 项 | 说明 | 优先级 |
|----|------|:------:|
| ~~阅读页代付直链~~ | **已禁止**gift=1&ref 打开 read 页时直接 redirectTo 代付页,统一在代付页代付 | ✅ |
| ~~阅读统计埋点~~ | chapters/read 页补充 trackClick篇章展开、章节点击、搜索、分享、购买 | ✅ |
| ~~目录页「每日新增」~~ | latest-chapters 拉取 + 每日新增区块展示 | ✅ |
| ~~P4 目录页与设计稿~~ | 免费/NEW/¥1/增值标签、每日新增区块 | ✅ |
### 稳定版已有2026-03-17 分析)
| 项 | 说明 | 与 new-soul 对比 |
|----|------|-----------------|
| ~~富文本渲染~~ | 按稳定版处理,用户已落地 | ✅ |
| ~~打包购买引导~~ | 购买 ≥3 章显示「解锁全书」按钮,两端一致 | 稳定版 = new-soul |
| ~~存客宝对接~~ | ckb/lead、index-lead、match、join 均已对接 | 稳定版更完善限频、linkTag ckb |
### 搁置项(无)
原搁置项富文本/打包引导/存客宝均已确认稳定版已有,无新增搁置。
### 新版细节未迁移2026-03-17 乘风分析)
| 项 | 说明 | 优先级 |
|----|------|:------:|
| 运行时配置 | getRuntimeBootstrapConfig、extConfig/Storage、默认生产 baseUrl | P0 |
| loadMpConfig 扩展 | apiDomain、auditMode、supportWechat | P0 |
| auditMode 审核模式 | index/my/wallet/read 支付相关 UI 按审核隐藏 | P1 |
| request timeout | app.request 增加 timeout | P2 |
详见 `开发文档/新版迁移-功能差异清单.md`(小程序)、`开发文档/新版迁移-管理端功能差异清单.md`(管理端)。
### 规则引擎2026-03-17 已迁移)
| 项 | 状态 |
|----|:----:|
| ruleEngine.js | ✅ 已接入,兼容 readCount/hasFullBook |
| GET /api/miniprogram/user-rules | ✅ soul-api 已新增 |
| after_login完善头像 | ✅ 吸收 _ensureProfileCompletedAfterLogin跳 avatar-nickname |
| after_match匹配后引导 | ✅ match.js reportMatch 后触发 |
| user_rules 表 + 默认规则 | ✅ AutoMigrate + add-user-rules-default.sql |
### 埋点(已补齐 2026-03-17
| 项 | 当前状态 |
|----|----------|
| **埋点 trackClick** | 已接入index、my、match、vip、search、referral、chapters、read、wallet |
---
## 三、文档待更新
| 文档 | 待更新内容 |
|------|------------|
| 稳定版-小程序与API对比.md | wallet 已迁移,可更新为 ✓ |
---
## 四、总结
**核心迁移已全部完成**:余额体系、代付美团式、埋点、首页/目录/阅读/VIP 相关功能均已落地。
**剩余**:导师预约支付(暂不处理);埋点待补充(见上表)。规则引擎已迁移,富文本、打包购买引导、存客宝对接均已确认稳定版已有。