Files
App.k12.Parents/api/student.ts
T

347 lines
8.9 KiB
TypeScript

/**
* 学生相关API接口
*/
import { post, get } from '../utils/request'
import type { ApiResponse } from '../utils/request'
// ==================== 类型定义 ====================
// 学生信息类型
export type StudentInfo = {
id: string
name: string
account: string
avatar: string
grade: string
class: string
}
// 首页当前学生基础信息
export type StudentHomeProfile = {
id: string
name: string
account: string
grade: string
school: string
avatar: string
comprehensiveLevel: 'excellent' | 'good' | 'qualified' | 'needs_improvement'
}
// 家长已绑定学生的选择列表项
export type BoundStudentSummary = {
id: string
name: string
account: string
grade: string
school: string
avatar: string
}
// 首页今日学习概览,所有数值均归属于 studentId 对应的学生。
export type StudentHomeMetrics = {
studentId: string
onlineToday: boolean
checkedInToday: boolean
learningMinutesToday: number
accuracyToday: number | null
learningDaysThisWeek: number
pendingHomeworkCount: number
updatedAt: string
}
export type TodayLearningCourse = {
id: string
time: string
subject: string
content: string
checkedIn: boolean
}
export type TodayLearningScore = {
accuracy: number
yesterdayAccuracy: number
change: number
}
export type TodayLearningPoint = {
id: string
label: string
points: number
}
export type StudyReportSubject = {
id: string
name: string
}
export type StudyReportTrendPoint = {
label: string
value: number
average: number
valueHeight: number
averageHeight: number
}
export type StudyReportTrend = {
subjectId: string
points: StudyReportTrendPoint[]
}
export type StudyReportActivityPoint = {
label: string
studyMinutes: number
plannedMinutes: number
newMasteredCount: number
studyHeight: number
plannedHeight: number
newMasteredHeight: number
}
export type StudyReportActivity = {
summary: string
activeDays: number
totalDurationText: string
points: StudyReportActivityPoint[]
}
export type StudyReportSubjectMastery = {
subjectName: string
masteredCount: number
totalCount: number
masteredPercent: number
}
export type StudyReportPeriod = {
rangeText: string
statusTitle: string
statusDescription: string
newMasteredPoints: number
consecutiveDays: number
averageAccuracy: number
scaleLabels: string[]
trends: StudyReportTrend[]
activity: StudyReportActivity
subjectMasteries: StudyReportSubjectMastery[]
}
export type StudentStudyReport = {
studentId: string
studentName: string
studentGrade: string
studentClass: string
updatedAtText: string
subjects: StudyReportSubject[]
week: StudyReportPeriod
month: StudyReportPeriod
}
export type TodayLearningDetail = {
studentId: string
studentName: string
dateText: string
checkedIn: boolean
learningMinutes: number
answerMinutes: number
answerCount: number
completedPackages: number
totalPackages: number
masteredPoints: number
courses: TodayLearningCourse[]
score: TodayLearningScore
pointsTotal: number
pointDetails: TodayLearningPoint[]
}
export type VocabularyBook = {
id: string
name: string
subtitle: string
totalWords: number
learnedWords: number
status: 'learning' | 'unfinished' | 'completed' | 'not_started'
statusText: string
levelText: string
color: 'green' | 'yellow' | 'blue' | 'gray'
}
export type StudentVocabulary = {
studentId: string
studentName: string
studentGrade: string
studentClass: string
bookCount: number
books: VocabularyBook[]
}
export type GrowthPointRecord = {
id: string
title: string
timeText: string
points: number
icon: 'calendar' | 'assignment' | 'streak' | 'accuracy' | 'mastery' | 'note'
}
export type StudentGrowth = {
studentId: string
studentName: string
studentGrade: string
studentClass: string
pointsBalance: number
level: number
rank: number
streakDays: number
totalPoints: number
records: GrowthPointRecord[]
}
export type LearningTaskItem = {
id: string
title: string
status: 'not_started' | 'in_progress' | 'success' | 'failed'
statusText: string
accuracyText: string
answerText: string
deadlineText: string
}
export type LearningTaskGroup = {
id: string
subject: string
unit: string
lesson: string
startText: string
endText: string
knowledgeCount: number
note: string
tasks: LearningTaskItem[]
}
export type StudentLearningTasks = {
studentId: string
studentName: string
studentGrade: string
studentClass: string
pendingCount: number
completedCount: number
failedCount: number
groups: LearningTaskGroup[]
}
export type StudentAlertLevel = 'critical' | 'high' | 'medium' | 'low'
export type StudentAlert = {
id: string
level: StudentAlertLevel
title: string
content: string
occurredAt: string
isRead: boolean
}
export type StudentAlertList = {
list: StudentAlert[]
pagination: {
page: number
pageSize: number
total: number
hasMore: boolean
}
}
// 验证学生二维码请求参数
export type VerifyQRCodeParams = {
qrCode: string
account: string
name: string
}
// 验证学生账号请求参数
export type VerifyAccountParams = {
account: string
name: string
}
// ==================== API方法 ====================
/**
* 验证学生二维码
*/
export function apiVerifyStudentQRCode(params: VerifyQRCodeParams): Promise<ApiResponse<StudentInfo> | null> {
return apiVerifyStudentAccount({ account: params.account, name: params.name })
}
/**
* 验证学生账号
*/
export function apiVerifyStudentAccount(params: VerifyAccountParams): Promise<ApiResponse<StudentInfo> | null> {
return get<any>('/api/v1/Parents/VerifyStudent', { RealName: params.name, Account: params.account }).then((res) => {
if (!res || !res.data) return null
return { code: res.code, message: res.message, data: { id: String(res.data.userId), name: res.data.name, account: res.data.account, avatar: res.data.avatar || '', grade: res.data.gradeLevel || '', class: res.data.className || '' } }
})
}
/**
* 检查手机号是否已注册
*/
export function apiCheckPhone(phone: string): Promise<ApiResponse<{ exists: boolean }> | null> {
return get<{ exists: boolean }>(`/api/parent/check-phone?phone=${phone}`)
}
/**
* 获取当前家长默认绑定学生的首页基础信息。
* 服务端根据 Authorization Token 识别家长并校验学生绑定关系。
*/
export function apiGetStudentHomeProfile(studentId?: string, showLoading: boolean = true): Promise<ApiResponse<StudentHomeProfile> | null> {
const url = studentId ? `/api/parent/home-profile?studentId=${studentId}` : '/api/parent/home-profile'
return get<StudentHomeProfile>(url, undefined, { showLoading })
}
/**
* 获取当前家长绑定的全部学生,用于首页切换学生。
*/
export function apiGetBoundStudents(): Promise<ApiResponse<{ students: BoundStudentSummary[], currentStudentId: string | null }> | null> {
return get<{ students: BoundStudentSummary[], currentStudentId: string | null }>('/api/parent/students')
}
/**
* 获取指定学生的首页今日学习概览。
*/
export function apiGetStudentHomeMetrics(studentId: string, showLoading: boolean = true): Promise<ApiResponse<StudentHomeMetrics> | null> {
return get<StudentHomeMetrics>(`/api/parent/home-metrics?studentId=${studentId}`, undefined, { showLoading })
}
/**
* 获取学生今日学习详情及课程打卡记录。
*/
export function apiGetTodayLearningDetail(studentId: string, showLoading: boolean = true): Promise<ApiResponse<TodayLearningDetail> | null> {
return get<TodayLearningDetail>(`/api/parent/today-learning?studentId=${studentId}`, undefined, { showLoading })
}
/**
* 获取学生学情报告。接口一次返回周报、月报和全部科目趋势数据。
*/
export function apiGetStudentStudyReport(studentId: string, showLoading: boolean = true): Promise<ApiResponse<StudentStudyReport> | null> {
return get<StudentStudyReport>(`/api/parent/study-report?studentId=${studentId}`, undefined, { showLoading })
}
export function apiGetStudentVocabulary(studentId: string, showLoading: boolean = true): Promise<ApiResponse<StudentVocabulary> | null> {
return get<StudentVocabulary>(`/api/parent/vocabulary?studentId=${studentId}`, undefined, { showLoading })
}
export function apiGetStudentGrowth(studentId: string, showLoading: boolean = true): Promise<ApiResponse<StudentGrowth> | null> {
return get<StudentGrowth>(`/api/parent/growth?studentId=${studentId}`, undefined, { showLoading })
}
export function apiGetStudentLearningTasks(studentId: string, showLoading: boolean = true): Promise<ApiResponse<StudentLearningTasks> | null> {
return get<StudentLearningTasks>(`/api/parent/learning-tasks?studentId=${studentId}`, undefined, { showLoading })
}
/**
* 获取当前学生的预警信息。首页调用时 limit 固定为 3。
*/
export function apiGetStudentAlerts(studentId: string, page: number = 1, pageSize: number = 20, limit?: number, showLoading: boolean = true): Promise<ApiResponse<StudentAlertList> | null> {
const suffix = limit ? `limit=${limit}` : `page=${page}&pageSize=${pageSize}`
return get<StudentAlertList>(`/api/parent/alerts?studentId=${studentId}&${suffix}`, undefined, { showLoading })
}