feat(admin): embed slot management with code snippet

P4b Task 5:/system/embed-slots 管理页(Task 8/9 页面模式:useCursorList
游标累积 + 对话框治理)。列表(名称/绑定相册/启停/configVersion/更新时间,
启停开关行内 PATCH → configVersion+1 toast 提示)+ 新建/编辑对话框
(设置表单位置/尺寸/间隔/语言/默认收起,intervalMs 契约区间夹取;编辑按
整体替换语义提交完整 settings)+ 绑定相册对话框(相册标题/ID 搜索选中 →
确认框携带 A22 文案「configVersion 将递增,官网无需改动」;清空即解绑)+
嵌入代码卡({EMBED_ORIGIN}/embed/v1/loader.js + data-slot 令牌,一键复制;
EMBED_ORIGIN=VITE_EMBED_ORIGIN 缺省本机 viewer dev,.env.example 登记)。

- API 层 src/api/embedSlots.ts + types/api/embedSlot.d.ts(契约镜像)
- vitest 9 例:表单→载荷(缺省+夹取)、编辑载荷收敛、snippet 拼接、
  环境基址兜底、绑定变更分类、zh/en 键一致 + A22 短语断言
- Playwright e2e(真实 cn+ov 后端):新建→绑定(gov-photos 直种 +
  seed-fixture 新增 sync-flush 模式经 bootstrap/真实发送管线投影 photos_ov)
  →嵌入代码卡含 token→ov 公开 feed 返回相册照片→换绑 configVersion+1 +
  feed 切换(A22)→停用 feed 404;admin playwright 配置补 ov webServer
- i18n zh/en(embedSlotsManage.* + menus.system.embedSlots)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-20 23:25:59 +08:00
parent 8f2c21d25a
commit 0238f505c4
17 changed files with 1452 additions and 8 deletions
+83 -1
View File
@@ -234,7 +234,8 @@
"title": "账号与同步",
"users": "账号管理",
"userSync": "用户同步",
"usage": "用量统计"
"usage": "用量统计",
"embedSlots": "展示位管理"
},
"albums": {
"title": "相册管理",
@@ -700,6 +701,87 @@
"colCreatedAt": "记录时间"
}
},
"embedSlotsManage": {
"list": {
"title": "展示位管理(悬浮轮播组件挂载点)",
"create": "新建展示位",
"loadMore": "加载更多",
"noMore": "已全部加载",
"empty": "暂无展示位,点击「新建展示位」创建",
"loadFailed": "展示位列表加载失败",
"retry": "重试",
"colName": "名称",
"colAlbum": "绑定相册",
"colEnabled": "启用",
"colConfigVersion": "配置版本",
"colUpdatedAt": "更新时间",
"colActions": "操作",
"unbound": "未绑定",
"actionEdit": "编辑",
"actionBind": "绑定相册",
"actionCode": "嵌入代码"
},
"form": {
"nameLabel": "名称",
"namePlaceholder": "如:官网首页悬浮位",
"nameRequired": "请输入展示位名称",
"submit": "保存",
"positionLabel": "悬浮位置",
"positionLeft": "左侧",
"positionRight": "右侧",
"sizeLabel": "组件尺寸",
"sizeSm": "小(窄屏降级档)",
"sizeMd": "标准",
"intervalLabel": "轮播间隔",
"intervalUnit": "毫秒(3000-30000)",
"langLabel": "内容语言",
"langAuto": "跟随相册",
"langZh": "中文",
"langEn": "英文",
"collapsedLabel": "默认收起",
"collapsedHint": "初始仅展示小把手,点击展开"
},
"create": {
"title": "新建展示位",
"created": "展示位已创建(嵌入代码可在「嵌入代码」查看)"
},
"edit": {
"title": "编辑展示位",
"noChanges": "未修改任何内容",
"saved": "已保存(configVersion 已递增至 {version})"
},
"bind": {
"title": "绑定相册:{name}",
"currentLabel": "当前绑定",
"targetLabel": "目标相册",
"searchPlaceholder": "输入相册标题或 ID 搜索",
"searching": "搜索中…",
"noMatch": "无匹配相册",
"clearHint": "清空选择并提交即解绑(公开端随即 404)",
"versionHint": "绑定变更仅递增 configVersion,已嵌入的官网无需改动(组件只认令牌)",
"confirmTitle": "确认绑定变更",
"confirmBind": "绑定相册后 configVersion 将递增,官网无需改动;组件将展示该相册的近期照片。",
"confirmRebind": "换绑相册后 configVersion 将递增,官网无需改动;组件将切换展示新相册的近期照片。",
"confirmUnbind": "解绑后 configVersion 将递增,官网无需改动;组件公开端将立即下线(404)。",
"actionBind": "绑定",
"actionRebind": "换绑",
"actionUnbind": "解绑",
"saved": "绑定已更新(configVersion 已递增至 {version})"
},
"code": {
"title": "嵌入代码:{name}",
"tokenLabel": "展示位令牌(data-slot)",
"snippetLabel": "嵌入代码(粘贴到官网宿主页)",
"copy": "复制",
"copied": "已复制嵌入代码",
"hint": "将代码粘贴到官网页面即可挂载悬浮轮播;后续换绑相册、启停均无需改动该代码。",
"close": "关闭"
},
"toast": {
"enabledOn": "已启用(configVersion 已递增至 {version})",
"enabledOff": "已停用(configVersion 已递增至 {version},公开端随即 404)"
}
},
"apiMsg": {
"AUTH_INVALID_CREDENTIALS": "账号或密码错误",
"AUTH_RATE_LIMITED": "登录失败次数过多,请稍后再试",