2026年3月14日14:37:06
This commit is contained in:
61
.cursor/agent/后端工程师/evolution/2026-03-12.md
Normal file
61
.cursor/agent/后端工程师/evolution/2026-03-12.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# 后端工程师 经验记录 - 2026-03-12
|
||||
|
||||
## 1. persons 表 token 字段与 DB 迁移
|
||||
|
||||
### 问题
|
||||
|
||||
新增 @ 人物时报错:`Unknown column 'token' in 'field list'`。GORM model 已加 `Token` 字段,但数据库未执行迁移。
|
||||
|
||||
### 解决方案
|
||||
|
||||
- **迁移脚本**:`soul-api/scripts/add-persons-token.sql`
|
||||
- **执行**:`node .cursor/scripts/db-exec/run.js -f soul-api/scripts/add-persons-token.sql`
|
||||
- **内容**:`ALTER TABLE persons ADD COLUMN token VARCHAR(36) NOT NULL DEFAULT '' AFTER person_id` + 唯一索引
|
||||
|
||||
### 规则
|
||||
|
||||
- **Model 新增字段后**:需编写并执行 ALTER 脚本,GORM AutoMigrate 不一定自动生效(取决于启动时机与连接)
|
||||
- **迁移脚本位置**:`soul-api/scripts/`,命名 `add-xxx.sql`
|
||||
- **执行方式**:db-exec 脚本读取 soul-api/.env 的 DB_DSN
|
||||
|
||||
---
|
||||
|
||||
## 2. CKBLead 用 token 兑换真实密钥
|
||||
|
||||
- `targetUserId` 现为 persons.token(非 person_id)
|
||||
- 查询:`db.Where("token = ?", body.TargetUserID).First(&p)`
|
||||
- 取 `p.CkbApiKey` 调用存客宝
|
||||
|
||||
---
|
||||
|
||||
## 3. 9.9 买断与后端开关(hasFullBook)
|
||||
|
||||
### 场景
|
||||
|
||||
- 小程序已通过 `hasFullBook` 标识「买断全书」,权限判断和文案都依赖该字段(由 `/api/miniprogram/user/purchase-status` 与 `/api/miniprogram/user/check-purchased` 返回)。
|
||||
- 现在需要在用户资料里增加一个布尔开关:运维/客服手动打开后,相当于该用户已经买过 9.9,全书可看,后续不再需要支付。
|
||||
|
||||
### 设计要点
|
||||
|
||||
- **统一事实来源**:9.9 买断是否生效完全由后端计算,前端只认:
|
||||
- `purchase-status` 返回的 `hasFullBook = true`;
|
||||
- 或 `check-purchased` 返回 `isPurchased = true` 且 `reason = "has_full_book"`。
|
||||
- **用户资料开关**:
|
||||
- 在 `users` 表或 user profile 中新增布尔字段(例如 `manual_fullbook`,具体命名按现有规范调整)。
|
||||
- 仅管理端/运维修改该字段,小程序不直接写入。
|
||||
- **接口契约调整**:
|
||||
- `/api/miniprogram/user/purchase-status`:
|
||||
- 计算 `hasFullBook` 时,将订单表中的全书订单结果与 `manual_fullbook` 做 **OR**,只要任一为真就返回 `hasFullBook = true`。
|
||||
- `/api/miniprogram/user/check-purchased`:
|
||||
- 对章节做权限判断时,如果由 `manual_fullbook` 推导出可看,应返回:
|
||||
- `isPurchased = true`
|
||||
- `reason = "has_full_book"`
|
||||
- 前端的 `chapterAccessManager.syncLocalCache` 会据此把 `app.globalData.hasFullBook = true` 并同步到 `userInfo.hasFullBook`。
|
||||
- **与 VIP 的边界**:
|
||||
- `hasFullBook`(9.9 买断)与 `isVip`(会员)继续解耦:手动开 fullbook 开关不会自动授予 VIP。
|
||||
- VIP 相关逻辑只看 `isVip` / `vipExpireDate`,不受 `manual_fullbook` 影响。
|
||||
|
||||
### 规则
|
||||
|
||||
- 不在前端增加「跳过支付」开关,所有免 9.9 行为都通过后端折叠到 `hasFullBook/has_full_book` 暴露给小程序。
|
||||
- 满足以上约定后,小程序现有代码无需修改即可支持「后台手动赠送 9.9 买断」。
|
||||
45
.cursor/agent/后端工程师/evolution/2026-03-13.md
Normal file
45
.cursor/agent/后端工程师/evolution/2026-03-13.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# 2026-03-13 - 文章详情预览统一与内容安全
|
||||
|
||||
## 问题 / 场景
|
||||
|
||||
- 文章详情目前小程序侧只展示约 20% 内容作为预览,再引导用户付费解锁。
|
||||
- 历史实现中前端本地按 20% 计算预览,后端曾同时返回外层 `content`(预览)和 `data.content`(全文),存在「接口约定不统一」和「误用 data.content 泄露全文」的风险。
|
||||
- 需求:统一由后端按业务规则截取预览(改为 50%),小程序只按「是否已付费」选择用预览还是全文;未付费时,无论字段层级都不能拿到全文。
|
||||
|
||||
## 解决方案
|
||||
|
||||
- 在 `internal/handler/book.go` 中调整章节预览逻辑:
|
||||
- `previewContent` 改为按字符数取正文前 50%(`total/2`),同时保证预览不少于 100 个字符;
|
||||
- 预览结尾统一追加 `……(购买后阅读完整内容)` 作为提示文案。
|
||||
- 在 `findChapterAndRespond` 中统一内容返回策略:
|
||||
- 先根据 system_config.free_chapters / chapter_config.freeChapters / chapters.is_free / price 判断章节是否免费;
|
||||
- 免费章节:`returnContent = ch.Content`(全文);
|
||||
- 付费章节:
|
||||
- 若 `checkUserChapterAccess` 判断用户已购买 / VIP / 全书:`returnContent = ch.Content`(全文);
|
||||
- 否则:`returnContent = previewContent(ch.Content)`(仅预览);
|
||||
- 构造响应时,将 `chForResponse.Content = returnContent`,并通过:
|
||||
- 外层 `content: returnContent`,
|
||||
- 内层 `data: chForResponse`(其中 `content` 也为 `returnContent`),
|
||||
- 确保未授权用户在任意字段上都拿不到完整正文。
|
||||
|
||||
## 与前端的接口约定
|
||||
|
||||
- 小程序阅读页通过 `userId` 查询章节详情,`accessManager` 基于返回的章节信息与用户购买状态计算 `accessState`:
|
||||
- 当 `accessState` 为 `free` 或 `unlocked_purchased` 时,前端使用 `res.data.content ?? res.content` 渲染全文;
|
||||
- 当 `accessState` 为未登录 / 未购买时,前端只使用 `res.content` 渲染预览。
|
||||
- 预览比例完全由后端控制(当前为 50%),小程序不再自行用 20% 做二次截断,只是把后端提供的预览完整展示出来。
|
||||
|
||||
## 代码位置
|
||||
|
||||
- 后端:
|
||||
- `soul-api/internal/handler/book.go`
|
||||
- 小程序(前端配合):
|
||||
- `miniprogram/pages/read/read.js`
|
||||
- `miniprogram/pages/read/read.wxml`
|
||||
|
||||
## 对后续开发的约定
|
||||
|
||||
- 预览长度(包括比例、最小字符数、提示文案)统一由后端控制;如需调整比例,只需修改 `previewContent`,保持接口字段含义不变。
|
||||
- 任何需要「只返回部分内容预览」的场景,应优先复用「外层 `content` + 内层 `data.content` 保持一致」的安全模式,避免在不同字段中混放全文与预览内容。
|
||||
- 涉及付费内容时,优先在后端用「权限判断 + 统一内容裁剪」实现安全边界,前端只根据状态选择展示预览还是全文。
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
| 2026-03-05 | soul-api 合并状态确认;orders、distribution 接口核对 | [2026-03-05.md](./2026-03-05.md) |
|
||||
| 2026-03-05 | 文章详情@某人:content 内嵌 @ 标记、miniprogram 添加好友接口 | [2026-03-05.md](./2026-03-05.md) |
|
||||
| 2026-03-10 | 管理端迁移 Mycontent-temp:接口边界不变;overview 聚合接口可选但需降级 | [2026-03-10.md](./2026-03-10.md) |
|
||||
| 2026-03-12 | persons token 字段与 DB 迁移;CKBLead 用 token 兑换 ckb_api_key | [2026-03-12.md](./2026-03-12.md) |
|
||||
|
||||
47
.cursor/agent/团队/evolution/2026-03-12.md
Normal file
47
.cursor/agent/团队/evolution/2026-03-12.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# 团队共享 经验记录 - 2026-03-12
|
||||
|
||||
## 密钥/token 设计:关联小程序与 @ 人物
|
||||
|
||||
### 背景
|
||||
|
||||
- **关联小程序**:添加时生成 32 位英文+数字密钥,链接标签存 key,小程序点击 # 时用 key 查 appId 再跳转
|
||||
- **@ 人物**:添加时生成 32 位 token,文章 @ 时存 token,小程序点击 @ 时用 token 兑换真实 ckb_api_key 后加好友
|
||||
|
||||
### 设计原则
|
||||
|
||||
1. **不暴露真实密钥**:管理端配置的真实密钥(appId、ckb_api_key)不写入文章内容,仅存可对外传递的 token/key
|
||||
2. **服务端兑换**:小程序端只传 token/key,后端用其查表得到真实密钥再调用第三方
|
||||
3. **不兼容旧数据**:项目未上架,无需兼容 person_id、appId 等旧格式
|
||||
|
||||
### 数据流
|
||||
|
||||
| 场景 | 添加时 | 内容存储 | 小程序点击 | 后端兑换 |
|
||||
|------|--------|----------|------------|----------|
|
||||
| 关联小程序 | 生成 key | data-mp-key | 传 mpKey | 查 linked_miniprograms 得 appId |
|
||||
| @ 人物 | 生成 token | data-id | 传 targetUserId | 查 persons 得 ckb_api_key |
|
||||
|
||||
### 适用角色
|
||||
|
||||
- 后端:persons.token、linked_miniprograms.key、CKBLead 兑换逻辑
|
||||
- 管理端:链接标签选 key、@ 人物 id=token、列表展示
|
||||
- 小程序:contentParser 解析 mpKey、onLinkTagTap/onMentionTap 传 key/token
|
||||
|
||||
---
|
||||
|
||||
## 9.9 买断与团队级约定
|
||||
|
||||
### 结论
|
||||
|
||||
- 「9.9 买断全书」在三端的唯一来源是后端的 `hasFullBook`/`has_full_book` 信号:
|
||||
- 小程序:只看 `/user/purchase-status` 的 `hasFullBook` 和 `/user/check-purchased` 的 `reason = "has_full_book"`。
|
||||
- 后端:可以通过订单或用户资料开关(如 `manual_fullbook`)计算该状态。
|
||||
- 管理端:如需赠送 9.9 买断,应只改后端用户资料中的开关,不直接改前端逻辑。
|
||||
|
||||
### 约定
|
||||
|
||||
- 任意「免 9.9」或「赠送全书」能力都必须:
|
||||
- 由后端在 purchase-status/check-purchased 中折叠为统一的 `hasFullBook/has_full_book`。
|
||||
- 不允许在小程序或管理端各自新增本地开关绕过后端逻辑。
|
||||
- VIP 与 9.9 买断继续分离:
|
||||
- `hasFullBook` → 只代表书的权限;
|
||||
- `isVip` → 代表会员权益(案例库、增值版等),两者可以独立打开。
|
||||
42
.cursor/agent/团队/evolution/2026-03-13.md
Normal file
42
.cursor/agent/团队/evolution/2026-03-13.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 2026-03-13 - 文章详情预览规则统一(小程序 + 后端)
|
||||
|
||||
## 场景
|
||||
|
||||
- 文章详情页采用「部分内容预览 + 付费解锁全文」的收费模式。
|
||||
- 历史实现中,预览比例由小程序本地按 20% 行数截取,后端可能同时返回预览与全文两个 content 字段,存在:
|
||||
- 三端对「预览长度」的理解不一致;
|
||||
- 前端误用 `data.content` 导致未付费用户拿到全文的潜在风险。
|
||||
- 本次目标:将「预览长度 + 安全边界」下沉到后端统一控制,小程序只按「是否已解锁」选择展示预览或全文。
|
||||
|
||||
## 团队级决策
|
||||
|
||||
- 预览长度统一由 **soul-api** 控制:
|
||||
- 当前规则:对付费章节,未解锁用户默认看到正文前 **50%**,且不少于 100 个字符,末尾追加「购买后阅读完整内容」提示;
|
||||
- 未来如需改为 40% / 30% 等,只需调整后端 `previewContent`,前端逻辑保持不变。
|
||||
- 接口约定统一:
|
||||
- 章节详情接口(含 `/api/miniprogram/book/chapter/:id`、`/api/miniprogram/book/chapter/by-mid/:mid`)返回的:
|
||||
- 外层 `content` 字段,
|
||||
- 内层 `data.content`(Chapter.Content)字段,
|
||||
- **在同一次响应中必须保持一致**:
|
||||
- 免费或已解锁:两处都是全文;
|
||||
- 未解锁:两处都是预览(50%)。
|
||||
- 不允许出现「外层是预览、`data.content` 是全文」这类混合返回,避免前端误用泄露付费内容。
|
||||
- 小程序阅读页约定:
|
||||
- 只根据 `accessState` 判断是否有权看全文;
|
||||
- 有权限时使用 `data.content` / `content` 渲染全文;
|
||||
- 无权限时仅使用后端返回的预览内容,不再在前端重新按 20% 行数切割。
|
||||
|
||||
## 影响角色
|
||||
|
||||
- **后端工程师(soul-api)**:
|
||||
- 负责实现和维护 `previewContent` 预览算法及权限判断逻辑;
|
||||
- 在新增/修改与付费内容相关的接口时,必须遵守「外层 content 与 data.content 一致」的安全约定。
|
||||
- **小程序开发工程师**:
|
||||
- 阅读页不自行决定预览比例,只展示后端返回的预览内容;
|
||||
- 通过 `accessManager` 与章节详情响应判断权限,严格按照 `accessState` 切换「预览 / 全文」视图。
|
||||
|
||||
## 对后续迭代的提示
|
||||
|
||||
- 若未来引入「增值版内容」「章节试读长度差异化」等新收费形态,优先在后端扩展 `previewContent` 与权限判断逻辑,对前端暴露统一、稳定的字段语义。
|
||||
- 若管理端需要控制预览比例或提示文案,可在配置中心增加相关配置项,由后端读取后影响 `previewContent` 行为,保持三端一致。
|
||||
|
||||
@@ -6,3 +6,4 @@
|
||||
|------|------|------|
|
||||
| 2026-03-05 | 分支冲突后各端完整性自查流程 | [2026-03-05.md](./2026-03-05.md) |
|
||||
| 2026-03-10 | 管理端迁移 Mycontent-temp:菜单/布局新规范基线与入口收敛规则 | [2026-03-10.md](./2026-03-10.md) |
|
||||
| 2026-03-12 | 密钥/token 设计:关联小程序 key、@ 人物 token,不暴露真实密钥、服务端兑换 | [2026-03-12.md](./2026-03-12.md) |
|
||||
|
||||
15
.cursor/agent/小程序开发工程师/evolution/2026-03-12.md
Normal file
15
.cursor/agent/小程序开发工程师/evolution/2026-03-12.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# 小程序开发工程师 经验记录 - 2026-03-12
|
||||
|
||||
## 链接标签与 @ 人物:key/token 兑换
|
||||
|
||||
### 链接标签(# 跳转小程序)
|
||||
|
||||
- **contentParser**:解析 `data-mp-key`,seg.mpKey 传给 wxml
|
||||
- **onLinkTagTap**:`mpKey` 从 dataset;用 `linkedMiniprograms.find(m => m.key === mpKey)` 查 appId
|
||||
- **config 预加载**:read.js onLoad 时拉取 `linkTags`、`linkedMiniprograms` 存 globalData
|
||||
|
||||
### @ 人物(加好友)
|
||||
|
||||
- **contentParser**:mention 的 `data-id` 为 token,seg.userId = token
|
||||
- **onMentionTap**:`targetUserId` 传 token,CKBLead 接口用 token 兑换 ckb_api_key
|
||||
- 无需在 config 中拉取 persons,token 已嵌入 content
|
||||
@@ -7,3 +7,4 @@
|
||||
| 2026-03-05 | 分支合并后核心流程自测;app.json 拆行;orders 接口确认 | [2026-03-05.md](./2026-03-05.md) |
|
||||
| 2026-03-05 | 文章详情@某人高亮与一键加好友(解析@、调添加好友接口) | [2026-03-05.md](./2026-03-05.md) |
|
||||
| 2026-03-10 | 管理端迁移 Mycontent-temp:关注内容产物格式与阅读页解析兼容回归 | [2026-03-10.md](./2026-03-10.md) |
|
||||
| 2026-03-12 | 链接标签 mpKey、@ 人物 token 兑换:contentParser、onLinkTagTap、onMentionTap | [2026-03-12.md](./2026-03-12.md) |
|
||||
|
||||
@@ -30,9 +30,17 @@
|
||||
| 2026-03-10 | 后端 | bug 修复 | api-dev SKILL | 聚合接口三处修复:recentChapters 去重、totalReadMinutes 最小1分钟、DB 错误返回 500 |
|
||||
| 2026-03-10 | 团队 | 方法论 | - | 新旧版代码对比:以功能完整性为基准,批量 diff + 分类取舍,不以日期判优劣 |
|
||||
| 2026-03-10 | 管理端 | 最佳实践 | admin-dev SKILL §toast | Toast 通知系统落地:utils/toast.ts 纯原生实现,全系统 18 文件 alert → toast 批量替换 |
|
||||
| 2026-03-12 | 管理端 | bug 修复 | admin-dev SKILL §ts | ContentPage TypeScript 严格类型:可选字段 ?? 兜底、接口补字段、API 映射、setState 传参 |
|
||||
| 2026-03-12 | 团队 | 架构/设计 | - | 密钥/token 设计:关联小程序 key、@ 人物 token;不暴露真实密钥、服务端兑换 |
|
||||
| 2026-03-12 | 后端 | 最佳实践 | mysql-direct SKILL | persons token 字段;Model 新增字段后需执行 ALTER 迁移脚本 |
|
||||
| 2026-03-12 | 管理端 | 设计落地 | - | 关联小程序存 key、@ 人物 id=token;链接标签与 PersonItem 约定 |
|
||||
| 2026-03-12 | 小程序 | 设计落地 | - | contentParser mpKey/token;onLinkTagTap、onMentionTap 传 key/token 兑换 |
|
||||
| 2026-03-10 | 后端 | bug 修复 | api-dev SKILL | chapters 表新增 hot_score 列,修复 1054 Unknown column 错误;DB 变更 SOP:ALTER→model→重启 |
|
||||
| 2026-03-10 | 团队 | 方法论 | - | DB 变更 SOP + Toast 批量替换方法论(脚本替换后必须人工复查 toast.info 语义) |
|
||||
|
||||
| 2026-03-12 | 后端、团队 | 业务规则 | api-dev SKILL、team three-tier-arch | 9.9 买断统一由后端折叠为 hasFullBook/has_full_book,小程序和管理端只认该信号;可通过用户资料开关 OR 订单实现赠送全书 |
|
||||
| 2026-03-13 | 小程序、后端、团队 | 业务规则 | api-dev SKILL、miniprogram-dev SKILL、three-tier-arch SKILL | 文章详情预览统一由后端按 50% 截取,小程序按 accessState 使用预览/全文,外层 content 与 data.content 始终一致以避免泄露全文 |
|
||||
|
||||
---
|
||||
|
||||
## 已吸收经验(历史)
|
||||
@@ -42,4 +50,4 @@
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:2026-03-10(Toast + hot_score 经验入库)
|
||||
**最后更新**:2026-03-13(文章预览规则统一、小程序与后端对齐)
|
||||
|
||||
@@ -24,9 +24,12 @@ soul-api(Go + Gin + GORM + MySQL)提供三组路由:`/api/miniprogram/*`
|
||||
| 2026-03-10 | 新增 GET /api/miniprogram/user/dashboard-stats:聚合阅读统计接口,含去重、min1分钟、500错误码修复 | 已完成 |
|
||||
| 2026-03-10 | chapters 表新增 hot_score 列(ALTER TABLE + model 同步),修复前端保存章节报 1054 错误 | 已完成 |
|
||||
| 2026-03-11 | users 迁移仅 VIP 身份/状态五字段,不再新增 VIP 资料列;chapters 补 hot_score;sync 脚本与 README-schema-sync 更新 | 已完成 |
|
||||
| 2026-03-12 | persons 表新增 token 字段(add-persons-token.sql);CKBLead 用 token 兑换 ckb_api_key | 已完成 |
|
||||
| 2026-03-12 | 9.9 买断后端开关方案:users 增手动 fullbook 开关,purchase-status/check-purchased 折叠为统一 hasFullBook/has_full_book,小程序免改即支持赠送全书 | 已完成 |
|
||||
| 2026-03-13 | 文章详情预览统一与安全:previewContent 改为截取正文前 50%,findChapterAndRespond 保证外层 content 与 data.content 一致,未授权只返回预览 | 已完成 |
|
||||
|
||||
> **格式说明**:每次开发后在此追加一行,日期格式 YYYY-MM-DD,状态用:已完成 / 进行中 / 待续 / 搁置
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:2026-03-11
|
||||
**最后更新**:2026-03-13
|
||||
|
||||
@@ -21,9 +21,12 @@ Soul 创业派对全项目架构与约定:路由隔离(miniprogram/admin/db
|
||||
| 2026-03-10 | 新旧版代码对比方法论:以功能完整性而非日期判断优劣,批量 diff + 分类取舍 + 移植修复 | 已完成 |
|
||||
|
||||
| 2026-03-11 | 以界面定需求文档建立;需求基准与业务逻辑对齐(用户/VIP 资料、三端路由);会议收尾纪要与各角色经验入库 | 已完成 |
|
||||
| 2026-03-12 | 密钥/token 设计:关联小程序 key、@ 人物 token;不暴露真实密钥、服务端兑换 | 已完成 |
|
||||
| 2026-03-12 | 9.9 买断团队约定:后端统一输出 hasFullBook/has_full_book,小程序和管理端只认该信号;支持通过用户资料开关 OR 订单赠送全书且不影响 VIP 逻辑 | 已完成 |
|
||||
| 2026-03-13 | 文章详情预览规则统一:预览长度由后端统一按 50% 计算,小程序按 accessState 切换预览/全文,接口约定 content 与 data.content 始终一致 | 已完成 |
|
||||
|
||||
> **格式说明**:每次架构级讨论后在此追加一行,日期格式 YYYY-MM-DD
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:2026-03-11
|
||||
**最后更新**:2026-03-13
|
||||
|
||||
@@ -27,9 +27,11 @@
|
||||
| 2026-03-10 | 移植 loadDashboardStats():my.js 阅读统计改为后端接口,去除随机数时间/标题占位 | 已完成 |
|
||||
| 2026-03-10 | 富文本渲染技术债分析:contentParser.js 剥除 HTML 格式,建议改 rich-text 组件(待实施) | 待续 |
|
||||
| 2026-03-11 | 以界面定需求:小程序界面清单纳入《以界面定需求》;展示以用户资料为准,与现有实现一致 | 已完成 |
|
||||
| 2026-03-12 | 链接标签 mpKey 兑换 appId;@ 人物 token 兑换 ckb_api_key;contentParser、onLinkTagTap、onMentionTap | 已完成 |
|
||||
| 2026-03-13 | 阅读页文章预览与付费解锁对齐:预览长度改由后端统一计算,前端按 accessState 显示预览/全文,避免 data.content 泄露全文 | 已完成 |
|
||||
|
||||
> **格式说明**:每次开发后在此追加一行,日期格式 YYYY-MM-DD,状态用:已完成 / 进行中 / 待续 / 搁置
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:2026-03-11
|
||||
**最后更新**:2026-03-13
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
| 2026-03-10 | 会议:管理端迁移 Mycontent-temp 新菜单/布局;主导航收敛、author/admin 并入 Settings Tab | 待续 |
|
||||
| 2026-03-10 | Toast 通知系统落地:创建 utils/toast.ts(纯原生),全系统 18 文件约 90 处 alert 全部替换为 toast.success/error/info | 已完成 |
|
||||
| 2026-03-11 | 以界面定需求:管理端界面清单纳入《以界面定需求》,作为验收基准 | 已完成 |
|
||||
| 2026-03-12 | ContentPage TypeScript 严格类型修复;关联小程序 key、@ 人物 token 设计(链接标签存 key、PersonItem.id=token) | 已完成 |
|
||||
|
||||
> **格式说明**:每次开发后在此追加一行,日期格式 YYYY-MM-DD,状态用:已完成 / 进行中 / 待续 / 搁置
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:2026-03-11
|
||||
**最后更新**:2026-03-12
|
||||
|
||||
43
.cursor/agent/管理端开发工程师/evolution/2026-03-12.md
Normal file
43
.cursor/agent/管理端开发工程师/evolution/2026-03-12.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# 管理端开发工程师 经验记录 - 2026-03-12
|
||||
|
||||
## ContentPage TypeScript 严格类型修复
|
||||
|
||||
### 问题
|
||||
|
||||
`soul-admin` 构建时 `ContentPage.tsx` 出现多处 TS2322 类型错误:
|
||||
|
||||
1. **可选字段赋给必填字段**:`LinkTagItem` 的 `appId`、`pagePath` 为可选(`string | undefined`),`setNewLinkTag` 期望 `string`
|
||||
2. **接口缺字段**:`SectionListItem` 无 `isPinned`,但 ranking API 返回该字段
|
||||
3. **API 映射类型**:`loadPersons` 中 `p.token`、`p.label`、`p.ckbApiKey` 可能为 `undefined`,映射后 `PersonItem.id` 等需为 `string`
|
||||
4. **可选参数传 setState**:`setEditingPersonKey(p.personId)` 中 `personId` 可选,setter 期望 `string | null`
|
||||
|
||||
### 解决方案
|
||||
|
||||
| 场景 | 写法 |
|
||||
|------|------|
|
||||
| 可选字段 → 必填 string | `t.appId ?? ''`、`t.pagePath ?? ''` |
|
||||
| 接口补字段 | 在 `SectionListItem` 添加 `isPinned?: boolean` |
|
||||
| API 映射兜底 | `id: p.token ?? p.personId ?? ''`,`label: p.label ?? ''`,`ckbApiKey: p.ckbApiKey ?? ''` |
|
||||
| 可选 → setState(string\|null) | `setEditingPersonKey(p.personId ?? null)` |
|
||||
|
||||
### 规则提炼
|
||||
|
||||
- 从可选类型(`T | undefined`)赋给必填类型(`T`)时,用 `?? defaultValue` 兜底
|
||||
- 接口类型需与 API 返回字段对齐,缺字段时补 `field?: Type`
|
||||
- `useState<string | null>` 的 setter 传参时,`undefined` 需显式转为 `null`
|
||||
|
||||
---
|
||||
|
||||
## 关联小程序与 @ 人物:密钥/token 设计
|
||||
|
||||
### 关联小程序
|
||||
|
||||
- 添加时生成 32 位 key,链接标签选择小程序时存 key(非 appId)
|
||||
- 列表展示:名称、密钥、AppID、路径;编辑/删除用 key
|
||||
- 链接标签下拉:选项显示 name + key,选中后 `appId` 字段存 key
|
||||
|
||||
### @ 人物
|
||||
|
||||
- 添加时生成 32 位 token,PersonItem.id = token(RichEditor 插入用)
|
||||
- 列表展示 token;编辑/删除用 personId(API 仍用 personId)
|
||||
- 文章 @ 时 data-id 存 token
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
| 日期 | 摘要 | 文件 |
|
||||
|------|------|------|
|
||||
| 2026-03-12 | ContentPage TypeScript 严格类型修复;关联小程序 key、@ 人物 token 设计 | [2026-03-12.md](./2026-03-12.md) |
|
||||
| 2026-03-05 | 分支合并后全功能自测,404/异常接口记录 | [2026-03-05.md](./2026-03-05.md) |
|
||||
| 2026-03-05 | 文章详情@某人:编辑页插入 @用户、保存约定 content 格式 | [2026-03-05.md](./2026-03-05.md) |
|
||||
| 2026-03-10 | 管理端迁移 Mycontent-temp 菜单/布局:主导航收敛、Settings Tab 承载 author/admin | [2026-03-10.md](./2026-03-10.md) |
|
||||
|
||||
Reference in New Issue
Block a user