Files
inkreach-uni/pages/index/components/PlatformFeatures.vue
T
RyRh 65356953ed
Test Runner / hello (push) Successful in 3s
首页轮播,裁剪标题,按钮间距
2026-08-25 12:04:57 +08:00

232 lines
5.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<!-- 用强大的功能开启盈利快车道 - Figma 1455:1490 -->
<view class="feature-section">
<text class="section-title">用强大的功能开启盈利快车道</text>
<!-- 功能卡片横向滚动
:scroll-left 绑定 featScrollLeftactiveFeat 变化时尽量把选中项滚到左侧 -->
<scroll-view
scroll-x
class="feat-scroll"
show-scrollbar="false"
:scroll-left="featScrollLeft"
:scroll-with-animation="true"
>
<view class="feat-list">
<view
class="feat-card"
:class="{ active: activeFeat === index }"
v-for="(item, index) in features"
:key="index"
@tap="onFeatTap(index)"
>
<text class="feat-num">{{ item.step }}</text>
<view class="feat-text">
<text class="feat-title">{{ item.title }}</text>
<text class="feat-desc">{{ item.desc }}</text>
</view>
</view>
</view>
</scroll-view>
<!-- 集成平台大图 - 370x257 8px圆角
图片来源features[activeFeat].img4张卡片分别对应一张大图占位时 4 张同图设计师供图后换 mock.js 即可 -->
<view class="integration-wrap">
<image
class="integration-img"
:src="integrationImg"
mode="widthFix"
></image>
</view>
</view>
</template>
<script>
// 功能卡片尺寸(与 CSS 保持一致,用于计算「选中卡片滚到左边」的 scrollLeft
// CSS: .feat-card { width:332rpx }, .feat-list gap:16rpx
// 1rpx = 0.5px,所以 1 张卡片+gap = (332 + 16) * 0.5 = 174px
const CARD_WIDTH_PX = 332 * 0.5 // 166
const CARD_GAP_PX = 16 * 0.5 // 8
const CARD_STEP_PX = CARD_WIDTH_PX + CARD_GAP_PX // 174
const AUTO_PLAY_INTERVAL = 3000 // 3 秒自动轮播一次
export default {
name: 'PlatformFeatures',
props: {
features: {
type: Array,
default: () => []
}
},
data() {
return {
activeFeat: 0, // 默认从第一张开始轮播
featScrollLeft: 0, // scroll-view 的 scroll-leftpx
_timer: null
}
},
computed: {
integrationImg() {
const f = this.features[this.activeFeat]
return (f && f.img) || ''
}
},
watch: {
activeFeat(idx) {
// 选中项变化时:把选中卡片「尽量滚到左边」
// index * step = 选中卡片起始 x
this.scrollToCard(idx)
}
},
mounted() {
this.startAutoPlay()
},
beforeDestroy() {
this.stopAutoPlay()
},
methods: {
onFeatTap(index) {
// 用户手动点击:切换 + 先停轮播,再隔 3 秒重启(避免刚点完又被立即切走)
this.stopAutoPlay()
this.activeFeat = index
this.$emit('change', index)
this.startAutoPlay()
},
/**
* 让横滚容器把第 idx 张卡片「尽量」滚到左边贴边。
* scroll-view 的 scroll-left 有最大上限(内容总长 - 视口宽度),
* 当 idx 是最后几张时,scroll-left 超过最大值,scroll-view 会自动截断到可滚的最大值,
* 因此卡片虽无法真的贴左,但已经是「滚到最接近左侧」的位置了。
*/
scrollToCard(idx) {
const target = Math.max(0, idx) * CARD_STEP_PX
// 先赋值一个不同的值,保证 uni-app scroll-view 每次都能识别到属性变化
// (否则从 0 → 0 这种无变化赋值不触发滚动)
if (this.featScrollLeft === target) {
this.featScrollLeft = target + 0.001
this.$nextTick(() => {
this.featScrollLeft = target
})
} else {
this.featScrollLeft = target
}
},
startAutoPlay() {
this.stopAutoPlay()
if (!this.features || this.features.length <= 1) return
this._timer = setInterval(() => {
const total = this.features.length
const next = (this.activeFeat + 1) % total
this.activeFeat = next
this.$emit('change', next)
}, AUTO_PLAY_INTERVAL)
},
stopAutoPlay() {
if (this._timer) {
clearInterval(this._timer)
this._timer = null
}
}
}
}
</script>
<style scoped>
.feature-section {
width: 100%;
padding: 96rpx 0 0 0;
background: #ffffff;
box-sizing: border-box;
}
/* 区块标题 - 20px Heavy #1A1A1A 居中 */
.section-title {
display: block;
text-align: center;
font-size: 40rpx;
font-weight: 900;
color: #1a1a1a;
line-height: 1.45;
margin-bottom: 64rpx;
}
/* 功能卡片横向滚动 */
.feat-scroll {
width: 100%;
white-space: nowrap;
padding: 0 20rpx;
box-sizing: border-box;
}
.feat-list {
display: inline-flex;
gap: 16rpx;
}
/* 卡片 - 166x80 圆角6px (332rpx × 160rpx) */
.feat-card {
flex-shrink: 0;
width: 332rpx;
height: 160rpx;
padding: 20rpx;
background: #f2f2f2;
border-radius: 12rpx;
box-sizing: border-box;
display: flex;
align-items: flex-start;
gap: 16rpx;
}
.feat-card.active {
background: #ff6800;
}
.feat-num {
font-size: 32rpx;
font-weight: 900;
color: #ff6800;
line-height: 52rpx;
}
.feat-card.active .feat-num {
color: #ffffff;
}
.feat-text {
flex: 1;
display: flex;
flex-direction: column;
}
.feat-title {
font-size: 32rpx;
font-weight: 500;
color: #000000;
line-height: 44rpx;
}
.feat-card.active .feat-title {
color: #ffffff;
}
.feat-desc {
margin-top: 6rpx;
font-size: 20rpx;
color: #000000;
opacity: 0.6;
line-height: 1.45;
white-space: normal;
}
.feat-card.active .feat-desc {
color: #ffffff;
opacity: 1;
}
/* 集成平台大图 - 370x257 8px圆角 */
.integration-wrap {
margin-top: 20rpx;
padding: 0 18rpx;
box-sizing: border-box;
}
.integration-img {
width: 100%;
border-radius: 16rpx;
display: block;
}
</style>