|
|
|
@ -4,45 +4,41 @@ |
|
|
|
<div class="common-title">通知公告</div> |
|
|
|
<div class="small-module module-content"> |
|
|
|
<span class="notice-icon-gif" /> |
|
|
|
<div class="seamless-warp"> |
|
|
|
<div class="notice-txt" v-html="content" /> |
|
|
|
|
|
|
|
<!-- 核心:给容器加固定宽度,避免宽度溢出导致滚动失效 --> |
|
|
|
<div ref="box" class="seamless-warp"> |
|
|
|
<div ref="text" class="notice-txt" v-html="content" /> |
|
|
|
</div> |
|
|
|
<!-- <vue-seamless-scroll :data="noticeData" :class-option="defaultOption" class="seamless-warp"> |
|
|
|
<p v-for="(item,index) in noticeData" :key="index"> {{ item.des }}</p> |
|
|
|
</vue-seamless-scroll> --> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
import { FetchInitNotice } from '@/api/library' |
|
|
|
|
|
|
|
export default { |
|
|
|
name: 'Notice', |
|
|
|
data() { |
|
|
|
return { |
|
|
|
noticeData: [], |
|
|
|
content: '' |
|
|
|
} |
|
|
|
}, |
|
|
|
computed: { |
|
|
|
defaultOption() { |
|
|
|
return { |
|
|
|
step: 0.3, // 数值越大速度滚动越快 |
|
|
|
limitMoveNum: 1, // 开始无缝滚动的数据量 |
|
|
|
hoverStop: false, // 是否开启鼠标悬停stop |
|
|
|
direction: 1, // 0向下 1向上 2向左 3向右 |
|
|
|
openWatch: true // 开启数据实时监控刷新dom |
|
|
|
} |
|
|
|
content: '', |
|
|
|
scrollTimer: null, // 滚动定时器 |
|
|
|
transitionTimer: null, // 过渡结束定时器 |
|
|
|
boxH: 0, // 容器高度 |
|
|
|
textH: 0, // 内容高度 |
|
|
|
duration: 40000 // 单次滚动时长 |
|
|
|
} |
|
|
|
}, |
|
|
|
created() { |
|
|
|
}, |
|
|
|
mounted() { |
|
|
|
this.getInitNotice() |
|
|
|
}, |
|
|
|
beforeDestroy() { |
|
|
|
// 销毁时清除所有定时器 |
|
|
|
if (this.scrollTimer) clearInterval(this.scrollTimer) |
|
|
|
if (this.transitionTimer) clearTimeout(this.transitionTimer) |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
// 处理方法 |
|
|
|
escapeHtml(str) { |
|
|
|
if (!str) return '' |
|
|
|
var arrEntities = { |
|
|
|
'lt': '<', |
|
|
|
'gt': '>', |
|
|
|
@ -50,18 +46,83 @@ export default { |
|
|
|
'amp': '&', |
|
|
|
'quot': '"' |
|
|
|
} |
|
|
|
return str.replace(/&(lt|gt|nbsp|amp|quot|pre);/ig, function(all, t) { |
|
|
|
return arrEntities[t] |
|
|
|
}) |
|
|
|
return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, (all, t) => arrEntities[t]) |
|
|
|
.replace(/<pre>|<\/pre>/gi, '') |
|
|
|
.replace(/\\r\\n/g, '') // 移除多余换行符 |
|
|
|
}, |
|
|
|
getInitNotice() { |
|
|
|
FetchInitNotice().then((res) => { |
|
|
|
FetchInitNotice().then(res => { |
|
|
|
if (res.errCode === 0) { |
|
|
|
this.content = this.escapeHtml(res.data) |
|
|
|
} else { |
|
|
|
this.$message.error('接口错误') |
|
|
|
// 等DOM完全渲染后再启动滚动 |
|
|
|
this.$nextTick(() => { |
|
|
|
this.startScroll() |
|
|
|
}) |
|
|
|
} |
|
|
|
}).catch(err => { |
|
|
|
console.log('接口请求失败:', err) |
|
|
|
}) |
|
|
|
}, |
|
|
|
startScroll() { |
|
|
|
const box = this.$refs.box |
|
|
|
const text = this.$refs.text |
|
|
|
|
|
|
|
// 先打印调试,看是否获取到DOM和高度 |
|
|
|
console.log('容器DOM:', box) |
|
|
|
console.log('内容DOM:', text) |
|
|
|
if (!box || !text) { |
|
|
|
console.log('DOM未获取到,滚动启动失败') |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// 强制计算高度(解决rem布局高度计算延迟) |
|
|
|
this.boxH = box.clientHeight || parseInt(getComputedStyle(box).height) |
|
|
|
this.textH = text.offsetHeight || parseInt(getComputedStyle(text).height) |
|
|
|
|
|
|
|
console.log('容器高度:', this.boxH, '内容高度:', this.textH) |
|
|
|
|
|
|
|
// 内容不够高,不滚动 |
|
|
|
if (this.textH <= this.boxH) { |
|
|
|
console.log('内容高度小于容器,无需滚动') |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// 初始化样式 |
|
|
|
text.style.position = 'absolute' |
|
|
|
text.style.top = '0px' |
|
|
|
text.style.left = '0px' |
|
|
|
text.style.width = '100%' |
|
|
|
text.style.transition = 'none' |
|
|
|
|
|
|
|
// 监听过渡结束事件,实现循环 |
|
|
|
text.addEventListener('transitionend', this.handleTransitionEnd) |
|
|
|
|
|
|
|
// 启动第一次滚动 |
|
|
|
this.rollToBottom() |
|
|
|
}, |
|
|
|
// 滚动到底部 |
|
|
|
rollToBottom() { |
|
|
|
const text = this.$refs.text |
|
|
|
// 重置过渡,立即回到顶部 |
|
|
|
text.style.transition = 'none' |
|
|
|
text.style.top = '0px' |
|
|
|
|
|
|
|
// 重新设置过渡,滚动到底部 |
|
|
|
setTimeout(() => { |
|
|
|
text.style.transition = `top ${this.duration}ms linear` |
|
|
|
text.style.top = `-${this.textH - this.boxH}px` |
|
|
|
}, 100) |
|
|
|
}, |
|
|
|
// 过渡结束处理函数 |
|
|
|
handleTransitionEnd() { |
|
|
|
// const text = this.$refs.text |
|
|
|
// 清除之前的定时器,避免重复触发 |
|
|
|
if (this.transitionTimer) clearTimeout(this.transitionTimer) |
|
|
|
|
|
|
|
// 停留2秒后重新滚动 |
|
|
|
this.transitionTimer = setTimeout(() => { |
|
|
|
this.rollToBottom() |
|
|
|
}, 2000) // 2000毫秒 = 2秒 |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -70,4 +131,22 @@ export default { |
|
|
|
<style lang="scss"> |
|
|
|
@import "~@/assets/styles/index.scss"; |
|
|
|
|
|
|
|
.notice .module-content { |
|
|
|
position: relative; |
|
|
|
} |
|
|
|
|
|
|
|
.notice .seamless-warp { |
|
|
|
position: relative !important; |
|
|
|
overflow: hidden !important; |
|
|
|
height: 3.1rem !important; |
|
|
|
} |
|
|
|
|
|
|
|
.notice-txt table { |
|
|
|
width: 100% !important; |
|
|
|
border-collapse: collapse !important; |
|
|
|
} |
|
|
|
|
|
|
|
.notice-txt td { |
|
|
|
word-break: break-all !important; |
|
|
|
} |
|
|
|
</style> |