Files
App.k12.Parents/pages/vocabulary/index.uvue
T
2026-11-05 11:01:12 +08:00

101 lines
7.5 KiB
Plaintext

<template>
<view class="page-container">
<view class="header-panel"><view class="header-back" @tap="goHome"><UniIcons type="back" class="header-back-icon"></UniIcons></view><view class="header-copy"><text class="header-title">英语词汇</text><text class="header-subtitle">{{ homeStudentProfile?.name ?? vocabulary.studentName }} · {{ homeStudentProfile?.school ?? '' }} {{ homeStudentProfile?.className ?? vocabulary.studentClass }}</text></view><view class="header-action"><UniIcons type="person-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="list-heading"><text class="list-title">全部词书</text><text class="book-count">{{ vocabulary.bookCount }} 本</text></view><text class="list-description">每本词书的总词量与已学进度</text><view v-for="book in vocabulary.books" :key="book.id" class="book-card" :class="'book-card-' + book.color"><view class="book-heading"><view class="book-icon" :class="'book-icon-' + book.color"><image v-if="book.cover" class="book-cover" :src="book.cover" mode="aspectFill"></image><UniIcons v-else type="font" class="book-icon-glyph" :class="'book-icon-glyph-' + book.color"></UniIcons></view><view class="book-copy"><text class="book-name">{{ book.name }}</text><view class="book-meta"><text class="book-total">{{ book.subtitle }}</text><text class="book-level">{{ book.levelText }}</text></view></view><text class="book-status" :class="'book-status-' + book.color">{{ book.statusText }}</text></view><view class="progress-heading"><text class="progress-label">学习进度</text><text class="progress-value">{{ book.learnedWords > 0 ? '已学 ' + book.learnedWords + ' / ' + book.totalWords + ' 词 · ' + progressPercent(book) + '%' : '未开始' }}</text></view><view class="progress-track"><view class="progress-fill" :class="'progress-fill-' + book.color" :style="{ width: progressPercent(book) + '%' }"></view></view></view></view></scroll-view>
</view>
</template>
<script setup lang="ts">
import UniIcons from '../../uni_modules/uni-icons-x/components/uni-icons/uni-icons.uvue'
import { apiGetStudentHomeProfile, apiGetStudentVocabulary, type StudentVocabulary, type VocabularyBook } from '../../api/student'
import { homeStudentProfile, setHomeStudentProfile } from '../../store/home'
const vocabulary = ref<StudentVocabulary>({ studentId: '', studentName: '', studentGrade: '', studentClass: '', bookCount: 0, books: [] })
const isLoading = ref(true)
onLoad(() => { loadVocabulary() })
async function loadVocabulary() {
let studentId = homeStudentProfile.value?.id ?? ''
if (!studentId) {
const profileRes = await apiGetStudentHomeProfile(undefined, false)
if (profileRes && profileRes.data) {
setHomeStudentProfile(profileRes.data)
studentId = profileRes.data.id
}
}
if (studentId) {
const res = await apiGetStudentVocabulary(studentId)
if (res && res.data) {
vocabulary.value = {
...res.data,
studentName: homeStudentProfile.value?.name ?? '',
studentGrade: homeStudentProfile.value?.grade ?? '',
studentClass: homeStudentProfile.value?.className ?? ''
}
}
}
isLoading.value = false
}
function progressPercent(book: VocabularyBook): number {
if (book.totalWords === 0) return 0
return Math.round(book.learnedWords / book.totalWords * 100)
}
function goHome() { uni.reLaunch({ url: '/pages/index/index' }) }
</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: #554be9; }
.content-scroll { flex: 1; }
.content-panel { display: flex; flex-direction: column; padding: 18px 22px 28px; }
.status-panel { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 260px; }
.status-text { font-size: 13px; color: #8992a5; }
.list-heading { display: flex; flex-direction: row; align-items: center; justify-content: space-between; }
.list-title { font-size: 16px; font-weight: 700; color: #242b3d; }
.book-count { font-size: 12px; color: #8992a5; }
.list-description { margin-top: 6px; font-size: 11px; color: #8992a5; }
.book-card { display: flex; flex-direction: column; margin-top: 12px; padding: 16px; border: 1px solid; border-radius: 16px; }
.book-card-green { border-color: #8ee8ca; background-color: #f0fff9; }
.book-card-yellow { border-color: #ffd66e; background-color: #fffaf0; }
.book-card-blue { border-color: #9cd7ff; background-color: #eff8ff; }
.book-card-gray { border-color: #dbe2eb; background-color: #f2f6fa; }
.book-heading { display: flex; flex-direction: row; align-items: flex-start; }
.book-icon { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 64px; height: 64px; flex-shrink: 0; border-radius: 11px; }
.book-cover { width: 64px; height: 64px; border-radius: 11px; }
.book-icon-green { background-color: #16bd88; }
.book-icon-yellow { background-color: #fff0c5; }
.book-icon-blue { background-color: #d9f0ff; }
.book-icon-gray { background-color: #ffffff; }
.book-icon-glyph { font-size: 20px; color: #ffffff; }
.book-icon-glyph-yellow, .book-icon-glyph-blue { color: #1598dc; }
.book-copy { display: flex; flex-direction: column; flex: 1; margin-left: 12px; min-width: 0; }
.book-name { font-size: 14px; font-weight: 700; color: #203329; }
.book-meta { display: flex; flex-direction: row; align-items: center; margin-top: 5px; }
.book-total { font-size: 10px; color: #657487; }
.book-level { margin-left: 9px; padding: 2px 6px; border-radius: 8px; font-size: 9px; color: #657487; background-color: #e4f8ef; }
.book-status { flex-shrink: 0; padding: 7px 11px; border-radius: 16px; font-size: 10px; }
.book-status-green { color: #ffffff; background-color: #16bd88; }
.book-status-yellow { color: #d99000; border: 1px solid #ffd66e; background-color: #fff4cf; }
.book-status-blue { color: #168ed0; border: 1px solid #9cd7ff; background-color: #e2f4ff; }
.book-status-gray { color: #68778b; border: 1px solid #d5dee9; background-color: #ffffff; }
.progress-heading { display: flex; flex-direction: row; justify-content: space-between; margin-top: 13px; }
.progress-label, .progress-value { font-size: 11px; color: #567084; }
.progress-value { text-align: right; }
.progress-track { height: 6px; margin-top: 7px; overflow: hidden; border-radius: 3px; background-color: rgba(150, 170, 185, 0.18); }
.progress-fill { height: 6px; border-radius: 3px; }
.progress-fill-green { background-color: #16bd88; }
.progress-fill-yellow { background-color: #ffc126; }
.progress-fill-blue { background-color: #159fe8; }
.progress-fill-gray { background-color: #ccd5df; }
</style>