feat(web/miniapp): 高发病天气预警展示(#12)
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import { get } from './request';
|
||||
|
||||
export interface WeatherAlert {
|
||||
id: string;
|
||||
disease: string;
|
||||
level: string;
|
||||
reason: string;
|
||||
createdAt?: string;
|
||||
}
|
||||
|
||||
export const getWeatherAlerts = (limit = 5) =>
|
||||
get<WeatherAlert[]>('/weather/alerts', { limit });
|
||||
@@ -6,6 +6,47 @@
|
||||
padding-bottom: $spacing-xl;
|
||||
}
|
||||
|
||||
.weatherWrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $spacing-sm;
|
||||
margin: $spacing-md $spacing-lg 0;
|
||||
}
|
||||
|
||||
.weatherCard {
|
||||
background: rgba(255, 125, 0, 0.08);
|
||||
border-radius: $radius-md;
|
||||
padding: $spacing-md;
|
||||
}
|
||||
|
||||
.weatherHeader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-sm;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.weatherBadge {
|
||||
font-size: $font-size-xs;
|
||||
color: $color-warning;
|
||||
background: rgba(255, 125, 0, 0.15);
|
||||
padding: 4rpx $spacing-sm;
|
||||
border-radius: $radius-round;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.weatherDisease {
|
||||
font-size: $font-size-md;
|
||||
font-weight: $font-weight-medium;
|
||||
color: $color-text-primary;
|
||||
}
|
||||
|
||||
.weatherReason {
|
||||
font-size: $font-size-xs;
|
||||
color: $color-text-secondary;
|
||||
line-height: $line-height-normal;
|
||||
}
|
||||
|
||||
.filterBar {
|
||||
display: flex;
|
||||
background: $color-bg-card;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useDidShow, usePullDownRefresh } from '@tarojs/taro';
|
||||
import styles from './index.module.scss';
|
||||
import { getAlarms, acknowledgeAlarm, getAlarmClip } from '@/api/alarms';
|
||||
import { getWeatherAlerts, type WeatherAlert } from '@/api/weather';
|
||||
import {
|
||||
formatDateTime,
|
||||
formatRelativeTime,
|
||||
@@ -16,6 +17,7 @@ import type { Alarm } from '@/types';
|
||||
|
||||
const AlertsPage: React.FC = () => {
|
||||
const [alarms, setAlarms] = useState<Alarm[]>([]);
|
||||
const [weatherAlerts, setWeatherAlerts] = useState<WeatherAlert[]>([]);
|
||||
const [filterOpen, setFilterOpen] = useState(true);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState('');
|
||||
@@ -25,6 +27,8 @@ const AlertsPage: React.FC = () => {
|
||||
setError('');
|
||||
const res = await getAlarms({ openOnly: filterOpen }).catch(() => [] as Alarm[]);
|
||||
setAlarms(res);
|
||||
const weatherRes = await getWeatherAlerts(5).catch(() => [] as WeatherAlert[]);
|
||||
setWeatherAlerts(weatherRes);
|
||||
} catch (err) {
|
||||
console.error('[Alerts] 数据加载失败:', err);
|
||||
setError(err instanceof Error ? err.message : '数据加载失败');
|
||||
@@ -147,6 +151,23 @@ const AlertsPage: React.FC = () => {
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 高发病天气预警 */}
|
||||
{weatherAlerts.length > 0 ? (
|
||||
<View className={styles.weatherWrap}>
|
||||
{weatherAlerts.map((w) => (
|
||||
<View key={w.id} className={styles.weatherCard}>
|
||||
<View className={styles.weatherHeader}>
|
||||
<Text className={styles.weatherBadge}>
|
||||
{w.level === 'orange' ? '高风险' : w.level === 'red' ? '极高风险' : '注意'}
|
||||
</Text>
|
||||
<Text className={styles.weatherDisease}>{w.disease}</Text>
|
||||
</View>
|
||||
<Text className={styles.weatherReason}>{w.reason}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
{alarms.length === 0 ? (
|
||||
<View className={styles.emptyWrap}>
|
||||
<Text className={styles.emptyIcon}>{filterOpen ? '✅' : '🔔'}</Text>
|
||||
|
||||
Reference in New Issue
Block a user