Files
hfb_sys/docs/首页轮播图配置说明.md

8.4 KiB
Raw Permalink Blame History

首页轮播图配置说明

适用范围:PC 首页 Hero 轮播(HomeBanner.vue)、移动端首页 Banner 轮播(MobileHomeView.vue)、主站后台「首页轮播图」弹窗(HomeBannersDialog.vue),以及分销站点后台「品牌装修 → 首页轮播横幅」(distribution-admin/src/pages/SiteSettings.tsx)。 配置存储位置:主站为系统配置表 mobile.home_banners(JSON 字符串),前台接口 GET /api/mobile-home-config;分销站点为 distribution_sites.banners_json,随 GET /api/distribution/site-info 下发。

一、出图规范(两端容器严格等比,按规范出图不裁切)

端 展示容器比例 建议出图尺寸 说明
PC 4:1 1600×400 Hero 卡片宽度自适应,高度由 aspect-ratio: 1600 / 400 推导
移动端 2:1 750×375(或 720×360) 只要有一条配图,整条轮播统一按 aspect-ratio: 2 / 1 展示

两端使用不同的图片字段,必须分别出图:

  • PC 端只用 pc.image_url;
  • 移动端只用 mobile.image_url;
  • 若该端未配图,会退回文字卡片(眉标 + 主标题 + 胶囊文案),不会用另一端的图硬撑(避免严重裁切)。

历史数据兼容:早期只有扁平 image_url 的轮播,读取时会自动并入 pc.image_url 与 mobile.image_url,不会丢图。

二、数据结构

[
  {
    "eyebrow": "三角洲行动账号专区",
    "title": "高哈夫币 · 安全交接 · 随租随玩",
    "badge": "HOT",
    "pill": "新人领券最高减 20 元",
    "tone": "blue",
    "enabled": true,
    "pc": {
      "image_url": "https://cdn.example/banner-pc.jpg",
      "alt": "首页活动横幅",
      "action": { "type": "route", "target": "/listings", "open_new_tab": false },
      "hotspots": [
        {
          "id": "hotspot-1",
          "label": "租币教程",
          "x": 6,
          "y": 20,
          "width": 20,
          "height": 24,
          "action": { "type": "route", "target": "/m/add-home-guide", "open_new_tab": false }
        }
      ]
    },
    "mobile": { "image_url": "...", "action": {}, "hotspots": [] }
  }
]

字段说明:

  • enabled:false 时前台不展示该条轮播(后台仍保留配置)。
  • pc / mobile:两端独立配置,结构相同(图片、整图点击行为、热区)。
  • action.type:none 不跳转 / route 站内路径 / link 外部链接 / preview 查看大图。
  • action.open_new_tab:仅 route、link 有意义。
  • hotspots[].x/y/width/height:相对图片的百分比(0-100),与出图分辨率解耦,改分辨率不会跑位。
  • hotspots[].image_url:热区按钮图(透明 PNG)。配了图就渲染成海报上的「胶囊按钮」,留空则用半透明高亮框提示可点击。
  • hotspots[].hover_scale:鼠标悬浮时按钮图的放大倍数,默认 1.06,范围 1-1.5(1 = 不放大)。

三、热区按钮图导出踩坑(重要)

热区按钮图必须是带 alpha 透明通道的 PNG,否则整个矩形会盖住海报。最常见的坑:

  • 把设计工具/Figma/PS 里显示「透明区域」的灰白棋盘格预览截图或另存,棋盘格就成了真实像素,前台会照实显示成一块格子;
  • 从 AI 出图工具导出时选了不透明背景(或导出成 JPG),透明区域变成白底;
  • 直接把整张海报(含按钮)当热区图用,等于又盖了一层。

自查方法:

  1. 把 PNG 拖到纯深色背景的窗口里看,如果还能看到灰白格子,就是图里带的;
  2. macOS 可用 sips -g hasAlpha 图片.png 检查是否真有 alpha 通道(hasAlpha: yes 才算透明图)。

后台已经加了兜底提示:上传「热区按钮图」时会做一次像素体检,若没有任何透明像素会立刻提示(「只有白/浅灰底色」还会明确点出疑似棋盘格);上传海报底图时也会提示疑似棋盘格的情况。提示只是提醒,不会阻止保存。

修复办法:回到设计源文件,隐藏背景后重新导出为 PNG(不要截图预览图);若只有一张带底纹的图,可在 PS 里用「色彩范围」选中浅灰网格后删除再导出。

