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.
205 lines
4.9 KiB
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> |