8.4 KiB
首页轮播图配置说明
适用范围: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),透明区域变成白底;
- 直接把整张海报(含按钮)当热区图用,等于又盖了一层。
自查方法:
- 把 PNG 拖到纯深色背景的窗口里看,如果还能看到灰白格子,就是图里带的;
- macOS 可用
sips -g hasAlpha 图片.png检查是否真有 alpha 通道(hasAlpha: yes才算透明图)。
后台已经加了兜底提示:上传「热区按钮图」时会做一次像素体检,若没有任何透明像素会立刻提示(「只有白/浅灰底色」还会明确点出疑似棋盘格);上传海报底图时也会提示疑似棋盘格的情况。提示只是提醒,不会阻止保存。
修复办法:回到设计源文件,隐藏背景后重新导出为 PNG(不要截图预览图);若只有一张带底纹的图,可在 PS 里用「色彩范围」选中浅灰网格后删除再导出。
已修复的历史坑:后台上传前会做一次「压缩优化」,旧实现先给 canvas 铺白底再编码,会把透明区域压成白底方块(透明按钮图上传后变白色矩形)。现在改为:检测到原图带透明像素时不铺白底并输出
image/png(无损保留 alpha),不透明图仍走 WebP 压缩。代码:frontend/src/shared/utils/imageUpload.ts。修复前上传过的图需要重新上传。
四、点击行为与悬浮反馈
- 命中热区(且热区配置了真实跳转)→ 执行该热区的跳转;
- 未命中热区 → 执行该端「整图点击」行为(
none时不跳转); - 完全没有配置跳转(整图
none且无有效热区)→ 保留原有「点击查看大图」能力。
preview 类型会打开大图预览:PC 用 Element Plus el-image-viewer,移动端用内置 lightbox(2:1 框 + object-fit: contain,整图完整可见)。
悬浮反馈分两种:
- 热区配了
image_url:渲染透明 PNG 按钮图,鼠标悬浮时按hover_scale轻微放大(transform: scale()+0.2s过渡)并加投影,按下时轻微回缩; - 热区没配图:悬浮显示半透明高亮框,提示「这里可点」。
这正是海报型轮播的常见做法:把海报上的按钮单独切透明 PNG 叠在底图上,既能点击跳转,又有「按钮浮起来」的手感。运营操作要点:
- 底图(PC 1600×400 / 移动 750×375)里不要烘焙按钮,按钮留空;
- 把按钮单独导出为透明 PNG(尺寸与海报上的位置匹配);
- 后台在同一端的预览图上拖框对齐,再填该按钮的跳转。
五、后台怎么配
后台 → 系统配置 → mobile.home_banners → 「编辑首页轮播图」:
- 每条轮播是一张卡片,可启用/停用、上移/下移、删除;卡片内先填文案(眉标/主标题/角标/胶囊/色调),无图时按文字卡片展示。
- 切到「PC 端 1600×400(4:1)」或「移动端 750×375(2:1)」页签,上传/填写该端图片,并配置「整图点击」行为。
- 在预览图上单击新增热区 → 拖动移动 → 拖右下角小方块缩放;下方可为选中热区设置名称、精确坐标、跳转,以及热区按钮图与悬浮放大倍数(后台预览图会把按钮图半透明铺在框内,所见即所得)。
- 保存时写入
mobile.home_banners,后台会顺带把旧的扁平image_url结构升级为pc/mobile结构。
六、分销站点后台
分销站点与主站使用完全相同的 pc / mobile 数据结构,但独立保存在 distribution_sites.banners_json,不影响主站配置。
入口:分销后台 → 品牌装修 → 「首页轮播横幅」。每条轮播同样支持:
- 启用/停用、上移/下移、删除,以及眉标/主标题/角标/胶囊/色调;
- PC 端与移动端分别上传图片、填写图片 URL、配置整图点击行为;
- 每端独立配置热区:单击新增、拖动移动、拖右下角缩放,热区可设置透明 PNG 按钮图、悬浮放大、坐标与跳转;
- 某一端留空时,该端前台回退为文字卡片,不会拿另一端的图强行裁切。
历史兼容:早期分销后台保存的扁平 { 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。