kindergarten_java/reading-platform-frontend/src/api/teacher.ts
En 1aec778dd6 fix: 修复教师端成长档案列表 loading 问题
- 删除 teacher.ts 中重复的 getTeacherCourseUsage 导出
- 修复 GrowthRecordView.vue 中字段名不匹配:items -> list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 16:36:57 +08:00

777 lines
20 KiB
TypeScript
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.

import { http } from './index';
import type {
TeacherCourseControllerGetTeacherSchedulesParams,
TeacherCourseControllerGetTeacherTimetableParams,
TeacherFeedbackControllerFindAllParams,
} from './generated/model';
// ============= 类型定义(保持向后兼容) =============
// ==================== 教师课程 API ====================
export interface TeacherCourseQueryParams {
pageNum?: number;
pageSize?: number;
grade?: string;
keyword?: string;
}
export interface TeacherCourse {
id: number;
name: string;
pictureBookName?: string;
coverImagePath?: string;
gradeTags: string[];
domainTags: string[];
duration: number;
avgRating: number;
usageCount: number;
publishedAt: string;
}
// 教师班级信息(更新:新增角色字段)
export interface TeacherClass {
id: number;
name: string;
grade: string;
studentCount: number;
lessonCount: number;
myRole: 'MAIN' | 'ASSIST' | 'CARE'; // 我在该班级的角色
isPrimary: boolean; // 是否班主任
}
// 班级教师信息
export interface TeacherClassTeacher {
teacherId: number;
teacherName: string;
teacherPhone?: string;
role: 'MAIN' | 'ASSIST' | 'CARE';
isPrimary: boolean;
}
// 获取教师可用的课程列表
export function getTeacherCourses(params: TeacherCourseQueryParams): Promise<{
items: TeacherCourse[];
total: number;
page: number;
pageSize: number;
}> {
// 使用 http 直接调用 API后端返回 list 字段,需要转换为 items
return http.get<{ list: TeacherCourse[]; total: number; pageNum: number; pageSize: number }>('/v1/teacher/courses', {
params: {
pageNum: params.pageNum,
pageSize: params.pageSize,
keyword: params.keyword,
category: params.grade,
},
}).then(res => ({
items: res.list || [],
total: res.total || 0,
page: res.pageNum || 1,
pageSize: res.pageSize || 10,
}));
}
// 获取课程详情
export function getTeacherCourse(id: number): Promise<any> {
return http.get(`/v1/teacher/courses/${id}`) as any;
}
// 获取教师的班级列表
export function getTeacherClasses(): Promise<TeacherClass[]> {
return http.get<TeacherClass[]>('/v1/teacher/classes');
}
// 获取教师所有学生列表(跨班级)
export function getTeacherStudents(params?: { pageNum?: number; pageSize?: number; keyword?: string }): Promise<{
items: Array<{
id: number;
name: string;
gender?: string;
birthDate?: string;
classId: number;
class?: {
id: number;
name: string;
grade: string;
};
parentName?: string;
parentPhone?: string;
createdAt: string;
}>;
total: number;
page: number;
pageSize: number;
}> {
return http.get('/v1/teacher/students', {
params: {
pageNum: params?.pageNum,
pageSize: params?.pageSize,
keyword: params?.keyword,
},
}) as any;
}
// 获取班级学生列表
export function getTeacherClassStudents(classId: number, params?: { pageNum?: number; pageSize?: number; keyword?: string }): Promise<{
items: Array<{
id: number;
name: string;
gender?: string;
birthDate?: string;
parentName?: string;
parentPhone?: string;
lessonCount?: number;
readingCount?: number;
createdAt: string;
}>;
total: number;
page: number;
pageSize: number;
class?: {
id: number;
name: string;
grade: string;
studentCount: number;
lessonCount: number;
};
}> {
return http.get(`/v1/teacher/classes/${classId}/students`, {
params: {
pageNum: params?.pageNum,
pageSize: params?.pageSize,
keyword: params?.keyword,
},
}) as any;
}
// 获取班级教师列表
export function getClassTeachers(classId: number): Promise<TeacherClassTeacher[]> {
return http.get(`/v1/teacher/classes/${classId}/teachers`) as any;
}
// ==================== 授课记录 API ====================
export interface CreateLessonDto {
courseId: number;
classId: number;
plannedDatetime?: string;
}
export interface FinishLessonDto {
overallRating?: string;
participationRating?: string;
completionNote?: string;
actualDuration?: number;
}
export interface StudentRecordDto {
focus?: number;
participation?: number;
interest?: number;
understanding?: number;
notes?: string;
}
// 获取授课记录列表
export function getLessons(params?: {
pageNum?: number;
pageSize?: number;
status?: string;
courseId?: number;
}): Promise<{
items: any[];
total: number;
page: number;
pageSize: number;
}> {
return http.get('/v1/teacher/lessons', {
params: {
pageNum: params?.pageNum,
pageSize: params?.pageSize,
status: params?.status,
startDate: params?.courseId, // 如果需要可以传其他参数
},
}) as any;
}
// 获取单个授课记录详情
export function getLesson(id: number): Promise<any> {
return http.get(`/v1/teacher/lessons/${id}`) as any;
}
// 创建授课记录(备课)
export function createLesson(data: CreateLessonDto): Promise<any> {
return http.post('/v1/teacher/lessons', data) as any;
}
// 开始上课
export function startLesson(id: number): Promise<any> {
return http.post(`/v1/teacher/lessons/${id}/start`) as any;
}
// 结束上课
export function finishLesson(id: number, data: FinishLessonDto): Promise<any> {
return http.post(`/v1/teacher/lessons/${id}/complete`, data) as any;
}
// 取消课程
export function cancelLesson(id: number): Promise<any> {
return http.post(`/v1/teacher/lessons/${id}/cancel`) as any;
}
// 保存学生评价记录
export function saveStudentRecord(
lessonId: number,
studentId: number,
data: StudentRecordDto
): Promise<any> {
return http.post(`/v1/teacher/lessons/${lessonId}/students/${studentId}/record`, data) as any;
}
// 获取课程所有学生记录
export interface StudentWithRecord {
id: number;
name: string;
gender?: string;
record: {
id: number;
focus?: number;
participation?: number;
interest?: number;
understanding?: number;
notes?: string;
} | null;
}
export interface StudentRecordsResponse {
lesson: {
id: number;
status: string;
className: string;
};
students: StudentWithRecord[];
}
export function getStudentRecords(lessonId: number): Promise<StudentRecordsResponse> {
return http.get(`/v1/teacher/lessons/${lessonId}/students/records`) as any;
}
// 批量保存学生评价记录
export function batchSaveStudentRecords(
lessonId: number,
records: Array<{ studentId: number } & StudentRecordDto>
): Promise<{ count: number; records: any[] }> {
return http.post(`/v1/teacher/lessons/${lessonId}/students/batch-records`, { records }) as any;
}
// ==================== 教师首页 API ====================
export interface DashboardData {
stats: {
classCount: number;
studentCount: number;
lessonCount: number;
courseCount: number;
};
todayLessons: Array<{
id: number;
courseId: number;
courseName: string;
pictureBookName?: string;
classId: number;
className: string;
plannedDatetime: string;
status: string;
duration: number;
}>;
recommendedCourses: Array<{
id: number;
name: string;
pictureBookName?: string;
coverImagePath?: string;
duration: number;
usageCount: number;
avgRating: number;
gradeTags: string[];
}>;
weeklyStats: {
lessonCount: number;
studentParticipation: number;
avgRating: number;
totalDuration: number;
};
recentActivities: Array<{
id: number;
type: string;
description: string;
time: string;
}>;
}
export const getTeacherDashboard = () =>
http.get('/v1/teacher/dashboard') as any;
export const getTodayLessons = () =>
http.get('/v1/teacher/today-lessons') as any;
export const getRecommendedCourses = () =>
http.get('/v1/teacher/recommended-courses') as any;
export const getWeeklyStats = () =>
http.get('/v1/teacher/weekly-stats') as any;
// ==================== 教师统计趋势 ====================
export interface TeacherLessonTrendItem {
month: string;
lessonCount: number;
avgRating: number;
}
export interface TeacherCourseUsageItem {
name: string;
value: number;
}
export const getTeacherLessonTrend = (months?: number) => {
return http.get('/v1/teacher/lesson-trend', { params: { months } }) as any;
};
export const getTeacherCourseUsage = () =>
http.get('/v1/teacher/course-usage') as any;
// ==================== 课程反馈 API ====================
export interface FeedbackDto {
designQuality?: number;
participation?: number;
goalAchievement?: number;
stepFeedbacks?: any;
pros?: string;
suggestions?: string;
activitiesDone?: any;
}
export interface LessonFeedback {
id: number;
lessonId: number;
teacherId: number;
designQuality?: number;
participation?: number;
goalAchievement?: number;
stepFeedbacks?: any;
pros?: string;
suggestions?: string;
activitiesDone?: any;
createdAt: string;
updatedAt: string;
teacher?: {
id: number;
name: string;
};
lesson?: {
id: number;
startDatetime?: string;
course: {
id: number;
name: string;
pictureBookName?: string;
};
class: {
id: number;
name: string;
};
};
}
// 提交课程反馈
export function submitFeedback(lessonId: number, data: FeedbackDto): Promise<LessonFeedback> {
return http.post(`/v1/teacher/lessons/${lessonId}/feedback`, data) as any;
}
// 获取课程反馈
export function getFeedback(lessonId: number): Promise<LessonFeedback | null> {
return http.get(`/v1/teacher/lessons/${lessonId}/feedback`) as any;
}
// ==================== 学校端反馈 API ====================
export interface FeedbackQueryParams {
pageNum?: number;
pageSize?: number;
teacherId?: number;
courseId?: number;
}
export interface FeedbackStats {
totalFeedbacks: number;
avgDesignQuality: number;
avgParticipation: number;
avgGoalAchievement: number;
courseStats: Record<number, { count: number; avgRating: number }>;
}
// 获取学校端反馈列表
export function getSchoolFeedbacks(params: FeedbackQueryParams): Promise<{
list: LessonFeedback[];
total: number;
pageNum: number;
pageSize: number;
}> {
return http.get<{ list: LessonFeedback[]; total: number; pageNum: number; pageSize: number }>('/v1/school/feedbacks', {
params: {
pageNum: params.pageNum,
pageSize: params.pageSize,
teacherId: params.teacherId,
courseId: params.courseId,
},
});
}
// 获取反馈统计
export function getFeedbackStats(): Promise<FeedbackStats> {
return http.get<FeedbackStats>('/v1/school/feedbacks/stats');
}
// 获取教师自己的反馈列表
export function getTeacherFeedbacks(params: FeedbackQueryParams): Promise<{
items: LessonFeedback[];
total: number;
page: number;
pageSize: number;
}> {
// 直接使用 http 调用后端 API
return http.get<{ list: LessonFeedback[]; total: number; pageNum: number; pageSize: number }>('/v1/teacher/feedbacks', {
params: {
pageNum: params.pageNum,
pageSize: params.pageSize,
},
}).then(res => ({
items: res.list || res.records || [],
total: res.total || 0,
page: res.pageNum || 1,
pageSize: res.pageSize || 10,
}));
}
// 获取教师自己的反馈统计
export function getTeacherFeedbackStats(): Promise<FeedbackStats> {
return http.get<{
totalFeedbacks: number;
avgDesignQuality: number;
avgParticipation: number;
avgGoalAchievement: number;
byType: Record<string, number>;
}>('/v1/teacher/feedbacks/stats').then(res => ({
totalFeedbacks: res.totalFeedbacks || 0,
avgDesignQuality: res.avgDesignQuality || 0,
avgParticipation: res.avgParticipation || 0,
avgGoalAchievement: res.avgGoalAchievement || 0,
courseStats: res.byType || {},
}));
}
// ==================== 课程进度追踪 API ====================
export interface LessonProgress {
id: number;
lessonIds: number[];
completedLessonIds: number[];
currentLessonId?: number;
currentStepId?: number;
progressData: any;
}
export interface SaveLessonProgressDto {
lessonIds?: number[];
completedLessonIds?: number[];
currentLessonId?: number;
currentStepId?: number;
progressData?: any;
}
// 保存课程进度
export function saveLessonProgress(lessonId: number, data: SaveLessonProgressDto): Promise<LessonProgress> {
return http.put(`/v1/teacher/lessons/${lessonId}/progress`, data) as any;
}
// 获取课程进度
export function getLessonProgress(lessonId: number): Promise<LessonProgress> {
return http.get(`/v1/teacher/lessons/${lessonId}/progress`) as any;
}
// ==================== 排课管理 API ====================
export interface TeacherSchedule {
id: number;
classId: number;
className: string;
courseId: number;
courseName: string;
teacherId?: number;
scheduledDate?: string;
scheduledTime?: string;
weekDay?: number;
repeatType: 'NONE' | 'DAILY' | 'WEEKLY';
source: 'SCHOOL' | 'TEACHER';
status: 'ACTIVE' | 'CANCELLED';
note?: string;
hasLesson: boolean;
lessonId?: number;
lessonStatus?: string;
createdAt: string;
}
export interface CreateTeacherScheduleDto {
classId: number;
courseId: number;
scheduledDate?: string;
scheduledTime?: string;
weekDay?: number;
repeatType?: 'NONE' | 'DAILY' | 'WEEKLY';
repeatEndDate?: string;
note?: string;
}
export interface TeacherTimetableItem {
date: string;
weekDay: number;
schedules: TeacherSchedule[];
}
export const getTeacherSchedules = (params?: {
startDate?: string;
endDate?: string;
status?: string;
pageNum?: number;
pageSize?: number;
}) => {
return http.get<{ list: TeacherSchedule[]; total: number }>('/v1/teacher/schedules', { params })
.then(res => ({
list: res.list || res.records || [],
total: res.total || 0,
}));
};
export const getTeacherTimetable = (params: { startDate: string; endDate: string }) => {
return http.get<any[]>('/v1/teacher/schedules/timetable', { params })
.then(res => {
// 后端返回的是数组格式或包含 schedules 的对象
if (Array.isArray(res)) {
return res;
}
return res?.schedules || res?.data || [];
});
};
export const getTodayTeacherSchedules = () =>
http.get<TeacherSchedule[]>('/v1/teacher/schedules/today');
export const createTeacherSchedule = (data: CreateTeacherScheduleDto) =>
http.post<TeacherSchedule>('/v1/teacher/schedules', data);
export const updateTeacherSchedule = (id: number, data: Partial<CreateTeacherScheduleDto> & { status?: string }) =>
http.put<TeacherSchedule>(`/v1/teacher/schedules/${id}`, data);
export const cancelTeacherSchedule = (id: number) =>
http.delete<{ message: string }>(`/v1/teacher/schedules/${id}`);
// ==================== 阅读任务 API ====================
export interface TeacherTask {
id: number;
tenantId: number;
title: string;
description?: string;
taskType: 'READING' | 'ACTIVITY' | 'HOMEWORK';
targetType: 'CLASS' | 'STUDENT';
status: 'DRAFT' | 'PUBLISHED' | 'ARCHIVED';
relatedCourseId?: number;
startDate: string;
endDate: string;
createdBy: number;
createdAt: string;
updatedAt: string;
course?: {
id: number;
name: string;
};
targetCount?: number;
completionCount?: number;
}
export interface TaskCompletion {
id: number;
taskId: number;
studentId: number;
status: 'PENDING' | 'IN_PROGRESS' | 'COMPLETED';
completedAt?: string;
feedback?: string;
parentFeedback?: string;
createdAt: string;
student: {
id: number;
name: string;
gender?: string;
class?: {
id: number;
name: string;
};
};
}
export interface CreateTeacherTaskDto {
title: string;
description?: string;
taskType: 'READING' | 'ACTIVITY' | 'HOMEWORK';
targetType: 'CLASS' | 'STUDENT';
targetIds: number[];
relatedCourseId?: number;
startDate: string;
endDate: string;
}
export interface UpdateTaskCompletionDto {
status: 'PENDING' | 'IN_PROGRESS' | 'COMPLETED';
feedback?: string;
}
// 获取教师任务列表
export const getTeacherTasks = (params?: { pageNum?: number; pageSize?: number; keyword?: string; type?: string; status?: string }) =>
http.get<{ list: any[]; total: number; pageNum: number; pageSize: number }>('/v1/teacher/tasks', { params })
.then(res => ({
items: res.list || [],
total: res.total || 0,
page: res.pageNum || 1,
pageSize: res.pageSize || 10,
}));
export const getTeacherTask = (id: number) =>
http.get(`/v1/teacher/tasks/${id}`) as any;
// 教师端没有这些接口,返回空数据
export const getTeacherTaskCompletions = (_taskId: number) =>
Promise.resolve([]);
export const createTeacherTask = (data: CreateTeacherTaskDto) =>
http.post('/v1/teacher/tasks', data) as any;
export const updateTeacherTask = (id: number, data: Partial<CreateTeacherTaskDto> & { status?: string }) =>
http.put(`/v1/teacher/tasks/${id}`, data) as any;
export const deleteTeacherTask = (id: number) =>
http.delete(`/v1/teacher/tasks/${id}`) as any;
// 后端没有这些接口
export const updateTaskCompletion = (_taskId: number, _studentId: number, _data: UpdateTaskCompletionDto) =>
Promise.reject(new Error('接口未实现'));
export const sendTaskReminder = (_taskId: number) =>
Promise.reject(new Error('接口未实现'));
// ==================== 任务模板 API ====================
export interface TaskTemplate {
id: number;
tenantId: number;
name: string;
description?: string;
taskType: 'READING' | 'ACTIVITY' | 'HOMEWORK';
relatedCourseId?: number;
defaultDuration: number;
isDefault: boolean;
status: string;
createdBy: number;
createdAt: string;
updatedAt: string;
course?: {
id: number;
name: string;
pictureBookName?: string;
};
}
export interface CreateTaskTemplateDto {
name: string;
description?: string;
taskType: 'READING' | 'ACTIVITY' | 'HOMEWORK';
relatedCourseId?: number;
defaultDuration?: number;
isDefault?: boolean;
}
export interface CreateTaskFromTemplateDto {
templateId: number;
targetIds: number[];
targetType: 'CLASS' | 'STUDENT';
startDate?: string;
}
export const getTaskTemplates = () =>
http.get<{ records: any[]; total: number }>('/v1/teacher/task-templates')
.then(res => ({
items: res.records || [],
total: res.total || 0,
}));
export const getTaskTemplate = (id: number) =>
http.get(`/v1/teacher/task-templates/${id}`) as any;
export const getDefaultTaskTemplate = (taskType: string) =>
http.get('/v1/teacher/task-templates/default', { params: { taskType } }) as any;
export const createTaskFromTemplate = (data: CreateTaskFromTemplateDto) =>
http.post('/v1/teacher/tasks/from-template', data) as any;
// ==================== 任务统计 API ====================
export interface TaskStats {
totalTasks: number;
publishedTasks: number;
completedTasks: number;
inProgressTasks: number;
pendingCount: number;
totalCompletions: number;
completionRate: number;
}
export interface TaskStatsByType {
[key: string]: {
total: number;
completed: number;
rate: number;
};
}
export interface TaskStatsByClass {
classId: number;
className: string;
grade: string;
total: number;
completed: number;
rate: number;
}
export interface MonthlyTaskStats {
month: string;
tasks: number;
completions: number;
completed: number;
rate: number;
}
export const getTaskStats = () =>
http.get('/v1/teacher/tasks/stats') as any;
export const getTaskStatsByType = () =>
http.get('/v1/teacher/tasks/stats/by-type') as any;
export const getTaskStatsByClass = () =>
http.get('/v1/teacher/tasks/stats/by-class') as any;
export const getMonthlyTaskStats = (months?: number) => {
return http.get('/v1/teacher/tasks/stats/monthly', { params: { months } }) as any;
};