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>
|