已修复的历史坑:后台上传前会做一次「压缩优化」,旧实现先给 canvas 铺白底再编码,会把透明区域压成白底方块(透明按钮图上传后变白色矩形)。现在改为:检测到原图带透明像素时不铺白底并输出 image/png(无损保留 alpha),不透明图仍走 WebP 压缩。代码:frontend/src/shared/utils/imageUpload.ts。修复前上传过的图需要重新上传。

四、点击行为与悬浮反馈

  1. 命中热区(且热区配置了真实跳转)→ 执行该热区的跳转;
  2. 未命中热区 → 执行该端「整图点击」行为(none 时不跳转);
  3. 完全没有配置跳转(整图 none 且无有效热区)→ 保留原有「点击查看大图」能力。

preview 类型会打开大图预览:PC 用 Element Plus el-image-viewer,移动端用内置 lightbox(2:1 框 + object-fit: contain,整图完整可见)。

悬浮反馈分两种:

  • 热区配了 image_url:渲染透明 PNG 按钮图,鼠标悬浮时按 hover_scale 轻微放大(transform: scale() + 0.2s 过渡)并加投影,按下时轻微回缩;
  • 热区没配图:悬浮显示半透明高亮框,提示「这里可点」。

这正是海报型轮播的常见做法:把海报上的按钮单独切透明 PNG 叠在底图上,既能点击跳转,又有「按钮浮起来」的手感。运营操作要点:

  1. 底图(PC 1600×400 / 移动 750×375)里不要烘焙按钮,按钮留空;
  2. 把按钮单独导出为透明 PNG(尺寸与海报上的位置匹配);
  3. 后台在同一端的预览图上拖框对齐,再填该按钮的跳转。

五、后台怎么配

后台 → 系统配置 → mobile.home_banners → 「编辑首页轮播图」:

  1. 每条轮播是一张卡片,可启用/停用、上移/下移、删除;卡片内先填文案(眉标/主标题/角标/胶囊/色调),无图时按文字卡片展示。
  2. 切到「PC 端 1600×400(4:1)」或「移动端 750×375(2:1)」页签,上传/填写该端图片,并配置「整图点击」行为。
  3. 在预览图上单击新增热区 → 拖动移动 → 拖右下角小方块缩放;下方可为选中热区设置名称、精确坐标、跳转,以及热区按钮图与悬浮放大倍数(后台预览图会把按钮图半透明铺在框内,所见即所得)。
  4. 保存时写入 mobile.home_banners,后台会顺带把旧的扁平 image_url 结构升级为 pc / mobile 结构。

六、分销站点后台

分销站点与主站使用完全相同的 pc / mobile 数据结构,但独立保存在 distribution_sites.banners_json,不影响主站配置。

入口:分销后台 → 品牌装修 → 「首页轮播横幅」。每条轮播同样支持:

  1. 启用/停用、上移/下移、删除,以及眉标/主标题/角标/胶囊/色调;
  2. PC 端与移动端分别上传图片、填写图片 URL、配置整图点击行为;
  3. 每端独立配置热区:单击新增、拖动移动、拖右下角缩放,热区可设置透明 PNG 按钮图、悬浮放大、坐标与跳转;
  4. 某一端留空时,该端前台回退为文字卡片,不会拿另一端的图强行裁切。

历史兼容:早期分销后台保存的扁平 { image_url, title, link } 或 { image_url, link_url } 会自动升级为两端共图;其中旧字段 link 与 link_url 都会被识别。分销前台归一化实现:frontend/src/stores/distributionSite.ts(mapDistributionHomeBanners)。

七、校验与兜底

  • 前后端都会归一化配置:坐标收敛到 0-100 且不越界,宽高为 0 的热区直接丢弃;route / link 缺少目标时退化为 none(避免「点了没反应」的死热区)。
  • 后端归一化实现:backend/internal/modules/systemconfig/normalize.go(normalizeHomeBanners)。
  • 前端归一化实现:frontend/src/features/listings/api/homeConfig.ts(normalizeHomeBanner);分销站点为 distribution-admin/src/homeBanner.ts。
  • 相关测试:frontend/src/features/listings/api/homeConfig.spec.ts、frontend/src/stores/distributionHomeBanner.spec.ts、backend/internal/modules/systemconfig/home_banners_test.go。