44 changed files with 6409 additions and 1444 deletions
@ -0,0 +1,84 @@ |
|||||
|
<template> |
||||
|
<view class="music-player" :class="{'playing': isPlaying}" @click="togglePlay"> |
||||
|
<text :class="['player-icon', isPlaying ? 'rotate' : '']">{{ isPlaying ? '🎵' : '🔇' }}</text> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import audioManager from '@/utils/audioManager'; |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
isPlaying: audioManager.getPlayingStatus() |
||||
|
}; |
||||
|
}, |
||||
|
mounted() { |
||||
|
audioManager.init(); |
||||
|
uni.$on('audioStateChanged', this.updateState); |
||||
|
this.isPlaying = audioManager.getPlayingStatus(); |
||||
|
uni.$on('playBackgroundMusic', () => { |
||||
|
if (!audioManager.getUserDisabled()) { |
||||
|
audioManager.play(); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
beforeDestroy() { |
||||
|
uni.$off('audioStateChanged', this.updateState); |
||||
|
}, |
||||
|
methods: { |
||||
|
updateState(state) { |
||||
|
this.isPlaying = state.isPlaying; |
||||
|
}, |
||||
|
togglePlay() { |
||||
|
audioManager.togglePlay(); |
||||
|
this.isPlaying = audioManager.getPlayingStatus(); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.music-player { |
||||
|
position: fixed; |
||||
|
right: 30rpx; |
||||
|
bottom: 30rpx; |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
background-color: rgba(255, 255, 255, 0.9); |
||||
|
border-radius: 50%; |
||||
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.2); |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
z-index: 9; |
||||
|
|
||||
|
&:active { |
||||
|
transform: scale(0.95); |
||||
|
} |
||||
|
|
||||
|
&.playing { |
||||
|
background-color: rgba(245, 163, 204, 0.9); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.player-icon { |
||||
|
font-size: 40rpx; |
||||
|
line-height: 1; |
||||
|
|
||||
|
&.rotate { |
||||
|
display: inline-block; |
||||
|
animation: rotate 3s linear infinite; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes rotate { |
||||
|
from { |
||||
|
transform: rotate(0deg); |
||||
|
} |
||||
|
|
||||
|
to { |
||||
|
transform: rotate(360deg); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,39 @@ |
|||||
|
<template> |
||||
|
<view> |
||||
|
<image @click="buyTaozi" class="taozi" src="https://static.ticket.sz-trip.com/epicSoul/taozi/taozi.png" mode=""></image> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
methods: { |
||||
|
buyTaozi() { |
||||
|
uni.setClipboardData({ |
||||
|
data: 'https://www.xiaohongshu.com/goods-detail/684beba28a6cef0001a9ed2c', |
||||
|
success: function() { |
||||
|
uni.showToast({ |
||||
|
title: '链接已复制,请打开小红书APP查看', |
||||
|
icon: 'none', |
||||
|
duration: 2000 |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.taozi { |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
position: fixed; |
||||
|
right: 0; |
||||
|
top: 25%; |
||||
|
z-index: 9; |
||||
|
|
||||
|
&:active { |
||||
|
transform: scale(0.9); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,106 @@ |
|||||
|
<template> |
||||
|
<view class="title-header-box" :style="{height:`${height}px`}"> |
||||
|
<view class="title-header" :style="{paddingTop:`${padHeight}px`,height:`${height}px`}"> |
||||
|
<view class="left" @click="goBack"><uni-icons type="left" size="30"></uni-icons></view> |
||||
|
<view class="center"> |
||||
|
<view class="title">三个桃子</view> |
||||
|
<view class="subtitle">时间里的约定</view> |
||||
|
</view> |
||||
|
<view class="right"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: "SearchHeader", |
||||
|
props: ['title', 'icon'], |
||||
|
watch: { |
||||
|
'title'(newVal, oldVal) { |
||||
|
this.title = newVal |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
keywords: '', |
||||
|
padHeight: 60, |
||||
|
height: 88 |
||||
|
} |
||||
|
}, |
||||
|
created() { |
||||
|
const systemInfo = uni.getSystemInfoSync(); |
||||
|
const statusBarHeight = systemInfo.statusBarHeight; |
||||
|
const rect = uni.getMenuButtonBoundingClientRect(); |
||||
|
this.height = statusBarHeight + 55 |
||||
|
uni.setStorageSync('titleHeight', this.height) |
||||
|
this.padHeight = systemInfo.statusBarHeight - 15 |
||||
|
this.right = (systemInfo.screenWidth - rect.right) + rect.width |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.title-header-box { |
||||
|
background-color: #FFF; |
||||
|
color: #000000; |
||||
|
} |
||||
|
|
||||
|
.title-header { |
||||
|
/* background-color: #FFC825; */ |
||||
|
background: white; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
height: 88rpx; |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
top: 0; |
||||
|
z-index: 1000; |
||||
|
padding-top: 60rpx; |
||||
|
} |
||||
|
|
||||
|
.title-header .left { |
||||
|
padding-left: 30rpx; |
||||
|
width: 58rpx; |
||||
|
display: flex; |
||||
|
position: absolute; |
||||
|
left: 0; |
||||
|
} |
||||
|
|
||||
|
.title-header .search-box { |
||||
|
width: 502rpx; |
||||
|
height: 58rpx; |
||||
|
border-radius: 29rpx; |
||||
|
background: #F0F0F0; |
||||
|
padding: 0 26rpx; |
||||
|
font-size: 26rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.title-header .search-box .iconfont { |
||||
|
flex-shrink: 0; |
||||
|
color: #999999; |
||||
|
font-size: 30rpx; |
||||
|
margin-right: 10; |
||||
|
} |
||||
|
|
||||
|
.title-header .search-box .input { |
||||
|
flex: 1; |
||||
|
border: none; |
||||
|
outline: none; |
||||
|
background: none; |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
.title{ |
||||
|
font-size: 30rpx; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.subtitle{ |
||||
|
font-size: 22rpx; |
||||
|
text-align: center; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,575 @@ |
|||||
|
<template> |
||||
|
<view> |
||||
|
<view class="message-board"> |
||||
|
<view class="header"> |
||||
|
<view class="title-container"> |
||||
|
<text class="title">留言板</text> |
||||
|
<text class="subtitle">查看所有留言</text> |
||||
|
</view> |
||||
|
<view class="decor decor-1"></view> |
||||
|
<view class="decor decor-2"></view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="content"> |
||||
|
<view class="stats-card"> |
||||
|
<view class="stats-header"> |
||||
|
<view class="stats-icon-container"> |
||||
|
<view class="stats-icon"> |
||||
|
<text class="icon-text">💬</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<text class="stats-title">全部留言</text> |
||||
|
<view class="stats-count"> |
||||
|
<text class="count-text">共 {{ total }} 条</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="message-list"> |
||||
|
<view v-if="loading && messageList.length === 0" class="empty-state"> |
||||
|
<view class="loading-container"> |
||||
|
<view class="loading-spinner"></view> |
||||
|
<text class="loading-text">加载中...</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view v-else-if="messageList.length === 0" class="empty-state"> |
||||
|
<view class="empty-container"> |
||||
|
<view class="empty-icon">📭</view> |
||||
|
<text class="empty-title">暂无留言</text> |
||||
|
<text class="empty-desc">还没有人留言呢</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view v-else class="message-items"> |
||||
|
<view v-for="(item, index) in messageList" :key="item.id" class="message-item" |
||||
|
:style="{ animationDelay: `${index * 100}ms` }"> |
||||
|
<view class="user-info"> |
||||
|
<view class="avatar"> |
||||
|
<text class="avatar-text">{{ getAvatarText(item.nickname) }}</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="user-details"> |
||||
|
<view class="user-header"> |
||||
|
<text class="username">{{ item.nickname }}</text> |
||||
|
<text class="message-id">#{{ item.id }}</text> |
||||
|
</view> |
||||
|
<text class="message-time">{{ formatTime(item.createtime) }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="message-content"> |
||||
|
<text class="message-text">{{ item.content }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view v-if="pages > 1" class="pagination"> |
||||
|
<view class="pagination-container"> |
||||
|
<button @click="changePage(page - 1)" :disabled="page <= 1" class="page-button prev-button"> |
||||
|
<text class="button-icon">◀</text> |
||||
|
<text>上一页</text> |
||||
|
</button> |
||||
|
|
||||
|
<view class="page-info"> |
||||
|
<text class="current-page">{{ page }}</text> |
||||
|
<text class="page-divider">/</text> |
||||
|
<text class="total-pages">{{ pages }}</text> |
||||
|
</view> |
||||
|
|
||||
|
<button @click="changePage(page + 1)" :disabled="page >= pages" class="page-button next-button"> |
||||
|
<text>下一页</text> |
||||
|
<text class="button-icon">▶</text> |
||||
|
</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="refresh-container"> |
||||
|
<button @click="refresh" :disabled="loading" class="refresh-button"> |
||||
|
<text class="refresh-icon" :class="{ 'rotating': loading }">🔄</text> |
||||
|
<text>{{ loading ? '刷新中...' : '刷新' }}</text> |
||||
|
</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { |
||||
|
getMessageList |
||||
|
} from '@/static/js/common'; |
||||
|
|
||||
|
export default { |
||||
|
props: { |
||||
|
isActive: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
loading: false, |
||||
|
messageList: [], |
||||
|
total: 0, |
||||
|
page: 1, |
||||
|
limit: 10, |
||||
|
pages: 0 |
||||
|
}; |
||||
|
}, |
||||
|
created() { |
||||
|
if (this.isActive) { |
||||
|
this.fetchMessages(); |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
isActive(newVal) { |
||||
|
if (newVal) { |
||||
|
this.fetchMessages(); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
getAvatarText(nickname) { |
||||
|
return nickname ? nickname.charAt(0).toUpperCase() : '?'; |
||||
|
}, |
||||
|
formatTime(timestamp) { |
||||
|
if (!timestamp) return '未知时间'; |
||||
|
|
||||
|
const date = new Date(timestamp * 1000); |
||||
|
const now = new Date(); |
||||
|
const diff = now - date; |
||||
|
|
||||
|
if (diff < 60000) { |
||||
|
return '刚刚'; |
||||
|
} |
||||
|
if (diff < 3600000) { |
||||
|
return `${Math.floor(diff / 60000)}分钟前`; |
||||
|
} |
||||
|
if (diff < 86400000) { |
||||
|
return `${Math.floor(diff / 3600000)}小时前`; |
||||
|
} |
||||
|
|
||||
|
const month = date.getMonth() + 1; |
||||
|
const day = date.getDate(); |
||||
|
const hour = date.getHours().toString().padStart(2, '0'); |
||||
|
const minute = date.getMinutes().toString().padStart(2, '0'); |
||||
|
|
||||
|
return `${month}月${day}日 ${hour}:${minute}`; |
||||
|
}, |
||||
|
async fetchMessages(pageNum = 1) { |
||||
|
try { |
||||
|
if (this.loading) return; |
||||
|
this.loading = true; |
||||
|
|
||||
|
const params = { |
||||
|
page: pageNum, |
||||
|
limit: this.limit |
||||
|
}; |
||||
|
|
||||
|
const res = await getMessageList(params, { |
||||
|
loading: { |
||||
|
title: '加载留言中...' |
||||
|
}, |
||||
|
error: true |
||||
|
}); |
||||
|
const data = res.data || {}; |
||||
|
this.messageList = data.list || []; |
||||
|
this.total = data.total || 0; |
||||
|
this.page = data.page || 1; |
||||
|
this.pages = data.pages || 0; |
||||
|
|
||||
|
} catch (error) { |
||||
|
console.error('获取留言异常:', error); |
||||
|
} finally { |
||||
|
this.loading = false; |
||||
|
} |
||||
|
}, |
||||
|
changePage(pageNum) { |
||||
|
if (pageNum < 1 || pageNum > this.pages || pageNum === this.page) return; |
||||
|
this.fetchMessages(pageNum); |
||||
|
uni.pageScrollTo({ |
||||
|
scrollTop: 0, |
||||
|
duration: 300 |
||||
|
}); |
||||
|
}, |
||||
|
refresh() { |
||||
|
if (this.loading) return; |
||||
|
this.fetchMessages(this.page); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.message-board { |
||||
|
min-height: 100vh; |
||||
|
background-color: #d76388; |
||||
|
} |
||||
|
|
||||
|
.header { |
||||
|
position: relative; |
||||
|
padding: 180rpx 30rpx 40rpx; |
||||
|
} |
||||
|
|
||||
|
.title-container { |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.title { |
||||
|
font-size: 48rpx; |
||||
|
font-weight: bold; |
||||
|
color: #ffffff; |
||||
|
margin-bottom: 10rpx; |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
.subtitle { |
||||
|
font-size: 26rpx; |
||||
|
color: rgba(255, 255, 255, 0.8); |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
.decor { |
||||
|
position: absolute; |
||||
|
border-radius: 50%; |
||||
|
|
||||
|
&.decor-1 { |
||||
|
top: 40rpx; |
||||
|
left: 30rpx; |
||||
|
width: 100rpx; |
||||
|
height: 100rpx; |
||||
|
background-color: rgba(255, 255, 255, 0.1); |
||||
|
filter: blur(30rpx); |
||||
|
} |
||||
|
|
||||
|
&.decor-2 { |
||||
|
top: 80rpx; |
||||
|
right: 40rpx; |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
background-color: rgba(255, 192, 203, 0.2); |
||||
|
filter: blur(20rpx); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
padding: 0 30rpx 40rpx; |
||||
|
} |
||||
|
|
||||
|
.stats-card { |
||||
|
background-color: rgba(255, 255, 255, 0.9); |
||||
|
backdrop-filter: blur(10rpx); |
||||
|
border-radius: 30rpx; |
||||
|
padding: 30rpx; |
||||
|
margin-bottom: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.stats-header { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.stats-icon-container { |
||||
|
margin-right: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.stats-icon { |
||||
|
width: 50rpx; |
||||
|
height: 50rpx; |
||||
|
background-color: #4299e1; |
||||
|
border-radius: 50%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.icon-text { |
||||
|
color: #ffffff; |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
|
||||
|
.stats-title { |
||||
|
color: #4a5568; |
||||
|
font-weight: 500; |
||||
|
font-size: 28rpx; |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.stats-count { |
||||
|
background-color: #f7fafc; |
||||
|
border-radius: 50rpx; |
||||
|
padding: 8rpx 20rpx; |
||||
|
} |
||||
|
|
||||
|
.count-text { |
||||
|
color: #718096; |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
|
||||
|
.message-list { |
||||
|
margin-bottom: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.empty-state { |
||||
|
background-color: rgba(255, 255, 255, 0.9); |
||||
|
backdrop-filter: blur(10rpx); |
||||
|
border-radius: 30rpx; |
||||
|
padding: 60rpx; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.loading-container { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.loading-spinner { |
||||
|
width: 60rpx; |
||||
|
height: 60rpx; |
||||
|
border: 6rpx solid #e2e8f0; |
||||
|
border-top-color: #9f7aea; |
||||
|
border-radius: 50%; |
||||
|
animation: spin 1s linear infinite; |
||||
|
margin-bottom: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.loading-text { |
||||
|
color: #718096; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
.empty-container { |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.empty-icon { |
||||
|
width: 100rpx; |
||||
|
height: 100rpx; |
||||
|
background-color: #f7fafc; |
||||
|
border-radius: 50%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
margin: 0 auto 30rpx; |
||||
|
font-size: 50rpx; |
||||
|
} |
||||
|
|
||||
|
.empty-title { |
||||
|
color: #2d3748; |
||||
|
font-size: 34rpx; |
||||
|
font-weight: 500; |
||||
|
margin-bottom: 10rpx; |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
.empty-desc { |
||||
|
color: #718096; |
||||
|
font-size: 26rpx; |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
.message-items { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.message-item { |
||||
|
background-color: rgba(255, 255, 255, 0.9); |
||||
|
backdrop-filter: blur(10rpx); |
||||
|
border-radius: 30rpx; |
||||
|
padding: 30rpx; |
||||
|
box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.05); |
||||
|
transition: box-shadow 0.2s; |
||||
|
animation: fadeIn 0.6s ease-out forwards; |
||||
|
|
||||
|
&:active { |
||||
|
box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.user-info { |
||||
|
display: flex; |
||||
|
align-items: flex-start; |
||||
|
margin-bottom: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.avatar { |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
background: linear-gradient(135deg, #a78bfa, #ec4899); |
||||
|
border-radius: 50%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
margin-right: 20rpx; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
.avatar-text { |
||||
|
color: #ffffff; |
||||
|
font-size: 32rpx; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.user-details { |
||||
|
flex: 1; |
||||
|
min-width: 0; |
||||
|
} |
||||
|
|
||||
|
.user-header { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
margin-bottom: 6rpx; |
||||
|
} |
||||
|
|
||||
|
.username { |
||||
|
font-weight: 500; |
||||
|
color: #2d3748; |
||||
|
font-size: 28rpx; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.message-id { |
||||
|
font-size: 22rpx; |
||||
|
color: #a0aec0; |
||||
|
background-color: #f7fafc; |
||||
|
padding: 4rpx 16rpx; |
||||
|
border-radius: 50rpx; |
||||
|
} |
||||
|
|
||||
|
.message-time { |
||||
|
font-size: 22rpx; |
||||
|
color: #a0aec0; |
||||
|
} |
||||
|
|
||||
|
.message-content { |
||||
|
margin-left: 100rpx; |
||||
|
} |
||||
|
|
||||
|
.message-text { |
||||
|
color: #4a5568; |
||||
|
font-size: 28rpx; |
||||
|
line-height: 1.6; |
||||
|
word-break: break-word; |
||||
|
} |
||||
|
|
||||
|
.pagination { |
||||
|
background-color: rgba(255, 255, 255, 0.9); |
||||
|
backdrop-filter: blur(10rpx); |
||||
|
border-radius: 30rpx; |
||||
|
padding: 20rpx; |
||||
|
margin-bottom: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.pagination-container { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
gap: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.page-button { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 10rpx; |
||||
|
padding: 0 30rpx; |
||||
|
height: 70rpx; |
||||
|
font-size: 26rpx; |
||||
|
font-weight: 500; |
||||
|
color: #4a5568; |
||||
|
background-color: #ffffff; |
||||
|
border: 2rpx solid #e2e8f0; |
||||
|
border-radius: 12rpx; |
||||
|
|
||||
|
&:active { |
||||
|
background-color: #f7fafc; |
||||
|
} |
||||
|
|
||||
|
&[disabled] { |
||||
|
opacity: 0.5; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.page-info { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 10rpx; |
||||
|
padding: 0 20rpx; |
||||
|
} |
||||
|
|
||||
|
.current-page, |
||||
|
.total-pages { |
||||
|
font-size: 26rpx; |
||||
|
color: #4a5568; |
||||
|
} |
||||
|
|
||||
|
.page-divider { |
||||
|
color: #cbd5e0; |
||||
|
font-size: 26rpx; |
||||
|
} |
||||
|
|
||||
|
.refresh-container { |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.refresh-button { |
||||
|
display: inline-flex; |
||||
|
align-items: center; |
||||
|
gap: 10rpx; |
||||
|
padding: 0 40rpx; |
||||
|
height: 80rpx; |
||||
|
background-color: rgba(255, 255, 255, 0.2); |
||||
|
color: #ffffff; |
||||
|
border: none; |
||||
|
border-radius: 16rpx; |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 500; |
||||
|
|
||||
|
&:active { |
||||
|
background-color: rgba(255, 255, 255, 0.3); |
||||
|
} |
||||
|
|
||||
|
&[disabled] { |
||||
|
opacity: 0.5; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.refresh-icon { |
||||
|
font-size: 28rpx; |
||||
|
|
||||
|
&.rotating { |
||||
|
animation: spin 1s linear infinite; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes spin { |
||||
|
from { |
||||
|
transform: rotate(0deg); |
||||
|
} |
||||
|
|
||||
|
to { |
||||
|
transform: rotate(360deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes fadeIn { |
||||
|
from { |
||||
|
opacity: 0; |
||||
|
transform: translateY(40rpx); |
||||
|
} |
||||
|
|
||||
|
to { |
||||
|
opacity: 1; |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,508 @@ |
|||||
|
<template> |
||||
|
<view> |
||||
|
<image @click="togglePopup" class="suspension-img" :class="{'rotated': isOpen}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/suspension-icon.png" mode=""></image> |
||||
|
|
||||
|
<view v-if="isOpen" class="mask" @click="closeMessage"></view> |
||||
|
|
||||
|
<view v-if="isOpen" class="message-popup" :style="popupStyle"> |
||||
|
<view class="popup-content"> |
||||
|
<view class="popup-header"> |
||||
|
<text class="popup-title">我要留言</text> |
||||
|
<view class="header-line"></view> |
||||
|
</view> |
||||
|
<input v-model="nickname" class="input-field" placeholder="我的昵称" maxlength="20" :disabled="loading" /> |
||||
|
<input v-model="email" type="text" class="input-field" placeholder="我的邮箱" :disabled="loading" /> |
||||
|
<textarea v-model="messageText" class="textarea-field" placeholder="我想对TA说:" maxlength="500" |
||||
|
:disabled="loading"></textarea> |
||||
|
<view class="char-count"> |
||||
|
<text>{{ messageText.length }}/500</text> |
||||
|
</view> |
||||
|
<view class="button-group"> |
||||
|
<button @click="closeMessage" :disabled="loading" class="btn-cancel"> |
||||
|
返回 |
||||
|
</button> |
||||
|
<button @click="handleSubmit" :disabled="loading" class="btn-submit" |
||||
|
:class="{'btn-disabled': !canSubmit}"> |
||||
|
<view v-if="loading" class="loading-icon"></view> |
||||
|
<text>{{ loading ? '发布中...' : '发布' }}</text> |
||||
|
</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view v-if="toast.show" class="toast" :class="toast.type"> |
||||
|
<view class="toast-icon" :class="toast.type"> |
||||
|
<view v-if="toast.type === 'success'" class="success-icon"></view> |
||||
|
<view v-if="toast.type === 'error'" class="error-icon"></view> |
||||
|
</view> |
||||
|
<text class="toast-message">{{ toast.message }}</text> |
||||
|
<view class="toast-progress"> |
||||
|
<view class="progress-bar" :style="{animationDuration: '3s'}"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { |
||||
|
sendMessage |
||||
|
} from '@/static/js/common'; |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
isOpen: false, |
||||
|
popupStyle: { |
||||
|
opacity: 0, |
||||
|
transform: 'translate(-50%, -50%) scale(0.9)' |
||||
|
}, |
||||
|
nickname: "", |
||||
|
email: "", |
||||
|
messageText: "", |
||||
|
loading: false, |
||||
|
toast: { |
||||
|
show: false, |
||||
|
type: 'success', |
||||
|
message: '' |
||||
|
} |
||||
|
}; |
||||
|
}, |
||||
|
computed: { |
||||
|
canSubmit() { |
||||
|
const hasNickname = this.nickname.trim().length > 0; |
||||
|
const hasMessage = this.messageText.trim().length > 0; |
||||
|
const validEmail = this.isValidEmail(this.email); |
||||
|
|
||||
|
return hasNickname && hasMessage && validEmail; |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
nickname() { |
||||
|
// 可以在这里添加日志输出 |
||||
|
}, |
||||
|
email() { |
||||
|
// 可以在这里添加日志输出 |
||||
|
}, |
||||
|
messageText() { |
||||
|
// 可以在这里添加日志输出 |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
togglePopup() { |
||||
|
if (this.isOpen) { |
||||
|
this.closeMessage(); |
||||
|
} else { |
||||
|
this.openPop(); |
||||
|
} |
||||
|
}, |
||||
|
openPop() { |
||||
|
this.isOpen = true; |
||||
|
setTimeout(() => { |
||||
|
this.popupStyle = { |
||||
|
opacity: 1, |
||||
|
transform: 'translate(-50%, -50%) scale(1)' |
||||
|
}; |
||||
|
}, 50); |
||||
|
}, |
||||
|
closeMessage() { |
||||
|
this.popupStyle = { |
||||
|
opacity: 0, |
||||
|
transform: 'translate(-50%, -50%) scale(0.9)' |
||||
|
}; |
||||
|
setTimeout(() => { |
||||
|
this.isOpen = false; |
||||
|
}, 400); |
||||
|
}, |
||||
|
isValidEmail(email) { |
||||
|
if (!email.trim()) return false; |
||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; |
||||
|
return emailRegex.test(email); |
||||
|
}, |
||||
|
showToast(type, message) { |
||||
|
this.toast.show = true; |
||||
|
this.toast.type = type; |
||||
|
this.toast.message = message; |
||||
|
setTimeout(() => { |
||||
|
this.toast.show = false; |
||||
|
}, 3000); |
||||
|
}, |
||||
|
handleSubmit() { |
||||
|
if (!this.nickname.trim()) { |
||||
|
this.showToast('error', '请填写昵称'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!this.isValidEmail(this.email)) { |
||||
|
this.showToast('error', '请填写正确的邮箱地址'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!this.messageText.trim()) { |
||||
|
this.showToast('error', '请填写留言内容'); |
||||
|
return; |
||||
|
} |
||||
|
this.submitMessage(); |
||||
|
}, |
||||
|
async submitMessage() { |
||||
|
try { |
||||
|
this.loading = true; |
||||
|
const res = await sendMessage({ |
||||
|
nickname: this.nickname.trim(), |
||||
|
email: this.email.trim(), |
||||
|
content: this.messageText.trim() |
||||
|
}); |
||||
|
|
||||
|
if (res && res.code === 1) { |
||||
|
this.nickname = ""; |
||||
|
this.email = ""; |
||||
|
this.messageText = ""; |
||||
|
this.showToast('success', '留言发布成功!'); |
||||
|
setTimeout(() => { |
||||
|
this.closeMessage(); |
||||
|
}, 1500); |
||||
|
} else { |
||||
|
this.showToast('error', res?.msg || '发布失败,请重试'); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('发布留言失败:', error); |
||||
|
this.showToast('error', '网络错误,请重试'); |
||||
|
} finally { |
||||
|
this.loading = false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.suspension-img { |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
position: fixed; |
||||
|
right: 0; |
||||
|
top: 18%; |
||||
|
z-index: 9; |
||||
|
transition: transform 0.3s ease; |
||||
|
|
||||
|
&.rotated { |
||||
|
transform: rotate(180deg); |
||||
|
} |
||||
|
|
||||
|
&:active { |
||||
|
opacity: 0.8; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.mask { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(0, 0, 0, 0.5); |
||||
|
z-index: 10; |
||||
|
animation: fadeIn 0.3s ease forwards; |
||||
|
} |
||||
|
|
||||
|
.message-popup { |
||||
|
position: fixed; |
||||
|
top: 50%; |
||||
|
left: 50%; |
||||
|
transform: translate(-50%, -50%) scale(0.9); |
||||
|
z-index: 11; |
||||
|
width: 75%; |
||||
|
max-width: 650rpx; |
||||
|
transition: opacity 0.4s ease, transform 0.4s ease; |
||||
|
} |
||||
|
|
||||
|
.popup-content { |
||||
|
background-color: #fff; |
||||
|
border-radius: 20rpx; |
||||
|
box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.2); |
||||
|
padding: 30rpx; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
max-height: 80vh; |
||||
|
} |
||||
|
|
||||
|
.popup-header { |
||||
|
margin-bottom: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.popup-title { |
||||
|
font-size: 40rpx; |
||||
|
font-weight: bold; |
||||
|
color: #ec4899; |
||||
|
margin-bottom: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.header-line { |
||||
|
height: 2rpx; |
||||
|
background-color: #ec4899; |
||||
|
width: 100%; |
||||
|
} |
||||
|
|
||||
|
.input-field { |
||||
|
height: 90rpx; |
||||
|
padding: 0 20rpx; |
||||
|
border: 2rpx solid #ccc; |
||||
|
border-radius: 10rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
font-size: 28rpx; |
||||
|
|
||||
|
&:focus { |
||||
|
border-color: #ec4899; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.textarea-field { |
||||
|
text-indent: 10rpx; |
||||
|
width: 100%; |
||||
|
height: 300rpx; |
||||
|
border: 2rpx solid #ccc; |
||||
|
border-radius: 10rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
font-size: 28rpx; |
||||
|
|
||||
|
&:focus { |
||||
|
border-color: #ec4899; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.char-count { |
||||
|
text-align: right; |
||||
|
font-size: 24rpx; |
||||
|
color: #888; |
||||
|
margin-bottom: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.button-group { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
gap: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.btn-cancel { |
||||
|
flex: 1; |
||||
|
background-color: #fff; |
||||
|
color: #ec4899; |
||||
|
height: 80rpx; |
||||
|
line-height: 80rpx; |
||||
|
border-radius: 40rpx; |
||||
|
border: 2rpx solid #ccc; |
||||
|
font-size: 28rpx; |
||||
|
text-align: center; |
||||
|
|
||||
|
&:active { |
||||
|
background-color: #f5f5f5; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.btn-submit { |
||||
|
flex: 1; |
||||
|
background-color: #f5a3cc; |
||||
|
color: #fff; |
||||
|
height: 80rpx; |
||||
|
line-height: 80rpx; |
||||
|
border-radius: 40rpx; |
||||
|
border: none; |
||||
|
font-size: 28rpx; |
||||
|
text-align: center; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
|
||||
|
&:active { |
||||
|
background-color: darken(#ec4899, 10%); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.loading-icon { |
||||
|
width: 30rpx; |
||||
|
height: 30rpx; |
||||
|
border: 4rpx solid #fff; |
||||
|
border-top-color: transparent; |
||||
|
border-radius: 50%; |
||||
|
margin-right: 10rpx; |
||||
|
animation: spin 1s linear infinite; |
||||
|
} |
||||
|
|
||||
|
@keyframes spin { |
||||
|
from { |
||||
|
transform: rotate(0deg); |
||||
|
} |
||||
|
|
||||
|
to { |
||||
|
transform: rotate(360deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.toast { |
||||
|
position: fixed; |
||||
|
top: 160rpx; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
z-index: 100000; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
padding: 20rpx 30rpx; |
||||
|
border-radius: 16rpx; |
||||
|
box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.3); |
||||
|
backdrop-filter: blur(10rpx); |
||||
|
max-width: 80%; |
||||
|
animation: toastIn 0.5s ease forwards; |
||||
|
|
||||
|
&.success { |
||||
|
background-color: rgba(34, 197, 94, 0.9); |
||||
|
} |
||||
|
|
||||
|
&.error { |
||||
|
background-color: rgba(239, 68, 68, 0.9); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes fadeIn { |
||||
|
from { |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
to { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes toastIn { |
||||
|
from { |
||||
|
opacity: 0; |
||||
|
transform: translateX(-50%) translateY(-20rpx); |
||||
|
} |
||||
|
|
||||
|
to { |
||||
|
opacity: 1; |
||||
|
transform: translateX(-50%) translateY(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.toast-icon { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
margin-right: 20rpx; |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.success-icon { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
border-radius: 50%; |
||||
|
border: 4rpx solid #fff; |
||||
|
position: relative; |
||||
|
|
||||
|
&:after { |
||||
|
content: ''; |
||||
|
position: absolute; |
||||
|
top: 40%; |
||||
|
left: 28%; |
||||
|
width: 45%; |
||||
|
height: 25%; |
||||
|
border-left: 4rpx solid #fff; |
||||
|
border-bottom: 4rpx solid #fff; |
||||
|
transform: rotate(-45deg); |
||||
|
animation: checkmark 0.8s ease-out forwards; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.error-icon { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
border-radius: 50%; |
||||
|
border: 4rpx solid #fff; |
||||
|
position: relative; |
||||
|
|
||||
|
&:before, |
||||
|
&:after { |
||||
|
content: ''; |
||||
|
position: absolute; |
||||
|
top: 50%; |
||||
|
left: 50%; |
||||
|
width: 60%; |
||||
|
height: 4rpx; |
||||
|
background-color: #fff; |
||||
|
animation: crossmark 0.8s ease-out forwards; |
||||
|
} |
||||
|
|
||||
|
&:before { |
||||
|
transform: translate(-50%, -50%) rotate(45deg); |
||||
|
} |
||||
|
|
||||
|
&:after { |
||||
|
transform: translate(-50%, -50%) rotate(-45deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.toast-message { |
||||
|
color: #fff; |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.toast-progress { |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
height: 4rpx; |
||||
|
background-color: rgba(255, 255, 255, 0.2); |
||||
|
border-radius: 0 0 16rpx 16rpx; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.progress-bar { |
||||
|
height: 100%; |
||||
|
background-color: rgba(255, 255, 255, 0.5); |
||||
|
width: 100%; |
||||
|
animation: progress 3s linear forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes progress { |
||||
|
from { |
||||
|
width: 100%; |
||||
|
} |
||||
|
|
||||
|
to { |
||||
|
width: 0%; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes checkmark { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: scale(0) rotate(-45deg); |
||||
|
} |
||||
|
|
||||
|
50% { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: scale(1) rotate(-45deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes crossmark { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: translate(-50%, -50%) scale(0) rotate(var(--rotation, 45deg)); |
||||
|
} |
||||
|
|
||||
|
50% { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: translate(-50%, -50%) scale(1) rotate(var(--rotation, 45deg)); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -1,311 +1,351 @@ |
|||||
{ |
{ |
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages |
"pages": [ |
||||
{ |
{ |
||||
"path": "pages/stratIndex", |
"path": "pages/stratIndex", |
||||
"style": { |
"style": { |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
} |
} |
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "pages/index/index", |
"path": "pages/index/index", |
||||
"style": { |
"style": { |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
// "navigationBarTitleText": "CGC-ICH" |
// "navigationBarTitleText": "CGC-ICH" |
||||
} |
} |
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "pages/index/readingBody", |
"path": "pages/index/readingBody", |
||||
"style": { |
"style": { |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
// "navigationBarTitleText": "阅读体" |
// "navigationBarTitleText": "阅读体" |
||||
} |
} |
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "pages/index/sensoryStore", |
"path": "pages/index/sensoryStore", |
||||
"style": { |
"style": { |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
// "navigationBarTitleText": "有感商店" |
// "navigationBarTitleText": "有感商店" |
||||
} |
} |
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "pages/index/intelligentAgent", |
"path": "pages/index/intelligentAgent", |
||||
"style": { |
"style": { |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
// "navigationBarTitleText": "智能体" |
// "navigationBarTitleText": "智能体" |
||||
} |
} |
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "pages/index/iSoul", |
"path": "pages/index/iSoul", |
||||
"style": { |
"style": { |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
// "navigationBarTitleText": "iSoul" |
// "navigationBarTitleText": "iSoul" |
||||
} |
} |
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "pages/login/login", |
"path": "pages/login/login", |
||||
"style": { |
"style": { |
||||
"navigationBarTitleText": "登录", |
"navigationBarTitleText": "登录", |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
} |
} |
||||
} |
} |
||||
], |
], |
||||
"subPackages": [{ |
"subPackages": [ |
||||
"root": "subPackages", |
{ |
||||
"pages": [{ |
"root": "subPackages", |
||||
"path": "order/trades", |
"pages": [ |
||||
"style": { |
{ |
||||
"navigationBarTitleText": "全部订单" |
"path": "order/trades", |
||||
} |
"style": { |
||||
}, |
"navigationBarTitleText": "全部订单" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "order/detail", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "订单详情", |
||||
|
"navigationStyle": "custom" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "techan/index", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "", |
||||
|
"navigationStyle": "custom" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "techan/detail", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "techan/order", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "确认订单" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "webPage/webPage", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "video/video", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "readingBody/index", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "阅读体", |
||||
|
"navigationStyle": "custom" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "haveFeeling/shopDetail", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "有感商店详情页", |
||||
|
"navigationStyle": "custom" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "haveFeeling/detailXiang", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "有感商店" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "letter/detail", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "文章详情" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "user/privacy", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "详情" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "user/privacyInfo", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "详情" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "user/travelerList", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "收货地址" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "user/myAddressAdd", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "收货地址" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "user/gwc", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "购物车" |
||||
|
} |
||||
|
}, |
||||
{ |
{ |
||||
"path": "order/detail", |
"path" : "order/gwcOrder", |
||||
"style": { |
"style" : { |
||||
"navigationBarTitleText": "订单详情", |
"navigationBarTitleText" : "下单" |
||||
"navigationStyle": "custom" |
|
||||
} |
} |
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "techan/index", |
"path": "user/profile", |
||||
"style": { |
"style": { |
||||
"navigationBarTitleText": "", |
"navigationBarTitleText": "个人信息" |
||||
"navigationStyle": "custom" |
} |
||||
} |
}, |
||||
}, |
{ |
||||
{ |
"path": "user/changeNickname", |
||||
"path": "techan/detail", |
"style": { |
||||
"style": { |
"navigationBarTitleText": "修改昵称" |
||||
"navigationBarTitleText": "" |
} |
||||
} |
}, |
||||
}, |
{ |
||||
{ |
"path": "search/search", |
||||
"path": "techan/order", |
"style": { |
||||
"style": { |
"navigationBarTitleText": "搜索" |
||||
"navigationBarTitleText": "确认订单" |
} |
||||
} |
} |
||||
}, |
] |
||||
|
}, |
||||
{ |
{ |
||||
"path": "webPage/webPage", |
"root": "xxdf", |
||||
"style": { |
"pages": [ |
||||
"navigationBarTitleText": "" |
{ |
||||
} |
"path": "home/home", |
||||
}, |
"style": { |
||||
{ |
"navigationBarTitleText": "", |
||||
"path": "video/video", |
"navigationStyle": "custom" |
||||
"style": { |
} |
||||
"navigationBarTitleText": "" |
}, |
||||
} |
{ |
||||
}, |
"path": "chapter1/cover1", |
||||
{ |
"style": { |
||||
"path": "readingBody/index", |
"navigationBarTitleText": "", |
||||
"style": { |
"navigationStyle": "custom" |
||||
"navigationBarTitleText": "阅读体", |
} |
||||
"navigationStyle": "custom" |
}, |
||||
} |
{ |
||||
}, |
"path": "chapter1/detail1", |
||||
{ |
"style": { |
||||
"path": "haveFeeling/shopDetail", |
"navigationBarTitleText": "", |
||||
"style": { |
"navigationStyle": "custom" |
||||
"navigationBarTitleText": "有感商店详情页", |
} |
||||
"navigationStyle": "custom" |
}, |
||||
} |
{ |
||||
}, |
"path": "chapter1/detail2", |
||||
{ |
"style": { |
||||
"path": "haveFeeling/detailXiang", |
"navigationBarTitleText": "", |
||||
"style": { |
"navigationStyle": "custom" |
||||
"navigationBarTitleText": "有感商店" |
} |
||||
} |
}, |
||||
}, |
{ |
||||
{ |
"path": "chapter1/detail3", |
||||
"path": "letter/detail", |
"style": { |
||||
"style": { |
"navigationBarTitleText": "", |
||||
"navigationBarTitleText": "文章详情" |
"navigationStyle": "custom" |
||||
} |
} |
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "user/privacy", |
"path": "chapter1/detail4", |
||||
"style": { |
"style": { |
||||
"navigationBarTitleText": "详情" |
"navigationBarTitleText": "", |
||||
} |
"navigationStyle": "custom" |
||||
}, |
} |
||||
{ |
}, |
||||
"path": "user/privacyInfo", |
{ |
||||
"style": { |
"path": "chapter1/detail5", |
||||
"navigationBarTitleText": "详情" |
"style": { |
||||
} |
"navigationBarTitleText": "", |
||||
}, |
"navigationStyle": "custom" |
||||
{ |
} |
||||
"path": "user/travelerList", |
}, |
||||
"style": { |
{ |
||||
"navigationBarTitleText": "收货地址" |
"path": "chapter2/cover", |
||||
} |
"style": { |
||||
}, |
"navigationBarTitleText": "", |
||||
{ |
"navigationStyle": "custom" |
||||
"path": "user/myAddressAdd", |
} |
||||
"style": { |
}, |
||||
"navigationBarTitleText": "收货地址" |
{ |
||||
} |
"path": "chapter3/cover", |
||||
}, |
"style": { |
||||
{ |
"navigationBarTitleText": "", |
||||
"path": "user/gwc", |
"navigationStyle": "custom" |
||||
"style": { |
} |
||||
"navigationBarTitleText": "购物车" |
}, |
||||
} |
{ |
||||
}, |
"path": "chapter3/randomImage", |
||||
{ |
"style": { |
||||
"path": "user/profile", |
"navigationBarTitleText": "", |
||||
"style": { |
"navigationStyle": "custom" |
||||
"navigationBarTitleText": "个人信息" |
} |
||||
} |
}, |
||||
}, |
{ |
||||
{ |
"path": "chapter4/cover", |
||||
"path": "user/changeNickname", |
"style": { |
||||
"style": { |
"navigationBarTitleText": "", |
||||
"navigationBarTitleText": "修改昵称" |
"navigationStyle": "custom", |
||||
} |
"enableShareAppMessage": true, |
||||
} |
"enableShareTimeline": true |
||||
] |
} |
||||
}, |
} |
||||
{ |
] |
||||
"root": "xxdf/home", |
}, |
||||
"pages": [{ |
|
||||
"path": "home", |
|
||||
"style": { |
|
||||
"navigationBarTitleText": "", |
|
||||
"navigationStyle": "custom" |
|
||||
} |
|
||||
}] |
|
||||
}, |
|
||||
{ |
{ |
||||
"root": "xxdf/chapter1", |
"root": "taozi", |
||||
"pages": [{ |
"pages": [ |
||||
"path": "cover1", |
{ |
||||
"style": { |
"path": "home/home", |
||||
"navigationBarTitleText": "", |
"style": { |
||||
"navigationStyle": "custom" |
"navigationBarTitleText": "", |
||||
} |
"navigationStyle": "custom" |
||||
}, |
} |
||||
{ |
}, |
||||
"path": "detail1", |
|
||||
"style": { |
|
||||
"navigationBarTitleText": "", |
|
||||
"navigationStyle": "custom" |
|
||||
} |
|
||||
}, |
|
||||
{ |
{ |
||||
"path": "detail2", |
"path": "chapter1/chapter1", |
||||
"style": { |
"style": { |
||||
"navigationBarTitleText": "", |
"navigationBarTitleText": "", |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
} |
} |
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "detail3", |
"path": "chapter2/chapter2", |
||||
"style": { |
"style": { |
||||
"navigationBarTitleText": "", |
"navigationBarTitleText": "", |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
} |
} |
||||
}, |
|
||||
{ |
|
||||
"path": "detail4", |
|
||||
"style": { |
|
||||
"navigationBarTitleText": "", |
|
||||
"navigationStyle": "custom" |
|
||||
} |
|
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "detail5", |
"path": "chapter3/chapter3", |
||||
"style": { |
"style": { |
||||
"navigationBarTitleText": "", |
"navigationBarTitleText": "", |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
} |
} |
||||
} |
|
||||
] |
|
||||
}, |
|
||||
{ |
|
||||
"root": "xxdf/chapter2", |
|
||||
"pages": [{ |
|
||||
"path": "cover", |
|
||||
"style": { |
|
||||
"navigationBarTitleText": "", |
|
||||
"navigationStyle": "custom" |
|
||||
} |
|
||||
}] |
|
||||
}, |
|
||||
{ |
|
||||
"root": "xxdf/chapter3", |
|
||||
"pages": [{ |
|
||||
"path": "cover", |
|
||||
"style": { |
|
||||
"navigationBarTitleText": "", |
|
||||
"navigationStyle": "custom" |
|
||||
} |
|
||||
}, |
}, |
||||
{ |
{ |
||||
"path": "randomImage", |
"path": "chapter4/chapter4", |
||||
"style": { |
"style": { |
||||
"navigationBarTitleText": "", |
"navigationBarTitleText": "", |
||||
"navigationStyle": "custom" |
"navigationStyle": "custom" |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
] |
] |
||||
}, |
|
||||
{ |
|
||||
"root": "xxdf/chapter4", |
|
||||
"pages": [{ |
|
||||
"path": "cover", |
|
||||
"style": { |
|
||||
"navigationBarTitleText": "", |
|
||||
"navigationStyle": "custom", |
|
||||
"enableShareAppMessage": true, |
|
||||
"enableShareTimeline": true |
|
||||
} |
|
||||
}] |
|
||||
} |
} |
||||
], |
], |
||||
"tabBar": { |
"tabBar": { |
||||
"custom": true, |
"custom": true, |
||||
"color": "#333333", |
"color": "#333333", |
||||
"selectedColor": "#6CA5AA", |
"selectedColor": "#6CA5AA", |
||||
"borderStyle": "black", |
"borderStyle": "black", |
||||
"backgroundColor": "#ffffff", |
"backgroundColor": "#ffffff", |
||||
"fontSize": "24rpx", |
"fontSize": "24rpx", |
||||
"height": "123rpx", |
"height": "123rpx", |
||||
"iconWidth": "40rpx", |
"iconWidth": "40rpx", |
||||
"list": [{ |
"list": [ |
||||
"pagePath": "pages/index/index", |
{ |
||||
"text": "首页", |
"pagePath": "pages/index/index", |
||||
"visible": false |
"text": "首页", |
||||
}, |
"visible": false |
||||
{ |
}, |
||||
"pagePath": "pages/index/readingBody", |
{ |
||||
"text": "阅读体", |
"pagePath": "pages/index/readingBody", |
||||
"visible": false |
"text": "阅读体", |
||||
}, |
"visible": false |
||||
{ |
}, |
||||
"pagePath": "pages/index/sensoryStore", |
{ |
||||
"text": "有感商店", |
"pagePath": "pages/index/sensoryStore", |
||||
"visible": false |
"text": "有感商店", |
||||
}, |
"visible": false |
||||
{ |
}, |
||||
"pagePath": "pages/index/intelligentAgent", |
{ |
||||
"text": "智能体", |
"pagePath": "pages/index/intelligentAgent", |
||||
"visible": false |
"text": "智能体", |
||||
}, |
"visible": false |
||||
{ |
}, |
||||
"pagePath": "pages/index/iSoul", |
{ |
||||
"text": "iSoul", |
"pagePath": "pages/index/iSoul", |
||||
"visible": false |
"text": "iSoul", |
||||
} |
"visible": false |
||||
|
} |
||||
] |
] |
||||
}, |
}, |
||||
"globalStyle": { |
"globalStyle": { |
||||
"navigationBarTextStyle": "black", |
"navigationBarTextStyle": "black", |
||||
"navigationBarTitleText": "uni-app", |
"navigationBarTitleText": "uni-app", |
||||
"navigationBarBackgroundColor": "#F8F8F8", |
"navigationBarBackgroundColor": "#F8F8F8", |
||||
"backgroundColor": "#F8F8F8" |
"backgroundColor": "#F8F8F8" |
||||
}, |
}, |
||||
"uniIdRouter": {} |
"uniIdRouter": {} |
||||
} |
} |
Binary file not shown.
@ -0,0 +1,36 @@ |
|||||
|
import { |
||||
|
get, |
||||
|
post |
||||
|
} from '@/utils/request'; |
||||
|
|
||||
|
const API = { |
||||
|
MESSAGE: { |
||||
|
LIST: '/api/questionnaire/index?page=1&limit=10', //获取问卷列表
|
||||
|
DETAIL: '/api/questionnaire/detail', //获取问卷详情
|
||||
|
ANSWER:'/api/questionnaire/answer', //提交答案
|
||||
|
STATISTICS:'/api/questionnaire/statistics', //获取统计选项
|
||||
|
ADD: '/api/liuyan/add', |
||||
|
LISTS: '/api/liuyan/lists' |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
export const getQuestionnaireList = (params, options = {}) => { |
||||
|
return get(API.MESSAGE.LIST, params, options); |
||||
|
}; |
||||
|
export const getQuestionnaireDetail = (params, options = {}) => { |
||||
|
return get(API.MESSAGE.DETAIL, params, options); |
||||
|
}; |
||||
|
export const getStatistics = (params, options = {}) => { |
||||
|
return get(API.MESSAGE.STATISTICS, params, options); |
||||
|
}; |
||||
|
export const sendAnswer = (data) => { |
||||
|
return post(API.MESSAGE.ANSWER, data); |
||||
|
}; |
||||
|
export const sendMessage = (data) => { |
||||
|
return post(API.MESSAGE.ADD, data); |
||||
|
}; |
||||
|
export const getMessageList = (params, options = {}) => { |
||||
|
return get(API.MESSAGE.LISTS, params, options); |
||||
|
}; |
||||
|
|
||||
|
export const ApiPath = API; |
@ -0,0 +1,912 @@ |
|||||
|
<template> |
||||
|
<view class="bg" v-if="info"> |
||||
|
<view class="address box" @click="changeAddressPopup('open', '', key)" v-if="!contacts && info[0].is_post == 1"> |
||||
|
<!-- <image src="https://kunshan.xmainc.com/uploads/20230105/870e4ce1d5a661986d8a54e9f3c2b0b3.png" mode="aspectFill"></image> --> |
||||
|
<view class="text">+ 添加邮寄地址</view> |
||||
|
</view> |
||||
|
<view class="contacts box" v-if="contacts && info[0].is_post == 1"> |
||||
|
<view class="contacts-left"> |
||||
|
<view class="name-phone"> |
||||
|
<view class="name">{{ contacts.name }}</view> |
||||
|
<view class="phone">{{ contacts.tel }}</view> |
||||
|
</view> |
||||
|
<view class="adds text-overflowRows">{{ contacts.province_text + contacts.city_text + contacts.district_text + contacts.detail_addr }}</view> |
||||
|
</view> |
||||
|
<image @click="changeAddressPopup('open', '', key)" src="https://static.ticket.sz-trip.com/taizhou/images/detail/edit.png" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
<view class="commodity box"> |
||||
|
<view class="merchant-name"> |
||||
|
{{info[0].merchant_name}} |
||||
|
</view> |
||||
|
<view style="margin-top: 20rpx;" class="" v-for="(item,index) in info" :key="item.id"> |
||||
|
<view class="goods"> |
||||
|
<image class="img" :src="showImg(item.specifications_image)" mode=""></image> |
||||
|
<view class="" style="display: flex;flex-direction: column;justify-content: space-between;"> |
||||
|
<view class=""> |
||||
|
{{item.good_name}} |
||||
|
</view> |
||||
|
<!-- <view> |
||||
|
<span class="info-tags" v-for="(itemT,indexT) in item.goods_new_tag.split(',').splice(0,2)" :key="indexT">{{itemT}}</span> |
||||
|
</view> --> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="sku-info"> |
||||
|
<view class="title"> |
||||
|
<view class="text-overflowRows" style="font-size: 31rpx;font-weight: 500;color: #000;">{{ item.specifications_name }}</view> |
||||
|
<view class="price-list"> |
||||
|
<view class="price-r">¥{{ item.Specifications_money / 100 }}</view> |
||||
|
<!-- <view class="price-g">¥{{ info.skuInfo.price / 100 }}</view> --> |
||||
|
<view class="price-g" v-if="item.post_money">¥{{ item.post_money / 100 }}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="num-box"> |
||||
|
<view class="ctrl" @click="reduce(item)">-</view> |
||||
|
<view class="num">{{item.num}}</view> |
||||
|
<!-- <input class="num" :disabled="true" type="text" v-model="item.num" @input="rge($event)" @blur="setV()" /> --> |
||||
|
<view class="ctrl" @click="plus(item)">+</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="person-info box" v-if="info[0].is_post == 0 && info[0].is_card == 1"> |
||||
|
<view class="person-title">购买信息</view> |
||||
|
<view class="p_name line flex"> |
||||
|
<view class="left">用户姓名:</view> |
||||
|
<input class="input" type="text" placeholder="请输入姓名" v-model="reserve_name" /> |
||||
|
</view> |
||||
|
<view class="p_id line flex"> |
||||
|
<view class="left">身份证号:</view> |
||||
|
<input class="input" type="text" placeholder="请输入身份证号" v-model="reserve_idcard" /> |
||||
|
</view> |
||||
|
<view class="p_tel flex"> |
||||
|
<view class="left">手机号码:</view> |
||||
|
<input class="input" type="text" placeholder="接受预定信息的号码" v-model="reserve_phone" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 优惠 --> |
||||
|
<view class="youhui"> |
||||
|
<view class="" style="font-size: 32rpx;font-weight: bold;color: #000;">优惠</view> |
||||
|
<view class="youhui-price"> |
||||
|
<view class="" style="color: #4D526C;font-weight: 500;"> |
||||
|
活动促销: |
||||
|
</view> |
||||
|
<view class="" style="color: #FC5109;font-weight: bold;"> |
||||
|
-¥{{delPrice}} |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- <view class="remark"> |
||||
|
<view class="">备注:</view> |
||||
|
<input type="text" placeholder="订单备注" v-model="remark" maxlength="50"/> |
||||
|
</view> --> |
||||
|
<!-- <view class="" style="font-size: 24rpx;font-weight: 500;color: #FC5109;margin-left: 26.7rpx;margin-top: 27.33rpx;"> |
||||
|
*温馨提示:本商品不支持退换货 |
||||
|
</view> --> |
||||
|
<view class="btn-list"> |
||||
|
<view class="price-box"> |
||||
|
<view class="text">合计:</view> |
||||
|
<view class="price">{{ (allPrice + post)/100}}</view> |
||||
|
<!-- <view class="price">{{ getAllPrice() - disPrice + (post / 100) }}</view> --> |
||||
|
<view class="post" v-if="post">含邮费:¥{{ post / 100 }}</view> |
||||
|
</view> |
||||
|
<view class="btn" @click="order()">立即购买</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 选择收货地址弹窗 --> |
||||
|
<uni-popup ref="addressPopup" type="bottom" backgroundColor="#F4F4F4"> |
||||
|
<view class="people-popup"> |
||||
|
<view class="top-box"> |
||||
|
<view class="top flex-between"> |
||||
|
<text class="text-overflow" @click="changeAddressPopup('close')">取消</text> |
||||
|
<text class="confirm" @click="changeAddressPopup('close', 'confirm')">确定</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<navigator url="/subPackages/user/myAddressAdd" class="button">添加收货地址</navigator> |
||||
|
<view class="popup-list" v-if="addressList.length > 0"> |
||||
|
<view class="popup-item" v-for="(item, index) in addressList" :key="index" @click="seldThisAddress(item)"> |
||||
|
<view class="item-top flex-between"> |
||||
|
<view> |
||||
|
<view class="name flex-start"> |
||||
|
{{ item.name }} |
||||
|
<text>{{ item.tel }}</text> |
||||
|
<text class="tag" v-if="item.is_default == 1">默认</text> |
||||
|
</view> |
||||
|
<view class="subtitle">{{ item.address }}</view> |
||||
|
</view> |
||||
|
<navigator :url="`/subPackages/user/myAddressAdd?id=${item.id}`"> |
||||
|
<img src="https://static.ticket.sz-trip.com/taizhou/images/detail/edit.png" alt="" /> |
||||
|
</navigator> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</uni-popup> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
contacts: null, |
||||
|
info: null, |
||||
|
num: 1, |
||||
|
post: 0, |
||||
|
flag: true, |
||||
|
addressList: [], |
||||
|
reserve_name: '', |
||||
|
reserve_idcard: '', |
||||
|
reserve_phone: '', |
||||
|
remark: '', |
||||
|
allPrice: 0, // 折扣后总价 |
||||
|
discounts:null, |
||||
|
disPrice: {}, // 折扣对象 |
||||
|
delPrice:0 |
||||
|
// disPrice: 0 |
||||
|
}; |
||||
|
}, |
||||
|
onLoad() { |
||||
|
this.info = this.$store.state.user.sshoppingCart |
||||
|
console.log('info',this.info); |
||||
|
|
||||
|
this.info.forEach(item => { |
||||
|
this.getDiscount(item) |
||||
|
}) |
||||
|
if (!this.info) { |
||||
|
uni.navigateBack(); |
||||
|
} |
||||
|
console.log('----***info***------',this.info); |
||||
|
}, |
||||
|
onShow() { |
||||
|
this.getContacts(); |
||||
|
this.getAllAddressList(); |
||||
|
// this.getAllPrice() |
||||
|
// this.getTotal() |
||||
|
}, |
||||
|
methods: { |
||||
|
// 获取总价 |
||||
|
getAllPrice() { |
||||
|
this.info.forEach(item => { |
||||
|
if ((item.Specifications_money * item.num) - (this.disPrice[item.specifications_id]*100) <= 0) { |
||||
|
item.price1 = this.disPrice[item.specifications_id] |
||||
|
item.price = 0 |
||||
|
} else{ |
||||
|
item.price1 = this.disPrice[item.specifications_id] |
||||
|
let price = (item.Specifications_money * item.num) - (this.disPrice[item.specifications_id]*100) |
||||
|
item.price = +price.toFixed(2) |
||||
|
} |
||||
|
}) |
||||
|
let allPrice = 0 |
||||
|
let delPrice = 0 |
||||
|
this.info.forEach(item => { |
||||
|
delPrice += item.price1 |
||||
|
allPrice += item.price |
||||
|
}) |
||||
|
this.delPrice = delPrice |
||||
|
console.log('delPrice',this.delPrice); |
||||
|
this.allPrice = allPrice |
||||
|
}, |
||||
|
|
||||
|
getContacts() { |
||||
|
if (this.info[0].is_post == 0) { |
||||
|
return; |
||||
|
} |
||||
|
this.Post({}, '/api/user/getDefaultConsignee').then(res => { |
||||
|
if (res) { |
||||
|
this.contacts = res.data; |
||||
|
this.getPost(); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
getPost() { |
||||
|
if (this.info[0].is_post == 0 || !this.contacts) { |
||||
|
return; |
||||
|
} |
||||
|
console.log(this.info,55555555,this.contacts); |
||||
|
this.flag = false; |
||||
|
let data = this.info.map((item) => { |
||||
|
return { specifications_id:item.specifications_id, num: item.num, consignee_id: this.contacts.id } |
||||
|
}) |
||||
|
// let data = [{ specifications_id: this.info.skuInfo.id, num: this.num, consignee_id: this.contacts.id }]; |
||||
|
console.log(data); |
||||
|
this.Post({ data:JSON.stringify(data)}, '/api/order/getNewPost').then(res => { |
||||
|
if (res) { |
||||
|
this.post = 0 |
||||
|
res.data.forEach((item)=> { |
||||
|
this.post += item.post_money |
||||
|
const postItem = this.info.find(i => i.specifications_id == item.specifications_id) |
||||
|
if(postItem) postItem.post_money = item.post_money |
||||
|
}) |
||||
|
this.flag = true; |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
rge(val) { |
||||
|
this.$nextTick(() => { |
||||
|
this.num = val.detail.value.replace(/^(0+)|[^\d]+/g, ''); |
||||
|
}); |
||||
|
}, |
||||
|
setV() { |
||||
|
if (!this.num) { |
||||
|
this.$nextTick(() => { |
||||
|
this.num = 1; |
||||
|
if (this.flag) { |
||||
|
this.getPost(); |
||||
|
} |
||||
|
}); |
||||
|
} else { |
||||
|
if (this.flag) { |
||||
|
this.getPost(); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
plus(item) { |
||||
|
// this.num = Number(this.num); |
||||
|
this.$nextTick(() => { |
||||
|
item.num += 1; |
||||
|
this.getDiscount(item) |
||||
|
// this.disPrice = this.calculateTotalPrice(this.discounts,this.num) |
||||
|
// console.log(this.disPrice); |
||||
|
if (this.flag) { |
||||
|
this.getPost(); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
reduce(item) { |
||||
|
if (item.num > 1) { |
||||
|
this.$nextTick(() => { |
||||
|
item.num -= 1; |
||||
|
this.getDiscount(item) |
||||
|
// this.disPrice = this.calculateTotalPrice(item.discounts,item.num) |
||||
|
console.log(this.disPrice); |
||||
|
if (this.flag) { |
||||
|
this.getPost(); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
// this.num = Number(this.num); |
||||
|
// if (this.num > 1) { |
||||
|
// this.$nextTick(() => { |
||||
|
// this.num -= 1; |
||||
|
// this.disPrice = this.calculateTotalPrice(this.discounts,this.num) |
||||
|
// console.log(this.disPrice); |
||||
|
// if (this.flag) { |
||||
|
// this.getPost(); |
||||
|
// } |
||||
|
// }); |
||||
|
// } |
||||
|
}, |
||||
|
//获取数量折扣 |
||||
|
getDiscount(item) { |
||||
|
this.Post({ specifications_id: item.specifications_id }, '/api/goods/getSpeNumDiscount').then(res => { |
||||
|
this.discounts = res.data.discount_rule; |
||||
|
if (this.discounts) { |
||||
|
let disPrice_item = this.calculateTotalPrice(this.discounts,item.num) |
||||
|
this.disPrice[item.specifications_id] = +disPrice_item |
||||
|
} else { |
||||
|
this.disPrice[item.specifications_id] = 0 |
||||
|
} |
||||
|
this.getAllPrice() |
||||
|
}); |
||||
|
}, |
||||
|
//计算折扣价 |
||||
|
calculateTotalPrice(discounts, selectedQuantity) { |
||||
|
if (discounts) { |
||||
|
let totalPrice = 0; |
||||
|
for (const discount of discounts) { |
||||
|
if (selectedQuantity >= discount.num) { |
||||
|
totalPrice = discount.money; |
||||
|
} |
||||
|
} |
||||
|
return totalPrice; |
||||
|
} else { |
||||
|
return 0; |
||||
|
} |
||||
|
}, |
||||
|
// 选择收货地址弹窗 |
||||
|
changeAddressPopup(type, confirm, index) { |
||||
|
if (type == 'open') { |
||||
|
this.$refs.addressPopup.open('bottom'); |
||||
|
} |
||||
|
else this.$refs.addressPopup.close(); |
||||
|
this.$forceUpdate(); |
||||
|
}, |
||||
|
// 获取收货地址列表 |
||||
|
getAllAddressList() { |
||||
|
this.Post({}, '/api/user/consigneeList').then(res => { |
||||
|
if (res.code === 200) this.addressList = res.data; |
||||
|
}); |
||||
|
}, |
||||
|
// 选择收货地址 |
||||
|
seldThisAddress(item) { |
||||
|
if (!this.contacts) this.contacts = {}; |
||||
|
Object.assign(this.contacts, item); |
||||
|
if (this.flag) { |
||||
|
this.getPost(); |
||||
|
} |
||||
|
this.$refs.addressPopup.close(); |
||||
|
this.$forceUpdate(); |
||||
|
}, |
||||
|
// 预定 |
||||
|
order() { |
||||
|
if (this.info[0].is_post == 1 && !this.contacts) { |
||||
|
uni.showToast({ |
||||
|
title: '请选择收货地址', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
if (this.info[0].is_post == 0 && this.info[0].is_card == 1) { |
||||
|
if (!this.reserve_name) { |
||||
|
uni.showToast({ |
||||
|
title: '请输入姓名', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
if (!this.reserve_phone) { |
||||
|
uni.showToast({ |
||||
|
title: '请输入电话', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
if (!this.reserve_idcard) { |
||||
|
uni.showToast({ |
||||
|
title: '请输入身份证', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
// let goods = []; |
||||
|
let goods = this.info.map((item) => { |
||||
|
return { specifications_id:item.specifications_id, num: item.num, consignee_id: item.is_post == 1 ? this.contacts.id : null } |
||||
|
}) |
||||
|
// let goodsItem = { |
||||
|
// specifications_id: this.info.skuInfo.id, |
||||
|
// num: this.num, |
||||
|
// consignee_id: this.info.skuInfo.is_post == 1 ? this.contacts.id : null |
||||
|
// }; |
||||
|
// goods.push(goodsItem); |
||||
|
let data = { |
||||
|
goods: goods, |
||||
|
coupon: null, |
||||
|
remark: this.remark, |
||||
|
is_post: this.info[0].is_post, |
||||
|
reserve_name: this.reserve_name, |
||||
|
reserve_phone: this.reserve_phone, |
||||
|
reserve_idcard: this.reserve_idcard |
||||
|
}; |
||||
|
this.Post( |
||||
|
{ |
||||
|
method: 'POST', |
||||
|
data: JSON.stringify(data) |
||||
|
}, |
||||
|
'/api/order/place' |
||||
|
).then(resT => { |
||||
|
if (resT.code == 200) { |
||||
|
this.Post( |
||||
|
{ |
||||
|
order_id: resT.data.order_id, |
||||
|
type: "miniprogram", |
||||
|
// #ifdef MP-WEIXIN |
||||
|
platform: 'miniprogram', |
||||
|
// #endif |
||||
|
// #ifdef H5 |
||||
|
platform: 'JSAPI', |
||||
|
// #endif |
||||
|
}, |
||||
|
'/api/pay/unify' |
||||
|
).then(res => { |
||||
|
if (res.data) { |
||||
|
// #ifdef MP-WEIXIN |
||||
|
uni.requestPayment({ |
||||
|
nonceStr: res.data.nonceStr, |
||||
|
package: res.data.package, |
||||
|
paySign: res.data.paySign, |
||||
|
signType: res.data.signType, |
||||
|
timeStamp: res.data.timeStamp, |
||||
|
complete() { |
||||
|
|
||||
|
}, |
||||
|
success(){ |
||||
|
uni.showLoading({ |
||||
|
title:'加载中...' |
||||
|
}) |
||||
|
setTimeout(()=>{ |
||||
|
uni.hideLoading() |
||||
|
uni.navigateTo({ |
||||
|
url: '/subPackages/order/detail?id='+resT.data.order_id |
||||
|
}); |
||||
|
},2000) |
||||
|
} |
||||
|
}); |
||||
|
// #endif |
||||
|
// #ifdef H5 |
||||
|
WeixinJSBridge.invoke('getBrandWCPayRequest', { |
||||
|
appId: res.data.appId, |
||||
|
timeStamp: res.data.timeStamp, |
||||
|
nonceStr: res.data.nonceStr, |
||||
|
package: res.data.package, |
||||
|
signType: res.data.signType, |
||||
|
paySign: res.data.paySign |
||||
|
}, function(Twores) { |
||||
|
if (Twores.err_msg === 'get_brand_wcpay_request:ok') { |
||||
|
uni.showLoading({ |
||||
|
title:'加载中...' |
||||
|
}) |
||||
|
setTimeout(()=>{ |
||||
|
uni.hideLoading() |
||||
|
uni.navigateTo({ |
||||
|
url: '/subPackages/order/detail?id='+resT.data.order_id |
||||
|
}); |
||||
|
},2000) |
||||
|
} else { |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
// #endif |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.bg { |
||||
|
min-height: 100vh; |
||||
|
overflow-x: hidden; |
||||
|
background: #f2f4f7; |
||||
|
padding-bottom: 200rpx; |
||||
|
} |
||||
|
view { |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
.box { |
||||
|
width: 710rpx; |
||||
|
min-height: 100rpx; |
||||
|
padding: 30rpx; |
||||
|
background: #ffffff; |
||||
|
border-radius: 16rpx; |
||||
|
margin: 0 auto; |
||||
|
margin-top: 20rpx; |
||||
|
} |
||||
|
.address { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
image { |
||||
|
width: 32rpx; |
||||
|
height: 32rpx; |
||||
|
} |
||||
|
.text { |
||||
|
font-size: 28rpx; |
||||
|
font-family: PingFangSC-Regular, PingFang SC; |
||||
|
font-weight: 400; |
||||
|
color: #6c7a94; |
||||
|
margin-left: 18rpx; |
||||
|
} |
||||
|
} |
||||
|
.commodity { |
||||
|
// display: flex; |
||||
|
// align-items: center; |
||||
|
.img { |
||||
|
width: 140rpx; |
||||
|
height: 140rpx; |
||||
|
background: #f2f4f7; |
||||
|
border-radius: 10rpx; |
||||
|
margin-right: 18rpx; |
||||
|
} |
||||
|
.title { |
||||
|
width: 300rpx; |
||||
|
margin-left: 20rpx; |
||||
|
font-size: 30rpx; |
||||
|
font-family: PingFangSC-Medium, PingFang SC; |
||||
|
font-weight: 500; |
||||
|
color: #000000; |
||||
|
|
||||
|
.price-list { |
||||
|
width: 600rpx; |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
margin-top: 18rpx; |
||||
|
align-items: center; |
||||
|
.price-r { |
||||
|
font-size: 32rpx; |
||||
|
font-family: PingFangSC-Regular, PingFang SC; |
||||
|
font-weight: 500; |
||||
|
color: #FC5109; |
||||
|
&:before { |
||||
|
content: '小计:'; |
||||
|
display: inline-block; |
||||
|
color: #000; |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
} |
||||
|
.price-g { |
||||
|
font-size: 32rpx; |
||||
|
font-family: PingFangSC-Regular, PingFang SC; |
||||
|
font-weight: 500; |
||||
|
color: #FC5109; |
||||
|
&:before { |
||||
|
content: '运费:'; |
||||
|
display: inline-block; |
||||
|
color: #000; |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.num-box { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-left: 20rpx; |
||||
|
width: 200rpx; |
||||
|
justify-content: space-between; |
||||
|
.num { |
||||
|
text-align: center; |
||||
|
width: 50rpx; |
||||
|
} |
||||
|
.ctrl { |
||||
|
width: 70rpx; |
||||
|
height: 60rpx; |
||||
|
line-height: 60rpx; |
||||
|
text-align: center; |
||||
|
font-weight: bold; |
||||
|
font-size: 36rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.btn-list { |
||||
|
width: 750rpx; |
||||
|
height: 166rpx; |
||||
|
background: #ffffff; |
||||
|
box-shadow: 0rpx -3rpx 9rpx 1rpx rgba(227, 229, 232, 0.5); |
||||
|
display: flex; |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
padding: 20rpx 50rpx; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
.btn { |
||||
|
width: 250rpx; |
||||
|
height: 80rpx; |
||||
|
background: #60989E; |
||||
|
border-radius: 44rpx; |
||||
|
text-align: center; |
||||
|
line-height: 80rpx; |
||||
|
font-size: 32rpx; |
||||
|
font-family: PingFangSC-Medium, PingFang SC; |
||||
|
font-weight: 500; |
||||
|
color: #ffffff; |
||||
|
} |
||||
|
.price-box { |
||||
|
display: flex; |
||||
|
align-items: baseline; |
||||
|
.text { |
||||
|
font-size: 28rpx; |
||||
|
font-family: PingFangSC-Regular, PingFang SC; |
||||
|
font-weight: 400; |
||||
|
color: #393b3e; |
||||
|
} |
||||
|
.price { |
||||
|
margin-left: 15rpx; |
||||
|
font-size: 48rpx; |
||||
|
font-family: PingFangSC-Regular, PingFang SC; |
||||
|
font-weight: 400; |
||||
|
color: #FC5109; |
||||
|
&:before { |
||||
|
content: '¥'; |
||||
|
display: inline-block; |
||||
|
color: #FC5109; |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
} |
||||
|
.post { |
||||
|
margin-left: 15rpx; |
||||
|
color: #FC5109; |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.contacts { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
image { |
||||
|
width: 36rpx; |
||||
|
height: 36rpx; |
||||
|
} |
||||
|
.contacts-left { |
||||
|
.name-phone { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
.name { |
||||
|
font-size: 32rpx; |
||||
|
font-family: PingFangSC-Medium, PingFang SC; |
||||
|
font-weight: 500; |
||||
|
color: #222222; |
||||
|
} |
||||
|
.phone { |
||||
|
margin-left: 27rpx; |
||||
|
font-size: 28rpx; |
||||
|
font-family: PingFangSC-Regular, PingFang SC; |
||||
|
font-weight: 400; |
||||
|
color: #303030; |
||||
|
} |
||||
|
} |
||||
|
.adds { |
||||
|
font-size: 28rpx; |
||||
|
font-family: PingFangSC-Regular, PingFang SC; |
||||
|
font-weight: 400; |
||||
|
color: #6c7a94; |
||||
|
margin-top: 20rpx; |
||||
|
max-width: 500rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.people-popup { |
||||
|
padding: 26rpx; |
||||
|
min-height: 800rpx; |
||||
|
|
||||
|
.top-box { |
||||
|
height: 80rpx; |
||||
|
|
||||
|
.top { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
color: #000; |
||||
|
height: 80rpx; |
||||
|
font-size: 0; |
||||
|
overflow: hidden; |
||||
|
padding: 0 26rpx; |
||||
|
|
||||
|
text { |
||||
|
text-align: left; |
||||
|
font-size: 30rpx; |
||||
|
font-weight: 400; |
||||
|
color: #000000; |
||||
|
} |
||||
|
|
||||
|
.confirm { |
||||
|
font-weight: 400; |
||||
|
color: #000000; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.popup-list { |
||||
|
height: 666rpx; |
||||
|
overflow: scroll; |
||||
|
|
||||
|
.popup-item { |
||||
|
border-radius: 12rpx; |
||||
|
padding: 0 20rpx; |
||||
|
margin-top: 24rpx; |
||||
|
font-size: 24rpx; |
||||
|
color: #333333; |
||||
|
font-weight: 400; |
||||
|
background-color: #ffffff; |
||||
|
|
||||
|
.item-top { |
||||
|
padding: 32rpx; |
||||
|
|
||||
|
img { |
||||
|
color: #666666; |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
} |
||||
|
|
||||
|
.name { |
||||
|
font-size: 30rpx; |
||||
|
color: #000000; |
||||
|
overflow: hidden; |
||||
|
|
||||
|
text { |
||||
|
color: #999999; |
||||
|
} |
||||
|
|
||||
|
.tag { |
||||
|
width: 70rpx; |
||||
|
height: 32rpx; |
||||
|
background: #00d7ed; |
||||
|
border-radius: 7rpx; |
||||
|
line-height: 32rpx; |
||||
|
text-align: center; |
||||
|
font-size: 21rpx; |
||||
|
font-family: PingFang SC; |
||||
|
font-weight: 500; |
||||
|
color: #ffffff; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.com-flex-start { |
||||
|
margin: 0 0 30rpx; |
||||
|
} |
||||
|
|
||||
|
.subtitle { |
||||
|
font-weight: 400; |
||||
|
flex: 1; |
||||
|
text-align: left; |
||||
|
margin-top: 33rpx; |
||||
|
|
||||
|
.mobile { |
||||
|
margin-bottom: 36rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.status { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
line-height: 40rpx; |
||||
|
border-radius: 50%; |
||||
|
text-align: center; |
||||
|
box-sizing: border-box; |
||||
|
|
||||
|
img { |
||||
|
width: 27rpx; |
||||
|
height: 21rpx; |
||||
|
} |
||||
|
} |
||||
|
.statuss { |
||||
|
background: linear-gradient(90deg, #fa2b66, #ff9834); |
||||
|
border: none; |
||||
|
} |
||||
|
.noSelect { |
||||
|
border: 1rpx solid #999999; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// .item-site { |
||||
|
// color: #666666; |
||||
|
// display: flex; |
||||
|
// align-items: center; |
||||
|
// padding: 36rpx 0; |
||||
|
|
||||
|
// view { |
||||
|
// width: 23rpx; |
||||
|
// height: 23rpx; |
||||
|
// margin-right: 10rpx; |
||||
|
// border: 1rpx solid #999999; |
||||
|
// border-radius: 50%; |
||||
|
|
||||
|
// view { |
||||
|
// width: 8rpx; |
||||
|
// height: 8rpx; |
||||
|
// background: #000000; |
||||
|
// border-radius: 50%; |
||||
|
// margin: auto; |
||||
|
// } |
||||
|
// } |
||||
|
// } |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.button { |
||||
|
font-size: 30rpx; |
||||
|
font-weight: 400; |
||||
|
color: #000000; |
||||
|
text-align: center; |
||||
|
width: 100%; |
||||
|
height: 80rpx; |
||||
|
line-height: 80rpx; |
||||
|
background-color: #ffffff; |
||||
|
border-radius: 60rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.person-info { |
||||
|
padding: 30rpx 30rpx 15rpx 30rpx; |
||||
|
background: #fff; |
||||
|
margin-top: 30rpx; |
||||
|
border-radius: 16rpx; |
||||
|
} |
||||
|
.person-title { |
||||
|
font-size: 32rpx; |
||||
|
font-weight: bold; |
||||
|
color: #000; |
||||
|
} |
||||
|
.line { |
||||
|
border-bottom: 1px solid #e3e5e8; |
||||
|
} |
||||
|
.flex { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
.left { |
||||
|
width: 140rpx; |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 500; |
||||
|
color: #4d526c; |
||||
|
height: 104rpx; |
||||
|
line-height: 104rpx; |
||||
|
} |
||||
|
.input { |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 400; |
||||
|
} |
||||
|
.remark { |
||||
|
padding: 30rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
width: 710rpx; |
||||
|
min-height: 150rpx; |
||||
|
background: #ffffff; |
||||
|
border-radius: 16rpx; |
||||
|
margin: 0 auto; |
||||
|
margin-top: 30rpx; |
||||
|
view { |
||||
|
color: #4d526c; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
input { |
||||
|
margin-left: 64rpx; |
||||
|
width: 500rpx; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.info-tags { |
||||
|
padding: 8rpx 7rpx; |
||||
|
text-align: center; |
||||
|
line-height: 35rpx; |
||||
|
font-size: 20rpx; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.info-tags:first-child { |
||||
|
background: rgba(252,81,9,.08); |
||||
|
color: #FC5109; |
||||
|
} |
||||
|
|
||||
|
.info-tags:last-child { |
||||
|
background: rgba(73,143,239,.1); |
||||
|
color: #498FEF; |
||||
|
} |
||||
|
|
||||
|
.merchant-name { |
||||
|
margin-bottom: 24rpx; |
||||
|
} |
||||
|
|
||||
|
.goods { |
||||
|
display: flex; |
||||
|
} |
||||
|
|
||||
|
.sku-info { |
||||
|
display: flex; |
||||
|
margin-top: 26rpx; |
||||
|
align-items: baseline; |
||||
|
justify-content: space-between; |
||||
|
border-bottom: 1rpx solid #ccc; |
||||
|
padding-bottom: 25.3rpx; |
||||
|
} |
||||
|
|
||||
|
.sku-info:last-child { |
||||
|
border:none !important; |
||||
|
} |
||||
|
|
||||
|
.youhui { |
||||
|
width: 710rpx; |
||||
|
margin: 0 auto; |
||||
|
margin-top: 22rpx; |
||||
|
padding: 32.67rpx 19.33rpx 32.67rpx 24rpx; |
||||
|
background: #FFFFFF; |
||||
|
border-radius: 13rpx; |
||||
|
} |
||||
|
|
||||
|
.youhui-price { |
||||
|
margin-top: 52.67rpx; |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
margin-left: .67rpx; |
||||
|
font-size: 27rpx; |
||||
|
} |
||||
|
|
||||
|
</style> |
@ -0,0 +1,173 @@ |
|||||
|
<template> |
||||
|
<view class="bg"> |
||||
|
<view class="search-box"> |
||||
|
<view class="search"> |
||||
|
<image src="https://static.ticket.sz-trip.com/taizhou/images/search.png" mode="widthFix"></image> |
||||
|
<input type="text" v-model="keywords" @confirm="getList" placeholder="请输入搜索关键词" /> |
||||
|
</view> |
||||
|
<view class="text" @click="goBack">取消</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="box flex-between" v-if="list && list.length > 0"> |
||||
|
<view v-for="(item,index) in list" :key="index" class="item" v-if="item.search_data" @click="gotoDetail(item)"> |
||||
|
<image :src="showImg(item.search_data.image)" mode="aspectFill" class="headimg"></image> |
||||
|
<view class="content flex-column"> |
||||
|
<view class="title text-overflowRows">{{item.title}}</view> |
||||
|
<view class="price" v-if="type == 'goods'">{{item.search_data.money / 100}}</view> |
||||
|
<view class="user-info" v-if="type == 'article'"> |
||||
|
<image :src="showImg(item.search_data.author_img)" mode="aspectFill" class="userImg"></image> |
||||
|
{{item.search_data.author}} |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view v-else class="noData">暂无数据</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
keywords: '', |
||||
|
list: [], |
||||
|
type: '' |
||||
|
} |
||||
|
}, |
||||
|
onLoad(option) { |
||||
|
if(option.type) this.type = option.type |
||||
|
}, |
||||
|
methods: { |
||||
|
getList() { |
||||
|
this.Post({ |
||||
|
name: this.keywords.trim(), |
||||
|
offset: 0, |
||||
|
type: this.type, |
||||
|
limit: 100, |
||||
|
}, '/api/search/search').then(res => { |
||||
|
this.list = res.data |
||||
|
}) |
||||
|
}, |
||||
|
gotoDetail(item) { |
||||
|
if(this.type == 'goods') { |
||||
|
uni.navigateTo({ |
||||
|
url: `/subPackages/techan/detail?id=${item.search_data.id}` |
||||
|
}) |
||||
|
}else if(this.type == 'article') { |
||||
|
this.gotoUrlNew(item.search_data) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.bg { |
||||
|
min-height: 100vh; |
||||
|
background-color: #f7f7f7; |
||||
|
} |
||||
|
|
||||
|
.search-box { |
||||
|
width: 100%; |
||||
|
padding: 20rpx; |
||||
|
border-bottom: 1rpx solid #ccc; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
background-color: #fff; |
||||
|
|
||||
|
.search { |
||||
|
flex: 1; |
||||
|
padding: 0 20rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
height: 65rpx; |
||||
|
border-radius: 33rpx; |
||||
|
background-color: rgb(245, 245, 245); |
||||
|
|
||||
|
image { |
||||
|
display: block; |
||||
|
width: 35rpx; |
||||
|
margin-right: 30rpx; |
||||
|
} |
||||
|
|
||||
|
input { |
||||
|
flex: 1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.text { |
||||
|
font-size: 30rpx; |
||||
|
color: #b9b9b9; |
||||
|
margin-left: 20rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.box { |
||||
|
flex-wrap: wrap; |
||||
|
padding: 30rpx 20rpx; |
||||
|
|
||||
|
.item { |
||||
|
width: 342rpx; |
||||
|
height: 498rpx; |
||||
|
background: #FFFFFF; |
||||
|
border-radius: 11rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
|
||||
|
.headimg { |
||||
|
width: 343rpx; |
||||
|
height: 327rpx; |
||||
|
border-radius: 11rpx 11rpx 0rpx 0rpx; |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
height: 170rpx; |
||||
|
justify-content: space-between; |
||||
|
padding: 15rpx 15rpx 20rpx 15rpx; |
||||
|
|
||||
|
.title { |
||||
|
font-weight: bold; |
||||
|
font-size: 30rpx; |
||||
|
color: #000000; |
||||
|
} |
||||
|
|
||||
|
.price { |
||||
|
font-weight: bold; |
||||
|
font-size: 33rpx; |
||||
|
color: #FF2D3B; |
||||
|
margin-left: auto; |
||||
|
} |
||||
|
.price::before { |
||||
|
font-size: 20rpx; |
||||
|
content: '¥'; |
||||
|
} |
||||
|
.price::after { |
||||
|
font-size: 20rpx; |
||||
|
content: '起'; |
||||
|
color: rgba(153, 153, 153, 1); |
||||
|
} |
||||
|
|
||||
|
.user-info { |
||||
|
font-weight: 500; |
||||
|
font-size: 28rpx; |
||||
|
color: #999999; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
|
||||
|
.userImg { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
border-radius: 50%; |
||||
|
margin-right: 10rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.noData { |
||||
|
padding: 30rpx 0; |
||||
|
text-align: center; |
||||
|
font-size: 30rpx; |
||||
|
color: #ccc; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,286 @@ |
|||||
|
<template> |
||||
|
<view> |
||||
|
<TitleHeader /> |
||||
|
<swiper class="main-swiper" :vertical="true" :current="currentIndex" @change="handleSwiperChange" |
||||
|
:duration="300" :style="{ height: `calc(100vh - ${titleHeight}px)` }"> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[0]"> |
||||
|
<image v-show="shouldShowContent(0)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg1s.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<image v-show="shouldShowContent(0)" class="layer-img1" |
||||
|
:class="{'slide-in-from-left': animationStates[0], 'hidden': !animationStates[0]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg1-info.png" :lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[1]"> |
||||
|
<image v-show="shouldShowContent(1)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg2.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<image v-show="shouldShowContent(1)" class="layer-img2" |
||||
|
:class="{'slide-in-from-left': animationStates[1], 'hidden': !animationStates[1]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg2-info.png" :lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[2]"> |
||||
|
<image v-show="shouldShowContent(2)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg3.jpg" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view class="content-layer" v-show="shouldShowContent(2)"> |
||||
|
<image class="layer-img3" |
||||
|
:class="{'slide-in-from-right': animationStates[2], 'hidden': !animationStates[2]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg3-info.png" :lazy-load="true" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[3]"> |
||||
|
<image v-show="shouldShowContent(3)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg4.jpg" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<image v-show="shouldShowContent(3)" class="layer-img4" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg4-info.gif" |
||||
|
:lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[4]"> |
||||
|
<image v-show="shouldShowContent(4)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg5.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<image :class="{'slide-in-from-right': animationStates[4], 'hidden': !animationStates[4]}" |
||||
|
v-show="shouldShowContent(4)" class="layer-img5" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg5-info.png" |
||||
|
:lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[5]"> |
||||
|
<image v-show="shouldShowContent(5)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg6.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[6]"> |
||||
|
<image v-show="shouldShowContent(6)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter1/bg7.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view @click="goBack" class="back-btn" type="default"> |
||||
|
<image class="back-icon" src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import TitleHeader from '@/components/TitleHeader.vue'; |
||||
|
export default { |
||||
|
components: { |
||||
|
TitleHeader |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
currentIndex: 0, |
||||
|
loadedPages: { |
||||
|
0: false, |
||||
|
1: false, |
||||
|
2: false, |
||||
|
3: false, |
||||
|
4: false, |
||||
|
5: false, |
||||
|
6: false |
||||
|
}, |
||||
|
animationStates: { |
||||
|
0: false, |
||||
|
1: false, |
||||
|
2: false, |
||||
|
3: false, |
||||
|
4: false, |
||||
|
5: false, |
||||
|
6: false |
||||
|
}, |
||||
|
preloadBuffer: 1, |
||||
|
titleHeight: 0 |
||||
|
}; |
||||
|
}, |
||||
|
watch: { |
||||
|
currentIndex(newIndex) { |
||||
|
for (let i = Math.max(0, newIndex - this.preloadBuffer); i <= Math.min(9, newIndex + this |
||||
|
.preloadBuffer); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.titleHeight = uni.getStorageSync('titleHeight') |
||||
|
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 9); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[this.currentIndex] = true; |
||||
|
}, 50); |
||||
|
}, |
||||
|
methods: { |
||||
|
handleSwiperChange(e) { |
||||
|
const newIndex = e.detail.current; |
||||
|
this.currentIndex = newIndex; |
||||
|
this.animationStates[newIndex] = false; |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[newIndex] = true; |
||||
|
}, 50); |
||||
|
}, |
||||
|
shouldShowContent(index) { |
||||
|
return Math.abs(index - this.currentIndex) <= this.preloadBuffer; |
||||
|
}, |
||||
|
goBack() { |
||||
|
uni.navigateTo({ |
||||
|
url: '/taozi/home/home?targetIndex=5' |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.main-swiper { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
.page-container { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.bg-image { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
z-index: 1; |
||||
|
} |
||||
|
|
||||
|
.layer-img1 { |
||||
|
width: 500rpx; |
||||
|
z-index: 2; |
||||
|
margin-right: 180rpx; |
||||
|
margin-top: 50rpx; |
||||
|
} |
||||
|
|
||||
|
.layer-img2 { |
||||
|
z-index: 2; |
||||
|
position: absolute; |
||||
|
bottom: 18%; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
height: 350rpx; |
||||
|
} |
||||
|
|
||||
|
.content-layer { |
||||
|
margin: 130rpx 0; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
display: flex; |
||||
|
justify-content: flex-end; |
||||
|
} |
||||
|
|
||||
|
.layer-img3 { |
||||
|
height: 100%; |
||||
|
width: 280rpx; |
||||
|
z-index: 2; |
||||
|
margin-top: 10rpx; |
||||
|
margin-right: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.layer-img4 { |
||||
|
z-index: 2; |
||||
|
width: 400rpx; |
||||
|
height: 400rpx; |
||||
|
margin-top: 400rpx; |
||||
|
margin-left: 80rpx; |
||||
|
} |
||||
|
|
||||
|
.layer-img5 { |
||||
|
z-index: 2; |
||||
|
position: absolute; |
||||
|
bottom: 90rpx; |
||||
|
right: 30rpx; |
||||
|
width: 320rpx; |
||||
|
height: 500rpx; |
||||
|
} |
||||
|
|
||||
|
.back-btn { |
||||
|
position: absolute; |
||||
|
top: 50rpx; |
||||
|
left: 50rpx; |
||||
|
z-index: 2; |
||||
|
background-color: rgb(0 0 0 / 0.3); |
||||
|
border-radius: 50%; |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.back-icon { |
||||
|
width: 50rpx; |
||||
|
height: 50rpx; |
||||
|
} |
||||
|
|
||||
|
.hidden { |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
.slide-in-from-left { |
||||
|
animation: slideInLeft 1.2s ease-out forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes slideInLeft { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: translateX(-100px); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.slide-in-from-right { |
||||
|
animation: slideInRight 1.2s ease-out forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes slideInRight { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: translateX(100px); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,336 @@ |
|||||
|
<template> |
||||
|
<view> |
||||
|
<TitleHeader /> |
||||
|
<swiper class="main-swiper" :vertical="true" :current="currentIndex" @change="handleSwiperChange" |
||||
|
:duration="300" :style="{ height: `calc(100vh - ${titleHeight}px)` }"> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[0]"> |
||||
|
<image v-show="shouldShowContent(0)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg1.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<image v-show="shouldShowContent(0)" class="layer-img1" |
||||
|
:class="{'slide-in-from-left': animationStates[0], 'hidden': !animationStates[0]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg1-info.png" :lazy-load="true" mode="aspectFill" /> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<view class="loadedPages-three-title"> |
||||
|
<view class="txt"> |
||||
|
#Chapter 贰 |
||||
|
</view> |
||||
|
|
||||
|
<view class="txt"> |
||||
|
IP Art Exhibition |
||||
|
</view> |
||||
|
</view> |
||||
|
<template v-if="loadedPages[1]"> |
||||
|
<image v-show="shouldShowContent(1)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg2.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<image v-show="shouldShowContent(1)" class="layer-img2" |
||||
|
:class="{'slide-in-from-left': animationStates[1], 'hidden': !animationStates[1]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg2-info.png" :lazy-load="true" mode="aspectFill" /> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[2]"> |
||||
|
<image v-show="shouldShowContent(2)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg3.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<image v-show="shouldShowContent(2)" class="layer-img3" |
||||
|
:class="{'slide-in-from-left': animationStates[2], 'hidden': !animationStates[2]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg3-info.png" :lazy-load="true" mode="aspectFill" /> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[3]"> |
||||
|
<image v-show="shouldShowContent(3)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg4.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<image v-show="shouldShowContent(3)" class="layer-img4" |
||||
|
:class="{'slide-in-from-left': animationStates[3], 'hidden': !animationStates[3]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg4-info.png" :lazy-load="true" mode="aspectFill" /> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[4]"> |
||||
|
<image v-show="shouldShowContent(4)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg5.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<video v-show="shouldShowContent(4)" ref="videoPlayer" id="videoPlayer" |
||||
|
class="loadedPages-video" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg5-video.mp4" |
||||
|
:autoplay="currentIndex === 4" :loop="true" :controls="true" :show-play-btn="true" |
||||
|
:enable-progress-gesture="true" @error="handleVideoError"></video> |
||||
|
<view @click="goBack" class="back-btn" type="default"> |
||||
|
<image class="back-icon" src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
<MusicControl /> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import MusicControl from '@/components/MusicControl.vue'; |
||||
|
import TitleHeader from '@/components/TitleHeader.vue'; |
||||
|
export default { |
||||
|
components: { |
||||
|
MusicControl, |
||||
|
TitleHeader |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
currentIndex: 0, |
||||
|
videoPlayer: null, |
||||
|
videoContext: null, |
||||
|
loadedPages: { |
||||
|
0: false, |
||||
|
1: false, |
||||
|
2: false, |
||||
|
3: false, |
||||
|
4: false |
||||
|
}, |
||||
|
animationStates: { |
||||
|
0: false, |
||||
|
1: false, |
||||
|
2: false, |
||||
|
3: false, |
||||
|
4: false |
||||
|
}, |
||||
|
preloadBuffer: 1, |
||||
|
titleHeight: 0 |
||||
|
}; |
||||
|
}, |
||||
|
watch: { |
||||
|
currentIndex(newIndex) { |
||||
|
for (let i = Math.max(0, newIndex - this.preloadBuffer); i <= Math.min(9, newIndex + this |
||||
|
.preloadBuffer); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.titleHeight = uni.getStorageSync('titleHeight') |
||||
|
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 9); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[this.currentIndex] = true; |
||||
|
}, 50); |
||||
|
this.$nextTick(() => { |
||||
|
try { |
||||
|
this.videoContext = uni.createVideoContext('videoPlayer'); |
||||
|
} catch (error) { |
||||
|
console.error('初始化视频上下文失败:', error); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
methods: { |
||||
|
handleSwiperChange(e) { |
||||
|
const newIndex = e.detail.current; |
||||
|
const oldIndex = this.currentIndex; |
||||
|
this.currentIndex = newIndex; |
||||
|
this.animationStates[newIndex] = false; |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[newIndex] = true; |
||||
|
}, 50); |
||||
|
this.$nextTick(() => { |
||||
|
this.handleVideoPlayback(oldIndex, newIndex); |
||||
|
}); |
||||
|
}, |
||||
|
handleVideoPlayback(oldIndex, newIndex) { |
||||
|
if (!this.videoContext) { |
||||
|
try { |
||||
|
this.videoContext = uni.createVideoContext('videoPlayer'); |
||||
|
} catch (error) {} |
||||
|
} |
||||
|
|
||||
|
if (!this.videoContext) return; |
||||
|
if (newIndex === 4) { |
||||
|
try { |
||||
|
this.videoContext.play(); |
||||
|
} catch (error) {} |
||||
|
} else if (oldIndex === 4) { |
||||
|
try { |
||||
|
this.videoContext.pause(); |
||||
|
this.videoContext.seek(0); |
||||
|
} catch (error) { |
||||
|
console.error('视频暂停失败:', error); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
handleVideoError(e) { |
||||
|
uni.showToast({ |
||||
|
title: '视频加载失败', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
}, |
||||
|
shouldShowContent(index) { |
||||
|
return Math.abs(index - this.currentIndex) <= this.preloadBuffer; |
||||
|
}, |
||||
|
goBack() { |
||||
|
uni.navigateTo({ |
||||
|
url: '/taozi/home/home?targetIndex=6' |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
onShow() { |
||||
|
if (this.currentIndex === 4 && this.videoContext) { |
||||
|
this.$nextTick(() => { |
||||
|
this.videoContext.play(); |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
onHide() { |
||||
|
if (this.videoContext) { |
||||
|
this.videoContext.pause(); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.main-swiper { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
.page-container { |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.bg-image { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
z-index: 1; |
||||
|
} |
||||
|
|
||||
|
.layer-img1 { |
||||
|
position: absolute; |
||||
|
width: 500rpx; |
||||
|
height: 800rpx; |
||||
|
z-index: 2; |
||||
|
top: 120rpx; |
||||
|
left: 60rpx; |
||||
|
} |
||||
|
|
||||
|
.layer-img2 { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
width: 640rpx; |
||||
|
height: 750rpx; |
||||
|
z-index: 2; |
||||
|
} |
||||
|
|
||||
|
.layer-img3 { |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
left: 30rpx; |
||||
|
width: 550rpx; |
||||
|
height: 1200rpx; |
||||
|
z-index: 2; |
||||
|
} |
||||
|
|
||||
|
.layer-img4 { |
||||
|
position: absolute; |
||||
|
bottom: 50rpx; |
||||
|
left: 30rpx; |
||||
|
width: 400rpx; |
||||
|
height: 900rpx; |
||||
|
z-index: 2; |
||||
|
} |
||||
|
|
||||
|
.hidden { |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
.slide-in-from-left { |
||||
|
animation: slideInLeft 1.2s ease-out forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes slideInLeft { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: translateX(-100px); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@font-face { |
||||
|
font-family: 'SourceHanSerif-Regular'; |
||||
|
src: url(https://static.ticket.sz-trip.com/epicSoul/taozi/fonts/SourceHanSerifSC-Regular.otf); |
||||
|
} |
||||
|
|
||||
|
.loadedPages-three-title { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
width: 100%; |
||||
|
margin-top: 30rpx; |
||||
|
z-index: 9; |
||||
|
position: absolute; |
||||
|
|
||||
|
.txt { |
||||
|
font-size: 24rpx; |
||||
|
color: #333; |
||||
|
font-family: SourceHanSerif-Regular; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
|
||||
|
text { |
||||
|
display: block; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.txt:first-child { |
||||
|
margin-left: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.txt:last-child { |
||||
|
margin-right: 30rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.loadedPages-video { |
||||
|
width: 100%; |
||||
|
height: 350rpx; |
||||
|
z-index: 9; |
||||
|
margin-top: 150rpx; |
||||
|
} |
||||
|
|
||||
|
.back-btn { |
||||
|
position: absolute; |
||||
|
top: 50rpx; |
||||
|
left: 50rpx; |
||||
|
z-index: 2; |
||||
|
background-color: rgb(0 0 0 / 0.3); |
||||
|
border-radius: 50%; |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.back-icon { |
||||
|
width: 50rpx; |
||||
|
height: 50rpx; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,369 @@ |
|||||
|
<template> |
||||
|
<view> |
||||
|
<TitleHeader /> |
||||
|
<swiper class="main-swiper" :vertical="true" :current="currentIndex" @change="handleSwiperChange" |
||||
|
:duration="300" :style="{ height: `calc(100vh - ${titleHeight}px)` }"> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[0]"> |
||||
|
<image v-show="shouldShowContent(0)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter3/bg1.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<image v-show="shouldShowContent(0)" class="layer-img1" |
||||
|
:class="{'rotate-bounce-in': animationStates[0], 'hidden': !animationStates[0]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter3/bg1-info.png" :lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
<image v-show="shouldShowContent(0)" class="layer-info" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter3/bg1-info2.png" |
||||
|
mode="aspectFill"></image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[1]"> |
||||
|
<image v-show="shouldShowContent(1)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter3/bg2.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view v-show="shouldShowContent(1)" class="layer-content"> |
||||
|
<view class="item"> |
||||
|
<image class="item-gif" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter3/liu.gif" mode="aspectFill"></image> |
||||
|
<view class="layer-item-txt"> |
||||
|
来!备的草编席垫送你,<br />咱席地而坐,边吃边唠,<br />便是人间好时节。 |
||||
|
</view> |
||||
|
<view class="layer-item-tx2"> |
||||
|
刘备 / 挚友款 · 同心桃 |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[2]"> |
||||
|
<image v-show="shouldShowContent(2)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter3/bg3.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view v-show="shouldShowContent(2)" class="layer-content"> |
||||
|
<view class="item"> |
||||
|
<image class="item-gif" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter3/guan.gif" mode="aspectFill"></image> |
||||
|
<view class="layer-item-txt"> |
||||
|
某卖的不是桃,<br />是当年与兄长、三弟<br />在桃林下对饮的春秋。 |
||||
|
</view> |
||||
|
<view class="layer-item-tx2"> |
||||
|
关羽 / 挚知己款 · 对饮桃 |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[3]"> |
||||
|
<image v-show="shouldShowContent(3)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter3/bg4.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view v-show="shouldShowContent(3)" class="layer-content"> |
||||
|
<view class="item"> |
||||
|
<image class="item-gif" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter3/zhang.gif" mode="aspectFill"></image> |
||||
|
<view class="layer-item-txt"> |
||||
|
瞧这桃!跟俺张飞的脾气<br />一样爽利,咬下去<br />「噗嗤」爆汁,<br />比俺大笑还痛快! |
||||
|
</view> |
||||
|
<view class="layer-item-tx2"> |
||||
|
张飞 / 热辣款款 · 快哉桃 |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[4]"> |
||||
|
<image v-show="shouldShowContent(4)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter3/bg5.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view class="layer2-content" |
||||
|
:class="{'fade-slide-up': animationStates[4], 'hidden': !animationStates[4]}"> |
||||
|
<view class="item"> |
||||
|
<view class="bottom-tit"> |
||||
|
一起回桃园 |
||||
|
</view> |
||||
|
<view class="bottom-tit2"> |
||||
|
桃园不是起点,而是时间里的约定 |
||||
|
</view> |
||||
|
<image class="bottom-img" src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/forewordThree_icon.png" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
|
||||
|
</view> |
||||
|
<view @click="goBack" class="back-btn" type="default"> |
||||
|
<image class="back-icon" src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import TitleHeader from '@/components/TitleHeader.vue'; |
||||
|
export default { |
||||
|
components: { |
||||
|
TitleHeader |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
currentIndex: 0, |
||||
|
loadedPages: { |
||||
|
0: false, |
||||
|
1: false, |
||||
|
2: false, |
||||
|
3: false |
||||
|
}, |
||||
|
animationStates: { |
||||
|
0: false, |
||||
|
1: false, |
||||
|
2: false, |
||||
|
3: false |
||||
|
}, |
||||
|
preloadBuffer: 1, |
||||
|
titleHeight: 0 |
||||
|
}; |
||||
|
}, |
||||
|
watch: { |
||||
|
currentIndex(newIndex) { |
||||
|
for (let i = Math.max(0, newIndex - this.preloadBuffer); i <= Math.min(9, newIndex + this |
||||
|
.preloadBuffer); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.titleHeight = uni.getStorageSync('titleHeight') |
||||
|
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 9); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[this.currentIndex] = true; |
||||
|
}, 50); |
||||
|
}, |
||||
|
methods: { |
||||
|
handleSwiperChange(e) { |
||||
|
const newIndex = e.detail.current; |
||||
|
this.currentIndex = newIndex; |
||||
|
this.animationStates[newIndex] = false; |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[newIndex] = true; |
||||
|
}, 50); |
||||
|
}, |
||||
|
shouldShowContent(index) { |
||||
|
return Math.abs(index - this.currentIndex) <= this.preloadBuffer; |
||||
|
}, |
||||
|
goBack() { |
||||
|
uni.navigateTo({ |
||||
|
url: '/taozi/home/home?targetIndex=7' |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.main-swiper { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
.page-container { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.bg-image { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
z-index: 1; |
||||
|
} |
||||
|
|
||||
|
.layer-img1 { |
||||
|
z-index: 2; |
||||
|
position: absolute; |
||||
|
bottom: 300rpx; |
||||
|
right: 60rpx; |
||||
|
width: 300rpx; |
||||
|
height: 300rpx; |
||||
|
} |
||||
|
|
||||
|
.layer-info { |
||||
|
width: 100%; |
||||
|
height: 280rpx; |
||||
|
z-index: 2; |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
} |
||||
|
|
||||
|
.layer-content { |
||||
|
position: absolute; |
||||
|
top: 36%; |
||||
|
left: 50%; |
||||
|
transform: translate(-50%, -50%); |
||||
|
z-index: 2; |
||||
|
|
||||
|
.item { |
||||
|
position: relative; |
||||
|
|
||||
|
.item-gif { |
||||
|
width: 600rpx; |
||||
|
height: 650rpx; |
||||
|
} |
||||
|
|
||||
|
.layer-item-txt { |
||||
|
position: absolute; |
||||
|
top: -50rpx; |
||||
|
left: 0; |
||||
|
font-size: 46rpx; |
||||
|
color: #e5007f; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.layer-item-tx2 { |
||||
|
position: absolute; |
||||
|
right: 0; |
||||
|
top: -40rpx; |
||||
|
font-size: 36rpx; |
||||
|
writing-mode: vertical-rl; |
||||
|
text-orientation: mixed; |
||||
|
color: #e5007f; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.layer2-content { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
display: flex; |
||||
|
justify-content: flex-end; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
z-index: 2; |
||||
|
|
||||
|
.item { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
width: calc(100% - 100rpx); |
||||
|
margin: 80rpx 0; |
||||
|
|
||||
|
.bottom-img { |
||||
|
width: 100%; |
||||
|
height: 190rpx; |
||||
|
margin-top: 50rpx; |
||||
|
} |
||||
|
|
||||
|
.bottom-tit { |
||||
|
width: 100%; |
||||
|
text-align: justify; |
||||
|
text-align-last: justify; |
||||
|
font-size: 100rpx; |
||||
|
display: inline-block; |
||||
|
} |
||||
|
|
||||
|
.bottom-tit2 { |
||||
|
width: 100%; |
||||
|
color: #e40080; |
||||
|
text-align: justify; |
||||
|
text-align-last: justify; |
||||
|
display: inline-block; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.back-btn { |
||||
|
position: absolute; |
||||
|
top: 50rpx; |
||||
|
left: 50rpx; |
||||
|
z-index: 2; |
||||
|
background-color: rgb(0 0 0 / 0.3); |
||||
|
border-radius: 50%; |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.back-icon { |
||||
|
width: 50rpx; |
||||
|
height: 50rpx; |
||||
|
} |
||||
|
|
||||
|
.rotate-bounce-in { |
||||
|
animation: rotateBounceIn 1.2s cubic-bezier(0.215, 0.610, 0.355, 1.000) forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes rotateBounceIn { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: rotate(-180deg) scale(0.3); |
||||
|
} |
||||
|
|
||||
|
40% { |
||||
|
opacity: 0.6; |
||||
|
transform: rotate(25deg) scale(0.9); |
||||
|
} |
||||
|
|
||||
|
60% { |
||||
|
opacity: 0.8; |
||||
|
transform: rotate(-15deg) scale(1.1); |
||||
|
} |
||||
|
|
||||
|
80% { |
||||
|
opacity: 0.9; |
||||
|
transform: rotate(5deg) scale(0.95); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: rotate(0deg) scale(1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.slide-in-from-right { |
||||
|
animation: slideInRight 1.2s ease-out forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes slideInRight { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: translateX(100px); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.fade-slide-up { |
||||
|
animation: fadeSlideUp 1s ease-out forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes fadeSlideUp { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: translateY(30px); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,297 @@ |
|||||
|
<template> |
||||
|
<view> |
||||
|
<TitleHeader /> |
||||
|
<swiper class="main-swiper" :vertical="true" :current="currentIndex" @change="handleSwiperChange" |
||||
|
:duration="300" :style="{ height: `calc(100vh - ${titleHeight}px)` }"> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[0]"> |
||||
|
<image v-show="shouldShowContent(0)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg1.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view v-show="shouldShowContent(0)" class="content-layer"> |
||||
|
<image class="layer-img" |
||||
|
:class="{'blur-to-clear': animationStates[0], 'hidden': !animationStates[0]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg1-infos.png" :lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
<image class="btn-img" @click="gotoPath('/subPackages/techan/detail?id=32')" |
||||
|
:class="{'blur-to-clear': animationStates[0], 'hidden': !animationStates[0]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/btn1.png" :lazy-load="true" mode="widthFix"> |
||||
|
</image> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[1]"> |
||||
|
<image v-show="shouldShowContent(1)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg2.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view v-show="shouldShowContent(1)" class="content-layer"> |
||||
|
<image class="layer-img" |
||||
|
:class="{'blur-to-clear': animationStates[1], 'hidden': !animationStates[1]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg2-infos.png" :lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
<image class="btn-img" style="right: 30rpx;top: 75vh;" @click="gotoPath('/subPackages/techan/detail?id=32')" |
||||
|
:class="{'blur-to-clear': animationStates[1], 'hidden': !animationStates[1]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/btn2.png" :lazy-load="true" mode="widthFix"> |
||||
|
</image> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[2]"> |
||||
|
<image v-show="shouldShowContent(2)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg3.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view v-show="shouldShowContent(2)" class="content-layer"> |
||||
|
<image class="layer-img" |
||||
|
:class="{'blur-to-clear': animationStates[2], 'hidden': !animationStates[2]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg3-infos.png" :lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
<image class="btn-img" style="right: 40vw;top: 65vh;" @click="gotoPath('/subPackages/techan/detail?id=32')" |
||||
|
:class="{'blur-to-clear': animationStates[1], 'hidden': !animationStates[1]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/btn3.png" :lazy-load="true" mode="widthFix"> |
||||
|
</image> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[3]"> |
||||
|
<image v-show="shouldShowContent(3)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg4.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view v-show="shouldShowContent(3)" class="content-layer2"> |
||||
|
<image class="layer-img2" |
||||
|
:class="{'slide-in-from-left': animationStates[3], 'hidden': !animationStates[3]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg4-info.png" :lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[4]"> |
||||
|
<image v-show="shouldShowContent(4)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg5.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[5]"> |
||||
|
<image v-show="shouldShowContent(5)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg6.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view v-show="shouldShowContent(5)" class="content-layer3"> |
||||
|
<image class="layer-img3" |
||||
|
:class="{'slide-in-from-left': animationStates[5], 'hidden': !animationStates[5]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter4/bg6-info.png" :lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
</view> |
||||
|
<view @click="goBack" class="back-btn" type="default"> |
||||
|
<image class="back-icon" src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import TitleHeader from '@/components/TitleHeader.vue'; |
||||
|
export default { |
||||
|
components: { |
||||
|
TitleHeader |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
currentIndex: 0, |
||||
|
loadedPages: { |
||||
|
0: false, |
||||
|
1: false, |
||||
|
2: false, |
||||
|
3: false, |
||||
|
4: false, |
||||
|
5: false |
||||
|
}, |
||||
|
animationStates: { |
||||
|
0: false, |
||||
|
1: false, |
||||
|
2: false, |
||||
|
3: false, |
||||
|
4: false, |
||||
|
5: false |
||||
|
}, |
||||
|
preloadBuffer: 1, |
||||
|
titleHeight: 0 |
||||
|
}; |
||||
|
}, |
||||
|
watch: { |
||||
|
currentIndex(newIndex) { |
||||
|
for (let i = Math.max(0, newIndex - this.preloadBuffer); i <= Math.min(9, newIndex + this |
||||
|
.preloadBuffer); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.titleHeight = uni.getStorageSync('titleHeight') |
||||
|
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 9); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[this.currentIndex] = true; |
||||
|
}, 50); |
||||
|
}, |
||||
|
methods: { |
||||
|
handleSwiperChange(e) { |
||||
|
const newIndex = e.detail.current; |
||||
|
this.currentIndex = newIndex; |
||||
|
this.animationStates[newIndex] = false; |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[newIndex] = true; |
||||
|
}, 50); |
||||
|
}, |
||||
|
shouldShowContent(index) { |
||||
|
return Math.abs(index - this.currentIndex) <= this.preloadBuffer; |
||||
|
}, |
||||
|
goBack() { |
||||
|
uni.navigateTo({ |
||||
|
url: '/taozi/home/home?targetIndex=7' |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.main-swiper { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
.page-container { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.content-layer { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
z-index: 2; |
||||
|
} |
||||
|
|
||||
|
.content-layer2 { |
||||
|
width: calc(100% - 100rpx); |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
z-index: 2; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: flex-end; |
||||
|
margin: 0 50rpx 400rpx; |
||||
|
} |
||||
|
|
||||
|
.content-layer3 { |
||||
|
width: calc(100% - 100rpx); |
||||
|
height: 100%; |
||||
|
z-index: 2; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.bg-image { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
z-index: 1; |
||||
|
} |
||||
|
|
||||
|
.layer-img { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
.layer-img2 { |
||||
|
width: 100%; |
||||
|
height: 350rpx; |
||||
|
} |
||||
|
|
||||
|
.layer-img3 { |
||||
|
width: 500rpx; |
||||
|
height: 300rpx; |
||||
|
} |
||||
|
|
||||
|
.back-btn { |
||||
|
position: absolute; |
||||
|
top: 50rpx; |
||||
|
left: 50rpx; |
||||
|
z-index: 2; |
||||
|
background-color: rgb(0 0 0 / 0.3); |
||||
|
border-radius: 50%; |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.back-icon { |
||||
|
width: 50rpx; |
||||
|
height: 50rpx; |
||||
|
} |
||||
|
|
||||
|
.blur-to-clear { |
||||
|
animation: blurToClear .8s ease-out forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes blurToClear { |
||||
|
0% { |
||||
|
filter: blur(10px); |
||||
|
opacity: 0.3; |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
filter: blur(0); |
||||
|
opacity: 1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.hidden { |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
.slide-in-from-left { |
||||
|
animation: slideInLeft 1.2s ease-out forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes slideInLeft { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: translateX(-100px); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.btn-img { |
||||
|
position: fixed; |
||||
|
top: 14vh; |
||||
|
right: 30rpx; |
||||
|
width: 20vw; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,786 @@ |
|||||
|
<template> |
||||
|
<view> |
||||
|
<TitleHeader /> |
||||
|
<swiper class="main-swiper" :vertical="true" :current="currentIndex" @change="handleSwiperChange" |
||||
|
:duration="300" :style="{ height: `calc(100vh - ${titleHeight}px)` }"> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[0]"> |
||||
|
<image v-show="shouldShowContent(0)" class="bg-image" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/foreword-bg1.gif" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<view v-show="shouldShowContent(0)" class="content-layer"> |
||||
|
<image class="layer-img" |
||||
|
:class="{'blur-to-clear': animationStates[0], 'hidden': !animationStates[0]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/foreword-bg1-text.png" |
||||
|
:lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
<view class="arrow-content"> |
||||
|
<image class="arrow-down" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/arrow-icon.png" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[1]"> |
||||
|
<image v-show="shouldShowContent(1)" class="bg-image" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/prologue1s.png" :lazy-load="true" |
||||
|
mode="aspectFill"></image> |
||||
|
<!-- <view v-show="shouldShowContent(1)" class="content-layer2"> |
||||
|
<image class="layer-icon" |
||||
|
:class="{'bounce-in': animationStates[1], 'hidden': !animationStates[1]}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/prologue1-icon.png" |
||||
|
:lazy-load="true" mode="aspectFill"> |
||||
|
</image> |
||||
|
</view> --> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[2]"> |
||||
|
<image v-show="shouldShowContent(2)" class="bg-image" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/foreword-bg2.gif" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<template v-if="loadedPages[3]"> |
||||
|
<view class="loadedPages-three"> |
||||
|
<view class="loadedPages-three-content"> |
||||
|
<view class="loadedPages-three-title"> |
||||
|
<view class="txt"> |
||||
|
DAYUN |
||||
|
</view> |
||||
|
<view class="txt"> |
||||
|
<text>IP Art</text> |
||||
|
<text>Exhibition</text> |
||||
|
</view> |
||||
|
<view class="txt"> |
||||
|
issue/01 |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="loadedPages-three-center"> |
||||
|
<view class="desc"> |
||||
|
<text>时间里</text> |
||||
|
<text>的</text> |
||||
|
<text>约定</text> |
||||
|
</view> |
||||
|
<view class="en-desc"> |
||||
|
<text>Agreements</text> |
||||
|
<text>Within</text> |
||||
|
<text>Time</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="loadedPages-three-bottom" |
||||
|
:class="{'fade-slide-up': animationStates[3], 'hidden': !animationStates[3]}"> |
||||
|
<image class="bottom-img" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/forewordThree_icon.png" |
||||
|
mode="aspectFill"></image> |
||||
|
<view class="bottom-tit"> |
||||
|
「三个桃子」IP美数展 |
||||
|
</view> |
||||
|
<view class="bottom-txt"> |
||||
|
Three Peaches IP Art Exhibition |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
</swiper-item> |
||||
|
<swiper-item v-for="index in [4, 5, 6, 7]" :key="index"> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[index]"> |
||||
|
<image v-show="shouldShowContent(index)" class="bg-image" |
||||
|
:src="`https://static.ticket.sz-trip.com/epicSoul/taozi/home/chapterCover${index-3}.png`" |
||||
|
:lazy-load="true" mode="aspectFill"></image> |
||||
|
<image @click="goChapter" class="chapterCover-btn" v-show="shouldShowContent(index)" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/toggle.png" :lazy-load="true" |
||||
|
mode="aspectFill"></image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
|
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[8]"> |
||||
|
<image v-show="shouldShowContent(8)" class="bg-image" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/footer.png" :lazy-load="true" |
||||
|
mode="aspectFill"></image> |
||||
|
<!-- <image class="qrcode-txt" v-show="shouldShowContent(8)" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/qrcode-txt.png" :lazy-load="true" |
||||
|
mode="aspectFill" :show-menu-by-longpress="true"></image> --> |
||||
|
<image class="qrcode-txt" v-show="shouldShowContent(8)" @click="gotoPath('/subPackages/techan/detail?id=32')" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/qrcode-btn.png" :lazy-load="true" |
||||
|
mode="widthFix" :show-menu-by-longpress="true"></image> |
||||
|
<!-- <image class="qrcode-txts" v-show="shouldShowContent(8)" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/home/qrcode-txtss.png" :lazy-load="true" |
||||
|
mode="widthFix"></image> --> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<template v-if="loadedPages[9]"> |
||||
|
<image v-show="shouldShowContent(9)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/footers.png" :lazy-load="true" mode="aspectFill"></image> |
||||
|
<image v-show="shouldShowContent(9)" class="qrCode-image" src="https://static.ticket.sz-trip.com/epicSoul/qrCode.png" |
||||
|
:lazy-load="true" mode="widthFix" :show-menu-by-longpress="true"></image> |
||||
|
</template> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<view class="page-container"> |
||||
|
<template v-if="loadedPages[10]"> |
||||
|
<messageBoard class="message-board" /> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
<view class="overlay" v-if="showMenu" @click="closeMenu"></view> |
||||
|
<view class="fixed-nav" :class="{'hidden': showMenu}" @click="showNavMenu"> |
||||
|
<image class="nav-icon" :class="{'rotated': iconRotated, 'bounce-back': iconBounceBack}" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/taozi/nav-icon.png" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
<view class="nav-menu" :class="{'show': showMenu}"> |
||||
|
<view class="nav-item" :class="{'item-active': isItemActive(item)}" v-for="item in menuItems" |
||||
|
:key="item.targetIndex" @click="() => jumpToPage(item.targetIndex)"> |
||||
|
<view v-if="item.text.includes('#Chapter')" class="chapter-text"> |
||||
|
<text class="chapter-title">#Chapter</text> |
||||
|
<text :class="{'active': isItemActive(item)}" class="chapter-number"> |
||||
|
{{ item.text.replace('#Chapter', '') }} |
||||
|
</text> |
||||
|
</view> |
||||
|
<text v-else :class="{'active': isItemActive(item)}">{{ item.text }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<!-- <BuyPeaches /> --> |
||||
|
<messagePop /> |
||||
|
<!-- <BackgroundMusic /> --> |
||||
|
<MusicControl /> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import BuyPeaches from '@/components/BuyPeaches.vue'; |
||||
|
import messagePop from '@/components/messagePop.vue'; |
||||
|
// import BackgroundMusic from '@/components/BackgroundMusic.vue'; |
||||
|
import messageBoard from '@/components/messageBoard.vue'; |
||||
|
import MusicControl from '@/components/MusicControl.vue'; |
||||
|
import TitleHeader from '@/components/TitleHeader.vue'; |
||||
|
|
||||
|
export default { |
||||
|
components: { |
||||
|
BuyPeaches, |
||||
|
messagePop, |
||||
|
// BackgroundMusic, |
||||
|
messageBoard, |
||||
|
MusicControl, |
||||
|
TitleHeader |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
currentIndex: 0, |
||||
|
loadedPages: { |
||||
|
0: false, |
||||
|
1: false, |
||||
|
2: false, |
||||
|
3: false, |
||||
|
4: false, |
||||
|
5: false, |
||||
|
6: false, |
||||
|
7: false, |
||||
|
8: false, |
||||
|
9: false, |
||||
|
10: false |
||||
|
}, |
||||
|
animationStates: { |
||||
|
0: false, |
||||
|
1: false, |
||||
|
2: false, |
||||
|
3: false, |
||||
|
4: false, |
||||
|
5: false, |
||||
|
6: false, |
||||
|
7: false, |
||||
|
8: false, |
||||
|
9: false |
||||
|
}, |
||||
|
preloadBuffer: 1, |
||||
|
isFirstSwipe: true, |
||||
|
showMenu: false, |
||||
|
iconRotated: false, |
||||
|
iconBounceBack: false, |
||||
|
menuItems: [{ |
||||
|
text: 'Intro序曲', |
||||
|
targetIndex: 0 |
||||
|
}, |
||||
|
{ |
||||
|
text: '#Chapter 壹', |
||||
|
targetIndex: 4 |
||||
|
}, |
||||
|
{ |
||||
|
text: '#Chapter 贰', |
||||
|
targetIndex: 5 |
||||
|
}, |
||||
|
{ |
||||
|
text: '#Chapter 叁', |
||||
|
targetIndex: 6 |
||||
|
}, |
||||
|
{ |
||||
|
text: '#Chapter 肆', |
||||
|
targetIndex: 7 |
||||
|
}, |
||||
|
{ |
||||
|
text: 'GuestBook', |
||||
|
targetIndex: 10 |
||||
|
} |
||||
|
], |
||||
|
chapterPaths: { |
||||
|
4: '/taozi/chapter1/chapter1', |
||||
|
5: '/taozi/chapter2/chapter2', |
||||
|
6: '/taozi/chapter3/chapter3', |
||||
|
7: '/taozi/chapter4/chapter4' |
||||
|
}, |
||||
|
titleHeight: 0 |
||||
|
}; |
||||
|
}, |
||||
|
computed: { |
||||
|
shouldShowContent() { |
||||
|
return (index) => { |
||||
|
return Math.abs(index - this.currentIndex) <= this.preloadBuffer; |
||||
|
}; |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
currentIndex(newIndex) { |
||||
|
for (let i = Math.max(0, newIndex - this.preloadBuffer); i <= Math.min(10, newIndex + this |
||||
|
.preloadBuffer); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
handleSwiperChange(e) { |
||||
|
const newIndex = e.detail.current; |
||||
|
this.currentIndex = newIndex; |
||||
|
this.animationStates[newIndex] = false; |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[newIndex] = true; |
||||
|
}, 50); |
||||
|
return; |
||||
|
if (this.isFirstSwipe && newIndex > 0) { |
||||
|
this.isFirstSwipe = false; |
||||
|
uni.$emit('playBackgroundMusic'); |
||||
|
} |
||||
|
}, |
||||
|
goChapter() { |
||||
|
const path = this.chapterPaths[this.currentIndex]; |
||||
|
uni.navigateTo({ |
||||
|
url: path |
||||
|
}); |
||||
|
}, |
||||
|
showNavMenu() { |
||||
|
this.iconRotated = true; |
||||
|
setTimeout(() => { |
||||
|
this.showMenu = true; |
||||
|
}, 300); |
||||
|
}, |
||||
|
closeMenu() { |
||||
|
this.showMenu = false; |
||||
|
setTimeout(() => { |
||||
|
this.iconBounceBack = true; |
||||
|
this.iconRotated = false; |
||||
|
setTimeout(() => { |
||||
|
this.iconBounceBack = false; |
||||
|
}, 500); |
||||
|
}, 300); |
||||
|
}, |
||||
|
jumpToPage(idx) { |
||||
|
const targetIndex = idx; |
||||
|
this.currentIndex = targetIndex; |
||||
|
this.closeMenu(); |
||||
|
this.animationStates[targetIndex] = false; |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[targetIndex] = true; |
||||
|
}, 50); |
||||
|
}, |
||||
|
isItemActive(item) { |
||||
|
return this.currentIndex === item.targetIndex; |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.titleHeight = uni.getStorageSync('titleHeight') |
||||
|
console.log(this.titleHeight) |
||||
|
const app = getApp(); |
||||
|
app.updateMusicSrc('https://static.ticket.sz-trip.com/epicSoul/taozi/bg.m4a'); |
||||
|
app.initBackgroundMusic(); // 初始化背景音乐 |
||||
|
uni.$bgMusic.play(); // 播放音乐 |
||||
|
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 6); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 10); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[this.currentIndex] = true; |
||||
|
}, 50); |
||||
|
}, |
||||
|
onUnload() { |
||||
|
uni.$bgMusic.pause(); // 停止音乐 |
||||
|
}, |
||||
|
onLoad(options) { |
||||
|
if (options && options.targetIndex) { |
||||
|
const targetIndex = parseInt(options.targetIndex); |
||||
|
this.currentIndex = targetIndex; |
||||
|
for (let i = Math.max(0, targetIndex - this.preloadBuffer); i <= Math.min(10, targetIndex + this |
||||
|
.preloadBuffer); i++) { |
||||
|
this.loadedPages[i] = true; |
||||
|
} |
||||
|
this.animationStates[targetIndex] = false; |
||||
|
setTimeout(() => { |
||||
|
this.animationStates[targetIndex] = true; |
||||
|
}, 50); |
||||
|
} |
||||
|
}, |
||||
|
// #ifdef MP-WEIXIN |
||||
|
onShareAppMessage() { |
||||
|
return { |
||||
|
title: '三个桃子·时间里的约定|「Epic Soul」阅读体 issue01', |
||||
|
mpId: 'wx8954209bb3ad489e', |
||||
|
path: '/taozi/home/home', |
||||
|
imageUrl: 'https://static.ticket.sz-trip.com/epicSoul/taozi/home/taoziShare.png' |
||||
|
}; |
||||
|
}, |
||||
|
onShareTimeline() { |
||||
|
return { |
||||
|
title: '三个桃子·时间里的约定|「Epic Soul」阅读体 issue01', |
||||
|
query: '', |
||||
|
imageUrl: 'https://static.ticket.sz-trip.com/epicSoul/taozi/home/taoziShare.png' |
||||
|
}; |
||||
|
} |
||||
|
// #endif |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
@font-face { |
||||
|
font-family: 'SourceHanSerif-Regular'; |
||||
|
src: url(/static/fonts/SourceHanSerifSC-Regular.otf); |
||||
|
} |
||||
|
|
||||
|
.main-swiper { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
.page-container { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.loadedPages-three { |
||||
|
height: 100%; |
||||
|
position: relative; |
||||
|
background: #fff; |
||||
|
} |
||||
|
|
||||
|
.loadedPages-three-content { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
flex-direction: column; |
||||
|
justify-content: space-between; |
||||
|
height: 100%; |
||||
|
|
||||
|
.loadedPages-three-title { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
width: 100%; |
||||
|
margin-top: 30rpx; |
||||
|
|
||||
|
.txt { |
||||
|
font-size: 24rpx; |
||||
|
color: #333; |
||||
|
font-family: SourceHanSerif-Regular; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
|
||||
|
text { |
||||
|
display: block; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.txt:first-child { |
||||
|
margin-left: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.txt:last-child { |
||||
|
margin-right: 30rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.loadedPages-three-center { |
||||
|
position: relative; |
||||
|
|
||||
|
.desc { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
font-family: SourceHanSerif-Regular; |
||||
|
font-size: 90rpx; |
||||
|
color: #ec4899; |
||||
|
|
||||
|
text { |
||||
|
display: block; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.en-desc { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
position: absolute; |
||||
|
top: 50%; |
||||
|
right: 0; |
||||
|
transform: translate(-25%, -50%); |
||||
|
font-size: 24rpx; |
||||
|
font-style: italic; |
||||
|
color: #4b5563; |
||||
|
|
||||
|
text { |
||||
|
display: block; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.loadedPages-three-bottom { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
margin-bottom: 30rpx; |
||||
|
|
||||
|
.bottom-img { |
||||
|
width: 400rpx; |
||||
|
height: 120rpx; |
||||
|
} |
||||
|
|
||||
|
.bottom-tit { |
||||
|
font-size: 38rpx; |
||||
|
} |
||||
|
|
||||
|
.bottom-txt { |
||||
|
font-size: 24rpx; |
||||
|
font-style: italic; |
||||
|
color: #4b5563; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.bg-image { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
z-index: 1; |
||||
|
} |
||||
|
|
||||
|
.content-layer { |
||||
|
position: relative; |
||||
|
z-index: 2; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
.content-layer2 { |
||||
|
z-index: 2; |
||||
|
position: absolute; |
||||
|
bottom: 5%; |
||||
|
right: 5%; |
||||
|
} |
||||
|
|
||||
|
.layer-img { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
.arrow-content { |
||||
|
width: 100%; |
||||
|
position: absolute; |
||||
|
bottom: 5%; |
||||
|
left: 50%; |
||||
|
transform: translate(-50%, 0); |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.arrow-down { |
||||
|
width: 100rpx; |
||||
|
height: 40rpx; |
||||
|
animation: bounce 1.5s infinite; |
||||
|
} |
||||
|
|
||||
|
.layer-icon { |
||||
|
width: 100rpx; |
||||
|
height: 100rpx; |
||||
|
animation: bounce 1.5s infinite; |
||||
|
} |
||||
|
|
||||
|
.overlay { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(0, 0, 0, 0.3); |
||||
|
z-index: 10; |
||||
|
} |
||||
|
|
||||
|
.fixed-nav { |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
background-color: rgb(0 0 0 / 0.7); |
||||
|
border-radius: 10rpx 0 0 10rpx; |
||||
|
position: fixed; |
||||
|
right: 0; |
||||
|
top: 0; |
||||
|
bottom: 0; |
||||
|
margin: auto 0; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
z-index: 9; |
||||
|
transition: transform 0.3s ease, opacity 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.fixed-nav.hidden { |
||||
|
transform: translateX(100%); |
||||
|
opacity: 0; |
||||
|
pointer-events: none; |
||||
|
} |
||||
|
|
||||
|
.nav-icon { |
||||
|
width: 35rpx; |
||||
|
height: 35rpx; |
||||
|
transition: transform 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.nav-icon.rotated { |
||||
|
transform: rotate(180deg); |
||||
|
} |
||||
|
|
||||
|
.nav-icon.bounce-back { |
||||
|
animation: bounceRotation 0.5s ease; |
||||
|
} |
||||
|
|
||||
|
@keyframes bounceRotation { |
||||
|
0% { |
||||
|
transform: rotate(180deg); |
||||
|
} |
||||
|
|
||||
|
50% { |
||||
|
transform: rotate(-20deg); |
||||
|
} |
||||
|
|
||||
|
75% { |
||||
|
transform: rotate(10deg); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
transform: rotate(0deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.nav-menu { |
||||
|
position: fixed; |
||||
|
top: 50%; |
||||
|
right: 0; |
||||
|
transform: translate(100%, -50%); |
||||
|
z-index: 11; |
||||
|
background-color: rgb(0 0 0 / 0.5); |
||||
|
border-radius: 16rpx 0 0 16rpx; |
||||
|
box-shadow: -4px 0 15px rgba(0, 0, 0, 0.1); |
||||
|
transition: transform 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.nav-menu.show { |
||||
|
transform: translate(0, -50%); |
||||
|
} |
||||
|
|
||||
|
.nav-item { |
||||
|
padding: 20rpx; |
||||
|
text-align: center; |
||||
|
|
||||
|
text { |
||||
|
color: #fff; |
||||
|
opacity: 0.7; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.item-active { |
||||
|
background-color: rgba(0, 0, 0, 0.718); |
||||
|
} |
||||
|
|
||||
|
.nav-item .active { |
||||
|
color: #fff; |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
.chapter-text { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
line-height: 1.3; |
||||
|
} |
||||
|
|
||||
|
.chapter-title { |
||||
|
color: #fff; |
||||
|
opacity: 0.7; |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
|
||||
|
.chapter-number { |
||||
|
color: #fff; |
||||
|
opacity: 0.7; |
||||
|
font-size: 28rpx; |
||||
|
margin-top: 8rpx; |
||||
|
} |
||||
|
|
||||
|
.item-active .chapter-title, |
||||
|
.item-active .chapter-number.active { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
@keyframes bounce { |
||||
|
|
||||
|
0%, |
||||
|
20%, |
||||
|
50%, |
||||
|
80%, |
||||
|
100% { |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
|
||||
|
40% { |
||||
|
transform: translateY(-20rpx); |
||||
|
} |
||||
|
|
||||
|
60% { |
||||
|
transform: translateY(-10rpx); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.blur-to-clear { |
||||
|
animation: blurToClear 1.5s ease-out forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes blurToClear { |
||||
|
0% { |
||||
|
filter: blur(10px); |
||||
|
opacity: 0.3; |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
filter: blur(0); |
||||
|
opacity: 1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.hidden { |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
.bounce-in { |
||||
|
animation: bounceIn 1s ease forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes bounceIn { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: scale(0.3) translateY(100px); |
||||
|
} |
||||
|
|
||||
|
50% { |
||||
|
opacity: 1; |
||||
|
transform: scale(1.05) translateY(-10px); |
||||
|
} |
||||
|
|
||||
|
70% { |
||||
|
transform: scale(0.9) translateY(5px); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: scale(1) translateY(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.fade-slide-up { |
||||
|
animation: fadeSlideUp 1s ease-out forwards; |
||||
|
} |
||||
|
|
||||
|
@keyframes fadeSlideUp { |
||||
|
0% { |
||||
|
opacity: 0; |
||||
|
transform: translateY(30px); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 1; |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.chapterCover-btn { |
||||
|
position: absolute; |
||||
|
left: 50%; |
||||
|
bottom: 10%; |
||||
|
transform: translate(-50%, -50%); |
||||
|
width: 300rpx; |
||||
|
height: 100rpx; |
||||
|
z-index: 2; |
||||
|
} |
||||
|
|
||||
|
.qrcode-txt { |
||||
|
width: 30vw; |
||||
|
z-index: 2; |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
margin: 100rpx auto 0; |
||||
|
} |
||||
|
.qrcode-txts { |
||||
|
width: 28vw; |
||||
|
z-index: 2; |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
margin: 335rpx auto 0; |
||||
|
} |
||||
|
|
||||
|
.message-board { |
||||
|
width: 100%; |
||||
|
} |
||||
|
|
||||
|
.qrCode-image { |
||||
|
position: absolute; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 192rpx; |
||||
|
margin: 0 auto; |
||||
|
z-index: 2; |
||||
|
width: 30vw; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,108 @@ |
|||||
|
let instance = null; |
||||
|
|
||||
|
class AudioManager { |
||||
|
constructor() { |
||||
|
if (instance) { |
||||
|
return instance; |
||||
|
} |
||||
|
|
||||
|
this.audioContext = null; |
||||
|
this.isPlaying = false; |
||||
|
this.userDisabled = false; |
||||
|
this.initialized = false; |
||||
|
|
||||
|
try { |
||||
|
const musicState = uni.getStorageSync('musicState') || {}; |
||||
|
this.userDisabled = musicState.userDisabled === true; |
||||
|
} catch (e) { |
||||
|
console.error('读取音乐状态失败:', e); |
||||
|
} |
||||
|
|
||||
|
instance = this; |
||||
|
} |
||||
|
|
||||
|
init() { |
||||
|
if (this.initialized) return this; |
||||
|
|
||||
|
this.audioContext = uni.createInnerAudioContext(); |
||||
|
this.audioContext.src = 'https://static.ticket.sz-trip.com/epicSoul/taozi/bg.m4a'; |
||||
|
this.audioContext.loop = true; |
||||
|
|
||||
|
this.audioContext.onPlay(() => { |
||||
|
this.isPlaying = true; |
||||
|
this._notifyStateChange(); |
||||
|
}); |
||||
|
|
||||
|
this.audioContext.onPause(() => { |
||||
|
this.isPlaying = false; |
||||
|
this._notifyStateChange(); |
||||
|
}); |
||||
|
|
||||
|
this.audioContext.onStop(() => { |
||||
|
this.isPlaying = false; |
||||
|
this._notifyStateChange(); |
||||
|
}); |
||||
|
|
||||
|
this.audioContext.onError((res) => { |
||||
|
this.isPlaying = false; |
||||
|
this._notifyStateChange(); |
||||
|
}); |
||||
|
|
||||
|
this.initialized = true; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
play() { |
||||
|
if (this.userDisabled) return; |
||||
|
|
||||
|
this.init(); |
||||
|
if (!this.isPlaying) { |
||||
|
this.audioContext.play(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
pause() { |
||||
|
if (!this.initialized || !this.isPlaying) return; |
||||
|
|
||||
|
this.audioContext.pause(); |
||||
|
} |
||||
|
|
||||
|
togglePlay() { |
||||
|
this.init(); |
||||
|
|
||||
|
if (this.isPlaying) { |
||||
|
this.pause(); |
||||
|
this.userDisabled = true; |
||||
|
} else { |
||||
|
this.userDisabled = false; |
||||
|
this.play(); |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
uni.setStorageSync('musicState', { |
||||
|
userDisabled: this.userDisabled |
||||
|
}); |
||||
|
} catch (e) { |
||||
|
console.error('保存音乐状态失败:', e); |
||||
|
} |
||||
|
|
||||
|
return this.isPlaying; |
||||
|
} |
||||
|
|
||||
|
_notifyStateChange() { |
||||
|
uni.$emit('audioStateChanged', { |
||||
|
isPlaying: this.isPlaying, |
||||
|
userDisabled: this.userDisabled |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
getPlayingStatus() { |
||||
|
return this.isPlaying; |
||||
|
} |
||||
|
|
||||
|
getUserDisabled() { |
||||
|
return this.userDisabled; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default new AudioManager(); |
@ -1,202 +1,276 @@ |
|||||
<template> |
<template> |
||||
<view> |
<view> |
||||
|
|
||||
|
|
||||
<swiper class="main-swiper" :current="currentIndex" @change="handleSwiperChange" :duration="300"> |
<swiper class="main-swiper" :current="currentIndex" @change="handleSwiperChange" :duration="300"> |
||||
<!-- 主swiper的第一个item --> |
<!-- 主swiper的第一个item --> |
||||
<swiper-item> |
<swiper-item> |
||||
<view class="page-container home-page"> |
<view class="page-container home-page"> |
||||
<template v-if="loadedPages[0]"> |
<view class="arrow-down"> |
||||
<image v-show="shouldShowContent(0)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/images/chapter2/cover2.png" mode="" :lazy-load="true"></image> |
<image src="https://static.ticket.sz-trip.com/epicSoul/image/chapter3/rightIcon.png" |
||||
</template> |
:lazy-load="true" mode="widthFix"> |
||||
</view> |
</image> |
||||
</swiper-item> |
</view> |
||||
|
<template v-if="loadedPages[0]"> |
||||
<!-- 主swiper的第二个item --> |
<image v-show="shouldShowContent(0)" class="bg-image" |
||||
<swiper-item> |
src="https://static.ticket.sz-trip.com/epicSoul/image/chapter2/cover2s.png" mode="" |
||||
<view class="page-container home-page"> |
:lazy-load="true"></image> |
||||
<template v-if="loadedPages[1]"> |
</template> |
||||
<image v-show="shouldShowContent(1)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/images/chapter2/cover3.png" mode="" :lazy-load="true"></image> |
</view> |
||||
</template> |
</swiper-item> |
||||
</view> |
|
||||
</swiper-item> |
<!-- 主swiper的第二个item --> |
||||
|
<swiper-item> |
||||
<!-- 主swiper的第三个item --> |
<view class="page-container home-page"> |
||||
<swiper-item> |
<view class="arrow-down"> |
||||
<view class="page-container home-page"> |
<image src="https://static.ticket.sz-trip.com/epicSoul/image/chapter3/rightIcon.png" |
||||
<template v-if="loadedPages[2]"> |
:lazy-load="true" mode="widthFix"> |
||||
<image v-show="shouldShowContent(2)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/images/chapter2/cover4.png" mode="" :lazy-load="true"></image> |
</image> |
||||
</template> |
</view> |
||||
</view> |
<template v-if="loadedPages[1]"> |
||||
</swiper-item> |
<image v-show="shouldShowContent(1)" class="bg-image" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/image/chapter2/cover3s.png" mode="" |
||||
<!-- 主swiper的第四个item(包含嵌套swiper) --> |
:lazy-load="true"></image> |
||||
<swiper-item> |
</template> |
||||
<!-- 当主swiper的第四个item被加载时才加载嵌套swiper --> |
</view> |
||||
<template v-if="loadedPages[3]"> |
</swiper-item> |
||||
<swiper v-show="shouldShowContent(3)" class="nested-swiper" :vertical="true" :duration="300" @change="handleVerticalChange" :current="verticalIndex"> |
|
||||
<!-- 嵌套swiper的第一个item --> |
<!-- 主swiper的第三个item --> |
||||
<swiper-item> |
<swiper-item> |
||||
<view class="page-container home-page"> |
<view class="page-container home-page"> |
||||
<template v-if="loadedNestedPages[0]"> |
<view class="arrow-down"> |
||||
<image v-show="shouldShowNestedContent(0)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/images/chapter2/cover5.png" mode="" :lazy-load="true"></image> |
<image src="https://static.ticket.sz-trip.com/epicSoul/image/chapter3/rightIcon.png" |
||||
</template> |
:lazy-load="true" mode="widthFix"> |
||||
</view> |
</image> |
||||
</swiper-item> |
</view> |
||||
|
<template v-if="loadedPages[2]"> |
||||
<!-- 嵌套swiper的第二个item --> |
<image v-show="shouldShowContent(2)" class="bg-image" |
||||
<swiper-item> |
src="https://static.ticket.sz-trip.com/epicSoul/image/chapter2/cover4s.png" mode="" |
||||
<view class="page-container home-page"> |
:lazy-load="true"></image> |
||||
<template v-if="loadedNestedPages[1]"> |
</template> |
||||
<image v-show="shouldShowNestedContent(1)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/images/chapter2/cover6.png" mode="" :lazy-load="true"></image> |
</view> |
||||
</template> |
</swiper-item> |
||||
</view> |
|
||||
</swiper-item> |
<!-- 主swiper的第四个item(包含嵌套swiper) --> |
||||
|
<swiper-item> |
||||
<!-- 嵌套swiper的第三个item --> |
<!-- 当主swiper的第四个item被加载时才加载嵌套swiper --> |
||||
<swiper-item> |
<template v-if="loadedPages[3]"> |
||||
<view class="page-container home-page"> |
<swiper v-show="shouldShowContent(3)" class="nested-swiper" :vertical="true" :duration="300" |
||||
<template v-if="loadedNestedPages[2]"> |
@change="handleVerticalChange" :current="verticalIndex"> |
||||
<image v-show="shouldShowNestedContent(2)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/images/chapter2/cover7.png" mode="" :lazy-load="true"></image> |
<!-- 嵌套swiper的第一个item --> |
||||
<image v-show="shouldShowNestedContent(2)" @click="goback" class="btn" src="https://static.ticket.sz-trip.com/epicSoul/seek-btn.png" mode="" :lazy-load="true"></image> |
<swiper-item> |
||||
</template> |
<view class="page-container home-page"> |
||||
</view> |
<template v-if="loadedNestedPages[0]"> |
||||
</swiper-item> |
<image v-show="shouldShowNestedContent(0)" class="bg-image" |
||||
</swiper> |
src="https://static.ticket.sz-trip.com/epicSoul/image/chapter2/cover5s.png" |
||||
</template> |
mode="" :lazy-load="true"></image> |
||||
</swiper-item> |
</template> |
||||
</swiper> |
</view> |
||||
<MusicControl /> |
</swiper-item> |
||||
</view> |
|
||||
|
<!-- 嵌套swiper的第二个item --> |
||||
|
<swiper-item> |
||||
|
<view class="page-container home-page"> |
||||
|
<template v-if="loadedNestedPages[1]"> |
||||
|
<image v-show="shouldShowNestedContent(1)" class="bg-image" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/image/chapter2/cover6s.png" |
||||
|
mode="" :lazy-load="true"></image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
|
||||
|
<!-- 嵌套swiper的第三个item --> |
||||
|
<swiper-item> |
||||
|
<view class="page-container home-page"> |
||||
|
<template v-if="loadedNestedPages[2]"> |
||||
|
<image v-show="shouldShowNestedContent(2)" class="bg-image" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/image/chapter2/cover7.png" |
||||
|
mode="" :lazy-load="true"></image> |
||||
|
<image v-show="shouldShowNestedContent(2)" @click="goback" class="btn" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/seek-btn.png" mode="" |
||||
|
:lazy-load="true"></image> |
||||
|
</template> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
</template> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
<MusicControl /> |
||||
|
</view> |
||||
</template> |
</template> |
||||
|
|
||||
<script> |
<script> |
||||
export default { |
import MusicControl from '@/components/MusicControl.vue'; |
||||
data() { |
export default { |
||||
return { |
components: { |
||||
currentIndex: 0, |
MusicControl |
||||
verticalIndex: 0, |
}, |
||||
// 记录主swiper哪些页面已经加载过 |
data() { |
||||
loadedPages: { |
return { |
||||
0: false, |
currentIndex: 0, |
||||
1: false, |
verticalIndex: 0, |
||||
2: false, |
// 记录主swiper哪些页面已经加载过 |
||||
3: false |
loadedPages: { |
||||
}, |
0: false, |
||||
// 记录嵌套swiper哪些页面已经加载过 |
1: false, |
||||
loadedNestedPages: { |
2: false, |
||||
0: false, |
3: false |
||||
1: false, |
}, |
||||
2: false |
// 记录嵌套swiper哪些页面已经加载过 |
||||
}, |
loadedNestedPages: { |
||||
// 预加载缓冲区大小 |
0: false, |
||||
preloadBuffer: 1, |
1: false, |
||||
nestedPreloadBuffer: 1 |
2: false |
||||
} |
}, |
||||
}, |
// 预加载缓冲区大小 |
||||
computed: { |
preloadBuffer: 1, |
||||
// 决定是否应该显示主swiper特定页面的内容 |
nestedPreloadBuffer: 1 |
||||
shouldShowContent() { |
} |
||||
return (index) => { |
}, |
||||
return Math.abs(index - this.currentIndex) <= this.preloadBuffer; |
computed: { |
||||
} |
// 决定是否应该显示主swiper特定页面的内容 |
||||
}, |
shouldShowContent() { |
||||
// 决定是否应该显示嵌套swiper特定页面的内容 |
return (index) => { |
||||
shouldShowNestedContent() { |
return Math.abs(index - this.currentIndex) <= this.preloadBuffer; |
||||
return (index) => { |
} |
||||
return Math.abs(index - this.verticalIndex) <= this.nestedPreloadBuffer; |
}, |
||||
} |
// 决定是否应该显示嵌套swiper特定页面的内容 |
||||
} |
shouldShowNestedContent() { |
||||
}, |
return (index) => { |
||||
watch: { |
return Math.abs(index - this.verticalIndex) <= this.nestedPreloadBuffer; |
||||
// 监听主swiper currentIndex变化,更新已加载页面状态 |
} |
||||
currentIndex(newIndex) { |
} |
||||
// 标记当前页面和前后buffer页为已加载 |
}, |
||||
for (let i = Math.max(0, newIndex - this.preloadBuffer); i <= Math.min(3, newIndex + this.preloadBuffer); i++) { |
watch: { |
||||
this.loadedPages[i] = true; |
// 监听主swiper currentIndex变化,更新已加载页面状态 |
||||
} |
currentIndex(newIndex) { |
||||
|
// 标记当前页面和前后buffer页为已加载 |
||||
// 当切换到第4个item时,初始化嵌套swiper的加载状态 |
for (let i = Math.max(0, newIndex - this.preloadBuffer); i <= Math.min(3, newIndex + this |
||||
if (newIndex === 3) { |
.preloadBuffer); i++) { |
||||
this.loadedNestedPages[0] = true; |
this.loadedPages[i] = true; |
||||
if (this.nestedPreloadBuffer >= 1) { |
} |
||||
this.loadedNestedPages[1] = true; |
|
||||
} |
// 当切换到第4个item时,初始化嵌套swiper的加载状态 |
||||
} |
if (newIndex === 3) { |
||||
}, |
this.loadedNestedPages[0] = true; |
||||
// 监听嵌套swiper verticalIndex变化,更新已加载页面状态 |
if (this.nestedPreloadBuffer >= 1) { |
||||
verticalIndex(newIndex) { |
this.loadedNestedPages[1] = true; |
||||
// 只有当主swiper在第4个item时才更新嵌套swiper状态 |
} |
||||
if (this.currentIndex === 3) { |
} |
||||
// 标记当前页面和前后buffer页为已加载 |
}, |
||||
for (let i = Math.max(0, newIndex - this.nestedPreloadBuffer); i <= Math.min(2, newIndex + this.nestedPreloadBuffer); i++) { |
// 监听嵌套swiper verticalIndex变化,更新已加载页面状态 |
||||
this.loadedNestedPages[i] = true; |
verticalIndex(newIndex) { |
||||
} |
// 只有当主swiper在第4个item时才更新嵌套swiper状态 |
||||
} |
if (this.currentIndex === 3) { |
||||
} |
// 标记当前页面和前后buffer页为已加载 |
||||
}, |
for (let i = Math.max(0, newIndex - this.nestedPreloadBuffer); i <= Math.min(2, newIndex + this |
||||
methods: { |
.nestedPreloadBuffer); i++) { |
||||
handleSwiperChange(e) { |
this.loadedNestedPages[i] = true; |
||||
this.currentIndex = e.detail.current; |
} |
||||
}, |
} |
||||
handleVerticalChange(e) { |
} |
||||
this.verticalIndex = e.detail.current; |
}, |
||||
}, |
methods: { |
||||
goback() { |
handleSwiperChange(e) { |
||||
const app = getApp(); |
this.currentIndex = e.detail.current; |
||||
app.globalData.mainSliderIndex = 4; |
}, |
||||
uni.navigateTo({ |
handleVerticalChange(e) { |
||||
url: '/xxdf/home/home' |
this.verticalIndex = e.detail.current; |
||||
}); |
}, |
||||
} |
goback() { |
||||
}, |
const app = getApp(); |
||||
mounted() { |
app.globalData.mainSliderIndex = 4; |
||||
// 初始化主swiper,标记第一页和相邻页为已加载 |
uni.navigateTo({ |
||||
this.currentIndex = 0; |
url: '/xxdf/home/home' |
||||
for (let i = 0; i <= Math.min(this.preloadBuffer, 3); i++) { |
}); |
||||
this.loadedPages[i] = true; |
} |
||||
} |
}, |
||||
|
mounted() { |
||||
// 初始化嵌套swiper的第一页为已加载(以防万一) |
// 初始化主swiper,标记第一页和相邻页为已加载 |
||||
this.verticalIndex = 0; |
this.currentIndex = 0; |
||||
this.loadedNestedPages[0] = true; |
for (let i = 0; i <= Math.min(this.preloadBuffer, 3); i++) { |
||||
} |
this.loadedPages[i] = true; |
||||
} |
} |
||||
|
|
||||
|
// 初始化嵌套swiper的第一页为已加载(以防万一) |
||||
|
this.verticalIndex = 0; |
||||
|
this.loadedNestedPages[0] = true; |
||||
|
} |
||||
|
} |
||||
</script> |
</script> |
||||
|
|
||||
<style scoped> |
<style scoped> |
||||
.main-swiper { |
.main-swiper { |
||||
width: 100%; |
width: 100%; |
||||
height: 100vh; |
height: 100vh; |
||||
} |
} |
||||
.nested-swiper { |
|
||||
width: 100%; |
.nested-swiper { |
||||
height: 100vh; |
width: 100%; |
||||
} |
height: 100vh; |
||||
.page-container { |
} |
||||
height: 100vh; |
|
||||
} |
.page-container { |
||||
|
height: 100vh; |
||||
.home-page { |
} |
||||
position: relative; |
|
||||
overflow: hidden; |
.home-page { |
||||
} |
position: relative; |
||||
|
overflow: hidden; |
||||
.bg-image { |
} |
||||
position: absolute; |
|
||||
top: 0; |
.bg-image { |
||||
left: 0; |
position: absolute; |
||||
width: 100%; |
top: 0; |
||||
height: 100%; |
left: 0; |
||||
z-index: 1; |
width: 100%; |
||||
} |
height: 100%; |
||||
.btn { |
z-index: 1; |
||||
position: absolute; |
} |
||||
left: 50%; |
|
||||
bottom: 12%; |
.btn { |
||||
transform: translate(-50%, -50%); |
position: absolute; |
||||
z-index: 2; |
left: 50%; |
||||
width: 250rpx; |
bottom: 12%; |
||||
height: 60rpx; |
transform: translate(-50%, -50%); |
||||
} |
z-index: 2; |
||||
|
width: 250rpx; |
||||
|
height: 60rpx; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.arrow-down { |
||||
|
width: fit-content; |
||||
|
height: fit-content; |
||||
|
position: absolute; |
||||
|
animation: bounce 1.5s infinite; |
||||
|
top: 35vh; |
||||
|
bottom: 0; |
||||
|
left: 20rpx; |
||||
|
margin: auto; |
||||
|
z-index: 100; |
||||
|
} |
||||
|
|
||||
|
.arrow-down image { |
||||
|
display: block; |
||||
|
width: 50rpx; |
||||
|
transform: rotate(180deg); |
||||
|
} |
||||
|
|
||||
|
@keyframes bounce { |
||||
|
|
||||
|
0%, |
||||
|
100% { |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
|
||||
|
25% { |
||||
|
transform: translateX(-3px); |
||||
|
} |
||||
|
|
||||
|
75% { |
||||
|
transform: translateX(3px); |
||||
|
} |
||||
|
} |
||||
</style> |
</style> |
@ -1,274 +1,360 @@ |
|||||
<template> |
<template> |
||||
<view> |
<view style="position: relative;"> |
||||
|
<swiper class="main-swiper" :vertical="true" :current="currentIndex" @change="handleSwiperChange" |
||||
|
:duration="300"> |
||||
<swiper class="main-swiper" :vertical="true" :current="currentIndex" @change="handleSwiperChange" :duration="300"> |
<swiper-item v-for="(_, outerIndex) in 7" :key="outerIndex"> |
||||
<swiper-item v-for="(_, outerIndex) in 7" :key="outerIndex"> |
<swiper class="nested-swiper" :duration="300" @change="handleVerticalChange($event, outerIndex)" |
||||
<swiper class="nested-swiper" :duration="300" @change="handleVerticalChange" :current="nestedIndices[outerIndex]"> |
:current="nestedIndices[outerIndex]"> |
||||
<!-- 嵌套swiper的第一个item(封面页) --> |
<!-- 嵌套swiper的第一个item(封面页) --> |
||||
<swiper-item> |
<swiper-item> |
||||
<view class="page-container home-page"> |
<view class="arrow-down" v-if="nestedIndices[outerIndex] == 0"> |
||||
<image class="bg-image" :src="'https://static.ticket.sz-trip.com/epicSoul/images/chapter3/cover' + (outerIndex+2) + '.png'" mode="" :lazy-load="true"></image> |
<image src="https://static.ticket.sz-trip.com/epicSoul/image/chapter3/rightIcon.png" :lazy-load="true" mode="widthFix"> |
||||
<image class="cover-txt" :class="{'cover-txt2': outerIndex > 0}" :src="'https://static.ticket.sz-trip.com/epicSoul/images/chapter3/cover' + (outerIndex+2) + '-txt.png'" mode="" :lazy-load="true"></image> |
</image> |
||||
<image class="btn" src="https://static.ticket.sz-trip.com/epicSoul/seek2-btn.png" mode="" :lazy-load="true"></image> |
</view> |
||||
</view> |
<view class="page-container home-page"> |
||||
</swiper-item> |
<image class="bg-image" |
||||
<!-- 嵌套swiper的第二个item--> |
:src="'https://static.ticket.sz-trip.com/epicSoul/image/chapter3/cover' + (outerIndex+2) + '.png'" |
||||
<swiper-item> |
mode="" :lazy-load="true"></image> |
||||
<view class="page-container home-page"> |
<image class="cover-txt" :class="{'cover-txt2': outerIndex > 0}" |
||||
<view class="gif-container"> |
:src="'https://static.ticket.sz-trip.com/epicSoul/image/chapter3/cover' + (outerIndex+2) + '-txt.png'" |
||||
<image v-if="shouldLoadContent(outerIndex)" class="gif-style" :src="'https://static.ticket.sz-trip.com/epicSoul/3-' + (outerIndex+1) + '-2.gif'" mode="aspectFill" :lazy-load="true"></image> |
mode="" :lazy-load="true"></image> |
||||
</view> |
<image class="btn" src="https://static.ticket.sz-trip.com/epicSoul/seek2-btn.png" mode="" |
||||
|
:lazy-load="true"></image> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
<!-- 嵌套swiper的第二个item--> |
||||
|
<swiper-item> |
||||
|
<view class="arrow-downs" v-if="nestedIndices[outerIndex] == 1"> |
||||
|
<image src="https://static.ticket.sz-trip.com/epicSoul/image/chapter3/botIcon.png" :lazy-load="true" mode="heightFix"> |
||||
|
</image> |
||||
|
</view> |
||||
|
<view class="page-container home-page"> |
||||
|
<view class="gif-container"> |
||||
|
<image v-if="shouldLoadContent(outerIndex)" class="gif-style" |
||||
|
:src="'https://static.ticket.sz-trip.com/epicSoul/3-' + (outerIndex+1) + '-2.gif'" |
||||
|
mode="aspectFill" :lazy-load="true"></image> |
||||
|
</view> |
||||
|
|
||||
<image class="bg-image" :src="'https://static.ticket.sz-trip.com/epicSoul/images/chapter3/cover' + (outerIndex+2) + '-1.png'" mode="" :lazy-load="true"></image> |
<image class="bg-image" |
||||
<view class="qrcode-content"> |
:src="'https://static.ticket.sz-trip.com/epicSoul/image/chapter3/cover' + (outerIndex+2) + '-1.png'" |
||||
<image class="qrCode" src="https://static.ticket.sz-trip.com/epicSoul/qrcode.png" mode="" :lazy-load="true"></image> |
mode="" :lazy-load="true"></image> |
||||
<view class="code-txt"> |
<view class="qrcode-content"> |
||||
扫码下单 |
<image class="qrCode" src="https://static.ticket.sz-trip.com/epicSoul/image/chapter3/btn1.png" |
||||
</view> |
mode="widthFix" :lazy-load="true" :show-menu-by-longpress="true" @click="gotoPath('/subPackages/techan/detail?id=34')"></image> |
||||
</view> |
<!-- <view class="code-txt"> |
||||
</view> |
扫码下单 |
||||
</swiper-item> |
</view> --> |
||||
</swiper> |
</view> |
||||
</swiper-item> |
</view> |
||||
<swiper-item> |
</swiper-item> |
||||
<view class="page-container home-page"> |
</swiper> |
||||
<image class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/images/chapter3/cover9.png" mode="" :lazy-load="true"></image> |
</swiper-item> |
||||
<image @click="goRandomImage" class="cover-txt9" src="https://static.ticket.sz-trip.com/epicSoul/images/chapter3/cover9-txt.png" mode="" :lazy-load="true"></image> |
<swiper-item> |
||||
</view> |
<view class="page-container home-page"> |
||||
</swiper-item> |
<image class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/image/chapter3/cover9s.png" |
||||
</swiper> |
mode="" :lazy-load="true"></image> |
||||
<MusicControl /> |
<image @click="goRandomImage" class="cover-txt9" |
||||
|
src="https://static.ticket.sz-trip.com/epicSoul/image/chapter3/cover9s-txt.png" mode="" |
||||
|
:lazy-load="true"></image> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
<MusicControl /> |
||||
</view> |
</view> |
||||
</template> |
</template> |
||||
|
|
||||
<script> |
<script> |
||||
export default { |
import MusicControl from '@/components/MusicControl.vue'; |
||||
data() { |
export default { |
||||
return { |
components: { |
||||
currentIndex: 0, |
MusicControl |
||||
// 嵌套swiper索引 |
}, |
||||
nestedIndices: { |
data() { |
||||
0: 0, |
return { |
||||
1: 0, |
currentIndex: 0, |
||||
2: 0, |
// 嵌套swiper索引 |
||||
3: 0, |
nestedIndices: { |
||||
4: 0, |
0: 0, |
||||
5: 0, |
1: 0, |
||||
6: 0 |
2: 0, |
||||
}, |
3: 0, |
||||
// 当前活跃的页面,用于内容加载判断 |
4: 0, |
||||
activePages: { |
5: 0, |
||||
mainIndex: 0, |
6: 0 |
||||
nestedIndices: { |
}, |
||||
0: 0, |
// 当前活跃的页面,用于内容加载判断 |
||||
1: 0, |
activePages: { |
||||
2: 0, |
mainIndex: 0, |
||||
3: 0, |
nestedIndices: { |
||||
4: 0, |
0: 0, |
||||
5: 0, |
1: 0, |
||||
6: 0 |
2: 0, |
||||
} |
3: 0, |
||||
}, |
4: 0, |
||||
// 预加载缓冲区大小 |
5: 0, |
||||
preloadBuffer: 2 |
6: 0 |
||||
} |
} |
||||
}, |
}, |
||||
methods: { |
// 预加载缓冲区大小 |
||||
// 主swiper切换事件处理 |
preloadBuffer: 2 |
||||
handleSwiperChange(e) { |
} |
||||
this.currentIndex = e.detail.current; |
}, |
||||
this.activePages.mainIndex = e.detail.current; |
methods: { |
||||
}, |
// 主swiper切换事件处理 |
||||
|
handleSwiperChange(e) { |
||||
// 嵌套swiper切换事件处理 |
this.currentIndex = e.detail.current; |
||||
handleVerticalChange(e) { |
this.activePages.mainIndex = e.detail.current; |
||||
const outerIndex = parseInt(e.target.dataset.index); |
}, |
||||
this.nestedIndices[outerIndex] = e.detail.current; |
|
||||
this.activePages.nestedIndices[outerIndex] = e.detail.current; |
// 嵌套swiper切换事件处理 |
||||
}, |
handleVerticalChange(e, outerIndex) { |
||||
|
this.nestedIndices[outerIndex] = e.detail.current; |
||||
goRandomImage() { |
this.activePages.nestedIndices[outerIndex] = e.detail.current; |
||||
const imageArray = [ |
}, |
||||
{ |
|
||||
id: 1, |
|
||||
image: 'https://static.ticket.sz-trip.com/epicSoul/images/chapter3/random/image1.png', |
|
||||
name: '雏菊', |
|
||||
desc: '宋 丛菊图页' |
|
||||
}, |
|
||||
{ |
|
||||
id: 2, |
|
||||
image: 'https://static.ticket.sz-trip.com/epicSoul/images/chapter3/random/image2.png', |
|
||||
name: '杜鹃', |
|
||||
desc: '清 恽寿平 花卉十开 杜鹃' |
|
||||
}, |
|
||||
{ |
|
||||
id: 3, |
|
||||
image: 'https://static.ticket.sz-trip.com/epicSoul/images/chapter3/random/image3.png', |
|
||||
name: '金桂', |
|
||||
desc: '清 蒋延锡 桂花图 局部 台北故宫博物馆院藏' |
|
||||
}, |
|
||||
{ |
|
||||
id: 4, |
|
||||
image: 'https://static.ticket.sz-trip.com/epicSoul/images/chapter3/random/image4.png', |
|
||||
name: '绿梅', |
|
||||
desc: '北宋 赵佶 梅花秀眼图页 北京故宫博物院藏' |
|
||||
}, |
|
||||
{ |
|
||||
id: 5, |
|
||||
image: 'https://static.ticket.sz-trip.com/epicSoul/images/chapter3/random/image5.png', |
|
||||
name: '墨兰', |
|
||||
desc: '宋 秋兰绽蕊图' |
|
||||
}, |
|
||||
{ |
|
||||
id: 6, |
|
||||
image: 'https://static.ticket.sz-trip.com/epicSoul/images/chapter3/random/image6.png', |
|
||||
name: '茉莉', |
|
||||
desc: '宋 茉莉花图页' |
|
||||
}, |
|
||||
{ |
|
||||
id: 7, |
|
||||
image: 'https://static.ticket.sz-trip.com/epicSoul/images/chapter3/random/image7.png', |
|
||||
name: '青莲', |
|
||||
desc: '宋 出水芙蓉图页' |
|
||||
}, |
|
||||
]; |
|
||||
|
|
||||
const app = getApp(); |
goRandomImage() { |
||||
app.globalData.randomImages = imageArray; |
const imageArray = [{ |
||||
uni.setStorageSync('randomImages', JSON.stringify(imageArray)); |
id: 1, |
||||
uni.navigateTo({ |
image: 'https://static.ticket.sz-trip.com/epicSoul/image/chapter3/random/image1.png', |
||||
url: '/xxdf/chapter3/randomImage' |
name: '雏菊', |
||||
}); |
desc: '宋 丛菊图页' |
||||
}, |
}, |
||||
|
{ |
||||
goback() { |
id: 2, |
||||
const app = getApp(); |
image: 'https://static.ticket.sz-trip.com/epicSoul/image/chapter3/random/image2.png', |
||||
app.globalData.mainSliderIndex = 4; |
name: '杜鹃', |
||||
uni.redirectTo({ |
desc: '清 恽寿平 花卉十开 杜鹃' |
||||
url: '/xxdf/home/home' |
}, |
||||
}); |
{ |
||||
} |
id: 3, |
||||
}, |
image: 'https://static.ticket.sz-trip.com/epicSoul/image/chapter3/random/image3.png', |
||||
computed: { |
name: '金桂', |
||||
shouldLoadContent() { |
desc: '清 蒋延锡 桂花图 局部 台北故宫博物馆院藏' |
||||
return (outerIndex) => { |
}, |
||||
// 当主索引在附近,且嵌套索引是第二页(GIF页)时预加载 |
{ |
||||
return Math.abs(outerIndex - this.currentIndex) <= this.preloadBuffer && |
id: 4, |
||||
(this.nestedIndices[outerIndex] === 1 || this.activePages.nestedIndices[outerIndex] === 1); |
image: 'https://static.ticket.sz-trip.com/epicSoul/image/chapter3/random/image4.png', |
||||
} |
name: '绿梅', |
||||
} |
desc: '北宋 赵佶 梅花秀眼图页 北京故宫博物院藏' |
||||
}, |
}, |
||||
mounted() { |
{ |
||||
// 初始化状态 |
id: 5, |
||||
this.currentIndex = 0; |
image: 'https://static.ticket.sz-trip.com/epicSoul/image/chapter3/random/image5.png', |
||||
this.activePages.mainIndex = 0; |
name: '墨兰', |
||||
}, |
desc: '宋 秋兰绽蕊图' |
||||
beforeDestroy() { |
}, |
||||
// 组件销毁前的清理工作(如果有) |
{ |
||||
} |
id: 6, |
||||
} |
image: 'https://static.ticket.sz-trip.com/epicSoul/image/chapter3/random/image6.png', |
||||
|
name: '茉莉', |
||||
|
desc: '宋 茉莉花图页' |
||||
|
}, |
||||
|
{ |
||||
|
id: 7, |
||||
|
image: 'https://static.ticket.sz-trip.com/epicSoul/image/chapter3/random/image7.png', |
||||
|
name: '青莲', |
||||
|
desc: '宋 出水芙蓉图页' |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
const app = getApp(); |
||||
|
app.globalData.randomImages = imageArray; |
||||
|
uni.setStorageSync('randomImages', JSON.stringify(imageArray)); |
||||
|
uni.navigateTo({ |
||||
|
url: '/xxdf/chapter3/randomImage' |
||||
|
}); |
||||
|
}, |
||||
|
shouldLoadContent(outerIndex) { |
||||
|
// 当主索引在附近,且嵌套索引是第二页(GIF页)时预加载 |
||||
|
return Math.abs(outerIndex - this.currentIndex) <= this.preloadBuffer && |
||||
|
(this.nestedIndices[outerIndex] === 1 || this.activePages.nestedIndices[outerIndex] === 1); |
||||
|
}, |
||||
|
goback() { |
||||
|
const app = getApp(); |
||||
|
app.globalData.mainSliderIndex = 4; |
||||
|
uni.redirectTo({ |
||||
|
url: '/xxdf/home/home' |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
// 初始化状态 |
||||
|
this.currentIndex = 0; |
||||
|
this.activePages.mainIndex = 0; |
||||
|
}, |
||||
|
beforeDestroy() { |
||||
|
// 组件销毁前的清理工作(如果有) |
||||
|
} |
||||
|
} |
||||
</script> |
</script> |
||||
|
|
||||
<style scoped> |
<style scoped> |
||||
.main-swiper { |
.main-swiper { |
||||
width: 100%; |
width: 100%; |
||||
height: 100vh; |
height: 100vh; |
||||
} |
} |
||||
|
|
||||
|
.nested-swiper { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
.page-container { |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
.home-page { |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.bg-image { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
z-index: 1; |
||||
|
} |
||||
|
|
||||
.nested-swiper { |
.cover-txt { |
||||
width: 100%; |
position: absolute; |
||||
height: 100vh; |
left: 50%; |
||||
} |
bottom: 22%; |
||||
|
transform: translate(-50%, -50%); |
||||
|
z-index: 2; |
||||
|
width: 74%; |
||||
|
height: 122rpx; |
||||
|
} |
||||
|
|
||||
.page-container { |
.cover-txt2 { |
||||
height: 100vh; |
width: 60% !important; |
||||
} |
height: 134rpx !important; |
||||
|
} |
||||
|
|
||||
.home-page { |
.cover-txt9 { |
||||
position: relative; |
position: absolute; |
||||
overflow: hidden; |
left: 50%; |
||||
} |
bottom: 0; |
||||
|
transform: translate(-50%, -20%); |
||||
|
z-index: 2; |
||||
|
width: 360rpx; |
||||
|
height: 280rpx; |
||||
|
} |
||||
|
|
||||
.bg-image { |
.btn { |
||||
position: absolute; |
position: absolute; |
||||
top: 0; |
left: 50%; |
||||
left: 0; |
bottom: 16%; |
||||
width: 100%; |
transform: translate(-50%, -50%); |
||||
height: 100%; |
z-index: 2; |
||||
z-index: 1; |
width: 244rpx; |
||||
} |
height: 60rpx; |
||||
|
} |
||||
|
|
||||
.cover-txt { |
.qrcode-content { |
||||
position: absolute; |
display: flex; |
||||
left: 50%; |
flex-direction: column; |
||||
bottom: 22%; |
align-items: center; |
||||
transform: translate(-50%, -50%); |
position: absolute; |
||||
z-index: 2; |
left: 50%; |
||||
width: 74%; |
bottom: 10vh; |
||||
height: 122rpx; |
transform: translate(-50%, -25%); |
||||
} |
z-index: 2; |
||||
|
} |
||||
|
|
||||
.cover-txt2 { |
.qrCode { |
||||
width: 60% !important; |
width: 400rpx; |
||||
height: 134rpx !important; |
} |
||||
} |
|
||||
|
|
||||
.cover-txt9 { |
.code-txt { |
||||
position: absolute; |
color: #333; |
||||
left: 50%; |
font-size: 24rpx; |
||||
bottom: 0; |
margin-top: 10rpx; |
||||
transform: translate(-50%, -20%); |
} |
||||
z-index: 2; |
|
||||
width: 360rpx; |
|
||||
height: 280rpx; |
|
||||
} |
|
||||
|
|
||||
.btn { |
.gif-container { |
||||
position: absolute; |
background: #333333; |
||||
left: 50%; |
position: absolute; |
||||
bottom: 16%; |
top: 0; |
||||
transform: translate(-50%, -50%); |
left: 0; |
||||
z-index: 2; |
width: 100%; |
||||
width: 244rpx; |
height: 400rpx; |
||||
height: 60rpx; |
z-index: 2; |
||||
} |
} |
||||
|
|
||||
.qrcode-content { |
.gif-style { |
||||
display: flex; |
width: 100%; |
||||
flex-direction: column; |
height: 100%; |
||||
align-items: center; |
object-fit: cover; |
||||
position: absolute; |
} |
||||
left: 50%; |
|
||||
bottom: 0; |
|
||||
transform: translate(-50%, -25%); |
|
||||
z-index: 2; |
|
||||
} |
|
||||
|
|
||||
.qrCode { |
.arrow-down { |
||||
width: 200rpx; |
width: fit-content; |
||||
height: 200rpx; |
height: fit-content; |
||||
} |
position: absolute; |
||||
|
animation: bounce 1.5s infinite; |
||||
|
top: 0; |
||||
|
bottom: 0; |
||||
|
left: 20rpx; |
||||
|
margin: auto; |
||||
|
z-index: 100; |
||||
|
} |
||||
|
|
||||
.code-txt { |
.arrow-down image { |
||||
color: #333; |
display: block; |
||||
font-size: 24rpx; |
width: 50rpx; |
||||
margin-top: 10rpx; |
transform: rotate(180deg); |
||||
} |
} |
||||
|
|
||||
|
.arrow-downs { |
||||
|
width: fit-content; |
||||
|
height: fit-content; |
||||
|
position: absolute; |
||||
|
animation: bounces 1.5s infinite; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 360rpx; |
||||
|
margin: 0 auto; |
||||
|
z-index: 100; |
||||
|
} |
||||
|
|
||||
|
.arrow-downs image { |
||||
|
display: block; |
||||
|
height: 50rpx; |
||||
|
} |
||||
|
|
||||
|
@keyframes bounce { |
||||
|
|
||||
|
0%, |
||||
|
100% { |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
|
||||
.gif-container { |
25% { |
||||
background: #333333; |
transform: translateX(-3px); |
||||
position: absolute; |
} |
||||
top: 0; |
|
||||
left: 0; |
|
||||
width: 100%; |
|
||||
height: 400rpx; |
|
||||
z-index: 2; |
|
||||
} |
|
||||
|
|
||||
.gif-style { |
75% { |
||||
width: 100%; |
transform: translateX(3px); |
||||
height: 100%; |
} |
||||
object-fit: cover; |
} |
||||
} |
|
||||
|
@keyframes bounces { |
||||
|
0%, |
||||
|
20%, |
||||
|
50%, |
||||
|
80%, |
||||
|
100% { |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
|
||||
|
40% { |
||||
|
transform: translateY(-20rpx); |
||||
|
} |
||||
|
|
||||
|
60% { |
||||
|
transform: translateY(-10rpx); |
||||
|
} |
||||
|
} |
||||
</style> |
</style> |
Loading…
Reference in new issue