230 lines
5.8 KiB
Vue
230 lines
5.8 KiB
Vue
<template>
|
||
<div class="weather-warning">
|
||
<!-- <span>天气预警:</span> -->
|
||
<!-- 预报内容 -->
|
||
<!-- <div class="weather-scroll-container" @mouseenter="stopWeatherScroll" @mouseleave="startWeatherScroll">
|
||
<div class="weather-scroll-content" :style="{ transform: `translateX(${scrollPosition}px)` }">
|
||
<span v-for="(item, index) in weatherData" :key="index" class="weather-item"
|
||
:style="{ color: getLevelColor(item.level_code) }">
|
||
{{ item.content }}
|
||
</span>
|
||
</div>
|
||
</div> -->
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, onMounted, onUnmounted } from 'vue'
|
||
import { getTableList } from '../report'
|
||
interface WeatherWarning {
|
||
content: string
|
||
level_code: 'severity' | 'major' | 'general'
|
||
}
|
||
|
||
interface Props {
|
||
// 可以传入自定义的天气数据
|
||
customData?: WeatherWarning[]
|
||
// 滚动速度
|
||
scrollSpeed?: number
|
||
// 是否自动获取数据
|
||
autoFetch?: boolean
|
||
// 数据更新间隔(分钟)
|
||
updateInterval?: number
|
||
}
|
||
|
||
const props = withDefaults(defineProps<Props>(), {
|
||
customData: undefined,
|
||
scrollSpeed: 1,
|
||
autoFetch: true,
|
||
updateInterval: 5
|
||
})
|
||
|
||
// 天气预报数据
|
||
const weatherData = ref<WeatherWarning[]>([
|
||
{
|
||
content: '2025年08月19日13:25分中央气象台发布雄安地区于17时至夜间将有200毫米强降雨,并伴有10级大风......',
|
||
level_code: 'severity'
|
||
},
|
||
{
|
||
content: '2025年08月19日10:30分河北省气象台发布石家庄地区今日下午有雷阵雨,请注意防范......',
|
||
level_code: 'major'
|
||
},
|
||
{
|
||
content: '2025年08月19日09:15分北京市气象台发布今日天气晴朗,气温25-32度,空气质量良好......',
|
||
level_code: 'general'
|
||
},
|
||
{
|
||
content: '2025年08月19日08:00分天津市气象台发布今日多云转晴,风力3-4级,适合户外活动......',
|
||
level_code: 'general'
|
||
}
|
||
])
|
||
|
||
// 滚动位置
|
||
const scrollPosition = ref(0)
|
||
const scrollInterval = ref<number | null>(null)
|
||
const updateTimerId = ref<number | null>(null)
|
||
|
||
// 获取预警级别对应的颜色
|
||
const getLevelColor = (level: string) => {
|
||
switch (level) {
|
||
case 'severity':
|
||
return 'red'
|
||
case 'major':
|
||
return 'orange'
|
||
case 'general':
|
||
return 'white'
|
||
default:
|
||
return 'white'
|
||
}
|
||
}
|
||
|
||
// 开始天气预报滚动
|
||
const startWeatherScroll = () => {
|
||
if (scrollInterval.value) return
|
||
|
||
console.log('开始滚动,天气数据条数:', weatherData.value.length)
|
||
|
||
scrollInterval.value = setInterval(() => {
|
||
scrollPosition.value -= props.scrollSpeed
|
||
|
||
// 动态计算需要滚动的总距离
|
||
// 每条预警的宽度 = 内容长度 + 右边距,估算更准确
|
||
const itemWidth = 820 // 每条预警的估算宽度:800px内容 + 20px右边距
|
||
const totalWidth = weatherData.value.length * itemWidth
|
||
const resetThreshold = -totalWidth
|
||
|
||
// 当滚动到一定位置时,重置位置实现循环效果
|
||
if (scrollPosition.value <= resetThreshold) {
|
||
console.log('重置滚动位置,当前:', scrollPosition.value, '阈值:', resetThreshold)
|
||
scrollPosition.value = 0
|
||
}
|
||
|
||
// 每100次更新输出一次调试信息
|
||
if (Math.abs(scrollPosition.value) % 100 === 0) {
|
||
console.log('滚动位置:', scrollPosition.value, '阈值:', resetThreshold)
|
||
}
|
||
}, 50) // 每50ms更新一次,控制滚动速度
|
||
}
|
||
|
||
// 停止天气预报滚动
|
||
const stopWeatherScroll = () => {
|
||
if (scrollInterval.value) {
|
||
clearInterval(scrollInterval.value)
|
||
scrollInterval.value = null
|
||
}
|
||
}
|
||
|
||
// 获取天气数据(模拟接口调用)
|
||
const fetchWeatherData = async () => {
|
||
const query = {
|
||
pageNo: 1,
|
||
pageSize: 10000,
|
||
parkCode: "",
|
||
regionCode: ""
|
||
}
|
||
//
|
||
try {
|
||
let weather_warning = await getTableList(
|
||
'weather_warning', query
|
||
)
|
||
|
||
if (weather_warning.records && weather_warning.records.length > 0) {
|
||
// 更新为新的数据格式
|
||
weatherData.value = weather_warning.records
|
||
} else {
|
||
weatherData.value = []
|
||
}
|
||
} catch (error) {
|
||
console.error('获取天气预警数据失败:', error)
|
||
}
|
||
}
|
||
|
||
// 定时更新天气数据
|
||
const startWeatherDataUpdate = () => {
|
||
if (!props.autoFetch) return
|
||
|
||
updateTimerId.value = setInterval(async () => {
|
||
await fetchWeatherData()
|
||
}, props.updateInterval * 60 * 1000)
|
||
}
|
||
|
||
// 停止定时更新
|
||
const stopWeatherDataUpdate = () => {
|
||
if (updateTimerId.value) {
|
||
clearInterval(updateTimerId.value)
|
||
updateTimerId.value = null
|
||
}
|
||
}
|
||
|
||
// 更新天气数据(供父组件调用)
|
||
const updateWeatherData = (data: WeatherWarning[]) => {
|
||
weatherData.value = data
|
||
}
|
||
|
||
// 暴露方法给父组件
|
||
defineExpose({
|
||
updateWeatherData,
|
||
startWeatherScroll,
|
||
stopWeatherScroll,
|
||
fetchWeatherData
|
||
})
|
||
|
||
onMounted(() => {
|
||
// 如果传入了自定义数据,使用自定义数据
|
||
if (props.customData) {
|
||
weatherData.value = props.customData
|
||
} else if (props.autoFetch) {
|
||
// 否则获取天气数据
|
||
fetchWeatherData().then(() => {
|
||
startWeatherScroll()
|
||
})
|
||
} else {
|
||
// 直接启动滚动
|
||
startWeatherScroll()
|
||
}
|
||
|
||
// 启动天气数据定时更新
|
||
startWeatherDataUpdate()
|
||
})
|
||
|
||
onUnmounted(() => {
|
||
stopWeatherScroll()
|
||
stopWeatherDataUpdate()
|
||
})
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.weather-warning {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
margin-left: 10%;
|
||
line-height: 45px;
|
||
|
||
.weather-scroll-container {
|
||
flex: 1;
|
||
position: relative;
|
||
overflow: hidden;
|
||
|
||
.weather-scroll-content {
|
||
display: flex;
|
||
white-space: nowrap;
|
||
|
||
/* 移除过渡动画,确保滚动流畅 */
|
||
|
||
/* transition: transform 0.05s linear; */
|
||
|
||
.weather-item {
|
||
min-width: 800px;
|
||
margin-right: 20px;
|
||
|
||
/* 每条预警之间的间距,从50px调整为20px */
|
||
white-space: nowrap;
|
||
|
||
/* 确保文本不会被截断 */
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|