129 lines
8.4 KiB
Markdown
129 lines
8.4 KiB
Markdown
# 首页轮播图配置说明
|
||
|
||
> 适用范围: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`,不会丢图。
|
||
|
||
## 二、数据结构
|
||
|
||
```json
|
||
[
|
||
{
|
||
"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`。
|