feat(template-07): 首页轮播图按后台配置的跳转类型跳转
轮播图原先只读 linkUrl 渲染 <a>,而后台「轮播图管理」的跳转是
linkType + linkUrl/linkTargetId 三元组:配「文章详情 / 产品详情」时
linkUrl 为空,前端拿不到地址,图片就渲染成不可点的纯 <img>,
运营配了也点不动。
- utils 新增 getBannerTarget():linkType 2 → /article/{id}、
3 → /product/{id}、1 → linkUrl;类型缺省但地址非空时按外链兜底
(兼容只存了地址的老数据);字段名兼容 link / linkUrl / link_url
- 新增 isExternalUrl():http(s)、//host、mailto 等视为站外
- getBannerLink() 保留为 getBannerTarget() 的薄封装,对外行为不变
- HeroSection:图片按目标渲染 NuxtLink(站内目标当前页跳转)/
<a target="_blank">(外链)/ 纯 <img>(未配置跳转,保持不可点)
- CmsBanner 补 linkType / linkUrl / linkTargetId 字段声明
首页 4 张图(政府采购代理 / 投融资服务 / AI数智化 / 工程代理)
已在后台配置为「产品详情」跳转。
This commit is contained in:
@@ -5,28 +5,42 @@
|
||||
<div class="absolute inset-0 z-0">
|
||||
<!-- 轮播图(绝对定位叠放,靠 opacity 交叉淡入) -->
|
||||
<div
|
||||
v-for="(b, i) in banners"
|
||||
:key="b.id || i"
|
||||
v-for="(item, i) in bannerItems"
|
||||
:key="item.banner.id || i"
|
||||
class="absolute inset-0 transition-opacity duration-1000 ease-in-out"
|
||||
:class="i === currentBannerIndex ? 'opacity-100' : 'opacity-0 pointer-events-none'"
|
||||
>
|
||||
<!-- 后台配了站内目标(文章详情 / 产品详情)→ 当前页跳转 -->
|
||||
<NuxtLink
|
||||
v-if="item.target && !item.target.external"
|
||||
:to="item.target.href"
|
||||
class="block w-full h-full"
|
||||
>
|
||||
<img
|
||||
:src="bannerImg(item.banner)"
|
||||
:alt="item.banner.title || ''"
|
||||
class="w-full h-full object-cover"
|
||||
>
|
||||
</NuxtLink>
|
||||
<!-- 后台配了外链 → 新标签页打开 -->
|
||||
<a
|
||||
v-if="bannerLink(b)"
|
||||
:href="bannerLink(b)"
|
||||
v-else-if="item.target"
|
||||
:href="item.target.href"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="block w-full h-full"
|
||||
>
|
||||
<img
|
||||
:src="bannerImg(b)"
|
||||
:alt="b.title || ''"
|
||||
:src="bannerImg(item.banner)"
|
||||
:alt="item.banner.title || ''"
|
||||
class="w-full h-full object-cover"
|
||||
>
|
||||
</a>
|
||||
<!-- 后台未配置跳转 → 纯图,不可点 -->
|
||||
<img
|
||||
v-else
|
||||
:src="bannerImg(b)"
|
||||
:alt="b.title || ''"
|
||||
:src="bannerImg(item.banner)"
|
||||
:alt="item.banner.title || ''"
|
||||
class="w-full h-full object-cover"
|
||||
>
|
||||
</div>
|
||||
@@ -156,10 +170,16 @@
|
||||
*
|
||||
* 文案优先级:当前 banner 的 title/subtitle → siteInfo.slogan/comments → siteName 拼接 → 硬编码兜底。
|
||||
* 即使某张 banner 未配文案也不会出现空白。
|
||||
*
|
||||
* 点击行为:点击轮播图按后台「轮播图管理」配置的跳转类型跳转
|
||||
* (linkType:1 外链、2 文章详情、3 产品详情,目标由 linkUrl / linkTargetId 决定):
|
||||
* - 站内目标(文章 / 产品详情)走 NuxtLink 当前页跳转;
|
||||
* - 外链新标签页打开;
|
||||
* - 未配置跳转的图片保持纯图不可点(不渲染空的可点区域)。
|
||||
*/
|
||||
import type { CmsNavigation, CmsBanner, ApiEnvelope, PageResult } from '~/types'
|
||||
import { ensureFullUrl } from '~/utils/image'
|
||||
import { getNavLink, getBannerLink } from '~/utils'
|
||||
import { getNavLink, getBannerTarget } from '~/utils'
|
||||
|
||||
interface Props {
|
||||
/** 是否启用 Banner 轮播背景;false 时即使有轮播图也回退到蓝渐变 */
|
||||
@@ -196,6 +216,15 @@ const banners = computed<CmsBanner[]>(() => {
|
||||
/** 是否进入轮播图模式:有可用轮播图且后台开启 Banner 轮播开关 */
|
||||
const bannerMode = computed(() => props.showBanner && banners.value.length > 0)
|
||||
|
||||
/**
|
||||
* 轮播项 + 解析好的点击目标(后台「轮播图管理」配置的跳转)。
|
||||
* target 为 null 表示该图未配置跳转,此时渲染纯图不可点。
|
||||
*/
|
||||
const bannerItems = computed(() => banners.value.map((b) => ({
|
||||
banner: b,
|
||||
target: getBannerTarget(b)
|
||||
})))
|
||||
|
||||
/** 当前帧索引 */
|
||||
const currentBannerIndex = ref(0)
|
||||
|
||||
@@ -246,11 +275,6 @@ function bannerImg(b: CmsBanner): string {
|
||||
return raw.replace(/resize,w_\d+/, 'resize,w_1920')
|
||||
}
|
||||
|
||||
/** 取轮播图跳转链接(统一走 utils.getBannerLink,兼容 link/linkUrl/link_url 多字段名) */
|
||||
function bannerLink(b: CmsBanner): string {
|
||||
return getBannerLink(b)
|
||||
}
|
||||
|
||||
/** 是否有可用图片 */
|
||||
function hasImage(b: CmsBanner): boolean {
|
||||
return !!(b.image || b.imageUrl || b.pic || b.url)
|
||||
|
||||
Reference in New Issue
Block a user