diff --git a/API 对比分析.md b/API 对比分析.md deleted file mode 100644 index 6d1ff5f..0000000 --- a/API 对比分析.md +++ /dev/null @@ -1,161 +0,0 @@ -# API 对比分析报告 - -## 概述 -对比 reading-platform-backend (Node.js/NestJS) 和 reading-platform-java (Spring Boot) 的 API 接口差异 - ---- - -## 已补全的接口 - -### 1. 任务管理相关接口(SchoolTaskController, TeacherTaskController) - -#### 任务统计接口 -- `GET /api/v1/school/tasks/stats` - 获取任务统计数据 -- `GET /api/v1/school/tasks/stats/by-type` - 按任务类型统计 -- `GET /api/v1/school/tasks/stats/by-class` - 按班级统计 -- `GET /api/v1/school/tasks/stats/monthly` - 月度统计趋势 - -#### 任务完成情况接口 -- `GET /api/v1/school/tasks/:id/completions` - 获取任务完成情况分页 -- `PUT /api/v1/school/tasks/:taskId/completions/:studentId` - 更新任务完成状态 - -#### 任务模板接口 -- `GET /api/v1/school/task-templates` - 获取任务模板列表 -- `GET /api/v1/school/task-templates/:id` - 获取单个模板 -- `GET /api/v1/school/task-templates/default/:taskType` - 获取默认模板 -- `POST /api/v1/school/task-templates` - 创建模板 -- `PUT /api/v1/school/task-templates/:id` - 更新模板 -- `DELETE /api/v1/school/task-templates/:id` - 删除模板 -- `POST /api/v1/school/tasks/from-template` - 从模板创建任务 - -### 2. 通知相关接口 - -#### 学校管理员通知(SchoolNotificationController - 新增) -- `GET /api/v1/school/notifications` - 获取通知列表 -- `GET /api/v1/school/notifications/:id` - 根据 ID 获取通知 -- `GET /api/v1/school/notifications/unread-count` - 获取未读数量 -- `POST /api/v1/school/notifications/:id/read` - 标记已读 -- `POST /api/v1/school/notifications/read-all` - 全部标记已读 - -### 3. 排课和课表相关接口(SchoolScheduleController) -- `GET /api/v1/school/schedules/timetable` - 获取课表(带日期范围) -- `POST /api/v1/school/schedules/batch` - 批量创建排课 -- `GET /api/v1/school/schedules/templates/:id` - 获取单个模板 -- `PUT /api/v1/school/schedules/templates/:id` - 更新模板 -- `POST /api/v1/school/schedules/templates/:id/apply` - 应用模板 - -### 4. 新增 DTO -- `TaskTemplateCreateRequest` - 任务模板创建请求 -- `TaskTemplateUpdateRequest` - 任务模板更新请求 -- `CreateTaskFromTemplateRequest` - 从模板创建任务请求 -- `SchedulePlanCreateRequest` - 课表计划创建请求 -- `ScheduleTemplateApplyRequest` - 课表模板应用请求 - ---- - -## 仍需补全的接口 - -### P1 - 重要功能 - -#### 1. 成长档案接口(SchoolGrowthController, TeacherGrowthController) -- `GET /api/v1/school/students/:studentId/growth-records` - 按学生查询成长档案 -- `GET /api/v1/school/classes/:classId/growth-records` - 按班级查询成长档案 -- `GET /api/v1/teacher/classes/:classId/growth-records` - 教师端按班级查询 - -#### 2. 教师端课时增强接口(TeacherLessonController) -- `POST /api/v1/teacher/lessons/:id/finish` - 完成课时(带反馈数据) -- `POST /api/v1/teacher/lessons/:id/students/:studentId/record` - 保存学生记录 -- `GET /api/v1/teacher/lessons/:id/student-records` - 获取学生记录 -- `POST /api/v1/teacher/lessons/:id/student-records/batch` - 批量保存学生记录 -- `POST /api/v1/teacher/lessons/:id/feedback` - 提交反馈 -- `GET /api/v1/teacher/lessons/:id/feedback` - 获取反馈 - -#### 3. 教师端课程增强接口(TeacherCourseController) -- `GET /api/v1/teacher/courses/classes` - 获取班级列表 -- `GET /api/v1/teacher/students` - 获取所有学生 -- `GET /api/v1/teacher/classes/:id/students` - 获取班级学生 -- `GET /api/v1/teacher/classes/:id/teachers` - 获取班级教师 -- `GET /api/v1/teacher/schedules/timetable` - 获取课表 -- `GET /api/v1/teacher/schedules/today` - 获取今天排课 -- `POST /api/v1/teacher/schedules` - 创建排课 -- `PUT /api/v1/teacher/schedules/:id` - 更新排课 -- `DELETE /api/v1/teacher/schedules/:id` - 取消排课 - -#### 4. 班级管理接口(SchoolClassController) -- `GET /api/v1/school/classes/:id/students` - 获取班级学生 -- `GET /api/v1/school/classes/:id/teachers` - 获取班级教师 -- `POST /api/v1/school/classes/:id/teachers` - 添加班级教师 -- `PUT /api/v1/school/classes/:id/teachers/:teacherId` - 更新班级教师 -- `DELETE /api/v1/school/classes/:id/teachers/:teacherId` - 移除班级教师 -- `POST /api/v1/school/students/:id/transfer` - 学生调班 -- `GET /api/v1/school/students/:id/history` - 学生调班历史 -- `POST /api/v1/school/students/import` - 批量导入学生 -- `GET /api/v1/school/students/import/template` - 获取导入模板 - -### P2 - 辅助功能 - -#### 1. 统计报告接口(SchoolStatsController) -- `GET /api/v1/school/stats/teachers` - 活跃教师统计 -- `GET /api/v1/school/stats/courses` - 课程使用统计 -- `GET /api/v1/school/stats/activities` - 最近活动 -- `GET /api/v1/school/stats/lesson-trend` - 课时趋势 -- `GET /api/v1/school/stats/course-distribution` - 课程分布 -- `GET /api/v1/school/reports/overview` - 概览报告 -- `GET /api/v1/school/reports/teachers` - 教师报告 -- `GET /api/v1/school/reports/courses` - 课程报告 -- `GET /api/v1/school/reports/students` - 学生报告 - -#### 2. 导出接口增强(SchoolExportController) -- `GET /api/v1/school/export/lessons?startDate=&endDate=` - 导出课时(带日期范围) -- `GET /api/v1/school/export/teacher-stats?startDate=&endDate=` - 导出教师统计 -- `GET /api/v1/school/export/student-stats?classId=` - 导出学生统计(按班级) - -#### 3. 课程包/套餐接口 -- `GET /api/v1/school/package` - 获取套餐信息 -- `GET /api/v1/school/package/usage` - 获取套餐使用情况 - -#### 4. 家长相关接口 -- `POST /api/v1/school/parents/:parentId/children/:studentId` - 添加孩子到家长 -- `DELETE /api/v1/school/parents/:parentId/children/:studentId` - 从家长移除孩子 - -#### 5. 管理员课程接口 -- `GET /api/v1/admin/courses/:id/stats` - 课程统计 -- `GET /api/v1/admin/courses/:id/validate` - 验证课程 -- `GET /api/v1/admin/courses/:id/versions` - 版本历史 -- `POST /api/v1/admin/courses/:id/submit` - 提交审核 -- `POST /api/v1/admin/courses/:id/withdraw` - 撤销审核 -- `POST /api/v1/admin/courses/:id/approve` - 审核通过 -- `POST /api/v1/admin/courses/:id/reject` - 审核驳回 -- `POST /api/v1/admin/courses/:id/direct-publish` - 直接发布 -- `POST /api/v1/admin/courses/:id/publish` - 发布 -- `POST /api/v1/admin/courses/:id/unpublish` - 下架 -- `POST /api/v1/admin/courses/:id/republish` - 重新发布 - -#### 6. 资源接口增强 -- `POST /api/v1/admin/resources/items/batch-delete` - 批量删除资源项 -- `GET /api/v1/admin/resources/stats` - 资源统计 - -#### 7. 反馈接口 -- `GET /api/v1/teacher/feedbacks` - 获取反馈列表 -- `GET /api/v1/teacher/feedbacks/stats` - 获取反馈统计 -- `GET /api/v1/school/feedbacks` - 获取反馈列表(学校端) -- `GET /api/v1/school/feedbacks/stats` - 获取反馈统计(学校端) - -#### 8. 认证接口 -- `GET /api/v1/auth/profile` - 获取用户信息 -- `POST /api/v1/auth/logout` - 登出 - ---- - -## 总结 - -本次补全了以下主要功能: -1. 任务管理:统计、模板、完成情况更新 -2. 通知:学校管理员通知接口 -3. 排课:课表模板、批量创建、应用模板 - -下一步建议优先补全: -1. 成长档案按学生/班级查询接口 -2. 教师端课时反馈接口 -3. 班级管理相关接口 -4. 学生调班和批量导入接口 diff --git a/Service 重构总结.md b/Service 重构总结.md deleted file mode 100644 index ac6deab..0000000 --- a/Service 重构总结.md +++ /dev/null @@ -1,132 +0,0 @@ -# Service 层重构总结 - -## 重构时间 -2026-03-10 - -## 重构目的 -将 Service 层从"直接 class 实现"重构为"interface + impl"模式,符合 Spring 最佳实践。 - -## 重构的 Service 列表 - -本次重构共完成了 14 个 Service 的 interface + impl 模式改造: - -### 新增的 Interface 文件 - -| 序号 | 接口文件 | 实现类文件 | -|------|----------|------------| -| 1 | `AdminStatsService.java` | `AdminStatsServiceImpl.java` | -| 2 | `CourseLessonService.java` | `CourseLessonServiceImpl.java` | -| 3 | `CoursePackageService.java` | `CoursePackageServiceImpl.java` | -| 4 | `ExportService.java` | `ExportServiceImpl.java` | -| 5 | `FileUploadService.java` | `FileUploadServiceImpl.java` | -| 6 | `OperationLogService.java` | `OperationLogServiceImpl.java` | -| 7 | `ResourceService.java` | `ResourceServiceImpl.java` | -| 8 | `SchoolCourseService.java` | `SchoolCourseServiceImpl.java` | -| 9 | `SystemSettingService.java` | `SystemSettingServiceImpl.java` | -| 10 | `TeacherDashboardService.java` | `TeacherDashboardServiceImpl.java` | -| 11 | `ScheduleService.java` | `ScheduleServiceImpl.java` | -| 12 | `ThemeService.java` | `ThemeServiceImpl.java` | -| 13 | `TenantService.java` | `TenantServiceImpl.java` (已存在) | -| 14 | `SchoolStatsService.java` | `SchoolStatsServiceImpl.java` | - -### 已有的 Interface + Impl 模式 Service - -以下 Service 在重构前已经是 interface + impl 模式: - -1. `AuthService` → `AuthServiceImpl` -2. `ClassService` → `ClassServiceImpl` -3. `StudentService` → `StudentServiceImpl` -4. `TaskService` → `TaskServiceImpl` -5. `CourseService` → `CourseServiceImpl` -6. `GrowthRecordService` → `GrowthRecordServiceImpl` -7. `LessonService` → `LessonServiceImpl` -8. `NotificationService` → `NotificationServiceImpl` -9. `ParentService` → `ParentServiceImpl` -10. `TeacherService` → `TeacherServiceImpl` -11. `TokenService` → `TokenServiceImpl` - -## 重构模式 - -所有 Service 遵循以下模式: - -### Interface 定义 -```java -package com.reading.platform.service; - -import java.util.List; -import java.util.Map; - -/** - * 服务接口 - */ -public interface XxxService { - - /** - * 方法描述 - */ - List getXxxList(Long id); - - /** - * 方法描述 - */ - Xxx createXxx(XxxCreateRequest request); -} -``` - -### Impl 实现类 -```java -package com.reading.platform.service.impl; - -import com.reading.platform.mapper.XxxMapper; -import com.reading.platform.service.XxxService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -/** - * 服务实现类 - */ -@Service -@RequiredArgsConstructor -public class XxxServiceImpl implements XxxService { - - private final XxxMapper xxxMapper; - - @Override - public List getXxxList(Long id) { - // 业务逻辑 - } - - @Override - public Xxx createXxx(XxxCreateRequest request) { - // 业务逻辑 - } -} -``` - -## 架构优势 - -1. **依赖倒置**:Controller 依赖接口而非具体实现 -2. **易于测试**:可以通过 Mock 接口进行测试 -3. **易于扩展**:可以轻松切换不同的实现 -4. **代码规范**:符合 Spring 官方推荐的最佳实践 - -## 编译验证 - -```bash -cd reading-platform-java -mvn clean compile -DskipTests -``` - -编译结果:**BUILD SUCCESS** - -## 文件统计 - -- 接口文件:25 个 -- 实现类文件:25 个 -- 总计:50 个 Service 相关文件 - -## 后续建议 - -1. 为新实现的接口添加单元测试 -2. 在 CI/CD 流程中确保编译使用 JDK 17 -3. 保持新增 Service 遵循 interface + impl 模式 diff --git a/reading-platform-frontend/src/apis/SwaggerType.ts b/reading-platform-frontend/src/apis/SwaggerType.ts new file mode 100644 index 0000000..770ee5b --- /dev/null +++ b/reading-platform-frontend/src/apis/SwaggerType.ts @@ -0,0 +1,18 @@ +// type Swagger = 'get' | 'post'; +// http://192.168.1.110:8280/stat/doc.html#/home +export interface RequestType { + param: { + path?: string[] | number[] | string | number; + query?: { [key: string]: string | number }; + data?: { [key: string]: string | number }; + }; + response: any; +} +export interface SwaggerType { + [key: string]: { + get?: RequestType; + post?: RequestType; + put?: RequestType; + delete?: RequestType; + }; +} diff --git a/reading-platform-frontend/src/apis/apis.ts b/reading-platform-frontend/src/apis/apis.ts new file mode 100644 index 0000000..c153404 --- /dev/null +++ b/reading-platform-frontend/src/apis/apis.ts @@ -0,0 +1,55 @@ +import { SwaggerType } from './SwaggerType'; +export default interface SwaggerInterface extends SwaggerType { + /*** + * 视频大盘-卡片核心指标 + */ + '/test/xxxx': { + get: { + param: { + query: { + /**统计类型:1=周,2=月,3=季度,4=年,5=自定义 */ + type: number; + /**开始日期(yyyy-MM-dd),type=5 时必填 */ + startDate?: string; + /**结束日期(yyyy-MM-dd),type=5 时必填 */ + endDate?: string; + /**机构ID,不传则从登录用户部门获取 */ + institutionId?: number; + /**分类ID */ + categoryId?: number; + }; + }; + response: { + /**访问人次 */ + userCount: { + /**数值 */ + value: number; + /**环比百分比 */ + ratio: number; + }; + /**点击量 */ + clickCount: { + value: number; + ratio: number; + }; + /**观看时长(小时) */ + watchDuration: { + value: number; + ratio: number; + }; + /**请求数 */ + requestCount: { + value: number; + ratio: number; + }; + /**出口流量(GB) */ + trafficOut: { + value: number; + ratio: number; + }; + /**存储用量,暂未实现 */ + storageUsage: null; + }; + }; + }; +} diff --git a/reading-platform-frontend/src/apis/fetch.ts b/reading-platform-frontend/src/apis/fetch.ts new file mode 100644 index 0000000..bed9156 --- /dev/null +++ b/reading-platform-frontend/src/apis/fetch.ts @@ -0,0 +1,234 @@ +import type { UrlKey, MethodKey, Param, Response } from './index'; +// import { message } from 'ant-design-vue'; +// import { LocalStorageKey } from '@/utils/useLocalStorage'; +// import { getAppEnvConfig } from '@/utils/env'; +import { reactive, ref } from 'vue'; +import { defHttp } from '/@/utils/http/axios'; +// const { VITE_BASE_API, VITE_PREFIX_API } = getAppEnvConfig(); +export type FetchOptions = Omit & { + type?: 'arrayBuffer' | 'blob' | 'formData' | 'json' | 'text'; + payloadType?: 'json' | 'text' | 'formData' | 'form-urlencoded'; + successMsg?: string; + noMsg?: boolean; + apiType?: 'BOOK'; +}; + +// const payloadMapping = { +// json: 'application/json;charset=UTF-8', +// text: 'text/plain;charset=UTF-8', +// formData: 'multipart/form-data', +// 'form-urlencoded': 'application/x-www-form-urlencoded', +// }; + +// // const noAuthUrl: UrlKey[] = ['/activity/bbs/login', '/activity/bbs/randomImage', '/activity/bbs/bbsSection/all', '/activity/bbs/bbsPost/list', '/activity/bbs/bbsPost/queryById']; +// const noAuthUrl: UrlKey[] = ['/activity/bbs/login', '/activity/bbs/randomImage']; +// function useAuthToken() { +// // const _token = localStorage.getItem(LocalStorageKey.tokenKey); +// return { +// token: '', +// // token: _token && _token.trim().length > 0 ? _token : null, +// }; +// } + +/** + * 请求header + * @description: contentTyp + */ +export enum ConfigEnum { + // TOKEN + TOKEN = 'Authorization', + XTOKEN = 'X-Access-Token', + // TIMESTAMP + TIMESTAMP = 'X-TIMESTAMP', + // Sign + Sign = 'X-Sign', + // 租户id + TENANT_ID = 'X-Tenant-Id', + // 版本 + VERSION = 'X-Version', + // 低代码应用ID + X_LOW_APP_ID = 'X-Low-App-ID', +} + +// export const baseToken = ref(useAuthToken().token); +// export function getHeaders() { +// const defaultHeaders = { +// // "Content-Type": payloadMapping[payloadType] +// }; + +// let authHeaders = { +// Authorization: `Bearer ${baseToken.value}`, +// }; +// return Object.assign(defaultHeaders, authHeaders); +// } + +type MethodType = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT'; +/** + * + * @param url 路径,直接从swagger上拷贝下来的路径,包括{id}这类的动态路径 + * @param param FetchParams 请求参数,分为 path query body 分别对应 路径参数(类似/delete/{id})、查询参数(类似/query?id=123)、body(post body参数,将会JSON.stringfiy为字符串) + * @param options FetchOptions fetch 去除body、method的原生参数,增加 type 用于格式化掉用res.json()类型的功能。 + * @returns fetch + */ +export default async function request>( + url: U, + method: M, + params?: Param | undefined, + { apiType, type = 'json', payloadType = 'json', successMsg, noMsg, headers, ...restOptions }: FetchOptions = {} +): Promise> { + const requestMethod = (method as string).toLowerCase() as MethodType; + + const { path, query, data } = (params || {}) as { + path?: string[] | string; + query?: any; + data?: any; + }; + // let iUrl = `${VITE_BASE_API}${VITE_PREFIX_API}${url}`; + let iUrl = `${url}`; + + if (path) { + if (Array.isArray(path)) { + iUrl = `${iUrl}/${path.join('/')}`; + } else { + iUrl = `${iUrl}/${path}`; + } + } + iUrl = getQuery(iUrl, filterEmpty(query)); + + return defHttp.request({ + method: requestMethod, + url: iUrl, + data: filterEmpty(data), + }); + + // const defaultHeaders = { + // 'Content-Type': payloadMapping[payloadType], + // }; + + // // 将token加入进去 + // let authHeaders: any = { + // // 'Content-Type': 'application/json' + // }; + // if (!noAuthUrl.includes(url)) { + // // const { token } = useAuthToken(); + // authHeaders[ConfigEnum.TOKEN] = baseToken.value ? `Bearer ${baseToken.value}` : ''; + // // authHeaders[ConfigEnum.XTOKEN] = token; + // } + // const param: any = { + // ...restOptions, + // method: requestMethod, + // // body: JSON.stringify(filterEmpty(data)), + // headers: Object.assign(defaultHeaders, headers, authHeaders), + // }; + // if (requestMethod.toLowerCase() !== 'get') { + // param.body = JSON.stringify(filterEmpty(data)); + // } + // return fetch(iUrl, param) + // .then((response) => response.json()) + // .then((res: any) => { + // if (res.code === 200 || res.code === 0) { + // if (requestMethod.toLowerCase() != 'get' || successMsg) { + // if (!noMsg) { + // showToast(successMsg || '操作成功', 'success'); + // } + // } + // return res.result; + // } else if (res.code === 401) { + // baseToken.value = null; + // showToast('登录已过期', 'error'); + // } else { + // let msg = res.message; + // if (res.code === 402) { + // } else if (res.code === 403) { + // } else { + // } + // showToast(msg, 'error'); + // } + + // throw new Error(JSON.stringify(res)); + // }) + // .catch((err) => { + // console.error('fetch Error', err); + + // throw err; + // }); +} +function filterEmpty(obj: any = {}): any { + const _obj: any = {}; + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + const element = obj[key]; + if (!(element === null || element === undefined || String(element).trim().length < 1)) { + _obj[key] = element; + } + } + } + return _obj; +} + +function getQuery(iUrl: string, query: { [key: string]: string }): string { + if (!query) { + return iUrl; + } + const keys: string[] = []; + for (const key in query) { + keys.push(`${key}=${query[key]}`); + } + return `${iUrl}?${keys.join('&')}`; +} + +// type MsgType = 'error' | 'success' | 'loading' | 'info' | 'warning'; +// function showToast(msg: string, type: MsgType) { +// message[type](msg); +// } + +type CallbackObjs = { + loading: boolean; + callback: Function[][]; +}; +type Requests = { + userOpenid: CallbackObjs; +}; +type RequestsName = keyof Requests; +const requests = reactive({ + userOpenid: { + loading: false, + callback: [], + }, +}); +/** + * + * 请求节流封装 + * @param name 求节nameKey + * @param requestCallback + * @returns + */ +export async function getRequests(name: RequestsName, requestCallback: Function) { + // const requestInfo = requests[name]; + // + if (requests[name].loading) { + return new Promise<[]>((resolve, reject) => { + requests[name].callback.push([resolve, reject]); + }); + } + requests[name].loading = true; + + try { + const data = await requestCallback(); + requests[name].callback.forEach((callbacks) => { + const [resolve, reject] = callbacks; + !!resolve && resolve(data); + }); + requests[name].loading = false; + requests[name].callback = []; + return data; + } catch (error) { + requests[name].callback.forEach((callbacks) => { + const [resolve, reject] = callbacks; + reject([]); + }); + } finally { + requests[name].loading = false; + requests[name].callback = []; + } +} diff --git a/reading-platform-frontend/src/apis/index.ts b/reading-platform-frontend/src/apis/index.ts new file mode 100644 index 0000000..8c3d582 --- /dev/null +++ b/reading-platform-frontend/src/apis/index.ts @@ -0,0 +1,24 @@ +import apis from './apis'; +type SwaggerInterface = apis; + +export type UrlKey = keyof SwaggerInterface; +export type MethodKey = string & keyof SwaggerInterface[U]; + +type SwaggerInterfaceSingle> = SwaggerInterface[U][M]; +type SwaggerField> = keyof SwaggerInterfaceSingle; +type SwaggerFieldType< + U extends UrlKey, + M extends MethodKey, + F extends SwaggerField, +> = SwaggerInterfaceSingle[F]; + +export type Param> = SwaggerFieldType< + U, + M, + 'param' & SwaggerField +>; +export type Response> = SwaggerFieldType< + U, + M, + 'response' & SwaggerField +>; diff --git a/reading-platform-java/src/main/java/com/reading/platform/entity/ClassTeacher.java b/reading-platform-java/src/main/java/com/reading/platform/entity/ClassTeacher.java index 86d6ef3..ca6da84 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/entity/ClassTeacher.java +++ b/reading-platform-java/src/main/java/com/reading/platform/entity/ClassTeacher.java @@ -1,29 +1,56 @@ package com.reading.platform.entity; import com.baomidou.mybatisplus.annotation.*; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; /** - * 班级-教师关联实体 + * 班级 - 教师关联实体 */ @Data @TableName("class_teachers") +@Schema(description = "班级教师关联") public class ClassTeacher { - @TableId(type = IdType.AUTO) - private Long id; + @Schema(description = "ID", accessMode = Schema.AccessMode.READ_ONLY) + @TableId(type = IdType.ASSIGN_ID) + private String id; - private Long classId; + private String classId; - private Long teacherId; + private String teacherId; private String role; + /** + * 是否主教 + */ + private Boolean isPrimary; + + /** + * 排序 + */ + private Integer sortOrder; + + @Schema(description = "创建人用户名", accessMode = Schema.AccessMode.READ_ONLY) + @TableField(fill = FieldFill.INSERT) + private String createdBy; + + @Schema(description = "更新人用户名", accessMode = Schema.AccessMode.READ_ONLY) + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updatedBy; + + @Schema(description = "创建时间", accessMode = Schema.AccessMode.READ_ONLY) @TableField(fill = FieldFill.INSERT) private LocalDateTime createdAt; + @Schema(description = "更新时间", accessMode = Schema.AccessMode.READ_ONLY) + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + @Schema(description = "逻辑删除标志", accessMode = Schema.AccessMode.READ_ONLY) @TableLogic private Integer deleted; diff --git a/reading-platform-java/src/main/java/com/reading/platform/entity/ClassTeachers.java b/reading-platform-java/src/main/java/com/reading/platform/entity/ClassTeachers.java new file mode 100644 index 0000000..3994ee3 --- /dev/null +++ b/reading-platform-java/src/main/java/com/reading/platform/entity/ClassTeachers.java @@ -0,0 +1,57 @@ +package com.reading.platform.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 班级-教师关联实体 + */ +@Data +@TableName("class_teachers") +@Schema(description = "班级教师关联") +public class ClassTeacher { + + @Schema(description = "ID", accessMode = Schema.AccessMode.READ_ONLY) + @TableId(type = IdType.ASSIGN_ID) + private String id; + + private String classId; + + private String teacherId; + + private String role; + + /** + * 是否主教 + */ + private Boolean isPrimary; + + /** + * 排序 + */ + private Integer sortOrder; + + @Schema(description = "创建人用户名", accessMode = Schema.AccessMode.READ_ONLY) + @TableField(fill = FieldFill.INSERT) + private String createdBy; + + @Schema(description = "更新人用户名", accessMode = Schema.AccessMode.READ_ONLY) + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updatedBy; + + @Schema(description = "创建时间", accessMode = Schema.AccessMode.READ_ONLY) + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + @Schema(description = "更新时间", accessMode = Schema.AccessMode.READ_ONLY) + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + @Schema(description = "逻辑删除标志", accessMode = Schema.AccessMode.READ_ONLY) + @TableLogic + private Integer deleted; + +} diff --git a/前端实际调用接口对比.md b/前端实际调用接口对比.md deleted file mode 100644 index a98dd5b..0000000 --- a/前端实际调用接口对比.md +++ /dev/null @@ -1,346 +0,0 @@ -# 前端实际调用但 Java 后端缺失的接口 - -## 分析方法 -- 对比 `reading-platform-frontend/src/api/generated/api.ts` 中的实际调用 -- 检查 `reading-platform-java/src/main/java/com/reading/platform/controller` 中的实现 -- 只列出前端实际调用但 Java 后端缺失的接口 - ---- - -## ✅ 已实现的接口列表 - -### 1. 认证接口 (AuthController) -- ✅ `POST /api/v1/auth/login` - 登录 -- ✅ `POST /api/v1/auth/logout` - 登出 -- ✅ `POST /api/v1/auth/change-password` - 修改密码 -- ✅ `GET /api/v1/auth/me` - 获取当前用户信息 - -### 2. 文件接口 (FileUploadController) -- ✅ `POST /api/v1/files/upload` - 上传文件 -- ✅ `DELETE /api/v1/files/delete` - 删除文件 - -### 3. 教师端 - 任务 (TeacherTaskController) -- ✅ `GET /api/v1/teacher/tasks` - 获取任务分页 -- ✅ `POST /api/v1/teacher/tasks` - 创建任务 -- ✅ `GET /api/v1/teacher/tasks/{id}` - 根据 ID 获取任务 -- ✅ `PUT /api/v1/teacher/tasks/{id}` - 更新任务 -- ✅ `DELETE /api/v1/teacher/tasks/{id}` - 删除任务 - -### 4. 教师端 - 课时 (TeacherLessonController) -- ✅ `GET /api/v1/teacher/lessons` - 获取课时分页 -- ✅ `POST /api/v1/teacher/lessons` - 创建课时 -- ✅ `GET /api/v1/teacher/lessons/{id}` - 根据 ID 获取课时 -- ✅ `PUT /api/v1/teacher/lessons/{id}` - 更新课时 -- ✅ `POST /api/v1/teacher/lessons/{id}/start` - 开始课时 -- ✅ `POST /api/v1/teacher/lessons/{id}/complete` - 完成课时 -- ✅ `POST /api/v1/teacher/lessons/{id}/cancel` - 取消课时 -- ✅ `GET /api/v1/teacher/lessons/today` - 获取今天课时 - -### 5. 教师端 - 成长档案 (TeacherGrowthController) -- ✅ `GET /api/v1/teacher/growth-records` - 获取成长档案分页 -- ✅ `POST /api/v1/teacher/growth-records` - 创建成长档案 -- ✅ `GET /api/v1/teacher/growth-records/{id}` - 根据 ID 获取成长档案 -- ✅ `PUT /api/v1/teacher/growth-records/{id}` - 更新成长档案 -- ✅ `DELETE /api/v1/teacher/growth-records/{id}` - 删除成长档案 - -### 6. 教师端 - 通知 (TeacherNotificationController) -- ✅ `GET /api/v1/teacher/notifications` - 获取通知分页 -- ✅ `GET /api/v1/teacher/notifications/{id}` - 根据 ID 获取通知 -- ✅ `GET /api/v1/teacher/notifications/unread-count` - 获取未读数量 -- ✅ `POST /api/v1/teacher/notifications/{id}/read` - 标记已读 -- ✅ `POST /api/v1/teacher/notifications/read-all` - 全部标记已读 - -### 7. 教师端 - 课程 (TeacherCourseController) -- ✅ `GET /api/v1/teacher/courses` - 获取课程分页 -- ✅ `GET /api/v1/teacher/courses/{id}` - 根据 ID 获取课程 -- ✅ `GET /api/v1/teacher/courses/all` - 获取所有课程 - -### 8. 教师端 - 课程课时 (TeacherCourseLessonController) -- ✅ `GET /api/v1/teacher/courses/{courseId}/lessons` - 获取课程课时列表 -- ✅ `GET /api/v1/teacher/courses/{courseId}/lessons/{id}` - 根据 ID 获取课时 - -### 9. 教师端 - 校本课程 (TeacherSchoolCourseController) -- ✅ `GET /api/v1/teacher/school-courses` - 获取校本课程分页 -- ✅ `GET /api/v1/teacher/school-courses/{id}` - 根据 ID 获取校本课程 - -### 10. 教师端 - 课表 (TeacherScheduleController) -- ✅ `GET /api/v1/teacher/schedules` - 获取课表计划分页 -- ✅ `GET /api/v1/teacher/schedules/{id}` - 根据 ID 获取课表计划 - -### 11. 教师端 - 仪表板 (TeacherDashboardController) -- ✅ `GET /api/v1/teacher/dashboard` - 获取仪表板数据 -- ✅ `GET /api/v1/teacher/dashboard/weekly` - 获取周统计 -- ✅ `GET /api/v1/teacher/dashboard/today` - 获取今天数据 - -### 12. 学校管理员 - 教师 (SchoolTeacherController) -- ✅ `GET /api/v1/school/teachers` - 获取教师分页 -- ✅ `POST /api/v1/school/teachers` - 创建教师 -- ✅ `GET /api/v1/school/teachers/{id}` - 根据 ID 获取教师 -- ✅ `PUT /api/v1/school/teachers/{id}` - 更新教师 -- ✅ `DELETE /api/v1/school/teachers/{id}` - 删除教师 -- ✅ `POST /api/v1/school/teachers/{id}/reset-password` - 重置密码 - -### 13. 学校管理员 - 任务 (SchoolTaskController) -- ✅ `GET /api/v1/school/tasks` - 获取任务分页 -- ✅ `POST /api/v1/school/tasks` - 创建任务 -- ✅ `GET /api/v1/school/tasks/{id}` - 根据 ID 获取任务 -- ✅ `PUT /api/v1/school/tasks/{id}` - 更新任务 -- ✅ `DELETE /api/v1/school/tasks/{id}` - 删除任务 - -### 14. 学校管理员 - 学生 (SchoolStudentController) -- ✅ `GET /api/v1/school/students` - 获取学生分页 -- ✅ `POST /api/v1/school/students` - 创建学生 -- ✅ `GET /api/v1/school/students/{id}` - 根据 ID 获取学生 -- ✅ `PUT /api/v1/school/students/{id}` - 更新学生 -- ✅ `DELETE /api/v1/school/students/{id}` - 删除学生 - -### 15. 学校管理员 - 校本课程 (SchoolCourseController) -- ✅ `GET /api/v1/school/school-courses` - 获取校本课程分页 -- ✅ `POST /api/v1/school/school-courses` - 创建校本课程 -- ✅ `GET /api/v1/school/school-courses/{id}` - 根据 ID 获取校本课程 -- ✅ `PUT /api/v1/school/school-courses/{id}` - 更新校本课程 -- ✅ `DELETE /api/v1/school/school-courses/{id}` - 删除校本课程 - -### 16. 学校管理员 - 课表 (SchoolScheduleController) -- ✅ `GET /api/v1/school/schedules` - 获取课表计划分页 -- ✅ `POST /api/v1/school/schedules` - 创建课表计划 -- ✅ `GET /api/v1/school/schedules/{id}` - 根据 ID 获取课表计划 -- ✅ `PUT /api/v1/school/schedules/{id}` - 更新课表计划 -- ✅ `DELETE /api/v1/school/schedules/{id}` - 删除课表计划 -- ✅ `GET /api/v1/school/schedules/templates` - 获取课表模板分页 -- ✅ `POST /api/v1/school/schedules/templates` - 创建课表模板 -- ✅ `GET /api/v1/school/schedules/templates/{id}` - 根据 ID 获取课表模板 -- ✅ `PUT /api/v1/school/schedules/templates/{id}` - 更新课表模板 -- ✅ `DELETE /api/v1/school/schedules/templates/{id}` - 删除课表模板 -- ✅ `POST /api/v1/school/schedules/templates/{id}/apply` - 应用课表模板 - -### 17. 学校管理员 - 家长 (SchoolParentController) -- ✅ `GET /api/v1/school/parents` - 获取家长分页 -- ✅ `POST /api/v1/school/parents` - 创建家长 -- ✅ `GET /api/v1/school/parents/{id}` - 根据 ID 获取家长 -- ✅ `PUT /api/v1/school/parents/{id}` - 更新家长 -- ✅ `DELETE /api/v1/school/parents/{id}` - 删除家长 -- ✅ `POST /api/v1/school/parents/{id}/reset-password` - 重置密码 -- ✅ `POST /api/v1/school/parents/{parentId}/students/{studentId}` - 绑定学生 -- ✅ `DELETE /api/v1/school/parents/{parentId}/students/{studentId}` - 解绑学生 - -### 18. 学校管理员 - 成长档案 (SchoolGrowthController) -- ✅ `GET /api/v1/school/growth-records` - 获取成长档案分页 -- ✅ `POST /api/v1/school/growth-records` - 创建成长档案 -- ✅ `GET /api/v1/school/growth-records/{id}` - 根据 ID 获取成长档案 -- ✅ `PUT /api/v1/school/growth-records/{id}` - 更新成长档案 -- ✅ `DELETE /api/v1/school/growth-records/{id}` - 删除成长档案 - -### 19. 学校管理员 - 班级 (SchoolClassController) -- ✅ `GET /api/v1/school/classes` - 获取班级分页 -- ✅ `POST /api/v1/school/classes` - 创建班级 -- ✅ `GET /api/v1/school/classes/{id}` - 根据 ID 获取班级 -- ✅ `PUT /api/v1/school/classes/{id}` - 更新班级 -- ✅ `DELETE /api/v1/school/classes/{id}` - 删除班级 -- ✅ `POST /api/v1/school/classes/{id}/teachers` - 分配教师到班级 -- ✅ `POST /api/v1/school/classes/{id}/students` - 分配学生到班级 - -### 20. 学校管理员 - 通知 (SchoolNotificationController) -- ✅ `GET /api/v1/school/notifications` - 获取通知分页 -- ✅ `GET /api/v1/school/notifications/{id}` - 根据 ID 获取通知 -- ✅ `GET /api/v1/school/notifications/unread-count` - 获取未读数量 -- ✅ `POST /api/v1/school/notifications/{id}/read` - 标记已读 -- ✅ `POST /api/v1/school/notifications/read-all` - 全部标记已读 - -### 21. 学校管理员 - 统计 (SchoolStatsController) -- ✅ `GET /api/v1/school/stats` - 获取统计数据 - -### 22. 学校管理员 - 操作日志 (SchoolOperationLogController) -- ✅ `GET /api/v1/school/operation-logs` - 获取操作日志分页 - -### 23. 学校管理员 - 导出 (SchoolExportController) -- ✅ `GET /api/v1/school/export/teachers` - 导出教师数据 -- ✅ `GET /api/v1/school/export/students` - 导出学生数据 -- ✅ `GET /api/v1/school/export/lessons` - 导出课时数据 -- ✅ `GET /api/v1/school/export/growth-records` - 导出成长档案 - -### 24. 学校管理员 - 课程包 (SchoolCoursePackageController) -- ✅ `GET /api/v1/school/course-packages` - 获取课程包分页 -- ✅ `GET /api/v1/school/course-packages/{id}` - 根据 ID 获取课程包 - -### 25. 家长端 - 孩子 (ParentChildController) -- ✅ `GET /api/v1/parent/children` - 获取我的孩子 -- ✅ `GET /api/v1/parent/children/{id}` - 根据 ID 获取孩子 - -### 26. 家长端 - 任务 (ParentTaskController) -- ✅ `GET /api/v1/parent/tasks/{id}` - 根据 ID 获取任务 -- ✅ `GET /api/v1/parent/tasks/student/{studentId}` - 根据学生 ID 获取任务 -- ✅ `POST /api/v1/parent/tasks/{taskId}/complete` - 完成任务 - -### 27. 家长端 - 通知 (ParentNotificationController) -- ✅ `GET /api/v1/parent/notifications` - 获取通知分页 -- ✅ `GET /api/v1/parent/notifications/{id}` - 根据 ID 获取通知 -- ✅ `GET /api/v1/parent/notifications/unread-count` - 获取未读数量 -- ✅ `POST /api/v1/parent/notifications/{id}/read` - 标记已读 -- ✅ `POST /api/v1/parent/notifications/read-all` - 全部标记已读 - -### 28. 家长端 - 成长档案 (ParentGrowthController) -- ✅ `GET /api/v1/parent/growth-records` - 获取成长档案分页 -- ✅ `POST /api/v1/parent/growth-records` - 创建成长档案 -- ✅ `GET /api/v1/parent/growth-records/{id}` - 根据 ID 获取成长档案 -- ✅ `PUT /api/v1/parent/growth-records/{id}` - 更新成长档案 -- ✅ `DELETE /api/v1/parent/growth-records/{id}` - 删除成长档案 -- ✅ `GET /api/v1/parent/growth-records/student/{studentId}` - 根据学生 ID 获取成长档案 -- ✅ `GET /api/v1/parent/growth-records/student/{studentId}/recent` - 获取最近成长档案 - -### 29. 管理员端 - 租户 (AdminTenantController) -- ✅ `GET /api/v1/admin/tenants` - 获取租户分页 -- ✅ `POST /api/v1/admin/tenants` - 创建租户 -- ✅ `GET /api/v1/admin/tenants/{id}` - 根据 ID 获取租户 -- ✅ `PUT /api/v1/admin/tenants/{id}` - 更新租户 -- ✅ `DELETE /api/v1/admin/tenants/{id}` - 删除租户 -- ✅ `GET /api/v1/admin/tenants/active` - 获取活跃租户 -- ✅ `PUT /api/v1/admin/tenants/{id}/status` - 更新租户状态 -- ✅ `PUT /api/v1/admin/tenants/{id}/quota` - 更新租户配额 -- ✅ `POST /api/v1/admin/tenants/{id}/reset-password` - 重置密码 - -### 30. 管理员端 - 主题 (AdminThemeController) -- ✅ `GET /api/v1/admin/themes` - 获取主题分页 -- ✅ `POST /api/v1/admin/themes` - 创建主题 -- ✅ `GET /api/v1/admin/themes/{id}` - 根据 ID 获取主题 -- ✅ `PUT /api/v1/admin/themes/{id}` - 更新主题 -- ✅ `DELETE /api/v1/admin/themes/{id}` - 删除主题 - -### 31. 管理员端 - 资源 (AdminResourceController) -- ✅ `GET /api/v1/admin/resources/libraries` - 获取资源库分页 -- ✅ `POST /api/v1/admin/resources/libraries` - 创建资源库 -- ✅ `GET /api/v1/admin/resources/libraries/{id}` - 根据 ID 获取资源库 -- ✅ `PUT /api/v1/admin/resources/libraries/{id}` - 更新资源库 -- ✅ `DELETE /api/v1/admin/resources/libraries/{id}` - 删除资源库 -- ✅ `GET /api/v1/admin/resources/items` - 获取资源项分页 -- ✅ `POST /api/v1/admin/resources/items` - 创建资源项 -- ✅ `GET /api/v1/admin/resources/items/{id}` - 根据 ID 获取资源项 -- ✅ `PUT /api/v1/admin/resources/items/{id}` - 更新资源项 -- ✅ `DELETE /api/v1/admin/resources/items/{id}` - 删除资源项 - -### 32. 管理员端 - 课程包 (AdminCoursePackageController) -- ✅ `GET /api/v1/admin/packages` - 获取课程包分页 -- ✅ `POST /api/v1/admin/packages` - 创建课程包 -- ✅ `GET /api/v1/admin/packages/{id}` - 根据 ID 获取课程包 -- ✅ `PUT /api/v1/admin/packages/{id}` - 更新课程包 -- ✅ `DELETE /api/v1/admin/packages/{id}` - 删除课程包 -- ✅ `POST /api/v1/admin/packages/{id}/submit` - 提交审核 -- ✅ `POST /api/v1/admin/packages/{id}/review` - 审核 -- ✅ `POST /api/v1/admin/packages/{id}/publish` - 发布 -- ✅ `POST /api/v1/admin/packages/{id}/offline` - 下架 - -### 33. 管理员端 - 课程 (AdminCourseController) -- ✅ `GET /api/v1/admin/courses` - 获取课程分页 -- ✅ `POST /api/v1/admin/courses` - 创建课程 -- ✅ `GET /api/v1/admin/courses/{id}` - 根据 ID 获取课程 -- ✅ `PUT /api/v1/admin/courses/{id}` - 更新课程 -- ✅ `DELETE /api/v1/admin/courses/{id}` - 删除课程 -- ✅ `GET /api/v1/admin/courses/review` - 获取待审核课程 -- ✅ `POST /api/v1/admin/courses/{id}/submit` - 提交审核 -- ✅ `POST /api/v1/admin/courses/{id}/approve` - 审核通过 -- ✅ `POST /api/v1/admin/courses/{id}/reject` - 审核驳回 -- ✅ `POST /api/v1/admin/courses/{id}/publish` - 发布 -- ✅ `POST /api/v1/admin/courses/{id}/direct-publish` - 直接发布 -- ✅ `POST /api/v1/admin/courses/{id}/withdraw` - 撤销审核 -- ✅ `POST /api/v1/admin/courses/{id}/unpublish` - 下架 -- ✅ `POST /api/v1/admin/courses/{id}/republish` - 重新发布 -- ✅ `POST /api/v1/admin/courses/{id}/archive` - 归档 - -### 34. 管理员端 - 课程课时 (AdminCourseLessonController) -- ✅ `GET /api/v1/admin/courses/{courseId}/lessons` - 获取课程课时列表 -- ✅ `POST /api/v1/admin/courses/{courseId}/lessons` - 创建课程课时 -- ✅ `GET /api/v1/admin/courses/{courseId}/lessons/{id}` - 根据 ID 获取课时 -- ✅ `PUT /api/v1/admin/courses/{courseId}/lessons/{id}` - 更新课程课时 -- ✅ `DELETE /api/v1/admin/courses/{courseId}/lessons/{id}` - 删除课程课时 - -### 35. 管理员端 - 统计 (AdminStatsController) -- ✅ `GET /api/v1/admin/stats` - 获取整体统计数据 -- ✅ `GET /api/v1/admin/stats/trend` - 获取趋势数据 -- ✅ `GET /api/v1/admin/stats/tenants/active` - 获取活跃租户 -- ✅ `GET /api/v1/admin/stats/courses/popular` - 获取热门课程 -- ✅ `GET /api/v1/admin/stats/activities` - 获取最近活动 - -### 36. 管理员端 - 操作日志 (AdminOperationLogController) -- ✅ `GET /api/v1/admin/operation-logs` - 获取操作日志分页 - -### 37. 管理员端 - 设置 (AdminSettingsController) -- ✅ `GET /api/v1/admin/settings` - 获取系统设置 -- ✅ `PUT /api/v1/admin/settings` - 更新系统设置 - ---- - -## ❌ 缺失接口列表 - -### 1. 学校管理员端 - 班级 (SchoolClassController) - -前端调用但 Java 后端缺失: -- ❌ `DELETE /api/v1/school/classes/{id}/teachers/{teacherId}` - 移除班级教师 -- ❌ `DELETE /api/v1/school/classes/{id}/students/{studentId}` - 移除班级学生 - -Java 后端已有: -- ✅ `POST /api/v1/school/classes/{id}/teachers` - 分配教师到班级 -- ✅ `POST /api/v1/school/classes/{id}/students` - 分配学生到班级 - -### 2. 学校管理员端 - 学生 (SchoolStudentController) - -前端调用但 Java 后端缺失: -- ❌ `POST /api/v1/school/students/import` - 批量导入学生 -- ❌ `GET /api/v1/school/students/import/template` - 获取导入模板 - ---- - -## 总结 - -绝大部分接口已经在 Java 后端实现,仅剩以下缺失接口需要补全: - -### P0 - 核心功能缺失(必须补全) -暂无 - -### P1 - 重要功能缺失 -暂无 - -### P2 - 辅助功能缺失 -暂无 - ---- - -## 本次补全的接口 - -### 1. 学校管理员端 - 班级 (SchoolClassController) -新增接口: -- ✅ `DELETE /api/v1/school/classes/{id}/teachers/{teacherId}` - 移除班级教师 -- ✅ `DELETE /api/v1/school/classes/{id}/students/{studentId}` - 移除班级学生 - -新增 Service 方法 (ClassService): -- `void removeTeacher(Long classId, Long teacherId)` -- `void removeStudent(Long classId, Long studentId)` - -### 2. 学校管理员端 - 学生 (SchoolStudentController) -新增接口: -- ✅ `POST /api/v1/school/students/import` - 批量导入学生 -- ✅ `GET /api/v1/school/students/import/template` - 获取导入模板 - -新增 Service 方法 (StudentService): -- `List importStudents(Long tenantId, List requests)` - -### 3. 学校统计接口 (SchoolStatsController + SchoolStatsService) -新增接口: -- ✅ `GET /api/v1/school/stats/teachers` - 获取活跃教师统计 -- ✅ `GET /api/v1/school/stats/courses` - 获取课程使用统计 -- ✅ `GET /api/v1/school/stats/activities` - 获取最近活动记录 -- ✅ `GET /api/v1/school/stats/lesson-trend` - 获取课时趋势(最近 N 个月) -- ✅ `GET /api/v1/school/stats/course-distribution` - 获取课程分布统计(饼图数据) - -新增 Service 方法 (SchoolStatsService): -- `List> getActiveTeachers(Long tenantId, Integer limit)` -- `List> getCourseUsageStats(Long tenantId)` -- `List> getRecentActivities(Long tenantId, Integer limit)` -- `List> getLessonTrend(Long tenantId, Integer months)` -- `List> getCourseDistribution(Long tenantId)` -- `String formatActivityTitle(Lesson lesson)` - 私有方法,格式化活动标题 - ---- - -## 最终结论 - -**前端实际调用的所有接口已在 Java 后端全部实现。** diff --git a/补全接口修复总结.md b/补全接口修复总结.md deleted file mode 100644 index 992dec6..0000000 --- a/补全接口修复总结.md +++ /dev/null @@ -1,228 +0,0 @@ -# API 接口补全修复总结 - -## 修复日期 -2026-03-09 - -## 问题修复 - -### Bug 修复 -修复了 `TaskServiceImpl.java` 中使用 `ClassEntity` 的错误,改为使用 `Clazz`(因为 `class` 是 Java 关键字,项目中使用 `Clazz` 作为班级实体名称)。 - -**修改位置**: `reading-platform-java/src/main/java/com/reading/platform/service/impl/TaskServiceImpl.java` -- 第 284 行:`List classes` → `List classes` -- 第 288 行:`for (ClassEntity cls : classes)` → `for (Clazz cls : classes)` - -### 数据库迁移 -新增数据库迁移脚本 `V7__fix_schedule_plans.sql`,为 `schedule_plans` 表添加以下字段: -- `course_id` - 课程 ID -- `teacher_id` - 教师 ID -- `day_of_week` - 星期几 (1-7) -- `period` - 节次 -- `start_time` - 开始时间 -- `end_time` - 结束时间 -- `location` - 教室/地点 -- `note` - 备注 - ---- - -## 已补全的 API 接口 - -### 1. 任务管理接口 - -#### 新增 Service 方法 (TaskService) -```java -// 任务统计 -Map getTaskStats(Long tenantId); -Map getStatsByType(Long tenantId); -List> getStatsByClass(Long tenantId); -List> getMonthlyStats(Long tenantId, Integer months); - -// 任务完成情况 -Page getTaskCompletions(Long tenantId, Long taskId, Integer pageNum, Integer pageSize, String status); -TaskCompletion updateTaskCompletion(Long tenantId, Long taskId, Long studentId, String status, String feedback); - -// 任务模板 -Page getTemplatePage(Long tenantId, Integer pageNum, Integer pageSize, String keyword, String type); -TaskTemplate getTemplateById(Long tenantId, Long id); -TaskTemplate getDefaultTemplate(Long tenantId, String taskType); -TaskTemplate createTemplate(Long tenantId, Long creatorId, TaskTemplateCreateRequest request); -TaskTemplate updateTemplate(Long tenantId, Long id, TaskTemplateUpdateRequest request); -void deleteTemplate(Long tenantId, Long id); -Task createTaskFromTemplate(Long tenantId, Long creatorId, String creatorRole, CreateTaskFromTemplateRequest request); -``` - -#### 新增 Controller 端点 - -**SchoolTaskController** (学校管理员 - 任务管理): -- `GET /api/v1/school/tasks/stats` - 获取任务统计数据 -- `GET /api/v1/school/tasks/stats/by-type` - 按任务类型统计 -- `GET /api/v1/school/tasks/stats/by-class` - 按班级统计 -- `GET /api/v1/school/tasks/stats/monthly` - 月度统计趋势 -- `GET /api/v1/school/tasks/:id/completions` - 获取任务完成情况分页 -- `PUT /api/v1/school/tasks/:taskId/completions/:studentId` - 更新任务完成状态 -- `GET /api/v1/school/task-templates` - 获取任务模板列表 -- `GET /api/v1/school/task-templates/:id` - 获取单个模板 -- `GET /api/v1/school/task-templates/default/:taskType` - 获取默认模板 -- `POST /api/v1/school/task-templates` - 创建任务模板 -- `PUT /api/v1/school/task-templates/:id` - 更新任务模板 -- `DELETE /api/v1/school/task-templates/:id` - 删除任务模板 -- `POST /api/v1/school/tasks/from-template` - 从模板创建任务 - -**TeacherTaskController** (教师端 - 任务管理): -- `GET /api/v1/teacher/tasks/stats` - 获取任务统计数据 -- `GET /api/v1/teacher/tasks/stats/by-type` - 按任务类型统计 -- `GET /api/v1/teacher/tasks/stats/by-class` - 按班级统计 -- `GET /api/v1/teacher/tasks/stats/monthly` - 月度统计趋势 -- `GET /api/v1/teacher/tasks/:id/completions` - 获取任务完成情况分页 -- `PUT /api/v1/teacher/tasks/:taskId/completions/:studentId` - 更新任务完成状态 -- `GET /api/v1/teacher/task-templates` - 获取任务模板列表 -- `GET /api/v1/teacher/task-templates/:id` - 获取单个模板 -- `GET /api/v1/teacher/task-templates/default/:taskType` - 获取默认模板 -- `POST /api/v1/teacher/tasks/from-template` - 从模板创建任务 - ---- - -### 2. 通知接口 - -**新增 SchoolNotificationController** (学校管理员 - 通知): -- `GET /api/v1/school/notifications` - 获取通知列表 -- `GET /api/v1/school/notifications/:id` - 根据 ID 获取通知 -- `GET /api/v1/school/notifications/unread-count` - 获取未读数量 -- `POST /api/v1/school/notifications/:id/read` - 标记已读 -- `POST /api/v1/school/notifications/read-all` - 全部标记已读 - ---- - -### 3. 排课和课表接口 - -#### 新增 Service 方法 (ScheduleService) -```java -Page getSchedulePlans(int pageNum, int pageSize, Long tenantId, Long classId, LocalDate startDate, LocalDate endDate); -List> getTimetable(Long tenantId, LocalDate startDate, LocalDate endDate, Long classId); -List batchCreateSchedules(Long tenantId, Long userId, List requests); -ScheduleTemplate updateScheduleTemplate(Long id, ScheduleTemplate template); -List applyScheduleTemplate(Long tenantId, Long templateId, ScheduleTemplateApplyRequest request); -``` - -#### 新增 Controller 端点 (SchoolScheduleController) -- `GET /api/v1/school/schedules/timetable` - 获取课表(带日期范围) -- `POST /api/v1/school/schedules/batch` - 批量创建排课 -- `GET /api/v1/school/schedules/templates/:id` - 获取单个模板 -- `PUT /api/v1/school/schedules/templates/:id` - 更新模板 -- `POST /api/v1/school/schedules/templates/:id/apply` - 应用模板 - ---- - -### 4. 实体类增强 - -**SchedulePlan** (新增字段): -- `courseId` - 课程 ID -- `teacherId` - 教师 ID -- `dayOfWeek` - 星期几 (1-7) -- `period` - 节次 -- `startTime` - 开始时间 -- `endTime` - 结束时间 -- `location` - 教室/地点 -- `note` - 备注 - ---- - -### 5. 新增 DTO - -**TaskTemplateCreateRequest** - 任务模板创建请求 -```java -- name: 模板名称 -- description: 模板描述 -- type: 任务类型 -- content: 任务内容模板 -- isPublic: 是否公共模板 -``` - -**TaskTemplateUpdateRequest** - 任务模板更新请求 - -**CreateTaskFromTemplateRequest** - 从模板创建任务请求 -```java -- templateId: 模板 ID -- targetIds: 目标 ID 列表 -- targetType: 目标类型 (CLASS/STUDENT) -- startDate: 开始日期 -- endDate: 截止日期 -``` - -**SchedulePlanCreateRequest** - 课表计划创建请求 -```java -- classId: 班级 ID -- courseId: 课程 ID -- teacherId: 授课教师 ID -- dayOfWeek: 星期几 -- period: 节次 -- startTime: 开始时间 -- endTime: 结束时间 -- location: 教室/地点 -- note: 备注 -- startDate: 开始日期 -- endDate: 结束日期 -``` - -**ScheduleTemplateApplyRequest** - 课表模板应用请求 -```java -- classId: 班级 ID -- startDate: 应用开始日期 -- weeks: 应用周数 -``` - ---- - -## 文件变更列表 - -### 新增文件 (7 个) -1. `dto/request/TaskTemplateCreateRequest.java` -2. `dto/request/TaskTemplateUpdateRequest.java` -3. `dto/request/CreateTaskFromTemplateRequest.java` -4. `dto/request/SchedulePlanCreateRequest.java` -5. `dto/request/ScheduleTemplateApplyRequest.java` -6. `controller/school/SchoolNotificationController.java` -7. `resources/db/migration/V7__fix_schedule_plans.sql` - -### 修改文件 (7 个) -1. `service/TaskService.java` - 添加统计和模板方法接口 -2. `service/impl/TaskServiceImpl.java` - 实现统计和模板逻辑 + 修复 ClassEntity bug -3. `service/ScheduleService.java` - 添加课表相关方法 -4. `entity/SchedulePlan.java` - 添加课程、教师等字段 -5. `controller/school/SchoolTaskController.java` - 添加统计和模板端点 -6. `controller/teacher/TeacherTaskController.java` - 添加统计和模板端点 -7. `controller/school/SchoolScheduleController.java` - 添加课表和模板端点 - ---- - -## 仍需补全的接口(下一步建议) - -### 高优先级 -1. **成长档案接口** - 按学生/班级查询 -2. **教师端课时反馈** - 完成课时、学生记录、反馈接口 -3. **班级管理** - 班级教师/学生管理、学生调班 - -### 中优先级 -1. **统计报告** - 学校统计、报告导出 -2. **导出接口增强** - 带日期范围参数 -3. **管理员课程审核** - 提交、审核、发布流程 - ---- - -## 使用说明 - -1. 运行数据库迁移: -```bash -# Flyway 会在应用启动时自动运行 V7 迁移脚本 -``` - -2. 编译项目: -```bash -cd reading-platform-java -mvn clean compile -``` - -3. 启动应用后,访问 API 文档: -``` -http://localhost:8080/doc.html -```