feat ui设计稿bug修复
This commit is contained in:
@@ -1,161 +1,157 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import type { BannerVo } from '@/types/business/home'
|
||||
import { useRouter } from 'vue-router'
|
||||
import bannerIllustration from '@/assets/home/banner-illustration.png'
|
||||
|
||||
interface Props {
|
||||
banners: BannerVo[]
|
||||
// 设计稿顶部为静态头图(非轮播、不走接口):底 #F3F4F8 渐变,
|
||||
// 左侧标题 60px + 副标题 24px + 双按钮 183×55,右侧插画 723×598(蓝湖设计稿切图)
|
||||
const router = useRouter()
|
||||
|
||||
function goDemand(): void {
|
||||
router.push('/demand')
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
/** 仅保留启用且带图的轮播项,按后端 sort 升序 */
|
||||
const slides = computed(() =>
|
||||
props.banners
|
||||
.filter((item) => item.enabled !== false && !!item.imageUrl)
|
||||
.slice()
|
||||
.sort((prev, next) => (prev.sort ?? 0) - (next.sort ?? 0)),
|
||||
)
|
||||
|
||||
const current = ref(0)
|
||||
let timer: number | undefined
|
||||
|
||||
function stop(): void {
|
||||
if (timer !== undefined) {
|
||||
window.clearInterval(timer)
|
||||
timer = undefined
|
||||
}
|
||||
function goCases(): void {
|
||||
router.push('/cases')
|
||||
}
|
||||
|
||||
function go(index: number): void {
|
||||
const total = slides.value.length
|
||||
if (total === 0) return
|
||||
current.value = (index + total) % total
|
||||
}
|
||||
|
||||
function start(): void {
|
||||
stop()
|
||||
if (slides.value.length <= 1) return
|
||||
timer = window.setInterval(() => go(current.value + 1), 5000)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => slides.value.length,
|
||||
() => {
|
||||
current.value = 0
|
||||
start()
|
||||
},
|
||||
)
|
||||
|
||||
onMounted(start)
|
||||
onBeforeUnmount(stop)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section v-if="slides.length" class="home-banner">
|
||||
<img
|
||||
v-for="(slide, index) in slides"
|
||||
v-show="index === current"
|
||||
:key="slide.id ?? index"
|
||||
class="home-banner__img"
|
||||
:src="slide.imageUrl ?? ''"
|
||||
:alt="`轮播图 ${index + 1}`"
|
||||
>
|
||||
<section class="home-banner">
|
||||
<div class="home-banner__inner">
|
||||
<h1 class="home-banner__title">虫子智造研发一体化平台</h1>
|
||||
<p class="home-banner__subtitle">一站式智能软硬件研发与量产综合服务商</p>
|
||||
|
||||
<template v-if="slides.length > 1">
|
||||
<button
|
||||
class="home-banner__arrow home-banner__arrow--prev"
|
||||
type="button"
|
||||
aria-label="上一张"
|
||||
@click="go(current - 1)"
|
||||
>
|
||||
‹
|
||||
</button>
|
||||
<button
|
||||
class="home-banner__arrow home-banner__arrow--next"
|
||||
type="button"
|
||||
aria-label="下一张"
|
||||
@click="go(current + 1)"
|
||||
>
|
||||
›
|
||||
</button>
|
||||
|
||||
<!-- 设计稿底部居中的指示条(长条=当前,圆点=其余) -->
|
||||
<div class="home-banner__dots">
|
||||
<span
|
||||
v-for="(slide, index) in slides"
|
||||
:key="`dot-${slide.id ?? index}`"
|
||||
class="home-banner__dot"
|
||||
:class="{ 'is-active': index === current }"
|
||||
/>
|
||||
<div class="home-banner__actions">
|
||||
<button class="home-banner__btn home-banner__btn--primary" type="button" @click="goDemand">
|
||||
需求提报
|
||||
</button>
|
||||
<button class="home-banner__btn home-banner__btn--ghost" type="button" @click="goCases">
|
||||
案例中心
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="home-banner__visual">
|
||||
<img
|
||||
class="home-banner__illustration"
|
||||
:src="bannerIllustration"
|
||||
alt="虫子智造研发一体化平台"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.home-banner {
|
||||
// 设计稿头图通栏 1920×661(画板 y73,位于顶栏 72 之下)
|
||||
position: relative;
|
||||
// 设计稿头图通栏 1920×661 设计px → 高 509 CSS,紧贴顶栏无圆角
|
||||
height: 509px;
|
||||
height: 661px;
|
||||
overflow: hidden;
|
||||
background: @home-banner-bg;
|
||||
// .home 是 column flex 容器,需显式占满整行,否则被内容宽度收缩
|
||||
width: 100%;
|
||||
flex: 0 0 auto;
|
||||
|
||||
&__img {
|
||||
// 内容区按设计稿 1920 画布居中;两侧内容一律相对它定位,保证 1:1
|
||||
&__inner {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: @container-width;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
// 设计稿标题 x150 y257(画板绝对)→ banner 内 y257−73=184
|
||||
&__title {
|
||||
position: absolute;
|
||||
top: 184px;
|
||||
left: 150px;
|
||||
margin: 0;
|
||||
color: @banner-title-color;
|
||||
font-size: @font-size-hero-lg;
|
||||
font-weight: 700;
|
||||
line-height: 87px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// 设计稿副标题 x150 y360 → banner 内 y287
|
||||
&__subtitle {
|
||||
position: absolute;
|
||||
top: 287px;
|
||||
left: 150px;
|
||||
margin: 0;
|
||||
color: @banner-title-color;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 35px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// 设计稿按钮组 x150 y465 → banner 内 y392;两钮 183×55,间距 20(150+183=333 → 353)
|
||||
&__actions {
|
||||
position: absolute;
|
||||
top: 392px;
|
||||
left: 150px;
|
||||
.flex(row, flex-start, center);
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
&__btn {
|
||||
width: 183px;
|
||||
height: 55px;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
|
||||
&--primary {
|
||||
background: linear-gradient(135deg, @btn-gradient-from 0%, @btn-gradient-to 100%);
|
||||
border: none;
|
||||
color: @white;
|
||||
}
|
||||
|
||||
// 设计稿:2px 渐变描边 + 白底 + 蓝色文字(实测 #2B5FF0)
|
||||
&--ghost {
|
||||
position: relative;
|
||||
background: @white;
|
||||
border: none;
|
||||
color: @btn-ghost-color;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 8px;
|
||||
padding: 2px;
|
||||
background: linear-gradient(135deg, @btn-gradient-from 0%, @btn-gradient-to 100%);
|
||||
-webkit-mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设计稿插画 723×598 @ canvas (928,104) → banner 内 y104−73=31
|
||||
&__visual {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 928px;
|
||||
width: 723px;
|
||||
height: 598px;
|
||||
}
|
||||
|
||||
&__illustration {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
&__arrow {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
transform: translateY(-50%);
|
||||
border-radius: @radius-round;
|
||||
background: fade(@black, 35%);
|
||||
color: @white;
|
||||
font-size: @font-size-xl;
|
||||
line-height: 1;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&--prev {
|
||||
left: @spacing-base;
|
||||
}
|
||||
|
||||
&--next {
|
||||
right: @spacing-base;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover &__arrow {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&__dots {
|
||||
position: absolute;
|
||||
bottom: 48px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
.flex(row, center, center);
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
&__dot {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
border-radius: @radius-round;
|
||||
background: @home-banner-dot;
|
||||
transition: width 0.2s;
|
||||
|
||||
// 当前页:设计稿 44×5 设计px 长条
|
||||
&.is-active {
|
||||
width: 34px;
|
||||
height: 4px;
|
||||
border-radius: @radius-round;
|
||||
}
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user