Browse Source
Document the public post detail markdown export design, including visitor access, image URL normalization to absolute links, UX states, and acceptance criteria. Made-with: Cursormain
1 changed files with 117 additions and 0 deletions
@ -0,0 +1,117 @@ |
|||
# 设计:个人主页文章详情页导出 Markdown |
|||
|
|||
**日期**:2026-04-23 |
|||
**状态**:已定稿(待你最终确认后进入实现计划) |
|||
|
|||
## 1. 背景与目标 |
|||
|
|||
当前个人主页文章详情页支持阅读与评论,但缺少“导出原始 Markdown”能力。 |
|||
本期目标是在公开文章详情页新增导出能力,满足“访客可直接下载 `.md` 文件”的需求。 |
|||
|
|||
## 2. 本期确认范围 |
|||
|
|||
- 导出格式:仅 `Markdown (.md)`。 |
|||
- 入口位置:个人主页文章详情页(`/@[publicSlug]/posts/[postSlug]`)。 |
|||
- 权限:所有访客可导出(无需登录)。 |
|||
- 导出内容:仅正文 `bodyMarkdown`。 |
|||
- 图片处理:导出时将站内相对图片链接转换为绝对 URL。 |
|||
|
|||
## 3. 非目标 |
|||
|
|||
- 不导出 PDF / HTML。 |
|||
- 不附带 Front Matter 元数据。 |
|||
- 不打包图片文件到本地,仅处理 Markdown 内图片链接文本。 |
|||
- 不新增后端导出 API(本期前端本地导出)。 |
|||
|
|||
## 4. 技术方案 |
|||
|
|||
采用前端本地导出(Blob + download): |
|||
|
|||
1. 在详情页数据加载完成后显示 `导出 .md` 按钮。 |
|||
2. 点击按钮时读取当前已加载的 `data.bodyMarkdown`。 |
|||
3. 仅对 Markdown 图片语法 `` 中的链接做归一化: |
|||
- 若为站内相对路径(如 `/public/assets/...`),替换为 `window.location.origin + path`。 |
|||
- 其他链接类型保持不变。 |
|||
4. 生成 `Blob(['...'], { type: 'text/markdown;charset=utf-8' })`。 |
|||
5. 通过临时 `<a download>` 触发下载,文件名按规则生成。 |
|||
|
|||
该方案不新增接口,改动范围小,符合“仅导出正文、访客可用、快速交付”的目标。 |
|||
|
|||
## 5. URL 归一化规则 |
|||
|
|||
### 5.1 处理对象 |
|||
|
|||
- 仅处理 Markdown 图片语法:``。 |
|||
- 普通链接语法 `[](...)` 不处理。 |
|||
|
|||
### 5.2 保持不变 |
|||
|
|||
- `http://...`、`https://...` |
|||
- `//...`(协议相对) |
|||
- `data:image...` |
|||
|
|||
### 5.3 转换条件 |
|||
|
|||
- 以 `/` 开头的站内相对路径(重点覆盖 `/public/assets/...`)。 |
|||
|
|||
### 5.4 基地址来源 |
|||
|
|||
- 使用 `window.location.origin` 作为导出时站点基地址。 |
|||
|
|||
### 5.5 示例 |
|||
|
|||
- 输入:`` |
|||
- 当前访问域名:`https://example.com` |
|||
- 输出:`` |
|||
|
|||
## 6. 交互与错误处理 |
|||
|
|||
- 按钮位置:详情页顶部操作区,与“返回主页 / 编辑”同级。 |
|||
- 显示与可用性: |
|||
- `pending` 状态禁用按钮。 |
|||
- `error && !data` 时不显示按钮。 |
|||
- `data` 就绪后访客可点击导出。 |
|||
- 成功反馈:导出完成后给轻量 Toast(如“已导出 Markdown”)。 |
|||
- 失败反馈:捕获异常并提示“导出失败,请稍后重试”,不影响页面其他功能。 |
|||
- 空正文:允许导出空 `.md` 文件。 |
|||
|
|||
## 7. 文件命名规则 |
|||
|
|||
- 优先:`${postSlug}.md` |
|||
- 回退:`post-${id}.md` |
|||
|
|||
确保命名稳定、可预测,便于用户归档。 |
|||
|
|||
## 8. 验收标准 |
|||
|
|||
### 8.1 功能验收 |
|||
|
|||
- 公开文章详情页可见 `导出 .md` 按钮,未登录访客可使用。 |
|||
- 点击后下载文件名符合规则。 |
|||
- 导出正文与 `bodyMarkdown` 一致(仅图片链接归一化除外)。 |
|||
|
|||
### 8.2 图片链接验收 |
|||
|
|||
- `` 转换为当前域名下绝对 URL。 |
|||
- 已是绝对地址、协议相对地址、data URI 的图片链接保持不变。 |
|||
- 普通链接 `[](...)` 不被误改。 |
|||
|
|||
### 8.3 状态与异常 |
|||
|
|||
- 加载中按钮禁用;加载失败场景不显示导出按钮。 |
|||
- 成功/失败提示可见且文案清晰。 |
|||
- 异常不导致页面崩溃。 |
|||
|
|||
### 8.4 回归检查 |
|||
|
|||
- 原有“返回主页”“编辑(作者可见)”“评论”功能不受影响。 |
|||
- 移动端与桌面端按钮布局保持可用。 |
|||
|
|||
## 9. 实现建议(供下一步计划使用) |
|||
|
|||
- 修改页面:`app/pages/@[publicSlug]/posts/[postSlug].vue` |
|||
- 可抽离工具函数(可选):`app/utils/markdown-export.ts` |
|||
- `normalizeMarkdownImageUrls(markdown: string, origin: string): string` |
|||
- `downloadMarkdownFile(filename: string, content: string): void` |
|||
|
|||
后续进入 implementation plan 时,可根据当前代码风格决定“内联实现”或“工具函数抽离”。 |
|||
Loading…
Reference in new issue