docs(work-log): 门户前端调整工作记录(多语言 + Pricing + Nav 重构 + 内容清理)
Some checks failed
Some checks failed
This commit is contained in:
165
docs/superpowers/work-logs/2026-04-23-portal-frontend-revamp.md
Normal file
165
docs/superpowers/work-logs/2026-04-23-portal-frontend-revamp.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# 门户前端调整工作记录
|
||||
|
||||
**时间窗口**:2026-04-19 ~ 2026-04-23
|
||||
**范围**:sub2api 项目前端门户页(公开访问的 5 页:Landing / Docs / Login / Register / Pricing)
|
||||
**目标**:完成多语言切换、新增 Pricing 页、消除导航栏抖动、清理对外不应展示的技术细节
|
||||
|
||||
---
|
||||
|
||||
## 阶段一:门户多语言 + Pricing 页
|
||||
|
||||
**问题**:门户 4 页(Landing / Docs / Login-narrative / Register-narrative)当时是 fidelity-port 自 Claude Design zip 的,约 100+ 处中文硬编码在 template 里。Pricing 页未实现。i18n 框架(`vue-i18n`)虽然到位,但门户页基本没用上。
|
||||
|
||||
**做了什么**:
|
||||
|
||||
1. 新建 `components/puro/PuroLocaleSwitcher.vue` —— 深色科技风的语言切换器,复用 `setLocale()` 核心,与 puro.css 设计 token 对齐(区别于 admin 用的 `LocaleSwitcher.vue`)
|
||||
2. 抽取 4 页所有中文到 i18n key(`landing.*`、`docs.*`、`auth.narrative.*` 命名空间),同步生成英文翻译;总计约 130 个 leaf key
|
||||
3. 新增 `/pricing` 路由 + `views/pricing/PricingView.vue`(约 500 行)+ `components/puro/PricingCalculator.vue` 子组件
|
||||
4. Pricing 页从一开始就 i18n-native(约 100 个 key),含 4 档定价 tier、cost calculator、12 工具 grid、10 FAQ、final CTA
|
||||
5. 关键决策(写进 spec 锁定):
|
||||
- 定价数字使用 zip 的 `$9.9 / $29.9 / $99` 作为占位,配 `// preview · 最终定价以开售为准` 标签
|
||||
- 未实现的功能(priority scheduling、zero-log mode)配 `SOON` 灰标签,不删除展示
|
||||
- Binding 卡片暂指 `/register`;联系商务用 `mailto:contact@puro.im`
|
||||
- Cost calculator 算法照搬 zip JS(`puro = official × 0.3`),配 `// estimated · 以实际计费为准` 标签
|
||||
- 移除 zip 中的 `注册送 $5 测试积分` 文案(Stage 1 决策)
|
||||
|
||||
**执行方式**:subagent-driven-development(Plan 文件 `docs/superpowers/plans/2026-04-20-portal-i18n-pricing.md`,10 个任务,3 个 subagent 实现 + 1 次回归修复)
|
||||
|
||||
**已合并 PR**:#2 → main `77bb69b2`
|
||||
|
||||
---
|
||||
|
||||
## 阶段二:Nav 抖动修复
|
||||
|
||||
**问题**:用户报告点击导航栏「产品/定价/文档」切换时元素位置发生轻微抖动。
|
||||
|
||||
**根因分析**:
|
||||
|
||||
第一直觉是 active class 引起的字体 weight 变化。grep CSS 后发现并非如此 —— `.active` 只改 color 不影响布局。
|
||||
|
||||
真正原因是:当前 Landing/Docs/Pricing 三个 View **各自在 template 里写了一份完整的 nav**(包括按钮文案)。Vue Router 切换路由时销毁整棵 view 组件树(含 nav),重新挂载下一个。虽然视觉上"看似同一个 nav",实际是三份独立拷贝被替换。
|
||||
|
||||
进一步发现两份拷贝间有差异:
|
||||
- Docs 的注册 CTA 文案是 `注册`(2 字符);Landing/Pricing 是 `免费试用 →`(5+1 字符)—— 按钮宽度不同
|
||||
- Docs 的英文 `Product`(单数)vs 其他两页的 `Products`(复数)
|
||||
- Pricing 的「定价」用 `<a href="#" class="active">` —— 点击会 scroll to top 且 URL 改成 `/pricing#`
|
||||
|
||||
**做了什么**(分两步):
|
||||
|
||||
**步骤 1(短期)** —— 文案统一:把三份 nav 的内容对齐到完全一致
|
||||
- `docs.nav.signup`: `注册` → `免费试用 →`
|
||||
- `docs.nav.products` (en): `Product` → `Products`
|
||||
- PricingView 的 `<a href="#">` → `<router-link to="/pricing">`
|
||||
- commit `779005e1`
|
||||
|
||||
**步骤 2(结构性修复)** —— 抽 `PortalLayout`:
|
||||
- 新建 `components/layout/PortalLayout.vue` —— 包含 nav + `<router-view />` + footer
|
||||
- 路由改为嵌套结构:`/`、`/docs`、`/pricing` 作为 PortalLayout 的子路由
|
||||
- 三个 View 删掉各自的 nav / footer / `bg-glow` / `.puro-page` 包装
|
||||
- 新增 `portal.nav.*` i18n 命名空间,删除原来的 `landing.nav.*` / `docs.nav.*` / `pricing.nav.*` 三份重复
|
||||
- `router-link` 用 `active-class="active"` prop 替代硬编码 class
|
||||
- `scrollBehavior` 加上 hash 锚点跳转(`offset 80px` 绕 sticky nav)
|
||||
- commit `e7f3fe5b`
|
||||
|
||||
**结果**:路由切换时 Nav 不再卸载重挂,真·SPA 行为。
|
||||
|
||||
**已合并 PR**:#3 → main `291e3bfe`
|
||||
|
||||
---
|
||||
|
||||
## 阶段三:对外内容清理
|
||||
|
||||
**Pass 1:删除 iShare 引用**
|
||||
- 用户要求:项目目前定位是独立运营,不要在前端展示 iShare 相关字样
|
||||
- 影响:`docs.sections.getKey.note` 一个 key("未来通过 iShare 入口开放订阅购买")+ DocsView 对应的 `<p class="note">`
|
||||
- commit `623a7518`,PR #4 → main `5c4b2980`
|
||||
|
||||
**Pass 2:移除 footer 技术细节**
|
||||
- 用户要求:不要透露项目技术开发细节
|
||||
- 删除:`更新日志` 链接(指向 Gitea commits)、`git.puro.im` 链接、`GitHub ↗` 链接、`fork of Wei-Shaw/sub2api` 字样
|
||||
- footer-meta 简化为 `© 2026 puro.im`
|
||||
- 同步删除 `linkChangelog` i18n key
|
||||
- commit `2b6b5fc6`,PR #5 → main `8be87883`
|
||||
|
||||
---
|
||||
|
||||
## 关键文件清单
|
||||
|
||||
新增:
|
||||
- `frontend/src/components/puro/PuroLocaleSwitcher.vue`
|
||||
- `frontend/src/components/puro/PricingCalculator.vue`
|
||||
- `frontend/src/components/layout/PortalLayout.vue`
|
||||
- `frontend/src/views/pricing/PricingView.vue`
|
||||
|
||||
修改(重点):
|
||||
- `frontend/src/router/index.ts` —— 加 `/pricing`、嵌套路由、scrollBehavior
|
||||
- `frontend/src/i18n/locales/{zh,en}.ts` —— 新增 portal/landing/docs/pricing/auth.narrative 命名空间
|
||||
- `frontend/src/views/{landing,docs,pricing}/*View.vue` —— 全量 i18n 化 + 移除各自 nav/footer
|
||||
- `frontend/src/views/auth/{Login,Register}View.vue` —— narrative slot i18n 化
|
||||
- `frontend/src/components/layout/AuthLayout.vue` —— 添加右上角语言切换器槽位
|
||||
|
||||
---
|
||||
|
||||
## commit / PR 索引
|
||||
|
||||
| 阶段 | commit | 描述 |
|
||||
|---|---|---|
|
||||
| 一 | `e711a203` | feat(i18n): add PuroLocaleSwitcher |
|
||||
| 一 | `63288818` | mount switcher in Landing/Docs/AuthLayout |
|
||||
| 一 | `fc7e2767` | landing i18n keys + EN |
|
||||
| 一 | `73b39807` | docs + auth narrative i18n |
|
||||
| 一 | `13bdd8f8` | restore dashboard link in models.note |
|
||||
| 一 | `b989c503` | PricingView + calculator |
|
||||
| 一 | `77bb69b2` | **Merge PR #2** → main |
|
||||
| 二 | `779005e1` | unify signup CTA |
|
||||
| 二 | `e7f3fe5b` | extract PortalLayout |
|
||||
| 二 | `291e3bfe` | **Merge PR #3** → main |
|
||||
| 三 | `623a7518` | remove iShare mention |
|
||||
| 三 | `5c4b2980` | **Merge PR #4** → main |
|
||||
| 三 | `2b6b5fc6` | footer remove tech details |
|
||||
| 三 | `8be87883` | **Merge PR #5** → main |
|
||||
|
||||
---
|
||||
|
||||
## 部署链路
|
||||
|
||||
每次 merge 到 main 后:
|
||||
1. Gitea webhook 触发 Drone CI
|
||||
2. Drone 运行 docker build + 推镜像
|
||||
3. VPS 上 docker compose 拉取新镜像 + 重启
|
||||
4. 总耗时约 3–5 分钟
|
||||
|
||||
每次部署完成的验证手段(curl):
|
||||
1. 取 `https://ai.puro.im/` 主 HTML,对比 `/assets/index-*.js` 文件名 hash 是否变化(Vite 内容寻址)
|
||||
2. fetch 新 chunk grep 关键字符串确认新代码上线
|
||||
3. 5 个门户路由全部 200
|
||||
|
||||
---
|
||||
|
||||
## 遗留事项 / 下次可继续
|
||||
|
||||
**门户层面**
|
||||
1. 浏览器实测 nav 持久化无抖动(用户已确认部署,肉眼验证待做)
|
||||
2. 翻译效果打磨(用户浏览后发现的不自然处随时改)
|
||||
3. Pricing 数字 / 功能列表定稿(从 preview 转正式)
|
||||
4. 后端 `SOON` 标记的功能落地:zero-log mode、priority scheduling
|
||||
5. Pricing FAQ 中的 24 小时上线新模型 等承诺类文案核实
|
||||
|
||||
**Admin / User 页面(之前搁置的两个决策)**
|
||||
- 决策 1:Admin reskin 深度(A 全局换肤 / B 深度 port 两页 / C 全量重写)
|
||||
- 决策 2:User-facing 页面 vs Admin 页面优先级
|
||||
- 推荐路径:Phase 2.1 全局换肤 → 2.2 user pages → 2.3 admin pages
|
||||
|
||||
**仓库卫生**
|
||||
- `backend/config.prod.yaml`、`backend/sub2api-linux`、`LOCAL_SETUP_NOTES.md` 在某次意外的 `git add -A` 中被提交到 main。
|
||||
- 用户判断:因 Gitea 是私有的,先不处理;仅要求前端层面不展示敏感信息(已通过 footer 清理实现)。
|
||||
- 建议:下次添加配置 / 二进制类文件前,往 `.gitignore` 补规则(`backend/config.*.yaml`、`backend/sub2api-*` 等),避免再次误提。
|
||||
|
||||
---
|
||||
|
||||
## 经验教训
|
||||
|
||||
1. **不要 `git add -A`** —— 主 worktree 里有累积的本地文件(生产配置、二进制、笔记),一次性 stage 会把这些都带进 commit。后续都用 `git add <具体文件>`。
|
||||
2. **设计稿里的 nav = 3 份独立 HTML** ≠ Vue 应该 3 份独立 template —— port 设计稿到 SPA 时,要把跨页共享的部分(nav、footer、layout shell)一开始就抽到 layout 组件。
|
||||
3. **Subagent 报告"我做完了"≠ 真的做对了** —— `73b39807` 提交里 subagent 静默删掉了 `<router-link>` 退化成纯文本。事后 grep 读 commit diff 才发现。下次 subagent 处理 i18n 抽取时,prompt 里要明确"原始 HTML 标签如 `<a>`/`<code>`/`<router-link>` 必须保留,使用 `<i18n-t>` 命名 slot"。
|
||||
4. **fidelity port 优先靠 `<i18n-t>` + 命名 slot,不要把带行内标签的句子拍平成纯文本** —— 这点已经写进下次的 i18n 提示模板中。
|
||||
Reference in New Issue
Block a user