Files
App.k12.Parents/pages/today-learning/index.uvue
T
2026-10-29 10:08:39 +08:00

148 lines
9.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="page-container">
<view class="header-panel">
<view class="header-back" @tap="goBack"><UniIcons type="back" class="header-back-icon"></UniIcons></view>
<view class="header-copy"><text class="header-title">今日学习</text><text class="header-subtitle">{{ detail.dateText }} {{ detail.studentName }}</text></view>
<view class="header-action" @tap="goBack"><UniIcons type="home-filled" class="header-action-icon"></UniIcons></view>
</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 class="content-panel">
<view class="overview-card">
<view class="overview-header"><text class="section-title">今日学习概览</text><text class="checkin-status" :class="detail.checkedIn ? 'checkin-complete' : 'checkin-pending'">{{ detail.checkedIn ? '已打卡' : '未打卡' }}</text></view>
<view class="metrics-grid">
<view class="metric-card"><text class="metric-label">学习时长</text><text class="metric-value">{{ detail.learningMinutes }} 分钟</text></view>
<view class="metric-card"><text class="metric-label">答题时长</text><text class="metric-value">{{ detail.answerMinutes }} 分钟</text></view>
<view class="metric-card"><text class="metric-label">答题数量</text><text class="metric-value metric-blue">{{ detail.answerCount }} 题</text></view>
<view class="metric-card"><text class="metric-label">完成学习包</text><text class="metric-value metric-purple">{{ detail.completedPackages }} / {{ detail.totalPackages }}</text></view>
<view class="metric-card"><text class="metric-label">攻克知识点</text><text class="metric-value metric-green">{{ detail.masteredPoints }} 个</text></view>
</view>
</view>
<view class="courses-card">
<text class="section-title">今日课表与每课打卡</text>
<view class="course-list">
<view v-for="course in detail.courses" :key="course.id" class="course-item">
<text class="course-time">{{ course.time }}</text>
<view class="course-copy"><text class="course-subject">{{ course.subject }}</text><text class="course-content">{{ course.content }}</text></view>
<text class="course-status" :class="course.checkedIn ? 'course-complete' : 'course-pending'">{{ course.checkedIn ? '已打卡' : '未打卡' }}</text>
</view>
</view>
</view>
<view class="score-card">
<text class="section-title">正确率(对比昨日)</text>
<text class="score-description">整体正确率较昨日全部答题目统计,与昨日对比</text>
<view class="score-row"><text class="score-label">整体正确率</text><view class="score-values"><text class="score-value">{{ detail.score.accuracy }}%</text><text class="score-change">+{{ detail.score.change }}%</text></view></view>
<text class="score-yesterday">昨日 {{ detail.score.yesterdayAccuracy }}%</text>
<view class="score-track"><view class="score-progress" :style="{ width: detail.score.accuracy + '%' }"></view></view>
</view>
<view class="points-card">
<view class="points-header"><text class="section-title">今日获得积分</text><text class="points-link">积分明细 ›</text></view>
<view class="points-total"><text class="points-number">+{{ detail.pointsTotal }}</text><text class="points-unit">积分</text></view>
<view class="points-list">
<view v-for="item in detail.pointDetails" :key="item.id" class="point-item"><text class="point-label">{{ item.label }}</text><text class="point-value">+{{ item.points }}</text></view>
</view>
</view>
</view>
</scroll-view>
<MainTabBar active-tab="home"></MainTabBar>
</view>
</template>
<script setup lang="ts">
import MainTabBar from '../../components/main-tab-bar.uvue'
import UniIcons from '../../uni_modules/uni-icons-x/components/uni-icons/uni-icons.uvue'
import { apiGetTodayLearningDetail, type TodayLearningDetail } from '../../api/student'
import { homeStudentProfile } from '../../store/home'
const isLoading = ref(true)
const detail = ref<TodayLearningDetail>({
studentId: '', studentName: '', dateText: '', checkedIn: false, learningMinutes: 0, answerMinutes: 0,
answerCount: 0, completedPackages: 0, totalPackages: 0, masteredPoints: 0, courses: [],
score: { accuracy: 0, yesterdayAccuracy: 0, change: 0 }, pointsTotal: 0, pointDetails: []
})
onLoad(() => {
loadTodayLearning()
})
async function loadTodayLearning() {
const studentId = homeStudentProfile.value?.id ?? ''
if (!studentId) {
isLoading.value = false
return
}
const res = await apiGetTodayLearningDetail(studentId)
if (res && res.data) {
detail.value = res.data
}
isLoading.value = false
}
function goBack() {
uni.navigateBack()
}
</script>
<style>
.page-container { display: flex; flex-direction: column; flex: 1; background-color: #f5f7fb; }
.header-panel { display: flex; flex-direction: row; align-items: center; padding: 12px 18px; background-color: #ffffff; }
.header-back { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 18px; background-color: #f1f4f8; }
.header-back-icon { font-size: 18px; color: #66758d; }
.header-copy { display: flex; flex-direction: column; flex: 1; margin-left: 12px; }
.header-title { font-size: 17px; font-weight: 700; color: #22283a; }
.header-subtitle { margin-top: 3px; font-size: 12px; color: #8992a5; }
.header-action { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 18px; background-color: #f0f1ff; }
.header-action-icon { font-size: 18px; color: #6558e9; }
.content-scroll { flex: 1; }
.status-panel { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 260px; }
.status-text { font-size: 13px; color: #8992a5; }
.content-panel { display: flex; flex-direction: column; padding: 16px 18px 24px; }
.overview-card { display: flex; flex-direction: column; padding: 16px; border-radius: 8px; background-color: #ffffff; }
.overview-header { display: flex; flex-direction: row; align-items: center; justify-content: space-between; }
.section-title { font-size: 16px; font-weight: 700; color: #242b3d; }
.checkin-status { padding: 4px 10px; border-radius: 12px; font-size: 11px; }
.checkin-complete { color: #00a66a; background-color: #e9fbf3; }
.checkin-pending { color: #f08a1a; background-color: #fff4e5; }
.metrics-grid { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: space-between; margin-top: 14px; }
.metric-card { display: flex; flex-direction: column; width: 48%; margin-bottom: 10px; padding: 12px; border-radius: 8px; background-color: #f6f8fb; }
.metric-label { font-size: 11px; color: #8992a5; }
.metric-value { margin-top: 6px; font-size: 15px; font-weight: 700; color: #20283a; }
.metric-blue { color: #008ddb; }
.metric-purple { color: #6558e9; }
.metric-green { color: #00a66a; }
.courses-card { display: flex; flex-direction: column; margin-top: 16px; padding: 16px; border-radius: 8px; background-color: #ffffff; }
.course-list { display: flex; flex-direction: column; margin-top: 14px; }
.course-item { display: flex; flex-direction: row; align-items: center; min-height: 58px; margin-bottom: 10px; padding: 10px 12px; border-radius: 8px; background-color: #f6f8fb; }
.course-time { width: 56px; font-size: 12px; color: #596275; }
.course-copy { display: flex; flex-direction: column; flex: 1; }
.course-subject { font-size: 13px; font-weight: 600; color: #2a3042; }
.course-content { margin-top: 4px; font-size: 12px; color: #596275; }
.course-status { padding: 4px 7px; border-radius: 10px; font-size: 10px; }
.course-complete { color: #00a66a; background-color: #e9fbf3; }
.course-pending { color: #f08a1a; background-color: #fff4e5; }
.score-card { display: flex; flex-direction: column; margin-top: 16px; padding: 16px; border-radius: 8px; background-color: #ffffff; }
.score-description { margin-top: 6px; font-size: 11px; color: #8992a5; }
.score-row { display: flex; flex-direction: row; align-items: center; justify-content: space-between; margin-top: 14px; }
.score-label { font-size: 12px; color: #596275; }
.score-values { display: flex; flex-direction: row; align-items: center; }
.score-value { font-size: 13px; font-weight: 700; color: #20283a; }
.score-change { margin-left: 8px; font-size: 12px; color: #00a66a; }
.score-yesterday { margin-top: 6px; font-size: 12px; color: #8992a5; }
.score-track { height: 8px; margin-top: 8px; border-radius: 4px; background-color: #edf1f7; }
.score-progress { height: 8px; border-radius: 4px; background-color: #7659ee; }
.points-card { display: flex; flex-direction: column; margin-top: 16px; padding: 16px; border-radius: 8px; background-color: #ffffff; }
.points-header { display: flex; flex-direction: row; align-items: center; justify-content: space-between; }
.points-link { font-size: 12px; color: #514ce8; }
.points-total { display: flex; flex-direction: row; align-items: baseline; margin-top: 10px; }
.points-number { font-size: 24px; font-weight: 700; color: #ee9500; }
.points-unit { margin-left: 5px; font-size: 12px; color: #8992a5; }
.points-list { display: flex; flex-direction: column; margin-top: 12px; }
.point-item { display: flex; flex-direction: row; justify-content: space-between; margin-bottom: 8px; padding: 10px 12px; border-radius: 8px; background-color: #f6f8fb; }
.point-label { font-size: 12px; color: #596275; }
.point-value { font-size: 12px; font-weight: 600; color: #ee9500; }
</style>