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.
 
 
livestock-trading/src/components/ScrollingAnnouncement.vue

205 lines
4.9 KiB

<template>
<div class="scrolling-announcement">
<div class="announcement-header">
<div class="header-icon">📢</div>
<div class="header-title">最新公告</div>
</div>
<div class="announcement-content">
<div class="scrolling-container" ref="scrollingContainer">
<div
class="announcement-item current"
:key="'current-' + currentIndex"
>
{{ announcements[currentIndex]?.content }}
</div>
<div
class="announcement-item next"
:key="'next-' + nextIndex"
>
{{ announcements[nextIndex]?.content }}
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, reactive, computed } from 'vue'
import { dataManager } from '../utils/dataManager.js'
const scrollingContainer = ref(null)
const currentIndex = ref(0)
const isAnimating = ref(false)
let scrollTimer = null
const announcements = reactive([])
// 计算下一个索引
const nextIndex = computed(() => {
return announcements.length > 0 ? (currentIndex.value + 1) % announcements.length : 0
})
// 加载公告数据
const loadAnnouncements = async () => {
try {
// 确保数据管理器已经加载完成
await dataManager.loadData()
const data = dataManager.getData('announcements')
if (data && Array.isArray(data)) {
announcements.splice(0, announcements.length, ...data.map(content => ({ content })))
console.log('公告数据加载成功:', data)
} else {
console.warn('未找到公告数据,使用默认数据')
loadDefaultAnnouncements()
}
} catch (error) {
console.error('加载公告数据失败:', error)
loadDefaultAnnouncements()
}
}
// 加载默认公告
const loadDefaultAnnouncements = () => {
announcements.splice(0, announcements.length,
{ content: '【重要】今日牦牛交易价格上涨2.5%,请各位商户注意市场行情变化' },
{ content: '【通知】新增北京地区优质采购商,欢迎牧民朋友联系洽谈业务' },
{ content: '【提醒】本周末系统维护,交易时间调整为09:00-17:00' },
{ content: '【资讯】春季牧草丰茂,预计下月牦牛供应量将增加15%' },
{ content: '【市场】西藏地区牦牛肉品质检测合格率达98.5%' },
{ content: '【政策】政府出台新政策支持牦牛产业发展,提供资金扶持' }
)
}
// 执行滚动动画
const performScroll = () => {
if (isAnimating.value || announcements.length <= 1) return
isAnimating.value = true
const container = scrollingContainer.value
// 添加滚动类来触发动画
container.classList.add('scrolling')
// 动画完成后更新索引并重置状态
setTimeout(() => {
currentIndex.value = nextIndex.value
container.classList.remove('scrolling')
isAnimating.value = false
}, 800) // 动画持续时间
}
// 开始垂直滚动
const startVerticalScroll = () => {
if (announcements.length <= 1) return
scrollTimer = setInterval(() => {
performScroll()
}, 5000) // 每5秒切换一次
}
// 停止滚动
const stopVerticalScroll = () => {
if (scrollTimer) {
clearInterval(scrollTimer)
scrollTimer = null
}
}
onMounted(async () => {
await loadAnnouncements()
// 等待数据加载完成后开始滚动
if (announcements.length > 1) {
startVerticalScroll()
}
})
onUnmounted(() => {
stopVerticalScroll()
})
</script>
<style scoped>
.scrolling-announcement {
position: absolute;
top: 20px;
left: 20px;
right: 20px;
height: 50px;
background: rgba(26, 31, 46, 0.95);
border: 1px solid rgba(64, 158, 255, 0.4);
border-radius: 8px;
backdrop-filter: blur(10px);
z-index: 100;
overflow: hidden;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
}
.announcement-header {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 100px;
background: rgba(64, 158, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
border-right: 1px solid rgba(64, 158, 255, 0.3);
}
.header-icon {
font-size: 16px;
}
.header-title {
font-size: 12px;
font-weight: bold;
color: #409EFF;
}
.announcement-content {
margin-left: 100px;
height: 100%;
overflow: hidden;
position: relative;
}
.scrolling-container {
position: relative;
height: 100%;
width: 100%;
}
.announcement-item {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
display: flex;
align-items: center;
font-size: 14px;
color: #fff;
padding: 0 20px;
white-space: nowrap;
transition: transform 0.8s ease-in-out;
}
.announcement-item.current {
transform: translateY(0);
}
.announcement-item.next {
transform: translateY(100%);
}
/* 滚动动画状态 */
.scrolling-container.scrolling .announcement-item.current {
transform: translateY(-100%);
}
.scrolling-container.scrolling .announcement-item.next {
transform: translateY(0);
}
</style>