You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

5.7 KiB

媒体库与「媒体」入口设计

背景与目标

控制台已有 /me/media/orphans(图片孤儿审查与删除)与 POST /api/file/upload(图片入库到 media_assets),但缺少面向作者的 资源库:集中上传、浏览自己名下的媒体,并 复制公开 URL / Markdown 图片语法,以便在文章等编辑器中手动粘贴使用。

本设计首版强调 与编辑器解耦:不修改 Markdown 编辑器行为;后续可在编辑器内增加「从媒体库选用」等深度集成。

需求结论(已确认)

  • 核心价值:以 上传 + 选用(复制) 为主,列表浏览为辅。
  • 首版范围媒体库页面 + 复制公开 URL + 复制 ![](url),不在文章/资料编辑器内做集成。
  • 复制形态:同时提供 「复制图片 URL」「复制 Markdown 图片」 两种操作(两个按钮或等价 UI)。
  • URL 策略:在浏览器端使用 window.location.origin + '/public/assets/<storageKey>' 生成 绝对 URL,两种复制均使用该地址,避免相对路径在外部编辑器中失效。
  • 导航单一「媒体」入口,下挂 资源库孤儿清理 两个子能力。
  • 首版不做:媒体库内对仍被引用的资源的一键删除(避免与 media_refs / 正文同步规则冲突);孤儿删除与宽限逻辑 继续仅在「孤儿清理」子页 完成。

信息架构与路由

采用 Nuxt 父布局 + 子页面(推荐方案,已采纳):

路径 说明
/me/media 默认落地:资源库media/index.vue
/me/media/orphans 图片孤儿审查(沿用现有逻辑与 API,页面作为子路由)

新增父级壳页面(例如 app/pages/me/media.vue):

  • 顶区标题:媒体
  • 子导航:资源库孤儿清理(与当前子路由联动高亮)
  • 内容区:<NuxtPage />

文件布局约定:

  • app/pages/me/media.vue — 壳(导航 + 插槽)
  • app/pages/me/media/index.vue — 资源库
  • app/pages/me/media/orphans.vue — 孤儿页(由现有页面迁入嵌套结构;业务与接口尽量不变)

媒体库页(功能)

列表

  • 数据源:当前登录用户的 media_assetsuserId 严格等于会话用户)。
  • 排序:默认 createdAt 降序
  • 分页:与孤儿页类似,提供 10 / 20 / 50 每页可选。
  • 展示:缩略图网格;每张卡片展示 文件大小上传时间
  • 引用数:对每条资产聚合 media_refs 行数 作为 refCount 展示,便于区分「已出现在文章/封面/资料等」与「仅上传未写入内容」。不展示可编辑的「引用详情」全文(首版保持简单)。

上传

  • 调用现有 POST /api/file/upload(multipart,与资料页一致:格式、大小上限、多文件上限等沿用服务端实现)。
  • 上传成功后 刷新列表,并用 toast 提示成功;失败展示服务端错误信息。

复制

  • 复制图片 URL:将绝对 URL 写入剪贴板。
  • 复制 Markdown 图片:写入 ![](<绝对URL>)
  • 复制成功 / 失败:toast 反馈。若剪贴板 API 不可用,首版以 toast 说明即可;可选增强:弹窗展示可手动复制的文本(实现阶段再决定是否纳入首版计划)。

明确不包含(首版)

  • 媒体库内 删除 仍被引用或非孤儿宽限内的资源。
  • 文章/资料编辑器内嵌媒体选择器、自动插入光标等。

服务端 API

GET /api/me/media/assets

  • 鉴权:必须登录;仅返回 当前用户media_assets
  • Querypage(从 1 起)、pageSize(允许值与前端分页选项对齐,服务端需校验上限)。
  • 响应(示意):{ items: [...], total: number }
    每项至少包含:idstorageKey(或等价字段)、sizeBytescreatedAt(ISO 或统一项目惯例)、mimerefCount公开路径可与前端约定为固定前缀 /public/assets/ + storageKey,或由服务端返回 publicPath 以避免重复逻辑。
  • 安全:禁止按参数指定其他 userId;不得泄露其他用户资源。

列表查询实现可放在 server/service/media 或并列模块,保持 handler 轻薄。

全局导航与控制台首页

AppShell 控制台子导航

  • 在现有「资料 / 文章 / 时光机 / RSS」基础上增加 「媒体」→ /me/media
  • 更新相关注释(原「桌面端下拉内仅四个子链接」等)以反映 五个 子项。

/me 控制台首页

  • 将原 「文章媒体清理」 卡片 合并 为单一 「媒体」 入口:文案说明内含 资源库孤儿清理,主按钮指向 /me/media
  • 不在首页重复放置两个独立卡片指向同一能力域(除非产品明确要求「孤儿」快捷直达,本 spec 不采用)。

错误处理与空状态

  • 列表加载失败:toast + 可重试(按钮或自动提示)。
  • 空列表:说明可上传图片,并提供上传入口。
  • 上传失败:toast,错误信息来自服务端。

测试建议

  • GET /api/me/media/assets:未登录返回 401;分页边界;用户隔离(仅本人数据);pageSize 非法值处理。
  • 若有可单测的纯函数(例如 Markdown 拼接),可补充 单元测试;UI 以手测为主。

后续扩展(非本 spec 交付范围)

  • 文章 Markdown 编辑器内:打开媒体库、插入链接或 Markdown。
  • 资料页头像/头图:从媒体库选用(仍可与裁剪流程组合)。
  • 媒体库内 删除:需与 syncPostMediaRefs / syncProfileMediaRefs 及孤儿规则统一产品设计后再做。