347 lines
8.9 KiB
TypeScript
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 })
|
|
}
|