71 lines
3.5 KiB
Plaintext
71 lines
3.5 KiB
Plaintext
<template>
|
|
<view class="page-container">
|
|
<view class="header-panel"><text class="header-title">预警信息</text><text class="header-subtitle">{{ studentName }}的学习动态</text></view>
|
|
<scroll-view class="content-scroll" direction="vertical" scroll-y="true">
|
|
<view v-if="isLoading" class="status-panel"><text class="status-text">预警信息加载中</text></view>
|
|
<view v-else-if="alerts.length === 0" class="status-panel"><text class="status-text">暂无预警信息</text></view>
|
|
<view v-else v-for="alert in alerts" :key="alert.id" class="alert-card">
|
|
<view class="alert-card-top"><view class="alert-level-dot" :class="levelDotClass(alert.level)"></view><text class="alert-title">{{ alert.title }}</text><text class="alert-status" :class="alert.isRead ? 'alert-status-normal' : 'alert-status-triggered'">{{ alert.statusName }}</text></view>
|
|
<text class="alert-content">{{ alert.content }}</text>
|
|
<text class="alert-time">{{ formatTime(alert.occurredAt) }}</text>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { apiGetStudentLearningWarnings, type StudentAlert, type StudentAlertLevel } from '../../api/student'
|
|
import { homeStudentProfile } from '../../store/home'
|
|
|
|
const alerts = ref<StudentAlert[]>([])
|
|
const isLoading = ref(true)
|
|
const studentName = computed((): string => homeStudentProfile.value?.name ?? '孩子')
|
|
|
|
onLoad(() => {
|
|
loadAlerts()
|
|
})
|
|
|
|
async function loadAlerts() {
|
|
const studentId = homeStudentProfile.value?.id ?? ''
|
|
if (!studentId) {
|
|
isLoading.value = false
|
|
return
|
|
}
|
|
const res = await apiGetStudentLearningWarnings(studentId, true, false)
|
|
if (res && res.data) {
|
|
alerts.value = res.data.list
|
|
}
|
|
isLoading.value = false
|
|
}
|
|
|
|
function levelDotClass(level: StudentAlertLevel): string {
|
|
return level === 'low' ? 'alert-level-low' : level === 'medium' ? 'alert-level-medium' : 'alert-level-high'
|
|
}
|
|
|
|
function formatTime(value: string): string {
|
|
return value.length > 0 ? value.substring(5, 16).replace('T', ' ') : ''
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.page-container { display: flex; flex-direction: column; flex: 1; background-color: #f5f7fb; }
|
|
.header-panel { display: flex; flex-direction: column; padding: 18px 20px; background-color: #5d3de8; }
|
|
.header-title { font-size: 21px; font-weight: 700; color: #ffffff; }
|
|
.header-subtitle { margin-top: 6px; font-size: 13px; color: #e5ddff; }
|
|
.content-scroll { flex: 1; padding: 16px 20px; }
|
|
.status-panel { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 160px; }
|
|
.status-text { font-size: 14px; color: #8992a5; }
|
|
.alert-card { display: flex; flex-direction: column; margin-bottom: 12px; padding: 16px; border-radius: 14px; background-color: #ffffff; }
|
|
.alert-card-top { display: flex; flex-direction: row; align-items: center; }
|
|
.alert-level-dot { width: 9px; height: 9px; margin-right: 8px; border-radius: 5px; }
|
|
.alert-level-high { background-color: #e25a5a; }
|
|
.alert-level-medium { background-color: #e8a129; }
|
|
.alert-level-low { background-color: #4d87cf; }
|
|
.alert-title { flex: 1; font-size: 15px; font-weight: 700; color: #30384a; }
|
|
.alert-status { padding: 3px 7px; border-radius: 8px; font-size: 10px; }
|
|
.alert-status-triggered { color: #e25a5a; background-color: #fff0f1; }
|
|
.alert-status-normal { color: #16a979; background-color: #e8fbf3; }
|
|
.alert-content { margin-top: 10px; font-size: 13px; line-height: 20px; color: #626c7e; }
|
|
.alert-time { margin-top: 10px; font-size: 11px; color: #9aa2b1; }
|
|
</style>
|