3 changed files with 426 additions and 62 deletions
@ -0,0 +1,334 @@ |
|||||
|
<template> |
||||
|
<view class="product-section"> |
||||
|
<view class="title-section"> |
||||
|
<div |
||||
|
style=" |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
" |
||||
|
@click="handleMoreClick" |
||||
|
> |
||||
|
<text class="title">EPIC SOUL阅读体</text> |
||||
|
</div> |
||||
|
</view> |
||||
|
<!-- 轮播容器 --> |
||||
|
<view class="carousel-container"> |
||||
|
<!-- 左箭头 --> |
||||
|
<view |
||||
|
class="nav-arrow left-arrow" |
||||
|
@click="prevSlide" |
||||
|
v-if="list.length > 1 && currentIndex > 0" |
||||
|
> |
||||
|
<uni-icons size="16" color="white" type="left" /> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 轮播内容 --> |
||||
|
<scroll-view |
||||
|
class="carousel-scroll" |
||||
|
scroll-x="true" |
||||
|
:show-scrollbar="false" |
||||
|
:enhanced="true" |
||||
|
:scroll-with-animation="true" |
||||
|
:scroll-left="scrollLeft" |
||||
|
@scroll="onScroll" |
||||
|
@scrollend="onScrollEnd" |
||||
|
> |
||||
|
<view class="carousel-content"> |
||||
|
<view |
||||
|
class="carousel-item" |
||||
|
v-for="(item, index) in list" |
||||
|
:key="index" |
||||
|
@click="gotoUrlNew(item)" |
||||
|
v-if="item && item.image" |
||||
|
> |
||||
|
<view class="issue-card"> |
||||
|
<!-- 背景图片 --> |
||||
|
<image |
||||
|
class="card-bg" |
||||
|
:src="showImg(item.image)" |
||||
|
mode="aspectFill" |
||||
|
></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 无数据时的提示 --> |
||||
|
<view v-if="!list || list.length === 0" class="no-data"> |
||||
|
<text>暂无数据</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
|
||||
|
<!-- 右箭头 --> |
||||
|
<view |
||||
|
class="nav-arrow right-arrow" |
||||
|
@click="nextSlide" |
||||
|
v-if="list.length > 1 && currentIndex < list.length - 1" |
||||
|
> |
||||
|
<uni-icons size="16" color="white" type="arrowright" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
list: [], |
||||
|
currentIndex: 0, |
||||
|
scrollLeft: 0, |
||||
|
itemWidth: 224, // 207rpx + 30rpx margin |
||||
|
JDSU_IMG_URL: "https://epic.js-dyyj.com", |
||||
|
}; |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.getList(); |
||||
|
}, |
||||
|
methods: { |
||||
|
getList() { |
||||
|
this.Post( |
||||
|
{ |
||||
|
type_id: 3, |
||||
|
offset: 0, |
||||
|
limit: 10, // 增加获取数量,确保有足够数据 |
||||
|
}, |
||||
|
"/api/article/getArticleByType" |
||||
|
).then((res) => { |
||||
|
if (res.data && res.data.length > 0) { |
||||
|
this.list = res.data; |
||||
|
// 重置索引,确保从第一项开始 |
||||
|
this.currentIndex = 0; |
||||
|
this.scrollLeft = 0; |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 图片显示方法 |
||||
|
showImg(img) { |
||||
|
if (!img) return ""; |
||||
|
if (img.indexOf("https://") != -1 || img.indexOf("http://") != -1) { |
||||
|
return img; |
||||
|
} else { |
||||
|
return this.JDSU_IMG_URL + img; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 上一张 |
||||
|
prevSlide() { |
||||
|
if (!this.validateData()) return; |
||||
|
|
||||
|
if (this.list.length > 1) { |
||||
|
this.currentIndex = |
||||
|
this.currentIndex > 0 ? this.currentIndex - 1 : this.list.length - 1; |
||||
|
this.$nextTick(() => { |
||||
|
this.scrollToCurrentItem(); |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 下一张 |
||||
|
nextSlide() { |
||||
|
if (!this.validateData()) return; |
||||
|
|
||||
|
if (this.list.length > 1) { |
||||
|
this.currentIndex = |
||||
|
this.currentIndex < this.list.length - 1 ? this.currentIndex + 1 : 0; |
||||
|
this.$nextTick(() => { |
||||
|
this.scrollToCurrentItem(); |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 滚动到当前项目 |
||||
|
scrollToCurrentItem() { |
||||
|
// 确保索引在有效范围内 |
||||
|
if (this.currentIndex < 0) { |
||||
|
this.currentIndex = 0; |
||||
|
} |
||||
|
if (this.currentIndex >= this.list.length) { |
||||
|
this.currentIndex = this.list.length - 1; |
||||
|
} |
||||
|
|
||||
|
const scrollPosition = this.currentIndex * this.itemWidth; |
||||
|
this.scrollLeft = scrollPosition; |
||||
|
}, |
||||
|
|
||||
|
// 滚动事件 |
||||
|
onScroll(e) { |
||||
|
const scrollLeft = e.detail.scrollLeft; |
||||
|
const index = Math.round(scrollLeft / this.itemWidth); |
||||
|
if ( |
||||
|
index !== this.currentIndex && |
||||
|
index >= 0 && |
||||
|
index < this.list.length |
||||
|
) { |
||||
|
this.currentIndex = index; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 滚动结束事件 |
||||
|
onScrollEnd(e) { |
||||
|
const scrollLeft = e.detail.scrollLeft; |
||||
|
const index = Math.round(scrollLeft / this.itemWidth); |
||||
|
// 确保索引在有效范围内 |
||||
|
this.currentIndex = Math.max(0, Math.min(index, this.list.length - 1)); |
||||
|
this.$nextTick(() => { |
||||
|
this.scrollToCurrentItem(); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 点击卡片 |
||||
|
handleItemClick(item) { |
||||
|
console.log("点击了卡片:", item); |
||||
|
// 这里可以添加跳转逻辑 |
||||
|
}, |
||||
|
|
||||
|
// 验证数据有效性 |
||||
|
validateData() { |
||||
|
if (!this.list || this.list.length === 0) { |
||||
|
this.currentIndex = 0; |
||||
|
this.scrollLeft = 0; |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// 确保当前索引在有效范围内 |
||||
|
if (this.currentIndex < 0) { |
||||
|
this.currentIndex = 0; |
||||
|
} |
||||
|
if (this.currentIndex >= this.list.length) { |
||||
|
this.currentIndex = this.list.length - 1; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.product-section { |
||||
|
width: 100%; |
||||
|
background-color: #fffdd6; |
||||
|
padding: 40rpx 25rpx; |
||||
|
margin: 30rpx 0; |
||||
|
border-radius: 40rpx; |
||||
|
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1), |
||||
|
0 0 0 1rpx rgba(255, 255, 255, 0.2) inset; |
||||
|
} |
||||
|
|
||||
|
// 轮播容器 |
||||
|
.carousel-container { |
||||
|
position: relative; |
||||
|
width: 100%; |
||||
|
height: 368rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
// 轮播滚动视图 |
||||
|
.carousel-scroll { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
// 轮播内容 |
||||
|
.carousel-content { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
height: 100%; |
||||
|
min-width: max-content; |
||||
|
} |
||||
|
|
||||
|
// 轮播项 |
||||
|
.carousel-item { |
||||
|
flex-shrink: 0; |
||||
|
width: 210rpx; |
||||
|
height: 368rpx; |
||||
|
margin: 0 7rpx; |
||||
|
will-change: transform; |
||||
|
} |
||||
|
|
||||
|
// 卡片样式 |
||||
|
.issue-card { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
// 背景图片 |
||||
|
.card-bg { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
// 导航箭头 |
||||
|
.nav-arrow { |
||||
|
position: absolute; |
||||
|
top: 50%; |
||||
|
transform: translateY(-50%); |
||||
|
width: 60rpx; |
||||
|
height: 60rpx; |
||||
|
background: rgba(255, 255, 255, 0.2); |
||||
|
border-radius: 50%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
cursor: pointer; |
||||
|
z-index: 3; |
||||
|
transition: all 0.3s ease; |
||||
|
backdrop-filter: blur(10rpx); |
||||
|
|
||||
|
&:hover { |
||||
|
background: rgba(255, 255, 255, 0.3); |
||||
|
transform: translateY(-50%) scale(1.1); |
||||
|
} |
||||
|
|
||||
|
&.left-arrow { |
||||
|
left: 0rpx; |
||||
|
} |
||||
|
|
||||
|
&.right-arrow { |
||||
|
right: 0rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.arrow-icon { |
||||
|
font-size: 32rpx; |
||||
|
color: #ffffff; |
||||
|
font-weight: bold; |
||||
|
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.3); |
||||
|
} |
||||
|
|
||||
|
// 无数据提示 |
||||
|
.no-data { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
width: 100%; |
||||
|
height: 368rpx; |
||||
|
color: #999; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
// 标题区域 |
||||
|
.title-section { |
||||
|
display: inline-block; |
||||
|
padding: 0rpx 0 30rpx; |
||||
|
width: 100%; |
||||
|
.title { |
||||
|
font-size: 34rpx; |
||||
|
font-weight: bold; |
||||
|
color: #000000; |
||||
|
} |
||||
|
|
||||
|
.more-btn { |
||||
|
font-size: 26rpx; |
||||
|
color: #000000; |
||||
|
margin-left: 35rpx; |
||||
|
} |
||||
|
} |
||||
|
</style> |
Loading…
Reference in new issue