Files
as-daycard-openapi/FE-RECOMMEND-GUIDE.md
zhaogd b537168895 feat: 新增整屏推荐页配置功能
- 7 个固定槽位(1920×1080 两行网格),槽位定义/校验/橘视厅元数据同步
- 海报按槽位自动选:竖图槽取 posterimg、横图槽取 thumbimg,支持自定义覆盖
- 一键导出 zip 交付包:海报按槽位精确尺寸居中裁剪 + config.json + README(am start 拉起命令)
- 管理后台接口 6 个(/manage/recommend-page/*),前端对接文档 FE-RECOMMEND-GUIDE.md
2026-09-26 14:28:19 +08:00

9.1 KiB
Raw Permalink Blame History

推荐页配置 · 前端对接文档

功能:设备厂商 1920×1080 整屏电影推荐页,运营在后台选片配置 7 个固定槽位,一键导出 zip 交付包发给厂商。 后端已上线,本文档为前端实施所需全部信息。


1. 通用约定

  • 鉴权:所有接口走管理后台 JWT,请求头带 token(与现有 /manage 接口一致)
  • 返回格式:{ code: 0, msg: "", data: {...} },code=0 成功,非 0 失败(msg 为错误信息)
  • 新增菜单:「媒资管理 → 推荐页配置」,路由 manage/recommend-page(后台 sys_menu 已配置 id=126,超管自动可见,其他角色需在角色管理勾选)

2. 槽位定义(固定 7 个,不可增减)

整屏排版(1920×1080 两行网格,槽位间距 20px,左右边距 70px):

┌────────────────┐ ┌─────┐ ┌─────┐ ┌─────┐
│  slot_01       │ │slot_02│ │slot_03│ │slot_04│   ← 上行
│  700×400       │ │340×440│ │340×440│ │340×440│
└────────────────┘ └─────┘ └─────┘ └─────┘
┌──────────────┐ ┌──────────────┐ ┌─────────┐
│ slot_05      │ │ slot_06      │ │ slot_07 │   ← 下行
│ 700×300      │ │ 700×300      │ │ 340×300 │
└──────────────┘ └──────────────┘ └─────────┘
槽位 类型 尺寸 说明 影片
slot_01 MAIN 主推 700×400 横图 必填 contentcode
slot_02 PORTRAIT 竖图 340×440 竖图 必填
slot_03 PORTRAIT 竖图 340×440 竖图 必填
slot_04 PORTRAIT 竖图 340×440 竖图 必填
slot_05 LANDSCAPE 横图 700×300 横图 必填
slot_06 LANDSCAPE 横图 700×300 横图 必填
slot_07 MORE 更多入口 340×300 无影片,点击拉起橘视厅 不填,必填海报 URL

编辑页建议:按 0.25 倍缩放渲染线框(175×100 / 85×110 / 175×75 / 85×75),每槽位显示海报缩略图 + 影片名 + 尺寸标注。


3. 接口清单

Base:/manage/recommend-page

方法 路径 说明
GET /list 分页列表,参数 page、limit、name(可选)
GET /info/{id} 详情(slots 已解析为数组)
GET /slot-definitions 槽位定义(渲染线框用,见 §3.1)
POST /save 新建或更新(有 id 更新,无 id 新建)
POST /delete 软删除,body: [1, 2](id 数组)
GET /export/{id} 导出 zip 交付包(必须 blob 方式下载,见 §6)

3.1 槽位定义 GET /slot-definitions

{
  "code": 0,
  "data": {
    "slots": {
      "slot_01": { "slotCode": "slot_01", "slotType": "MAIN", "width": 700, "height": 400,
                    "defaultActionType": "DETAIL", "mediaRequired": true, "posterField": "thumbimg" },
      "slot_02": { "slotCode": "slot_02", "slotType": "PORTRAIT", "width": 340, "height": 440,
                    "defaultActionType": "DETAIL", "mediaRequired": true, "posterField": "posterimg" }
      // ... slot_03~07
    }
  }
}

3.2 列表 GET /list?page=1&limit=10

{
  "code": 0,
  "data": {
    "page": {
      "totalCount": 5, "pageSize": 10, "currPage": 1, "totalPage": 1,
      "list": [
        { "id": 1, "name": "2026年10月推荐", "remark": "备注", "deleteFlag": "UNDEL",
          "createdAt": "2026-09-26 15:00:00", "updatedAt": "2026-09-26 15:00:00" }
      ]
    }
  }
}

3.3 详情 GET /info/{id}

{
  "code": 0,
  "data": {
    "recommendPage": { "id": 1, "name": "2026年10月推荐", "remark": "", "slots": "[...原始JSON字符串...]", "createdAt": "..." },
    "slots": [
      {
        "slotCode": "slot_01",
        "slotType": "MAIN",
        "width": 700, "height": 400,
        "contentcode": "23010012026061709581101832",
        "mediaName": "影片名(后端从橘视厅同步)",
        "posterUrl": "https://imgcms.jetsenx.huashi.tv/.../448x252_xxx.png",
        "customPoster": false,
        "actionType": "DETAIL",
        "actionParam": "am start -n tv.huashi.jetsenx.jetsenfilx.jsttv.home/com.pukka.jiecheng.MainActivity --es media_id \"{contentcode}\"",
        "rawMedia": { "...橘视厅完整元数据(posterimg/thumbimg/description等)..." }
      },
      {
        "slotCode": "slot_07",
        "slotType": "MORE",
        "width": 340, "height": 300,
        "contentcode": null,
        "mediaName": "更多影片",
        "posterUrl": "https://.../more.jpg",
        "customPoster": true,
        "actionType": "LAUNCH",
        "actionParam": "am start -n tv.huashi.jetsenx.jetsenfilx.jsttv.home/com.pukka.jiecheng.MainActivity",
        "rawMedia": null
      }
    ]
  }
}

前端渲染用 data.slots(已解析),按 slotCode 匹配到线框位置。

3.4 保存 POST /save

前端只需传必要字段,影片名/海报由后端从橘视厅自动同步:

{
  "id": null,
  "name": "2026年10月推荐",
  "remark": "备注(可选)",
  "slots": [
    { "slotCode": "slot_01", "contentcode": "23010012026061709581101832" },
    { "slotCode": "slot_02", "contentcode": "..." },
    { "slotCode": "slot_03", "contentcode": "..." },
    { "slotCode": "slot_04", "contentcode": "..." },
    { "slotCode": "slot_05", "contentcode": "..." },
    { "slotCode": "slot_06", "contentcode": "..." },
    { "slotCode": "slot_07", "posterUrl": "https://.../more.jpg" }
  ]
}

槽位可选字段:

字段 说明
posterUrl 自定义海报 URL。横图槽位(slot_01/05/06/07)默认用橘视厅横版图,效果不佳时运营可手动填横图 URL 覆盖
actionParam 自定义拉起命令(一般不填,用后端默认值)

后端校验规则(错误信息会原样返回 msg):

  • 期名 name 必填
  • slots 必须 7 个、slotCode 齐全不重复
  • slot_01~06 contentcode 必填;无效 contentcode 报错 contentcode 无效: xxx(保存时后端实时调橘视厅校验)
  • slot_07 必填 posterUrl
  • 影片无海报时报错 影片 xxx 无可用海报

成功返回:{ code: 0, data: { recommendPage: { id: 1, ... } } }


4. 选片弹窗(复用已有媒资接口)

搜索:GET /manage/jetsen-media/search?keyword=xxx&pageindex=1&pagesize=20(已存在的接口)

{
  "code": 0,
  "data": {
    "list": [
      { "contentcode": "23010022026090109192132084", "name": "后悔没有好好爱过你",
        "posterimg": "https://...", "categoryname": "电影", "score": "8.0",
        "releaseyear": "2026", "originalcountry": "中国大陆" }
    ],
    "totalCount": 100, "currPage": 1, "pageSize": 20, "totalPage": 5
  }
}

弹窗交互:搜索框 → 结果列表(海报缩略图 + 片名 + contentcode)→ 选中回填槽位。 槽位预览图可直接用选中结果的 posterimg(保存后以 info 接口返回的 posterUrl 为准)。


5. 页面结构

5.1 列表页 /recommend(路由建议)

列 说明
期名 name
备注 remark
创建时间 createdAt
操作 编辑 / 复制新一期 / 导出zip / 删除

复制新一期:调 info/{id} 取 slots 预填新建表单(id 置 null),运营只改差异影片。

5.2 编辑页

  • 顶部表单:期名(必填)、备注
  • 槽位线框区(§2 尺寸 × 0.25 缩放)
  • slot_01~06:点槽位 → 打开选片弹窗 → 回填 contentcode + 预览图
  • 每个槽位可展开「自定义海报 URL」输入框(可选,横图槽位补横版图用)
  • slot_07:仅海报 URL 输入(必填)+ 可选拉起参数
  • 工具栏:保存、导出 zip(保存后才可导出,需有 id)

前端预校验(7 槽位齐、slot_01~06 contentcode 齐、slot_07 海报齐),后端保存时再校验一遍。


6. 导出下载(重要:不能用 window.open)

导出接口走 JWT 请求头,window.open / <a href> 无法带 token,必须用 axios blob 方式:

axios.get(`/manage/recommend-page/export/${id}`, {
  responseType: 'blob',
  headers: { token: getToken() }
}).then(res => {
  const url = window.URL.createObjectURL(new Blob([res.data]))
  const link = document.createElement('a')
  link.href = url
  link.download = `推荐页_${name}.zip`
  link.click()
  window.URL.revokeObjectURL(url)
})

注意:导出需实时下载 7 张海报并裁剪,耗时约 5~15 秒,建议按钮加 loading 态。失败时(如某海报下载失败)返回 JSON 错误而非 zip,前端可判断 res.data.type === 'application/json' 提示错误。


7. zip 交付包结构(导出结果,无需前端处理,仅供了解)

推荐页_2026年10月推荐.zip
├── images/slot_01.png ~ slot_07.png   # 已按槽位精确尺寸居中裁剪
├── recommend_config.json              # contentcode + actionType + actionParam(占位符已替换真实值)
└── README.txt                         # 排版与拉起规则说明