Files
TradeMate Dev 6850ceff56 fix(seo): 详情页服务端渲染写入静态HTML并修复skills预渲染报错
- courses/skills/contents/practices 详情页改为服务端取数 + initialData 渲染,正文进入静态 HTML(解决百度弱 JS 收录盲点)
- contents 的 markdown 由 useEffect+setState 改为 useMemo 同步输出
- 四个 generateStaticParams 改用 API 真实 id;getX 校验 data.id 防后端 200+error 体被当有效数据导致 undefined.map 报错
- 更新进度文档至 v1.3.0
2026-07-11 17:46:31 +08:00

107 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 宇之然 AI 平台 - 进度追踪
**文档版本:** v1.3.0
**最后更新:** 2026-07-11
**状态:** 🟢 联盟返佣 + 打赏(个人码捐赠)双变现模式已落地;详情页正文已服务端渲染(SEO 盲点已解决);付费订阅/付费 Skill/用量包已下线
**负责人:** Hermes Agent
---
## 项目概览
- **目标:** 在「无 ICP 经营许可证」阶段,将全部经营性收费(会员订阅、付费 Skill、沙箱用量包)下架,改为合规的「打赏(个人码捐赠)+ 联盟返佣」模式
- **合规定位:** 会员付费/付费 Skill/虚拟商品属经营性收费,需 ICP 经营许可证。在取证前:以**联盟返佣**(第三方平台结算佣金,非平台经营性收款)为主力变现;以**打赏/捐赠**(个人收款码,自愿赠与,平台不提供对价)作为补充;所有内容(技能、练习、工具指南)保持免费开放
- **范围:** 打赏数据模型与 API、前端 /donate 页、会员/技能广场/用量包三处付费面改造为免费+赞助、导航与页脚入口、单元测试、种子数据
---
## 已完成
| 模块 | 内容 | 说明 |
|------|------|------|
| 数据模型 | `AffiliateProgram` / `AffiliateLink` / `AffiliateClick` | 规范化 Prisma 模型,取代原手写裸表 `affiliate_stats`/`affiliate_clicks` |
| 迁移 | `prisma/migrations/20260711000000_add_affiliate_models` | 建表 + 清理旧裸表;部署时 `prisma migrate deploy` |
| 后端服务 | `affiliate.service.ts` | 改用 Prisma ORM**消除 SQL 注入**;统计从 `affiliate_clicks` 实时聚合 |
| 后端接口 | `affiliate.controller.ts` | `GET /affiliate/programs``/affiliate/links`(支持 `?skillId`/`?toolId`)、`/affiliate/stats``POST /affiliate/click/:id` |
| 前端展示 | `affiliate/page.tsx` | 接入真实接口,移除硬编码 demo 数据 |
| 技能打通 | `skills/[id]/client.tsx` | 技能详情页展示「学此技能推荐使用的工具」联盟链接 |
| 测试 | `affiliate.service.spec.ts` | 4 个用例(聚合/点击/异常/过滤),已通过 |
| 种子 | `prisma/seed-affiliate.ts` | 幂等 upsert 阿里云云大使计划 + 推广链接;`npx ts-node prisma/seed-affiliate.ts` |
### 打赏(个人码捐赠)模式 — v1.2.0
| 模块 | 内容 | 说明 |
|------|------|------|
| 数据模型 | `Donation` | Prisma 模型(`name`/`message`/`channel`/`amount`/`createdAt`),仅用于「感谢墙」展示,不记录支付流水 |
| 迁移 | `prisma/migrations/20260711010000_add_donations` | 建 `donations` 表;部署时 `prisma migrate deploy` |
| 后端服务 | `donations.service.ts` | `getList(limit)` 最近留言、`create(dto)` 保存自愿留言 |
| 后端接口 | `donations.controller.ts` | `GET /donations``POST /donations`(公开,无鉴权) |
| 前端页 | `donate/page.tsx` | 个人收款码(支付宝/微信,环境变量 `NEXT_PUBLIC_DONATE_ALIPAY_QR`/`NEXT_PUBLIC_DONATE_WECHAT_QR`+ 感谢留言表单 + 感谢墙 |
| 会员页 | `my/member/page.tsx` | 移除付费订阅与 PaymentModal,改为免费说明 + 赞助/联盟入口 |
| 技能广场 | `marketplace/page.tsx` | 所有 Skill 免费开放,下架付费购买与 PaymentModal |
| 用量包 | `practices/packages/page.tsx` | 下架付费用量包,仅展示免费配额 + 赞助入口 |
| 沙箱 | `sandbox/page.tsx` | 用量耗尽提示改为引导至 /donate 赞助 |
| 课程详情 | `courses/[id]/client.tsx` | 下架付费购买按钮与微信扫码支付弹窗,全部免费开放 |
| 首页/能力导览 | `page.tsx` / `models.*` | 文案由"购买即用"改为"免费使用" |
| 导航/页脚 | `header.tsx` / `footer.tsx` | 新增「赞助」「联盟返佣」入口 |
| i18n | `zh.ts` / `en.ts` | 新增 `donate.*`、导航 `affiliate`/`donate`、说明文案 |
> **说明:** 后端 `orders` / `payment` 模块代码保留(取证后可复用),但前端已不再调用付费购买流程。
### SEO 基础优化 — v1.2.0
| 项目 | 改动 | 说明 |
|------|------|------|
| 结构化数据 | 详情页注入 JSON-LD | 课程/技能/文章/练习:`Article` + `BreadcrumbList`;工具:`SoftwareApplication`(含免费 Offer) |
| 每页元数据 | 详情页 `generateMetadata` | 课程/技能/文章/练习动态生成 unique title/description + canonical + OG |
| 列表页元数据 | 新增 `skills/contents/practices/prompts/models``layout.tsx` | 补齐各频道独立 title/description/canonical,消除与首页重复 |
| hreflang | 修正 `layout.tsx` | 删除不存在的 `/en` 备用语言,仅保留 `zh-CN` 自引用 |
| OG 分享图 | 新增 `app/opengraph-image.tsx` | 用 `next/og` 在构建期生成 1200x630 分享图(Latin 文案,规避 CJK 字体缺失),替换原缺失的 `/images/og-image.png` |
| 工具页 | 增强 `SoftwareApplication` JSON-LD | 补充 publisher / offers(免费) / operatingSystem |
> **已知最大盲点(已解决):** 原 `courses/[id]`、`skills/[id]`、`contents/[id]`、`practices/[id]` 正文在客户端 `useEffect` 拉取,静态 HTML 无正文。已于 v1.3.0 改为「服务端 `getX()` 取数 → 作为 `initialData` 传入客户端组件」,正文(含文章渲染)写入静态 HTML,百度等弱 JS 渲染引擎可正常收录。
### 详情页服务端渲染(解决 SEO 盲点)— v1.3.0
| 项目 | 改动 | 说明 |
|------|------|------|
| courses/[id] | `page.tsx` 服务端 `getCourse()` + `client.tsx` 接收 `initialCourse` | 课程正文/章节服务端取数,静态 HTML 含实质内容 |
| skills/[id] | `page.tsx` 服务端 `getSkill()` + `client.tsx` 接收 `initialSkill` | 技能描述/systemPrompt 写入静态 HTML |
| contents/[id] | `page.tsx` 服务端 `getContent()` + `client.tsx``useMemo` 同步渲染 markdown | 文章正文由 `useEffect+setState` 改为同步输出,进入静态 HTML |
| practices/[id] | `page.tsx` 服务端 `getPractice()` + `client.tsx` 接收 `initialQuestion` | 练习题干写入静态 HTML |
| generateStaticParams | 四页均改为从 API 取真实 id 列表 | 课程/技能/文章/练习全部按真实数据生成静态页(技能/练习原硬编码 id 会导致 404 错误体被当作有效数据) |
| 取数健壮性 | 四个 `getX()` 均校验 `data.id` | 后端对缺失资源返回 `HTTP 200 + {error}`(非 404),须据此判定缺失并 `return null`,避免客户端对 undefined 数组 `.map` 报错 |
| 构建验证 | `npm run build` | EXIT=0216 个 HTML 页面成功导出,技能/课程/文章/练习静态 HTML 实测含正文与 JSON-LD |
---
## 待办(下一阶段)
| 任务 | 说明 |
|------|------|
| 部署配置 | 在部署环境设置支付宝/微信收款码环境变量(`NEXT_PUBLIC_DONATE_*_QR` |
| 管理后台 UI | AffiliateProgram/Link 的列表与编辑页(T-009~T-013 |
| 首页/工具页嵌入 | 在首页与工具详情侧边栏插入「云产品推荐」区块(T-016/T-017 |
| 曝光埋点 | 记录推广位曝光(目前仅记录点击) |
| 后端捐赠单测 | 为 `donations.service.spec.ts` 补充用例(mock Prisma |
---
## 变现模式排序(无 ICP 证阶段)
1. **联盟返佣**(已落地)— 风险最低,第三方结算佣金
2. **打赏/个人码捐赠**(已落地)— 自愿赠与,平台不提供对价,不构成经营性收费
3. 免费内容 + SEO 引流
4. (取证后)会员订阅 / 付费 Skill / 企业版
---
## 变更日志
| 日期 | 版本 | 作者 | 变更摘要 |
|------|------|------|----------|
| 2026-06-25 | v1.0.0 | Hermes Agent | 初始化进度文档 |
| 2026-07-11 | v1.1.0 | Hermes Agent | 规范化联盟数据模型+迁移+ORM服务+前端打通+测试+种子;明确无 ICP 证下的合规变现路径 |
| 2026-07-11 | v1.2.0 | Hermes Agent | 落地打赏(个人码捐赠)模式:Donation 模型+迁移+API+前端 /donate 页;会员/技能广场/用量包三处付费面改造为免费+赞助;导航页脚入口;i18n 中文化 |
| 2026-07-11 | v1.3.0 | Hermes Agent | 解决 SEO 盲点:课程/技能/文章/练习四详情页改为服务端取数 + initialData 渲染,正文写入静态 HTMLgenerateStaticParams 取真实 idgetX 校验 data.id 防 200 错误体;构建通过 |