You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
408 lines
14 KiB
408 lines
14 KiB
<template>
|
|
<div class="page-wrapper page-four-wrapper">
|
|
<div class="page-four">
|
|
<div class="four-video">
|
|
<!-- {{ slideData[videoIndex].title }} -->
|
|
<h4>宣传视频</h4>
|
|
<el-carousel
|
|
ref="carousel"
|
|
indicator-position="none"
|
|
:autoplay="false"
|
|
:autoplay-hover-pause="true"
|
|
@setActiveItem="setActiveItem"
|
|
@change="carouselChange"
|
|
>
|
|
<div v-if="slideData && slideData.length > 0">
|
|
<el-carousel-item v-for="(item, index) in slideData" :key="index">
|
|
<video
|
|
ref="videos"
|
|
class="tsgz-video"
|
|
width="100%"
|
|
height="100%"
|
|
controls
|
|
preload="auto"
|
|
:src="item.cover"
|
|
:poster="poster"
|
|
autoplay
|
|
type="video/mp4"
|
|
muted
|
|
@ended="playNextVideo(index)"
|
|
@loadedmetadata="playVideo"
|
|
>
|
|
您的浏览器不支持 video 标签。
|
|
</video>
|
|
</el-carousel-item>
|
|
</div>
|
|
<el-empty
|
|
v-else
|
|
description="暂无视频"
|
|
style="height: 710px"
|
|
:image-size="40"
|
|
image=""
|
|
/>
|
|
</el-carousel>
|
|
</div>
|
|
<div class="four-right">
|
|
<div class="four-notice">
|
|
<div class="database-title">通知公告</div>
|
|
<div class="seamless-warp">
|
|
<swiper ref="mySwiper" :options="swiperOption" class="big-list">
|
|
<swiper-slide v-for="(item,index) in noticeList" :key="index">
|
|
<div class="notice-text">
|
|
<div class="notice-title">
|
|
<span>{{ item.title }}</span>
|
|
<span>{{ item.startTime | parseTime('{y}-{m}-{d}') }}</span>
|
|
</div>
|
|
<div style="width: calc(100%); height: .5rem;" />
|
|
<p :ref="el => { if (el) marqueeRefs[index] = el }" v-html="item.context" />
|
|
</div>
|
|
</swiper-slide>
|
|
</swiper>
|
|
</div>
|
|
</div>
|
|
<div class="four-ranking lending-ranking">
|
|
<div class="database-title">图书借阅排行榜</div>
|
|
<div class="ranking-cont">
|
|
<ul class="ranking-title">
|
|
<li style="width: 0.725rem;">排名</li>
|
|
<li style="flex:1; text-align: left;">题名</li>
|
|
<!-- <li style="flex:1;" /> -->
|
|
<li style="width: 1.5rem; padding-right: .25rem; text-align: right;">借阅数量</li>
|
|
</ul>
|
|
<ul class="ranking-list">
|
|
<li v-for="(item,index) in rankingData" :key="index" :class="{ 'hovered': index === currentHover }" style="font-size: .28rem !important; line-height: 36px !important;">
|
|
<div style="width: 0.725rem; color: #79B8FF;" :class="[{'ranking-num1':index===0},{'ranking-num2':index===1},{'ranking-num3':index===2}]">{{ index>=3 ? index+1 : null }}</div>
|
|
<div style="flex:1; text-align: left; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;">{{ item.TITLE }}</div>
|
|
<!-- <div class="ranking-progress" style="flex:1; align-self: center;">
|
|
<el-progress :percentage="item.percentage" :stroke-width="8" :show-text="false" color="#009afb" />
|
|
</div> -->
|
|
<div style="width: 1.5rem; padding-right: .25rem; text-align: right;">{{ item.TOTALNUM }}<i style="padding-left:.0625rem;">次</i></div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<!-- <div class="four-contact">
|
|
<div class="wechat-img">
|
|
<img :src="wecharQrCodeSrc">
|
|
</div>
|
|
<span>扫一扫关注我们</span>
|
|
</div> -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { FetchInitSetting, FetchTotalResource, FetchNoticeList, FetchSync36 } from '@/api/library'
|
|
import { swiper, swiperSlide } from 'vue-awesome-swiper'
|
|
import 'swiper/dist/css/swiper.css'
|
|
export default {
|
|
name: 'PageFour',
|
|
components: {
|
|
swiper,
|
|
swiperSlide
|
|
},
|
|
data() {
|
|
// const _self = this
|
|
return {
|
|
wecharQrCodeSrc: null,
|
|
currentHover: -1,
|
|
poster: require('@/assets/images/poster.png'),
|
|
videoIndex: 0,
|
|
slideData: [],
|
|
rankingData: [],
|
|
noticeList: [],
|
|
noticeIndex: 0,
|
|
rankInterval: null,
|
|
marqueeRefs: [], // 存所有 p 元素
|
|
currentIndex: 0, // 当前播放的公告索引
|
|
scrollTimer: null, // 滚动动画定时器(防止内存泄漏)
|
|
waitTimer: null, // 新增:停留等待定时器
|
|
swiperOption: {
|
|
direction: 'vertical',
|
|
autoHeight: true,
|
|
observer: true,
|
|
observeParents: true,
|
|
autoplay: false, // 关闭自带自动轮播
|
|
loop: true
|
|
},
|
|
config: {
|
|
waitBeforeScroll: 3000, // 内容加载后先停留3秒再滚动(单位:毫秒)
|
|
waitAfterScroll: 1000, // 滚动到底部后停留1秒再切换(单位:毫秒)
|
|
scrollSpeed: 60 // 滚动速度(px/秒,数值越小越慢)
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
},
|
|
beforeDestroy() {
|
|
this.destroy()
|
|
},
|
|
created() {
|
|
this.getNotice()
|
|
this.getBookRanking()
|
|
},
|
|
activated() {
|
|
this.getVideoResource()
|
|
this.load()
|
|
if (this.rankingData.length !== 0) {
|
|
this.currentHover = -1
|
|
this.rankInterval = setInterval(() => {
|
|
this.currentHover = (this.currentHover + 1) % this.rankingData.length
|
|
}, 1000)
|
|
}
|
|
},
|
|
deactivated() {
|
|
this.destroy()
|
|
},
|
|
mounted() {
|
|
// 二维码部分
|
|
if (localStorage.getItem('wecharQrCodeSrc')) {
|
|
this.wecharQrCodeSrc = localStorage.getItem('wecharQrCodeSrc')
|
|
} else {
|
|
this.getInitData()
|
|
}
|
|
// 缓存重要通知的index
|
|
if (localStorage.getItem('noticeIndex')) {
|
|
this.$nextTick(() => {
|
|
const index = localStorage.getItem('noticeIndex')
|
|
this.$refs.mySwiper.swiper.slideTo(index, 1000, true)
|
|
})
|
|
}
|
|
},
|
|
methods: {
|
|
load() {
|
|
const videos = this.$refs.videos
|
|
if (videos) {
|
|
videos[this.videoIndex].load()
|
|
videos[this.videoIndex].currentTime = localStorage.getItem('videoCurrentTime') ? localStorage.getItem('videoCurrentTime') : 0
|
|
// videos[this.videoIndex].pause()
|
|
// setTimeout(() => {
|
|
// // videos[this.videoIndex].play()
|
|
// }, 2000)
|
|
}
|
|
},
|
|
destroy() {
|
|
clearInterval(this.rankInterval)
|
|
localStorage.setItem('videoIndex', this.videoIndex)
|
|
localStorage.setItem('videoCurrentTime', this.$refs.videos[this.videoIndex].currentTime)
|
|
localStorage.setItem('noticeIndex', this.noticeIndex)
|
|
this.$refs.videos[this.videoIndex].pause()
|
|
|
|
this.rankInterval = null
|
|
|
|
clearTimeout(this.scrollTimer)
|
|
clearTimeout(this.waitTimer)
|
|
},
|
|
getInitData() {
|
|
// wecharQrCode 二维码 用/downloadFile/+wecharQrCode
|
|
const linkSrc = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API
|
|
console.log('linkSrc', linkSrc)
|
|
FetchInitSetting().then(res => {
|
|
const result = JSON.parse(res.data)
|
|
this.wecharQrCodeSrc = linkSrc + '/downloadFile' + result.wecharQrCode
|
|
})
|
|
},
|
|
getNotice() {
|
|
FetchNoticeList().then(res => {
|
|
this.noticeList = res.data
|
|
this.$nextTick(() => {
|
|
this.playNoticeByIndex(this.currentIndex)
|
|
})
|
|
}).catch(error => {
|
|
console.error('Error', error)
|
|
})
|
|
},
|
|
// 公告
|
|
playNoticeByIndex(index) {
|
|
clearTimeout(this.scrollTimer)
|
|
clearTimeout(this.waitTimer)
|
|
|
|
const pEl = this.marqueeRefs[index]
|
|
if (!pEl) return
|
|
|
|
// 1. 重置样式和动画,先让内容完整显示
|
|
pEl.classList.remove('scroll-animation')
|
|
pEl.style.transform = 'translateY(0)' // 强制回到顶部
|
|
const container = this.$el.querySelector('.seamless-warp')
|
|
const containerHeight = container.offsetHeight
|
|
const contentHeight = pEl.offsetHeight
|
|
|
|
// 2. 如果内容高度 <= 容器高度(无需滚动)
|
|
if (contentHeight <= containerHeight) {
|
|
// 停留指定时间后切换下一条
|
|
this.waitTimer = setTimeout(() => {
|
|
this.switchToNextNotice()
|
|
}, this.config.waitBeforeScroll + 2000) // 多停留2秒
|
|
return
|
|
}
|
|
|
|
// 3. 内容需要滚动:先停留,再滚动
|
|
this.waitTimer = setTimeout(() => {
|
|
// 设置CSS变量(精准计算滚动终点)
|
|
pEl.style.setProperty('--content-height', `${contentHeight}px`)
|
|
pEl.style.setProperty('--container-height', `${containerHeight}px`)
|
|
|
|
// 计算滚动时长(速度越慢,时长越长)
|
|
const scrollDistance = contentHeight - containerHeight // 实际需要滚动的距离
|
|
const scrollDuration = scrollDistance / this.config.scrollSpeed
|
|
|
|
// 设置动画时长并启动滚动
|
|
pEl.style.setProperty('--scroll-duration', `${scrollDuration}s`)
|
|
pEl.classList.add('scroll-animation')
|
|
console.log('scrollDuration', scrollDuration)
|
|
|
|
// 4. 滚动完成后,停留一段时间再切换
|
|
this.scrollTimer = setTimeout(() => {
|
|
// 滚动到底部后停留
|
|
this.waitTimer = setTimeout(() => {
|
|
this.switchToNextNotice()
|
|
}, this.config.waitAfterScroll)
|
|
}, scrollDuration * 1000) // 等待滚动完成
|
|
}, this.config.waitBeforeScroll) // 先停留再滚动
|
|
},
|
|
|
|
// 切换下一条(保证循环)
|
|
switchToNextNotice() {
|
|
// 计算下一个索引(循环)
|
|
this.currentIndex = (this.currentIndex + 1) % this.noticeList.length
|
|
|
|
// 切换swiper
|
|
const swiperInstance = this.$refs.mySwiper?.swiper
|
|
if (swiperInstance) {
|
|
swiperInstance.slideTo(this.currentIndex)
|
|
}
|
|
|
|
// 切换后播放新的一条
|
|
this.$nextTick(() => {
|
|
this.playNoticeByIndex(this.currentIndex)
|
|
})
|
|
},
|
|
// 视频资源
|
|
getVideoResource() {
|
|
FetchTotalResource().then(res => {
|
|
const result = JSON.parse(res.data)
|
|
const linkSrc = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API
|
|
this.slideData = result.map((item, index) => {
|
|
if (item.filePath) {
|
|
item.cover = linkSrc + '/downloadFile' + item.filePath
|
|
} else {
|
|
item.cover = null
|
|
}
|
|
return item
|
|
})
|
|
// 下次进入页面时优先缓存的部分
|
|
if (localStorage.getItem('videoIndex')) {
|
|
this.videoIndex = parseInt(localStorage.getItem('videoIndex'))
|
|
this.$nextTick(() => {
|
|
this.$refs.carousel.setActiveItem(this.videoIndex)
|
|
const videos = this.$refs.videos
|
|
const nextVideo = videos[this.videoIndex]
|
|
videos.forEach((video) => {
|
|
video.pause()
|
|
video.currentTime = 0
|
|
})
|
|
setTimeout(() => {
|
|
nextVideo.currentTime = localStorage.getItem('videoCurrentTime') ? localStorage.getItem('videoCurrentTime') : 0
|
|
nextVideo.play()
|
|
}, 2000)
|
|
})
|
|
}
|
|
}).catch(error => {
|
|
console.error('Error', error)
|
|
})
|
|
},
|
|
playVideo() {
|
|
this.$refs.videos[this.videoIndex].play().catch(error => {
|
|
console.error(error)
|
|
})
|
|
},
|
|
setActiveItem(index) {
|
|
this.$refs.carousel.setActiveItem(index)
|
|
},
|
|
carouselChange(index) {
|
|
const videos = this.$refs.videos
|
|
this.videoIndex = index
|
|
videos.forEach((video) => {
|
|
video.currentTime = 0 // 将视频回到起始时间
|
|
video.pause() // 暂停视频播放
|
|
})
|
|
videos[index].play()
|
|
},
|
|
playNextVideo(index) {
|
|
const videos = this.$refs.videos
|
|
let nextIndex = index
|
|
this.videoIndex = nextIndex
|
|
if (index < this.slideData.length - 1) {
|
|
nextIndex = nextIndex + 1
|
|
} else {
|
|
nextIndex = 0
|
|
}
|
|
const carousel = this.$refs.carousel
|
|
carousel.setActiveItem(nextIndex)
|
|
const nextVideo = videos[nextIndex]
|
|
videos.forEach((video) => {
|
|
video.pause()
|
|
video.currentTime = 0
|
|
})
|
|
setTimeout(() => {
|
|
nextVideo.play()
|
|
}, 1000)
|
|
},
|
|
getBookRanking() {
|
|
const currentDate = new Date() // 获取当前日期
|
|
currentDate.setDate(currentDate.getDate() - 30) // 将当前日期减去30天
|
|
const year = currentDate.getFullYear() // 获取年份
|
|
const month = currentDate.getMonth() + 1 // 获取月份(注意月份从0开始,需要加1)
|
|
const day = currentDate.getDate() // 获取日期
|
|
const formattedDate = `${year}-${month < 10 ? '0' + month : month}-${day < 10 ? '0' + day : day}`
|
|
|
|
const params = {
|
|
'libcode': this.libcode,
|
|
'starttime': formattedDate,
|
|
'endtime': this.getFormattedDate(new Date()),
|
|
'rownum': 5
|
|
}
|
|
FetchSync36(params).then(res => {
|
|
const result = JSON.parse(res.data)
|
|
if (result.success && result.resultlist.length > 0) {
|
|
this.rankingData = result.resultlist.sort((a, b) => b.TOTALNUM - a.TOTALNUM).slice(0, 6)
|
|
this.rankInterval = setInterval(() => {
|
|
this.currentHover = (this.currentHover + 1) % this.rankingData.length
|
|
}, 1000)
|
|
} else {
|
|
throw new Error('Failed' + libcode)
|
|
}
|
|
}).catch(error => {
|
|
console.error('Error', error)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@import "~@/assets/styles/index.scss";
|
|
.el-carousel{
|
|
margin-top: 0.475rem !important;
|
|
}
|
|
::v-deep .el-carousel__container{
|
|
height: 8.875rem !important;
|
|
}
|
|
video {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.big-list>.swiper-wrapper>.swiper-slide {
|
|
height: 100vh;
|
|
overflow: hidden;
|
|
}
|
|
.swiper-container-vertical .swiper-wrapper{
|
|
flex-direction: column;
|
|
}
|
|
.swiper-container {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
</style>
|