kindergarten_java/reading-platform-frontend/src/api/teacher.ts

772 lines
18 KiB
TypeScript
Raw Normal View History

import { http } from "./index";
import { readingApi } from "./client";
import type {
ResultPageResultCourse,
Course as ApiCourse,
} from "./generated/model";
// ==================== 教师课程 API ====================
export interface TeacherCourseQueryParams {
page?: 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;
}> {
// 使用 Orval 生成的教师课程分页接口,并适配为原有扁平结构
return readingApi.getCoursePage(params as any).then((res) => {
const wrapped = res as ResultPageResultCourse;
const page = wrapped.data;
return {
items:
(page?.items as ApiCourse[] | undefined)?.map((c) => ({
id: c.id ?? 0,
name: c.name ?? "",
pictureBookName: (c as any).pictureBookName,
coverImagePath: (c as any).coverImagePath,
gradeTags: ((c as any).gradeTags as string[]) ?? [],
domainTags: ((c as any).domainTags as string[]) ?? [],
duration: (c as any).duration ?? 0,
avgRating: (c as any).avgRating ?? 0,
usageCount: (c as any).usageCount ?? 0,
publishedAt: (c as any).publishedAt ?? "",
})) ?? [],
total: page?.total ?? 0,
page: page?.page ?? params.page ?? 1,
pageSize: page?.pageSize ?? params.pageSize ?? 10,
};
});
}
// 获取课程详情
export function getTeacherCourse(id: number): Promise<unknown> {
return readingApi.getCourse1(id).then((res) => res);
}
// 获取教师的班级列表
export function getTeacherClasses(): Promise<TeacherClass[]> {
2026-03-11 16:27:37 +08:00
return http.get("/api/v1/teacher/courses/classes");
}
// 获取教师所有学生列表(跨班级)
export function getTeacherStudents(params?: {
page?: 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;
}> {
2026-03-11 16:27:37 +08:00
return http.get("/api/v1/teacher/students", { params });
}
// 获取班级学生列表
export function getTeacherClassStudents(
classId: number,
params?: { page?: 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(`/api/v1/teacher/classes/${classId}/students`, { params });
}
// 获取班级教师列表
export function getClassTeachers(
classId: number,
): Promise<TeacherClassTeacher[]> {
return http.get(`/api/v1/teacher/classes/${classId}/teachers`);
}
// ==================== 授课记录 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?: {
page?: number;
pageSize?: number;
status?: string;
courseId?: number;
}): Promise<{
items: any[];
total: number;
page: number;
pageSize: number;
}> {
2026-03-11 16:27:37 +08:00
return http.get("/api/v1/teacher/lessons", { params });
}
// 获取单个授课记录详情
export function getLesson(id: number): Promise<unknown> {
return http.get(`/api/v1/teacher/lessons/${id}`);
}
// 创建授课记录(备课)
export function createLesson(data: CreateLessonDto): Promise<unknown> {
2026-03-11 16:27:37 +08:00
return http.post("/api/v1/teacher/lessons", data);
}
// 开始上课
export function startLesson(id: number): Promise<unknown> {
return http.post(`/api/v1/teacher/lessons/${id}/start`);
}
// 结束上课
export function finishLesson(
id: number,
data: FinishLessonDto,
): Promise<unknown> {
return http.post(`/api/v1/teacher/lessons/${id}/finish`, data);
}
// 取消课程
export function cancelLesson(id: number): Promise<unknown> {
return http.post(`/api/v1/teacher/lessons/${id}/cancel`);
}
// 保存学生评价记录
export function saveStudentRecord(
lessonId: number,
studentId: number,
data: StudentRecordDto,
): Promise<unknown> {
return http.post(
`/api/v1/teacher/lessons/${lessonId}/students/${studentId}/record`,
data,
);
}
// 获取课程所有学生记录
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(`/api/v1/teacher/lessons/${lessonId}/student-records`);
}
// 批量保存学生评价记录
export function batchSaveStudentRecords(
lessonId: number,
records: Array<{ studentId: number } & StudentRecordDto>,
): Promise<{ count: number; records: any[] }> {
return http.post(
`/api/v1/teacher/lessons/${lessonId}/student-records/batch`,
{ records },
);
}
// ==================== 教师首页 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 = () =>
2026-03-11 16:27:37 +08:00
http.get<DashboardData>("/api/v1/teacher/dashboard");
export const getTodayLessons = () =>
2026-03-11 16:27:37 +08:00
http.get<DashboardData["todayLessons"]>("/api/v1/teacher/dashboard/today");
export const getRecommendedCourses = () =>
2026-03-11 16:27:37 +08:00
http.get<DashboardData["recommendedCourses"]>(
"/api/v1/teacher/dashboard/recommend",
);
export const getWeeklyStats = () =>
2026-03-11 16:27:37 +08:00
http.get<DashboardData["weeklyStats"]>("/api/v1/teacher/dashboard/weekly");
// ==================== 教师统计趋势 ====================
export interface TeacherLessonTrendItem {
month: string;
lessonCount: number;
avgRating: number;
}
export interface TeacherCourseUsageItem {
name: string;
value: number;
}
export const getTeacherLessonTrend = (months?: number) =>
2026-03-11 16:27:37 +08:00
http.get<TeacherLessonTrendItem[]>("/api/v1/teacher/dashboard/lesson-trend", {
params: { months },
});
export const getTeacherCourseUsage = () =>
2026-03-11 16:27:37 +08:00
http.get<TeacherCourseUsageItem[]>("/api/v1/teacher/dashboard/course-usage");
// ==================== 课程反馈 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(`/api/v1/teacher/lessons/${lessonId}/feedback`, data);
}
// 获取课程反馈
export function getFeedback(lessonId: number): Promise<LessonFeedback | null> {
return http.get(`/api/v1/teacher/lessons/${lessonId}/feedback`);
}
// ==================== 学校端反馈 API ====================
export interface FeedbackQueryParams {
page?: 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<{
items: LessonFeedback[];
total: number;
page: number;
pageSize: number;
}> {
2026-03-11 16:27:37 +08:00
return http.get("/api/v1/school/feedbacks", { params });
}
// 获取反馈统计
export function getFeedbackStats(): Promise<FeedbackStats> {
2026-03-11 16:27:37 +08:00
return http.get("/api/v1/school/feedbacks/stats");
}
// 获取教师自己的反馈列表
export function getTeacherFeedbacks(params: FeedbackQueryParams): Promise<{
items: LessonFeedback[];
total: number;
page: number;
pageSize: number;
}> {
2026-03-11 16:27:37 +08:00
return http.get("/api/v1/teacher/feedbacks", { params });
}
// 获取教师自己的反馈统计
export function getTeacherFeedbackStats(): Promise<FeedbackStats> {
2026-03-11 16:27:37 +08:00
return http.get("/api/v1/teacher/feedbacks/stats");
}
// ==================== 排课管理 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 SchedulePlanUpdateRequest {
teacherId?: number;
startDate?: string;
endDate?: string;
startTime?: string;
endTime?: string;
status?: string;
note?: string;
}
export interface TeacherTimetableItem {
date: string;
weekDay: number;
schedules: TeacherSchedule[];
}
export const getTeacherSchedules = (params?: {
startDate?: string;
endDate?: string;
status?: string;
page?: number;
pageSize?: number;
}) =>
http.get<{
items: TeacherSchedule[];
total: number;
page: number;
pageSize: number;
2026-03-11 16:27:37 +08:00
}>("/api/v1/teacher/schedules", { params });
export const getTeacherTimetable = (params: {
startDate: string;
endDate: string;
}) =>
2026-03-11 16:27:37 +08:00
http.get<TeacherTimetableItem[]>("/api/v1/teacher/schedules/timetable", {
params,
});
export const getTodayTeacherSchedules = () =>
2026-03-11 16:27:37 +08:00
http.get<TeacherSchedule[]>("/api/v1/teacher/schedules/today");
export const createTeacherSchedule = (data: CreateTeacherScheduleDto) =>
2026-03-11 16:27:37 +08:00
http.post<TeacherSchedule>("/api/v1/teacher/schedules", data);
export const updateTeacherSchedule = (
id: number,
data: Partial<CreateTeacherScheduleDto> & { status?: string },
2026-03-11 16:27:37 +08:00
) => http.put<TeacherSchedule>(`/api/v1/teacher/schedules/${id}`, data);
export const cancelTeacherSchedule = (id: number) =>
2026-03-11 16:27:37 +08:00
http.delete<{ message: string }>(`/api/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?: {
page?: number;
pageSize?: number;
status?: string;
taskType?: string;
keyword?: string;
}) =>
http.get<{
items: TeacherTask[];
total: number;
page: number;
pageSize: number;
2026-03-11 16:27:37 +08:00
}>("/api/v1/teacher/tasks", { params });
export const getTeacherTask = (id: number) =>
2026-03-11 16:27:37 +08:00
http.get<TeacherTask>(`/api/v1/teacher/tasks/${id}`);
export const getTeacherTaskCompletions = (
taskId: number,
params?: {
page?: number;
pageSize?: number;
status?: string;
},
) =>
http.get<{
items: TaskCompletion[];
total: number;
page: number;
pageSize: number;
2026-03-11 16:27:37 +08:00
}>(`/api/v1/teacher/tasks/${taskId}/completions`, { params });
export const createTeacherTask = (data: CreateTeacherTaskDto) =>
2026-03-11 16:27:37 +08:00
http.post<TeacherTask>("/api/v1/teacher/tasks", data);
export const updateTeacherTask = (
id: number,
data: Partial<CreateTeacherTaskDto> & { status?: string },
2026-03-11 16:27:37 +08:00
) => http.put<TeacherTask>(`/api/v1/teacher/tasks/${id}`, data);
export const deleteTeacherTask = (id: number) =>
2026-03-11 16:27:37 +08:00
http.delete<{ message: string }>(`/api/v1/teacher/tasks/${id}`);
export const updateTaskCompletion = (
taskId: number,
studentId: number,
data: UpdateTaskCompletionDto,
) =>
http.put<TaskCompletion>(
2026-03-11 16:27:37 +08:00
`/api/v1/teacher/tasks/${taskId}/completions/${studentId}`,
data,
);
export const sendTaskReminder = (taskId: number) =>
2026-03-11 16:27:37 +08:00
http.post<{ message: string }>(`/api/v1/teacher/tasks/${taskId}/remind`);
// ==================== 任务模板 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 = (params?: {
page?: number;
pageSize?: number;
taskType?: string;
keyword?: string;
}) =>
http.get<{
items: TaskTemplate[];
total: number;
page: number;
pageSize: number;
2026-03-11 16:27:37 +08:00
}>("/api/v1/teacher/task-templates", { params });
export const getTaskTemplate = (id: number) =>
2026-03-11 16:27:37 +08:00
http.get<TaskTemplate>(`/api/v1/teacher/task-templates/${id}`);
export const getDefaultTaskTemplate = (taskType: string) =>
2026-03-11 16:27:37 +08:00
http.get<TaskTemplate | null>(
`/api/v1/teacher/task-templates/default/${taskType}`,
);
export const createTaskFromTemplate = (data: CreateTaskFromTemplateDto) =>
2026-03-11 16:27:37 +08:00
http.post<TeacherTask>("/api/v1/teacher/tasks/from-template", data);
// ==================== 任务统计 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;
}
2026-03-11 16:27:37 +08:00
export const getTaskStats = () =>
http.get<TaskStats>("/api/v1/teacher/tasks/stats");
export const getTaskStatsByType = () =>
2026-03-11 16:27:37 +08:00
http.get<TaskStatsByType>("/api/v1/teacher/tasks/stats/by-type");
export const getTaskStatsByClass = () =>
2026-03-11 16:27:37 +08:00
http.get<TaskStatsByClass[]>("/api/v1/teacher/tasks/stats/by-class");
export const getMonthlyTaskStats = (months?: number) =>
2026-03-11 16:27:37 +08:00
http.get<MonthlyTaskStats[]>("/api/v1/teacher/tasks/stats/monthly", {
params: { months },
});