diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 1f16127..4f9b308 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -3,7 +3,8 @@ "allow": [ "Bash(mvn compile:*)", "Bash(sed:*)", - "Bash(grep:*)" + "Bash(grep:*)", + "Bash(export:*)" ] } } diff --git a/reading-platform-frontend/src/api/generated/model/tenantUpdateRequest.ts b/reading-platform-frontend/src/api/generated/model/tenantUpdateRequest.ts index 6a805d2..a6722db 100644 --- a/reading-platform-frontend/src/api/generated/model/tenantUpdateRequest.ts +++ b/reading-platform-frontend/src/api/generated/model/tenantUpdateRequest.ts @@ -24,7 +24,7 @@ export interface TenantUpdateRequest { logoUrl?: string; /** 状态 */ status?: string; - /** 课程套餐ID(用于三层架构) */ + /** 课程套餐 ID(用于三层架构) */ collectionIds?: number[]; /** 教师配额 */ teacherQuota?: number; @@ -34,4 +34,6 @@ export interface TenantUpdateRequest { startDate?: string; /** 结束日期 */ expireDate?: string; + /** 是否强制移除套餐(当套餐下有排课计划时需要此参数) */ + forceRemove?: boolean; } diff --git a/reading-platform-frontend/src/api/school.ts b/reading-platform-frontend/src/api/school.ts index ba6ac47..e5b00ea 100644 --- a/reading-platform-frontend/src/api/school.ts +++ b/reading-platform-frontend/src/api/school.ts @@ -875,29 +875,49 @@ export const getOperationLogs = (params?: { action?: string; startDate?: string; endDate?: string; -}) => http.get<{ records: OperationLog[]; total: number; pageNum: number; pageSize: number; pages: number }>( +}) => http.get<{ list: any; total: number; pageNum: number; pageSize: number; pages: number }>( '/v1/school/operation-logs', { params } -).then(res => ({ - list: res.records || [], - total: res.total || 0, - pageNum: res.pageNum || 1, - pageSize: res.pageSize || 10, - pages: res.pages || 0, -})); +).then(res => { + // 字段映射:后端 userRole -> 前端 userType,后端 details -> 前端 description + return { + list: (res.list || []).map(log => ({ + ...log, + userType: (log as any).userRole, // 后端字段 userRole 映射为前端 userType + description: (log as any).details, // 后端字段 details 映射为前端 description + oldValue: null, // 后端暂未支持 + newValue: null, // 后端暂未支持 + })), + total: res.total || 0, + pageNum: res.pageNum || 1, + pageSize: res.pageSize || 10, + pages: res.pages || 0, + }; +}); export const getOperationLogStats = (startDate?: string, endDate?: string) => http.get<{ totalLogs: number; byModule: Record; byOperator: Record }>('/v1/school/operation-logs/stats', { params: { startDate, endDate }, - }).then(res => ({ - totalLogs: res.totalLogs || 0, - byModule: res.byModule || {}, - byOperator: res.byOperator || {}, - })); + }).then(res => { + // 字段映射:后端 byModule -> 前端 modules 数组格式 + return { + total: res.totalLogs || 0, + modules: Object.entries(res.byModule || {}).map(([name, count]) => ({ name, count })), + byModule: res.byModule || {}, + byOperator: res.byOperator || {}, + }; + }); export const getOperationLogById = (id: number) => http.get(`/v1/school/operation-logs/${id}`); +/** + * 获取可用模块列表 + * 用于操作日志页面的模块筛选下拉框 + */ +export const getOperationLogModules = () => + http.get('/v1/school/operation-logs/modules'); + // ==================== 任务模板 API ==================== export interface TaskTemplate { diff --git a/reading-platform-frontend/src/constants/logOperationType.ts b/reading-platform-frontend/src/constants/logOperationType.ts new file mode 100644 index 0000000..6863fe4 --- /dev/null +++ b/reading-platform-frontend/src/constants/logOperationType.ts @@ -0,0 +1,21 @@ +/** + * 操作类型映射(后端 code → 前端中文描述) + * 对应后端 LogOperationType 枚举 + */ +export const LOG_OPERATION_TYPE_LABELS: Record = { + CREATE: '新增', + UPDATE: '修改', + DELETE: '删除', + QUERY: '查询', + EXPORT: '导出', + IMPORT: '导入', + OTHER: '其他', +}; + +/** + * 操作类型选项(用于下拉选择) + */ +export const LOG_OPERATION_TYPE_OPTIONS = Object.entries(LOG_OPERATION_TYPE_LABELS).map(([code, label]) => ({ + code, + label, +})); diff --git a/reading-platform-frontend/src/router/index.ts b/reading-platform-frontend/src/router/index.ts index d49e637..f72c69f 100644 --- a/reading-platform-frontend/src/router/index.ts +++ b/reading-platform-frontend/src/router/index.ts @@ -467,7 +467,9 @@ const router = createRouter({ // 路由守卫 router.beforeEach((to, from, next) => { const token = localStorage.getItem('token'); - const userRole = localStorage.getItem('role'); + const userRoleRaw = localStorage.getItem('role'); + // role 转为小写以匹配路由 + const userRole = userRoleRaw ? userRoleRaw.toLowerCase() : null; // 设置页面标题 if (to.meta.title) { diff --git a/reading-platform-frontend/src/utils/tagMaps.ts b/reading-platform-frontend/src/utils/tagMaps.ts index c7c71b9..25f3c28 100644 --- a/reading-platform-frontend/src/utils/tagMaps.ts +++ b/reading-platform-frontend/src/utils/tagMaps.ts @@ -490,10 +490,10 @@ export function translateResourceType(type: string): string { // 通用状态映射(用于 Student、Teacher、Parent、Class 等实体的 active/ACTIVE 状态) export const GENERIC_STATUS_MAP: Record = { - ACTIVE: "激活", - active: "激活", - INACTIVE: "未激活", - inactive: "未激活", + ACTIVE: "启用", + active: "启用", + INACTIVE: "停用", + inactive: "停用", ARCHIVED: "归档", archived: "归档", }; @@ -503,8 +503,8 @@ export const GENERIC_STATUS_COLORS: Record< string, { bg: string; text: string } > = { - 激活: { bg: "#E8F5E9", text: "#43A047" }, - 未激活: { bg: "#F5F5F5", text: "#9E9E9E" }, + 启用: { bg: "#E8F5E9", text: "#43A047" }, + 停用: { bg: "#F5F5F5", text: "#9E9E9E" }, 归档: { bg: "#FFF8E1", text: "#F9A825" }, }; diff --git a/reading-platform-frontend/src/views/admin/tenants/modify_tenant.py b/reading-platform-frontend/src/views/admin/tenants/modify_tenant.py new file mode 100644 index 0000000..c9e7981 --- /dev/null +++ b/reading-platform-frontend/src/views/admin/tenants/modify_tenant.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +with open('TenantListView.vue', 'r', encoding='utf-8') as f: + content = f.read() + +# 找到 handleModalOk 函数中的 catch 块并修改 +old_catch = ''' } catch (error: any) { + message.error(error.response?.data?.message || '操作失败'); + } finally { + modalLoading.value = false; + } +};''' + +new_catch = ''' } catch (error: any) { + // 处理错误码 3102 - 套餐下有排课计划 + if (error.response?.data?.code === 3102) { + const warnings = error.response.data.data as Array<{ + collectionId: number; + collectionName: string; + scheduleCount: number; + }>; + // 保存当前表单数据 + pendingFormData.value = { + ...formData, + startDate, + expireDate, + }; + // 显示强制移除确认弹窗 + forceRemoveWarnings.value = warnings; + forceRemoveModalVisible.value = true; + modalLoading.value = false; + return; + } + message.error(error.response?.data?.message || '操作失败'); + } finally { + modalLoading.value = false; + } +}; + +// 强制移除确认弹窗 - 确认 +const handleForceRemoveConfirm = async () => { + if (!pendingFormData.value || !editingId.value) { + return; + } + + modalLoading.value = true; + try { + // 传递 forceRemove: true 重新调用更新接口 + await updateTenant(editingId.value, { ...pendingFormData.value, forceRemove: true } as UpdateTenantDto); + message.success('更新成功'); + modalVisible.value = false; + forceRemoveModalVisible.value = false; + pendingFormData.value = null; + loadData(); + } catch (error: any) { + message.error(error.response?.data?.message || '操作失败'); + } finally { + modalLoading.value = false; + } +}; + +// 强制移除确认弹窗 - 取消 +const handleForceRemoveCancel = () => { + forceRemoveModalVisible.value = false; + pendingFormData.value = null; + forceRemoveWarnings.value = []; +};''' + +content = content.replace(old_catch, new_catch) + +with open('TenantListView.vue', 'w', encoding='utf-8') as f: + f.write(content) + +print('修改成功') diff --git a/reading-platform-frontend/src/views/school/settings/OperationLogView.vue b/reading-platform-frontend/src/views/school/settings/OperationLogView.vue index 4d231f4..d6fae76 100644 --- a/reading-platform-frontend/src/views/school/settings/OperationLogView.vue +++ b/reading-platform-frontend/src/views/school/settings/OperationLogView.vue @@ -25,8 +25,8 @@ style="width: 150px" @change="loadLogs" > - - {{ action }} + + {{ option.label }} ([]); -const modules = ref(['排课管理', '教师管理', '学生管理', '班级管理', '课程管理']); -const actions = ref(['创建', '更新', '删除', '创建排课', '批量创建排课', '取消排课']); +const modules = ref([]); +const actions = ref(LOG_OPERATION_TYPE_OPTIONS); // 筛选 const filters = reactive({ @@ -215,6 +216,16 @@ const loadLogs = async () => { } }; +// 加载模块列表 +const loadModules = async () => { + try { + const res = await getOperationLogModules(); + modules.value = res; + } catch (error) { + console.error('加载模块列表失败', error); + } +}; + // 加载统计 const loadStats = async () => { try { @@ -278,6 +289,7 @@ const getUserTypeColor = (type: string) => { }; onMounted(() => { + loadModules(); loadLogs(); loadStats(); }); diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/annotation/Log.java b/reading-platform-java/src/main/java/com/reading/platform/common/annotation/Log.java index b2a8e62..7d28844 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/common/annotation/Log.java +++ b/reading-platform-java/src/main/java/com/reading/platform/common/annotation/Log.java @@ -1,5 +1,8 @@ package com.reading.platform.common.annotation; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; + import java.lang.annotation.*; /** @@ -22,7 +25,7 @@ public @interface Log { * 例如:用户管理、课程管理、学校管理等 *

*/ - String module() default ""; + LogModule module() default LogModule.OTHER; /** * 操作类型 @@ -30,7 +33,7 @@ public @interface Log { * 例如:新增、修改、删除、查询、导出等 *

*/ - String type() default ""; + LogOperationType type() default LogOperationType.OTHER; /** * 操作描述 @@ -49,54 +52,4 @@ public @interface Log { * 默认:true */ boolean recordParams() default true; - - /** - * 操作状态(枚举) - */ - enum OperationType { - /** - * 新增 - */ - CREATE("新增"), - - /** - * 修改 - */ - UPDATE("修改"), - - /** - * 删除 - */ - DELETE("删除"), - - /** - * 查询 - */ - QUERY("查询"), - - /** - * 导出 - */ - EXPORT("导出"), - - /** - * 导入 - */ - IMPORT("导入"), - - /** - * 其他 - */ - OTHER("其他"); - - private final String description; - - OperationType(String description) { - this.description = description; - } - - public String getDescription() { - return description; - } - } } diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/aspect/LogAspect.java b/reading-platform-java/src/main/java/com/reading/platform/common/aspect/LogAspect.java index ef01c4a..73e859a 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/common/aspect/LogAspect.java +++ b/reading-platform-java/src/main/java/com/reading/platform/common/aspect/LogAspect.java @@ -19,7 +19,6 @@ import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import java.lang.reflect.Method; import java.time.LocalDateTime; /** @@ -59,8 +58,9 @@ public class LogAspect { // 构建操作日志对象 OperationLog operationLog = new OperationLog(); operationLog.setId(IdWorker.getId()); - operationLog.setModule(logAnnotation.module()); - operationLog.setAction(logAnnotation.description()); + operationLog.setModule(logAnnotation.module().toString()); + operationLog.setAction(logAnnotation.type().getCode()); + operationLog.setDetails(logAnnotation.description()); operationLog.setCreatedAt(LocalDateTime.now()); // 记录操作人信息 @@ -76,6 +76,20 @@ public class LogAspect { log.debug("获取当前用户信息失败:{}", e.getMessage()); } + // 设置租户 ID:超管端使用 0,其他端使用当前租户 ID + try { + Long tenantId = SecurityUtils.getCurrentTenantId(); + if (tenantId != null) { + operationLog.setTenantId(tenantId); + } else { + // 超管端操作,使用 0 作为标记 + operationLog.setTenantId(0L); + } + } catch (Exception e) { + // 获取租户 ID 失败(可能是超管端),使用 0 作为标记 + operationLog.setTenantId(0L); + } + // 记录请求信息 operationLog.setIpAddress(getIpAddress(request)); operationLog.setUserAgent(request.getHeader("User-Agent")); @@ -83,8 +97,11 @@ public class LogAspect { // 记录请求参数 if (logAnnotation.recordParams()) { try { - String params = JSON.toJSONString(getRequestParams(joinPoint)); - operationLog.setDetails(params); + Object[] params = getRequestParams(joinPoint); + // 对参数进行脱敏处理(移除敏感信息) + Object[] sanitizedParams = desensitizeParams(joinPoint, params); + String paramsJson = JSON.toJSONString(sanitizedParams); + operationLog.setRequestParams(paramsJson); } catch (Exception e) { log.warn("记录请求参数失败:{}", e.getMessage()); } @@ -192,4 +209,68 @@ public class LogAspect { private Object[] getRequestParams(JoinPoint joinPoint) { return joinPoint.getArgs(); } + + /** + * 对请求参数进行脱敏处理(密码字段) + *

+ * 注意:DTO 类中的密码字段使用 @JsonIgnore 注解,序列化时会自动忽略 + * 本方法主要处理 String 类型的直接参数(如 oldPassword, newPassword) + *

+ * + * @param joinPoint 切面连接点 + * @param params 原始参数 + * @return 脱敏后的参数 + */ + private Object[] desensitizeParams(JoinPoint joinPoint, Object[] params) { + if (params == null || params.length == 0) { + return params; + } + + Object[] sanitized = new Object[params.length]; + for (int i = 0; i < params.length; i++) { + if (params[i] instanceof String strParam) { + // 检查参数名是否包含敏感词(通过方法参数名判断) + String paramName = getParameterName(joinPoint, i); + if (isSensitiveParam(paramName)) { + sanitized[i] = "***"; + } else { + sanitized[i] = strParam; + } + } else { + // DTO 对象:依赖 @JsonIgnore 注解自动脱敏 + sanitized[i] = params[i]; + } + } + return sanitized; + } + + /** + * 获取参数名 + */ + private String getParameterName(JoinPoint joinPoint, int paramIndex) { + try { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + String[] paramNames = signature.getParameterNames(); + if (paramNames != null && paramIndex < paramNames.length) { + return paramNames[paramIndex]; + } + } catch (Exception e) { + log.debug("获取参数名失败:{}", e.getMessage()); + } + return ""; + } + + /** + * 判断是否为敏感参数名 + */ + private boolean isSensitiveParam(String paramName) { + if (paramName == null || paramName.isEmpty()) { + return false; + } + String lowerName = paramName.toLowerCase(); + return lowerName.contains("password") || + lowerName.contains("passwd") || + lowerName.contains("secret") || + lowerName.contains("token"); + } } diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/enums/ErrorCode.java b/reading-platform-java/src/main/java/com/reading/platform/common/enums/ErrorCode.java index e7d9ecd..1bf9a87 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/common/enums/ErrorCode.java +++ b/reading-platform-java/src/main/java/com/reading/platform/common/enums/ErrorCode.java @@ -8,42 +8,44 @@ import lombok.Getter; @Getter public enum ErrorCode { - SUCCESS(200, "success"), - BAD_REQUEST(400, "Bad Request"), - UNAUTHORIZED(401, "Unauthorized"), - FORBIDDEN(403, "Forbidden"), - NOT_FOUND(404, "Resource Not Found"), - METHOD_NOT_ALLOWED(405, "Method Not Allowed"), - INTERNAL_ERROR(500, "Internal Server Error"), + SUCCESS(200, "成功"), + BAD_REQUEST(400, "请求失败"), + UNAUTHORIZED(401, "未授权"), + FORBIDDEN(403, "禁止访问"), + NOT_FOUND(404, "资源不存在"), + METHOD_NOT_ALLOWED(405, "方法不允许"), + INTERNAL_ERROR(500, "服务器内部错误"), // Business Errors (1000+) - LOGIN_FAILED(1001, "Login failed"), - ACCOUNT_DISABLED(1002, "Account is disabled"), - TOKEN_EXPIRED(1003, "Token expired"), - TOKEN_INVALID(1004, "Token invalid"), - PERMISSION_DENIED(1005, "Permission denied"), + LOGIN_FAILED(1001, "登录失败"), + ACCOUNT_NOT_FOUND(1002, "账号不存在"), + ACCOUNT_DISABLED(1003, "账户已停用"), + INCORRECT_PASSWORD(1004, "密码错误"), + TOKEN_EXPIRED(1005, "Token 已过期"), + TOKEN_INVALID(1006, "Token 无效"), + PERMISSION_DENIED(1007, "权限不足"), // Data Errors (2000+) - DATA_NOT_FOUND(2001, "Data not found"), - DATA_ALREADY_EXISTS(2002, "Data already exists"), - DATA_IN_USE(2003, "Data is in use"), - INVALID_PARAMETER(2004, "Invalid parameter"), + DATA_NOT_FOUND(2001, "数据不存在"), + DATA_ALREADY_EXISTS(2002, "数据已存在"), + DATA_IN_USE(2003, "数据使用中"), + INVALID_PARAMETER(2004, "参数无效"), // Tenant Errors (3000+) - TENANT_NOT_FOUND(3001, "Tenant not found"), - TENANT_EXPIRED(3002, "Tenant has expired"), - TENANT_DISABLED(3003, "Tenant is disabled"), + TENANT_NOT_FOUND(3001, "租户不存在"), + TENANT_EXPIRED(3002, "租户已过期"), + TENANT_DISABLED(3003, "租户已停用"), TENANT_SUSPENDED(3004, "您的账户因租户服务暂停而无法登录,请联系学校管理员"), // Package Errors (3100+) - PACKAGE_NOT_FOUND(3101, "Package not found"), - REMOVE_PACKAGE_HAS_SCHEDULES(3102, "该套餐下有排课计划"), + PACKAGE_NOT_FOUND(3101, "套餐不存在"), + REMOVE_PACKAGE_HAS_SCHEDULES(3102, "该套餐下有排课计划,请确认是否强制移除"), // User Errors (4000+) - USER_NOT_FOUND(4001, "User not found"), - USER_ALREADY_EXISTS(4002, "User already exists"), - PASSWORD_MISMATCH(4003, "Password mismatch"), - OLD_PASSWORD_ERROR(4004, "Old password is incorrect"); + USER_NOT_FOUND(4001, "用户不存在"), + USER_ALREADY_EXISTS(4002, "用户已存在"), + PASSWORD_MISMATCH(4003, "密码不匹配"), + OLD_PASSWORD_ERROR(4004, "原密码错误"); private final Integer code; private final String message; diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/enums/GenericStatus.java b/reading-platform-java/src/main/java/com/reading/platform/common/enums/GenericStatus.java index cbd8efa..25159bd 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/common/enums/GenericStatus.java +++ b/reading-platform-java/src/main/java/com/reading/platform/common/enums/GenericStatus.java @@ -9,8 +9,8 @@ import lombok.Getter; @Getter public enum GenericStatus { - ACTIVE("ACTIVE", "激活"), - INACTIVE("INACTIVE", "未激活"), + ACTIVE("ACTIVE", "启用"), + INACTIVE("INACTIVE", "停用"), ARCHIVED("ARCHIVED", "归档"); private final String code; diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/enums/LogModule.java b/reading-platform-java/src/main/java/com/reading/platform/common/enums/LogModule.java new file mode 100644 index 0000000..af9086b --- /dev/null +++ b/reading-platform-java/src/main/java/com/reading/platform/common/enums/LogModule.java @@ -0,0 +1,177 @@ +package com.reading.platform.common.enums; + +import lombok.Getter; + +/** + * 日志操作模块枚举 + *

+ * 用于 @Log 注解的 module 参数赋值,统一管理操作日志的模块名称 + *

+ * + * @author reading-platform + * @since 2026-03-23 + */ +@Getter +public enum LogModule { + + /** + * 认证管理 + */ + AUTH("认证管理"), + + /** + * 文件管理 + */ + FILE("文件管理"), + + /** + * 班级管理 + */ + CLASS("班级管理"), + + /** + * 教师管理 + */ + TEACHER("教师管理"), + + /** + * 学生管理 + */ + STUDENT("学生管理"), + + /** + * 家长管理 + */ + PARENT("家长管理"), + + /** + * 排课管理 + */ + SCHEDULE("排课管理"), + + /** + * 任务管理 + */ + TASK("任务管理"), + + /** + * 任务模板 + */ + TASK_TEMPLATE("任务模板"), + + /** + * 任务评价 + */ + TASK_FEEDBACK("任务评价"), + + /** + * 套餐管理 + */ + PACKAGE("套餐管理"), + + /** + * 成长记录 + */ + GROWTH("成长记录"), + + /** + * 数据导出 + */ + EXPORT("数据导出"), + + /** + * 通知管理 + */ + NOTIFICATION("通知管理"), + + /** + * 课程套餐管理 + */ + COURSE_COLLECTION("课程套餐管理"), + + /** + * 课程包管理 + */ + COURSE_PACKAGE("课程包管理"), + + /** + * 课程环节管理 + */ + COURSE_LESSON("课程环节管理"), + + /** + * 资源库管理 + */ + COURSE_RESOURCE("资源库管理"), + + /** + * 主题管理 + */ + THEME("主题管理"), + + /** + * 租户管理 + */ + TENANT("租户管理"), + + /** + * 系统设置 + */ + SYSTEM_SETTING("系统设置"), + + /** + * 课时管理 + */ + LESSON("课时管理"), + + /** + * 课时反馈 + */ + LESSON_FEEDBACK("课时反馈"), + + /** + * 学生记录 + */ + STUDENT_RECORD("学生记录"), + + /** + * 阿里云 IMM 服务 + */ + IMM("阿里云 IMM 服务"), + + /** + * 其他(未分类的模块) + */ + OTHER("其他"); + + private final String description; + + LogModule(String description) { + this.description = description; + } + + /** + * 重写 toString 方法,返回描述文字 + * 这样可以直接使用枚举值作为字符串存储到数据库 + */ + @Override + public String toString() { + return this.description; + } + + /** + * 根据 description 获取枚举 + * + * @param description 模块描述 + * @return 日志操作模块枚举 + */ + public static LogModule fromDescription(String description) { + for (LogModule module : values()) { + if (module.description.equals(description)) { + return module; + } + } + // 找不到返回 null,表示未知的模块 + return null; + } +} diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/enums/LogOperationType.java b/reading-platform-java/src/main/java/com/reading/platform/common/enums/LogOperationType.java new file mode 100644 index 0000000..23079c1 --- /dev/null +++ b/reading-platform-java/src/main/java/com/reading/platform/common/enums/LogOperationType.java @@ -0,0 +1,74 @@ +package com.reading.platform.common.enums; + +import lombok.Getter; + +/** + * 日志操作类型枚举 + *

+ * 用于 @Log 注解的 type 参数赋值 + *

+ * + * @author reading-platform + * @since 2026-03-23 + */ +@Getter +public enum LogOperationType { + + /** + * 新增 + */ + CREATE("CREATE", "新增"), + + /** + * 修改 + */ + UPDATE("UPDATE", "修改"), + + /** + * 删除 + */ + DELETE("DELETE", "删除"), + + /** + * 查询 + */ + QUERY("QUERY", "查询"), + + /** + * 导出 + */ + EXPORT("EXPORT", "导出"), + + /** + * 导入 + */ + IMPORT("IMPORT", "导入"), + + /** + * 其他 + */ + OTHER("OTHER", "其他"); + + private final String code; + private final String description; + + LogOperationType(String code, String description) { + this.code = code; + this.description = description; + } + + /** + * 根据 code 获取枚举 + * + * @param code 操作类型码 + * @return 日志操作类型枚举 + */ + public static LogOperationType fromCode(String code) { + for (LogOperationType type : values()) { + if (type.code.equals(code)) { + return type; + } + } + return OTHER; + } +} diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/enums/UserRole.java b/reading-platform-java/src/main/java/com/reading/platform/common/enums/UserRole.java index 28d7c3a..5913192 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/common/enums/UserRole.java +++ b/reading-platform-java/src/main/java/com/reading/platform/common/enums/UserRole.java @@ -22,8 +22,11 @@ public enum UserRole { } public static UserRole fromCode(String code) { + if (code == null) { + throw new IllegalArgumentException("Role code cannot be null"); + } for (UserRole role : values()) { - if (role.getCode().equals(code)) { + if (role.getCode().equalsIgnoreCase(code)) { return role; } } diff --git a/reading-platform-java/src/main/java/com/reading/platform/common/response/Result.java b/reading-platform-java/src/main/java/com/reading/platform/common/response/Result.java index ce8926c..e035291 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/common/response/Result.java +++ b/reading-platform-java/src/main/java/com/reading/platform/common/response/Result.java @@ -95,6 +95,7 @@ public class Result implements Serializable { return result; } + /** * 错误响应(默认 500) */ diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/AuthController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/AuthController.java index 4b64a00..e3c7df1 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/AuthController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/AuthController.java @@ -1,5 +1,8 @@ package com.reading.platform.controller; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.mapper.AdminUserMapper; import com.reading.platform.common.mapper.ParentMapper; import com.reading.platform.common.mapper.TenantMapper; @@ -37,12 +40,14 @@ public class AuthController { private final AdminUserMapper adminUserMapper; @Operation(summary = "用户登录") + @Log(module = LogModule.AUTH, type = LogOperationType.OTHER, description = "用户登录") @PostMapping("/login") public Result login(@Valid @RequestBody LoginRequest request) { return Result.success(authService.login(request)); } @Operation(summary = "用户登出") + @Log(module = LogModule.AUTH, type = LogOperationType.OTHER, description = "用户登出") @PostMapping("/logout") public Result logout() { authService.logout(); @@ -64,6 +69,7 @@ public class AuthController { } @Operation(summary = "修改密码") + @Log(module = LogModule.AUTH, type = LogOperationType.UPDATE, description = "修改密码", recordParams = false) @PostMapping("/change-password") public Result changePassword( @RequestParam String oldPassword, @@ -75,6 +81,7 @@ public class AuthController { } @Operation(summary = "修改个人信息") + @Log(module = LogModule.AUTH, type = LogOperationType.UPDATE, description = "修改个人信息") @PutMapping("/profile") public Result updateProfile( @Valid @RequestBody UpdateProfileRequest request) { diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/FileUploadController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/FileUploadController.java index fad3a49..c37161f 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/FileUploadController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/FileUploadController.java @@ -1,5 +1,8 @@ package com.reading.platform.controller; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.response.Result; import com.reading.platform.common.util.OssUtils; import com.reading.platform.dto.response.OssTokenVo; @@ -47,6 +50,7 @@ public class FileUploadController { @PostMapping("/upload") @Operation(summary = "上传文件") + @Log(module = LogModule.FILE, type = LogOperationType.CREATE, description = "上传文件") public Result> uploadFile( @RequestParam("file") MultipartFile file, @RequestParam(value = "type", defaultValue = "other") String type) { @@ -79,6 +83,7 @@ public class FileUploadController { @DeleteMapping("/delete") @Operation(summary = "删除文件") + @Log(module = LogModule.FILE, type = LogOperationType.DELETE, description = "删除文件") public Result> deleteFile(@RequestBody Map request) { String filePath = request.get("filePath"); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/ImmController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/ImmController.java index 32db5af..c5ec54d 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/ImmController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/ImmController.java @@ -1,5 +1,7 @@ package com.reading.platform.controller; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.response.Result; import com.reading.platform.common.util.ImmUtil; import com.reading.platform.dto.response.ImmTokenVo; diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseCollectionController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseCollectionController.java index 30fc5d7..df5f336 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseCollectionController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseCollectionController.java @@ -2,6 +2,9 @@ package com.reading.platform.controller.admin; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.CourseStatus; import com.reading.platform.common.enums.UserRole; @@ -59,6 +62,7 @@ public class AdminCourseCollectionController { @PostMapping @Operation(summary = "创建课程套餐") + @Log(module = LogModule.COURSE_COLLECTION, type = LogOperationType.CREATE, description = "创建课程套餐") @RequireRole(UserRole.ADMIN) public Result create(@Valid @RequestBody CreateCollectionRequest request) { CourseCollectionResponse response = collectionService.createCollection( @@ -74,6 +78,7 @@ public class AdminCourseCollectionController { @PutMapping("/{id}") @Operation(summary = "更新课程套餐") + @Log(module = LogModule.COURSE_COLLECTION, type = LogOperationType.UPDATE, description = "更新课程套餐") @RequireRole(UserRole.ADMIN) public Result update( @PathVariable Long id, @@ -92,6 +97,7 @@ public class AdminCourseCollectionController { @DeleteMapping("/{id}") @Operation(summary = "删除课程套餐") + @Log(module = LogModule.COURSE_COLLECTION, type = LogOperationType.DELETE, description = "删除课程套餐") @RequireRole(UserRole.ADMIN) public Result delete(@PathVariable Long id) { collectionService.deleteCollection(id); @@ -100,6 +106,7 @@ public class AdminCourseCollectionController { @PutMapping("/{id}/packages") @Operation(summary = "设置套餐课程包") + @Log(module = LogModule.COURSE_COLLECTION, type = LogOperationType.UPDATE, description = "设置套餐课程包") @RequireRole(UserRole.ADMIN) public Result setPackages( @PathVariable Long id, @@ -110,6 +117,7 @@ public class AdminCourseCollectionController { @PostMapping("/{id}/publish") @Operation(summary = "发布套餐") + @Log(module = LogModule.COURSE_COLLECTION, type = LogOperationType.UPDATE, description = "发布套餐") @RequireRole(UserRole.ADMIN) public Result publish(@PathVariable Long id) { collectionService.publishCollection(id); @@ -118,6 +126,7 @@ public class AdminCourseCollectionController { @PostMapping("/{id}/archive") @Operation(summary = "下架套餐") + @Log(module = LogModule.COURSE_COLLECTION, type = LogOperationType.UPDATE, description = "下架套餐") @RequireRole(UserRole.ADMIN) public Result archive(@PathVariable Long id) { collectionService.archiveCollection(id); @@ -126,6 +135,7 @@ public class AdminCourseCollectionController { @PostMapping("/{id}/republish") @Operation(summary = "重新发布套餐") + @Log(module = LogModule.COURSE_COLLECTION, type = LogOperationType.UPDATE, description = "重新发布套餐") @RequireRole(UserRole.ADMIN) public Result republish(@PathVariable Long id) { collectionService.republishCollection(id); @@ -134,6 +144,7 @@ public class AdminCourseCollectionController { @PostMapping("/{id}/withdraw") @Operation(summary = "撤销审核") + @Log(module = LogModule.COURSE_COLLECTION, type = LogOperationType.UPDATE, description = "撤销审核") @RequireRole(UserRole.ADMIN) public Result withdraw(@PathVariable Long id) { collectionService.withdrawCollection(id); @@ -142,6 +153,7 @@ public class AdminCourseCollectionController { @PostMapping("/{id}/submit") @Operation(summary = "提交审核") + @Log(module = LogModule.COURSE_COLLECTION, type = LogOperationType.UPDATE, description = "提交审核") @RequireRole(UserRole.ADMIN) public Result submit(@PathVariable Long id) { collectionService.submitCollection(id); @@ -150,6 +162,7 @@ public class AdminCourseCollectionController { @PostMapping("/{id}/reject") @Operation(summary = "审核驳回") + @Log(module = LogModule.COURSE_COLLECTION, type = LogOperationType.UPDATE, description = "审核驳回") @RequireRole(UserRole.ADMIN) public Result reject(@PathVariable Long id, @Valid @RequestBody CourseCollectionRejectRequest request) { collectionService.rejectCollection(id, request.getComment()); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseController.java index b74f407..9ca0f11 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseController.java @@ -2,6 +2,9 @@ package com.reading.platform.controller.admin; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.CourseStatus; import com.reading.platform.common.enums.UserRole; @@ -39,6 +42,7 @@ public class AdminCourseController { private final CoursePackageService courseService; @PostMapping + @Log(module = LogModule.COURSE_PACKAGE, type = LogOperationType.CREATE, description = "创建课程包") @Operation(summary = "创建课程包") public Result createCourse(@Valid @RequestBody CourseCreateRequest request) { log.info("收到课程包创建请求,name={}, themeId={}, gradeTags={}", request.getName(), request.getThemeId(), request.getGradeTags()); @@ -53,6 +57,7 @@ public class AdminCourseController { } @PutMapping("/{id}") + @Log(module = LogModule.COURSE_PACKAGE, type = LogOperationType.UPDATE, description = "更新课程包") @Operation(summary = "更新课程包") public Result updateCourse(@PathVariable Long id, @RequestBody CourseUpdateRequest request) { courseService.updateCourse(id, request); @@ -97,6 +102,7 @@ public class AdminCourseController { } @DeleteMapping("/{id}") + @Log(module = LogModule.COURSE_PACKAGE, type = LogOperationType.DELETE, description = "删除课程包") @Operation(summary = "删除课程包") public Result deleteCourse(@PathVariable Long id) { courseService.deleteCourse(id); @@ -104,6 +110,7 @@ public class AdminCourseController { } @PostMapping("/{id}/publish") + @Log(module = LogModule.COURSE_PACKAGE, type = LogOperationType.UPDATE, description = "发布课程包") @Operation(summary = "发布课程包") public Result publishCourse(@PathVariable Long id) { courseService.publishCourse(id); @@ -111,6 +118,7 @@ public class AdminCourseController { } @PostMapping("/{id}/archive") + @Log(module = LogModule.COURSE_PACKAGE, type = LogOperationType.UPDATE, description = "归档课程包") @Operation(summary = "归档课程包") public Result archiveCourse(@PathVariable Long id) { courseService.archiveCourse(id); @@ -118,6 +126,7 @@ public class AdminCourseController { } @PostMapping("/{id}/submit") + @Log(module = LogModule.COURSE_PACKAGE, type = LogOperationType.UPDATE, description = "提交课程包审核") @Operation(summary = "提交课程包审核") public Result submitCourse(@PathVariable Long id) { courseService.submitCourse(id); @@ -125,6 +134,7 @@ public class AdminCourseController { } @PostMapping("/{id}/reject") + @Log(module = LogModule.COURSE_PACKAGE, type = LogOperationType.UPDATE, description = "驳回课程包审核") @Operation(summary = "驳回课程包审核") public Result rejectCourse(@PathVariable Long id, @Valid @RequestBody CourseRejectRequest request) { courseService.rejectCourse(id, request.getComment()); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseLessonController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseLessonController.java index ad78053..8d55780 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseLessonController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminCourseLessonController.java @@ -1,5 +1,8 @@ package com.reading.platform.controller.admin; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.response.Result; @@ -63,6 +66,7 @@ public class AdminCourseLessonController { @PostMapping("/{courseId}/lessons") @Operation(summary = "创建课程环节") + @Log(module = LogModule.COURSE_LESSON, type = LogOperationType.CREATE, description = "创建课程环节") @RequireRole(UserRole.ADMIN) public Result create( @PathVariable Long courseId, @@ -91,6 +95,7 @@ public class AdminCourseLessonController { @PutMapping("/{courseId}/lessons/{id}") @Operation(summary = "更新课程环节") + @Log(module = LogModule.COURSE_LESSON, type = LogOperationType.UPDATE, description = "更新课程环节") @RequireRole(UserRole.ADMIN) public Result update( @PathVariable Long courseId, @@ -119,6 +124,7 @@ public class AdminCourseLessonController { @DeleteMapping("/{courseId}/lessons/{id}") @Operation(summary = "删除课程环节") + @Log(module = LogModule.COURSE_LESSON, type = LogOperationType.DELETE, description = "删除课程环节") @RequireRole(UserRole.ADMIN) public Result delete( @PathVariable Long courseId, @@ -129,6 +135,7 @@ public class AdminCourseLessonController { @PutMapping("/{courseId}/lessons/reorder") @Operation(summary = "重新排序课程环节") + @Log(module = LogModule.COURSE_LESSON, type = LogOperationType.UPDATE, description = "重新排序课程环节") @RequireRole(UserRole.ADMIN) public Result reorder( @PathVariable Long courseId, @@ -153,6 +160,7 @@ public class AdminCourseLessonController { @PostMapping("/{courseId}/lessons/{lessonId}/steps") @Operation(summary = "创建教学环节") + @Log(module = LogModule.COURSE_LESSON, type = LogOperationType.CREATE, description = "创建教学环节") @RequireRole(UserRole.ADMIN) public Result createStep( @PathVariable Long courseId, @@ -171,6 +179,7 @@ public class AdminCourseLessonController { @PutMapping("/{courseId}/lessons/steps/{stepId}") @Operation(summary = "更新教学环节") + @Log(module = LogModule.COURSE_LESSON, type = LogOperationType.UPDATE, description = "更新教学环节") @RequireRole(UserRole.ADMIN) public Result updateStep( @PathVariable Long courseId, @@ -189,6 +198,7 @@ public class AdminCourseLessonController { @DeleteMapping("/{courseId}/lessons/steps/{stepId}") @Operation(summary = "删除教学环节") + @Log(module = LogModule.COURSE_LESSON, type = LogOperationType.DELETE, description = "删除教学环节") @RequireRole(UserRole.ADMIN) public Result removeStep( @PathVariable Long courseId, @@ -199,6 +209,7 @@ public class AdminCourseLessonController { @PutMapping("/{courseId}/lessons/{lessonId}/steps/reorder") @Operation(summary = "重新排序教学环节") + @Log(module = LogModule.COURSE_LESSON, type = LogOperationType.UPDATE, description = "重新排序教学环节") @RequireRole(UserRole.ADMIN) public Result reorderSteps( @PathVariable Long courseId, diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminResourceController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminResourceController.java index cf33ff0..92a7b69 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminResourceController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminResourceController.java @@ -1,6 +1,9 @@ package com.reading.platform.controller.admin; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.response.PageResult; @@ -65,6 +68,7 @@ public class AdminResourceController { @PostMapping("/libraries") @Operation(summary = "创建资源库") + @Log(module = LogModule.COURSE_RESOURCE, type = LogOperationType.CREATE, description = "创建资源库") @RequireRole(UserRole.ADMIN) public Result createLibrary(@Valid @RequestBody ResourceLibraryCreateRequest request) { ResourceLibrary library = resourceLibraryService.createLibrary( @@ -78,6 +82,7 @@ public class AdminResourceController { @PutMapping("/libraries/{id}") @Operation(summary = "更新资源库") + @Log(module = LogModule.COURSE_RESOURCE, type = LogOperationType.UPDATE, description = "更新资源库") @RequireRole(UserRole.ADMIN) public Result updateLibrary( @PathVariable String id, @@ -92,6 +97,7 @@ public class AdminResourceController { @DeleteMapping("/libraries/{id}") @Operation(summary = "删除资源库") + @Log(module = LogModule.COURSE_RESOURCE, type = LogOperationType.DELETE, description = "删除资源库") @RequireRole(UserRole.ADMIN) public Result deleteLibrary(@PathVariable String id) { resourceLibraryService.deleteLibrary(id); @@ -126,6 +132,7 @@ public class AdminResourceController { @PostMapping("/items") @Operation(summary = "创建资源项目") + @Log(module = LogModule.COURSE_RESOURCE, type = LogOperationType.CREATE, description = "创建资源项目") @RequireRole(UserRole.ADMIN) public Result createItem(@Valid @RequestBody ResourceItemCreateRequest request) throws JsonProcessingException { String tagsStr = null; @@ -147,6 +154,7 @@ public class AdminResourceController { @PutMapping("/items/{id}") @Operation(summary = "更新资源项目") + @Log(module = LogModule.COURSE_RESOURCE, type = LogOperationType.UPDATE, description = "更新资源项目") @RequireRole(UserRole.ADMIN) public Result updateItem( @PathVariable String id, @@ -166,6 +174,7 @@ public class AdminResourceController { @DeleteMapping("/items/{id}") @Operation(summary = "删除资源项目") + @Log(module = LogModule.COURSE_RESOURCE, type = LogOperationType.DELETE, description = "删除资源项目") @RequireRole(UserRole.ADMIN) public Result deleteItem(@PathVariable String id) { resourceLibraryService.deleteItem(id); @@ -174,6 +183,7 @@ public class AdminResourceController { @PostMapping("/items/batch-delete") @Operation(summary = "批量删除资源项目") + @Log(module = LogModule.COURSE_RESOURCE, type = LogOperationType.DELETE, description = "批量删除资源项目") @RequireRole(UserRole.ADMIN) public Result batchDeleteItems(@RequestBody List ids) { resourceLibraryService.batchDeleteItems(ids); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminTenantController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminTenantController.java index 646a200..a6f155b 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminTenantController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminTenantController.java @@ -1,6 +1,9 @@ package com.reading.platform.controller.admin; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.response.PageResult; @@ -38,6 +41,7 @@ public class AdminTenantController { private final CourseCollectionMapper collectionMapper; @Operation(summary = "Create tenant") + @Log(module = LogModule.TENANT, type = LogOperationType.CREATE, description = "创建租户") @PostMapping public Result createTenant(@Valid @RequestBody TenantCreateRequest request) { Tenant tenant = tenantService.createTenant(request); @@ -45,6 +49,7 @@ public class AdminTenantController { } @Operation(summary = "Update tenant") + @Log(module = LogModule.TENANT, type = LogOperationType.UPDATE, description = "修改租户") @PutMapping("/{id}") public Result updateTenant(@PathVariable Long id, @RequestBody TenantUpdateRequest request) { Tenant tenant = tenantService.updateTenant(id, request); @@ -77,6 +82,7 @@ public class AdminTenantController { } @Operation(summary = "Delete tenant") + @Log(module = LogModule.TENANT, type = LogOperationType.DELETE, description = "删除租户") @DeleteMapping("/{id}") public Result deleteTenant(@PathVariable Long id) { tenantService.deleteTenant(id); @@ -104,6 +110,7 @@ public class AdminTenantController { } @Operation(summary = "更新租户配额") + @Log(module = LogModule.TENANT, type = LogOperationType.UPDATE, description = "更新租户配额") @PutMapping("/{id}/quota") public Result updateTenantQuota(@PathVariable Long id, @RequestBody Map quota) { // TODO: 实现更新租户配额逻辑 @@ -112,6 +119,7 @@ public class AdminTenantController { } @Operation(summary = "更新租户状态") + @Log(module = LogModule.TENANT, type = LogOperationType.UPDATE, description = "更新租户状态") @PutMapping("/{id}/status") public Result updateTenantStatus(@PathVariable Long id, @RequestBody Map status) { String newStatus = (String) status.get("status"); @@ -121,6 +129,7 @@ public class AdminTenantController { } @Operation(summary = "重置租户密码") + @Log(module = LogModule.TENANT, type = LogOperationType.UPDATE, description = "重置租户密码") @PostMapping("/{id}/reset-password") public Result> resetTenantPassword(@PathVariable Long id) { String tempPassword = tenantService.resetPasswordAndReturnTemp(id); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminThemeController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminThemeController.java index f358235..4bcf9ce 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminThemeController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/admin/AdminThemeController.java @@ -1,5 +1,8 @@ package com.reading.platform.controller.admin; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.response.Result; @@ -46,6 +49,7 @@ public class AdminThemeController { @PostMapping @Operation(summary = "创建主题") + @Log(module = LogModule.THEME, type = LogOperationType.CREATE, description = "创建主题") @RequireRole(UserRole.ADMIN) public Result create(@Valid @RequestBody ThemeCreateRequest request) { Theme theme = themeService.create( @@ -58,6 +62,7 @@ public class AdminThemeController { @PutMapping("/{id}") @Operation(summary = "更新主题") + @Log(module = LogModule.THEME, type = LogOperationType.UPDATE, description = "更新主题") @RequireRole(UserRole.ADMIN) public Result update( @PathVariable Long id, @@ -74,6 +79,7 @@ public class AdminThemeController { @DeleteMapping("/{id}") @Operation(summary = "删除主题") + @Log(module = LogModule.THEME, type = LogOperationType.DELETE, description = "删除主题") @RequireRole(UserRole.ADMIN) public Result delete(@PathVariable Long id) { themeService.delete(id); @@ -82,6 +88,7 @@ public class AdminThemeController { @PutMapping("/reorder") @Operation(summary = "重新排序主题") + @Log(module = LogModule.THEME, type = LogOperationType.UPDATE, description = "重新排序主题") @RequireRole(UserRole.ADMIN) public Result reorder(@RequestBody List ids) { themeService.reorder(ids); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/parent/ParentNotificationController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/parent/ParentNotificationController.java index e645587..2a190b0 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/parent/ParentNotificationController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/parent/ParentNotificationController.java @@ -6,6 +6,9 @@ import com.reading.platform.common.response.Result; import com.reading.platform.common.security.SecurityUtils; import com.reading.platform.dto.response.NotificationForParentResponse; import com.reading.platform.entity.Notification; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.UserRole; import com.reading.platform.service.NotificationService; @@ -61,6 +64,7 @@ public class ParentNotificationController { } @Operation(summary = "Mark notification as read") + @Log(module = LogModule.NOTIFICATION, type = LogOperationType.UPDATE, description = "标记通知为已读") @PostMapping("/{id}/read") public Result markAsRead(@PathVariable Long id) { notificationService.markAsRead(id); @@ -68,6 +72,7 @@ public class ParentNotificationController { } @Operation(summary = "Mark all notifications as read") + @Log(module = LogModule.NOTIFICATION, type = LogOperationType.UPDATE, description = "标记所有通知为已读") @PostMapping("/read-all") public Result markAllAsRead() { Long userId = SecurityUtils.getCurrentUserId(); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/parent/ParentTaskController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/parent/ParentTaskController.java index e54a6c2..0837f97 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/parent/ParentTaskController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/parent/ParentTaskController.java @@ -11,6 +11,9 @@ import com.reading.platform.dto.response.TaskFeedbackResponse; import com.reading.platform.dto.response.TaskResponse; import com.reading.platform.dto.response.TaskWithCompletionResponse; import com.reading.platform.entity.Task; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.ErrorCode; import com.reading.platform.common.enums.UserRole; @@ -72,6 +75,7 @@ public class ParentTaskController { // =============== 提交与评价 API =============== @Operation(summary = "提交任务完成") + @Log(module = LogModule.TASK, type = LogOperationType.CREATE, description = "提交任务完成") @PostMapping("/{taskId}/submit") public Result submitTask( @PathVariable Long taskId, @@ -84,6 +88,7 @@ public class ParentTaskController { } @Operation(summary = "修改任务提交") + @Log(module = LogModule.TASK, type = LogOperationType.UPDATE, description = "修改任务提交") @PutMapping("/{taskId}/submit") public Result updateSubmission( @PathVariable Long taskId, @@ -117,6 +122,7 @@ public class ParentTaskController { // =============== 兼容旧接口 =============== @Operation(summary = "完成任务(旧接口,兼容使用,支持 JSON body)") + @Log(module = LogModule.TASK, type = LogOperationType.UPDATE, description = "完成任务") @PostMapping("/{id}/complete") public Result completeTask( @PathVariable Long id, diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolClassController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolClassController.java index a50a39a..29d3826 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolClassController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolClassController.java @@ -2,6 +2,9 @@ package com.reading.platform.controller.school; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.mapper.ClassMapper; import com.reading.platform.common.response.PageResult; import com.reading.platform.common.response.Result; @@ -46,6 +49,7 @@ public class SchoolClassController { private final LessonMapper lessonMapper; @Operation(summary = "Create class") + @Log(module = LogModule.CLASS, type = LogOperationType.CREATE, description = "创建新班级") @PostMapping public Result createClass(@Valid @RequestBody ClassCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -54,6 +58,7 @@ public class SchoolClassController { } @Operation(summary = "Update class") + @Log(module = LogModule.CLASS, type = LogOperationType.UPDATE, description = "修改班级信息") @PutMapping("/{id}") public Result updateClass(@PathVariable Long id, @RequestBody ClassUpdateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -111,6 +116,7 @@ public class SchoolClassController { } @Operation(summary = "Delete class") + @Log(module = LogModule.CLASS, type = LogOperationType.DELETE, description = "删除班级") @DeleteMapping("/{id}") public Result deleteClass(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -119,6 +125,7 @@ public class SchoolClassController { } @Operation(summary = "Assign teachers to class") + @Log(module = LogModule.CLASS, type = LogOperationType.UPDATE, description = "分配教师到班级") @PostMapping("/{id}/teachers") public Result assignTeachers(@PathVariable Long id, @RequestBody List teacherIds) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -127,6 +134,7 @@ public class SchoolClassController { } @Operation(summary = "Assign students to class") + @Log(module = LogModule.CLASS, type = LogOperationType.UPDATE, description = "分配学生到班级") @PostMapping("/{id}/students") public Result assignStudents(@PathVariable Long id, @RequestBody List studentIds) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -172,6 +180,7 @@ public class SchoolClassController { } @Operation(summary = "Update class teacher role") + @Log(module = LogModule.CLASS, type = LogOperationType.UPDATE, description = "更新班级教师角色") @PutMapping("/{id}/teachers/{teacherId}") public Result updateClassTeacher( @PathVariable Long id, @@ -185,6 +194,7 @@ public class SchoolClassController { } @Operation(summary = "Remove teacher from class") + @Log(module = LogModule.CLASS, type = LogOperationType.DELETE, description = "从班级移除教师") @DeleteMapping("/{id}/teachers/{teacherId}") public Result removeClassTeacher( @PathVariable Long id, diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolExportController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolExportController.java index aa9355c..07d6514 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolExportController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolExportController.java @@ -1,5 +1,8 @@ package com.reading.platform.controller.school; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.security.SecurityUtils; @@ -36,6 +39,7 @@ public class SchoolExportController { */ @GetMapping("/lessons") @Operation(summary = "导出授课记录") + @Log(module = LogModule.EXPORT, type = LogOperationType.EXPORT, description = "导出授课记录") public void exportLessons( @RequestParam(required = false) String startDate, @RequestParam(required = false) String endDate, @@ -60,6 +64,7 @@ public class SchoolExportController { */ @GetMapping("/teacher-stats") @Operation(summary = "导出教师绩效统计") + @Log(module = LogModule.EXPORT, type = LogOperationType.EXPORT, description = "导出教师绩效统计") public void exportTeacherStats( @RequestParam(required = false) String startDate, @RequestParam(required = false) String endDate, @@ -83,6 +88,7 @@ public class SchoolExportController { */ @GetMapping("/student-stats") @Operation(summary = "导出学生统计") + @Log(module = LogModule.EXPORT, type = LogOperationType.EXPORT, description = "导出学生统计") public void exportStudentStats( @RequestParam(required = false) Long classId, HttpServletResponse response) throws IOException { diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolGrowthController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolGrowthController.java index 0a589de..8f49da7 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolGrowthController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolGrowthController.java @@ -1,6 +1,9 @@ package com.reading.platform.controller.school; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.mapper.GrowthRecordMapper; import com.reading.platform.common.response.PageResult; import com.reading.platform.common.response.Result; @@ -28,6 +31,7 @@ public class SchoolGrowthController { private final GrowthRecordMapper growthRecordMapper; @Operation(summary = "Create growth record") + @Log(module = LogModule.GROWTH, type = LogOperationType.CREATE, description = "创建成长记录") @PostMapping public Result createGrowthRecord(@Valid @RequestBody GrowthRecordCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -38,6 +42,7 @@ public class SchoolGrowthController { } @Operation(summary = "Update growth record") + @Log(module = LogModule.GROWTH, type = LogOperationType.UPDATE, description = "修改成长记录") @PutMapping("/{id}") public Result updateGrowthRecord(@PathVariable Long id, @RequestBody GrowthRecordUpdateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -67,6 +72,7 @@ public class SchoolGrowthController { } @Operation(summary = "Delete growth record") + @Log(module = LogModule.GROWTH, type = LogOperationType.DELETE, description = "删除成长记录") @DeleteMapping("/{id}") public Result deleteGrowthRecord(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolOperationLogController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolOperationLogController.java index 214018d..ad0eaed 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolOperationLogController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolOperationLogController.java @@ -2,6 +2,7 @@ package com.reading.platform.controller.school; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.reading.platform.common.annotation.RequireRole; +import com.reading.platform.common.enums.LogModule; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.response.PageResult; import com.reading.platform.common.response.Result; @@ -14,6 +15,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -36,14 +38,14 @@ public class SchoolOperationLogController { @RequestParam(required = false, defaultValue = "1") Integer pageNum, @RequestParam(required = false, defaultValue = "10") Integer pageSize, @RequestParam(required = false) String module, - @RequestParam(required = false) String operator) { + @RequestParam(required = false) String action) { // 获取当前租户 ID Long tenantId = SecurityUtils.getCurrentTenantId(); // 调用 Service 层查询 Page page = operationLogService.getLogPage( - tenantId, pageNum, pageSize, module, operator + tenantId, pageNum, pageSize, module, action ); // Entity 转为 Response @@ -80,6 +82,16 @@ public class SchoolOperationLogController { return Result.success(convertToResponse(log)); } + @GetMapping("/modules") + @Operation(summary = "获取可用模块列表") + public Result> getAvailableModules() { + // 从枚举获取所有模块描述 + List modules = Arrays.stream(LogModule.values()) + .map(LogModule::toString) + .collect(Collectors.toList()); + return Result.success(modules); + } + /** * Entity 转 Response */ diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolPackageController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolPackageController.java index d017ddb..9e93b78 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolPackageController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolPackageController.java @@ -1,5 +1,8 @@ package com.reading.platform.controller.school; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.response.Result; @@ -64,6 +67,7 @@ public class SchoolPackageController { @PostMapping("/{collectionId}/renew") @Operation(summary = "续费课程套餐") + @Log(module = LogModule.PACKAGE, type = LogOperationType.UPDATE, description = "续费课程套餐") @RequireRole(UserRole.SCHOOL) public Result renewCollection( @PathVariable Long collectionId, diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolParentController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolParentController.java index da6a9d5..5438a02 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolParentController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolParentController.java @@ -2,6 +2,9 @@ package com.reading.platform.controller.school; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.mapper.ParentMapper; import com.reading.platform.mapper.ParentStudentMapper; import com.reading.platform.common.response.PageResult; @@ -36,6 +39,7 @@ public class SchoolParentController { private final ParentStudentMapper parentStudentMapper; @Operation(summary = "Create parent") + @Log(module = LogModule.PARENT, type = LogOperationType.CREATE, description = "创建新家长") @PostMapping public Result createParent(@Valid @RequestBody ParentCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -44,6 +48,7 @@ public class SchoolParentController { } @Operation(summary = "Update parent") + @Log(module = LogModule.PARENT, type = LogOperationType.UPDATE, description = "修改家长信息") @PutMapping("/{id}") public Result updateParent(@PathVariable Long id, @RequestBody ParentUpdateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -79,6 +84,7 @@ public class SchoolParentController { } @Operation(summary = "Delete parent") + @Log(module = LogModule.PARENT, type = LogOperationType.DELETE, description = "删除家长") @DeleteMapping("/{id}") public Result deleteParent(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -87,6 +93,7 @@ public class SchoolParentController { } @Operation(summary = "Reset parent password") + @Log(module = LogModule.PARENT, type = LogOperationType.UPDATE, description = "重置家长密码") @PostMapping("/{id}/reset-password") public Result resetPassword(@PathVariable Long id, @RequestParam String newPassword) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -95,6 +102,7 @@ public class SchoolParentController { } @Operation(summary = "Bind student to parent") + @Log(module = LogModule.PARENT, type = LogOperationType.CREATE, description = "绑定学生到家长") @PostMapping("/{parentId}/students/{studentId}") public Result bindStudent( @PathVariable Long parentId, @@ -107,6 +115,7 @@ public class SchoolParentController { } @Operation(summary = "Add child to parent (alias for bind student)") + @Log(module = LogModule.PARENT, type = LogOperationType.CREATE, description = "添加孩子到家长") @PostMapping("/{parentId}/children/{studentId}") public Result addChild( @PathVariable Long parentId, @@ -130,6 +139,7 @@ public class SchoolParentController { } @Operation(summary = "Unbind student from parent") + @Log(module = LogModule.PARENT, type = LogOperationType.DELETE, description = "从家长解绑学生") @DeleteMapping("/{parentId}/students/{studentId}") public Result unbindStudent(@PathVariable Long parentId, @PathVariable Long studentId) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -138,6 +148,7 @@ public class SchoolParentController { } @Operation(summary = "Remove child from parent (alias for unbind student)") + @Log(module = LogModule.PARENT, type = LogOperationType.DELETE, description = "从家长移除孩子") @DeleteMapping("/{parentId}/children/{studentId}") public Result removeChild(@PathVariable Long parentId, @PathVariable Long studentId) { Long tenantId = SecurityUtils.getCurrentTenantId(); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolScheduleController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolScheduleController.java index 8d8420b..397e606 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolScheduleController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolScheduleController.java @@ -1,6 +1,9 @@ package com.reading.platform.controller.school; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.response.PageResult; @@ -82,6 +85,7 @@ public class SchoolScheduleController { @PostMapping @Operation(summary = "创建排课") + @Log(module = LogModule.SCHEDULE, type = LogOperationType.CREATE, description = "创建排课计划") public Result> createSchedule(@Valid @RequestBody SchedulePlanCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); List plans = schoolScheduleService.createSchedule(tenantId, request); @@ -93,6 +97,7 @@ public class SchoolScheduleController { @PutMapping("/{id}") @Operation(summary = "更新排课") + @Log(module = LogModule.SCHEDULE, type = LogOperationType.UPDATE, description = "更新排课计划") public Result updateSchedule( @PathVariable Long id, @RequestBody SchedulePlanUpdateRequest request) { @@ -104,6 +109,7 @@ public class SchoolScheduleController { @DeleteMapping("/{id}") @Operation(summary = "取消排课") + @Log(module = LogModule.SCHEDULE, type = LogOperationType.DELETE, description = "取消排课计划") public Result cancelSchedule(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); schoolScheduleService.cancelSchedule(id, tenantId); @@ -112,6 +118,7 @@ public class SchoolScheduleController { @PostMapping("/batch") @Operation(summary = "批量创建排课") + @Log(module = LogModule.SCHEDULE, type = LogOperationType.CREATE, description = "批量创建排课计划") public Result> batchCreateSchedules( @RequestBody List<@Valid SchedulePlanCreateRequest> requests) { @@ -147,6 +154,7 @@ public class SchoolScheduleController { @PostMapping("/batch-by-classes") @Operation(summary = "批量创建排课(按班级)") + @Log(module = LogModule.SCHEDULE, type = LogOperationType.CREATE, description = "按班级批量创建排课") public Result> createSchedulesByClasses( @Valid @RequestBody ScheduleCreateByClassesRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolSettingsController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolSettingsController.java index af115a1..fc2d5db 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolSettingsController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolSettingsController.java @@ -1,5 +1,8 @@ package com.reading.platform.controller.school; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.response.Result; @@ -41,6 +44,7 @@ public class SchoolSettingsController { @PutMapping @Operation(summary = "更新系统设置") + @Log(module = LogModule.SYSTEM_SETTING, type = LogOperationType.UPDATE, description = "更新系统设置") public Result updateSettings(@RequestBody SchoolSettingsUpdateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); // TODO: 实现系统设置更新,根据 tenantId 更新 @@ -57,6 +61,7 @@ public class SchoolSettingsController { @PutMapping("/basic") @Operation(summary = "更新基础设置") + @Log(module = LogModule.SYSTEM_SETTING, type = LogOperationType.UPDATE, description = "更新基础设置") public Result updateBasicSettings(@RequestBody BasicSettingsUpdateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); // TODO: 实现基础设置更新,根据 tenantId 更新 @@ -73,6 +78,7 @@ public class SchoolSettingsController { @PutMapping("/notification") @Operation(summary = "更新通知设置") + @Log(module = LogModule.SYSTEM_SETTING, type = LogOperationType.UPDATE, description = "更新通知设置") public Result updateNotificationSettings(@RequestBody NotificationSettingsUpdateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); // TODO: 实现通知设置更新,根据 tenantId 更新 @@ -89,6 +95,7 @@ public class SchoolSettingsController { @PutMapping("/security") @Operation(summary = "更新安全设置") + @Log(module = LogModule.SYSTEM_SETTING, type = LogOperationType.UPDATE, description = "更新安全设置") public Result updateSecuritySettings(@RequestBody SecuritySettingsUpdateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); // TODO: 实现安全设置更新,根据 tenantId 更新 diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolStudentController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolStudentController.java index 6359aa5..6a781f2 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolStudentController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolStudentController.java @@ -1,6 +1,9 @@ package com.reading.platform.controller.school; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.mapper.StudentMapper; import com.reading.platform.common.response.PageResult; import com.reading.platform.common.response.Result; @@ -30,6 +33,7 @@ public class SchoolStudentController { private final StudentMapper studentMapper; @Operation(summary = "Create student") + @Log(module = LogModule.STUDENT, type = LogOperationType.CREATE, description = "创建学生") @PostMapping public Result createStudent(@Valid @RequestBody StudentCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -38,6 +42,7 @@ public class SchoolStudentController { } @Operation(summary = "Update student") + @Log(module = LogModule.STUDENT, type = LogOperationType.UPDATE, description = "修改学生") @PutMapping("/{id}") public Result updateStudent(@PathVariable Long id, @RequestBody StudentUpdateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -76,6 +81,7 @@ public class SchoolStudentController { } @Operation(summary = "Delete student") + @Log(module = LogModule.STUDENT, type = LogOperationType.DELETE, description = "删除学生") @DeleteMapping("/{id}") public Result deleteStudent(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTaskTemplateController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTaskTemplateController.java index 5635eeb..9882649 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTaskTemplateController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTaskTemplateController.java @@ -1,6 +1,9 @@ package com.reading.platform.controller.school; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.annotation.RequireRole; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.mapper.TaskTemplateMapper; @@ -70,6 +73,7 @@ public class SchoolTaskTemplateController { @PostMapping @Operation(summary = "创建模板") + @Log(module = LogModule.TASK_TEMPLATE, type = LogOperationType.CREATE, description = "创建任务模板") public Result createTemplate(@Valid @RequestBody TaskTemplateCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); Long userId = SecurityUtils.getCurrentUserId(); @@ -79,6 +83,7 @@ public class SchoolTaskTemplateController { @PutMapping("/{id}") @Operation(summary = "更新模板") + @Log(module = LogModule.TASK_TEMPLATE, type = LogOperationType.UPDATE, description = "更新任务模板") public Result updateTemplate( @PathVariable Long id, @RequestBody TaskTemplateCreateRequest request) { @@ -94,6 +99,7 @@ public class SchoolTaskTemplateController { @DeleteMapping("/{id}") @Operation(summary = "删除模板") + @Log(module = LogModule.TASK_TEMPLATE, type = LogOperationType.DELETE, description = "删除任务模板") public Result deleteTemplate(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); TaskTemplate template = taskTemplateService.getTemplateById(id); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTeacherController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTeacherController.java index 01229c7..8ed74ce 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTeacherController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTeacherController.java @@ -1,6 +1,9 @@ package com.reading.platform.controller.school; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.response.PageResult; import com.reading.platform.common.response.Result; import com.reading.platform.common.security.SecurityUtils; @@ -26,6 +29,7 @@ public class SchoolTeacherController { private final TeacherService teacherService; @Operation(summary = "Create teacher") + @Log(module = LogModule.TEACHER, type = LogOperationType.CREATE, description = "创建新教师") @PostMapping public Result createTeacher(@Valid @RequestBody TeacherCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -34,6 +38,7 @@ public class SchoolTeacherController { } @Operation(summary = "Update teacher") + @Log(module = LogModule.TEACHER, type = LogOperationType.UPDATE, description = "修改教师信息") @PutMapping("/{id}") public Result updateTeacher(@PathVariable Long id, @RequestBody TeacherUpdateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -63,6 +68,7 @@ public class SchoolTeacherController { } @Operation(summary = "Delete teacher") + @Log(module = LogModule.TEACHER, type = LogOperationType.DELETE, description = "删除教师") @DeleteMapping("/{id}") public Result deleteTeacher(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -71,6 +77,7 @@ public class SchoolTeacherController { } @Operation(summary = "Reset teacher password") + @Log(module = LogModule.TEACHER, type = LogOperationType.UPDATE, description = "重置教师密码") @PostMapping("/{id}/reset-password") public Result> resetPassword(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherCourseController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherCourseController.java index a3d8eaa..0c055ce 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherCourseController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherCourseController.java @@ -3,6 +3,7 @@ package com.reading.platform.controller.teacher; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.reading.platform.common.enums.CourseStatus; +import com.reading.platform.common.annotation.Log; import com.reading.platform.common.mapper.ClassMapper; import com.reading.platform.common.mapper.CoursePackageMapper; import com.reading.platform.common.mapper.StudentMapper; diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherFeedbackController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherFeedbackController.java index f181375..8565848 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherFeedbackController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherFeedbackController.java @@ -2,6 +2,7 @@ package com.reading.platform.controller.teacher; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.reading.platform.common.annotation.RequireRole; +import com.reading.platform.common.annotation.Log; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.mapper.LessonFeedbackMapper; import com.reading.platform.common.response.PageResult; diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherGrowthController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherGrowthController.java index d8c4227..acdb34f 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherGrowthController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherGrowthController.java @@ -1,6 +1,9 @@ package com.reading.platform.controller.teacher; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.mapper.GrowthRecordMapper; import com.reading.platform.common.response.PageResult; import com.reading.platform.common.response.Result; @@ -28,6 +31,7 @@ public class TeacherGrowthController { private final GrowthRecordMapper growthRecordMapper; @Operation(summary = "创建成长记录") + @Log(module = LogModule.GROWTH, type = LogOperationType.CREATE, description = "创建成长记录") @PostMapping public Result createGrowthRecord(@Valid @RequestBody GrowthRecordCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -37,6 +41,7 @@ public class TeacherGrowthController { } @Operation(summary = "更新成长记录") + @Log(module = LogModule.GROWTH, type = LogOperationType.UPDATE, description = "更新成长记录") @PutMapping("/{id}") public Result updateGrowthRecord(@PathVariable Long id, @RequestBody GrowthRecordUpdateRequest request) { GrowthRecord record = growthRecordService.updateGrowthRecord(id, request); @@ -64,6 +69,7 @@ public class TeacherGrowthController { } @Operation(summary = "删除成长记录") + @Log(module = LogModule.GROWTH, type = LogOperationType.DELETE, description = "删除成长记录") @DeleteMapping("/{id}") public Result deleteGrowthRecord(@PathVariable Long id) { growthRecordService.deleteGrowthRecord(id); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherLessonController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherLessonController.java index 0c049d0..9adc53e 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherLessonController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherLessonController.java @@ -1,6 +1,9 @@ package com.reading.platform.controller.teacher; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.mapper.ClassMapper; import com.reading.platform.common.mapper.LessonMapper; import com.reading.platform.common.mapper.StudentRecordMapper; @@ -55,6 +58,7 @@ public class TeacherLessonController { private final SchoolScheduleService schoolScheduleService; @Operation(summary = "创建课时") + @Log(module = LogModule.LESSON, type = LogOperationType.CREATE, description = "创建课时") @PostMapping public Result createLesson(@Valid @RequestBody LessonCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -65,6 +69,7 @@ public class TeacherLessonController { } @Operation(summary = "更新课时") + @Log(module = LogModule.LESSON, type = LogOperationType.UPDATE, description = "更新课时") @PutMapping("/{id}") public Result updateLesson(@PathVariable Long id, @RequestBody LessonUpdateRequest request) { Lesson lesson = lessonService.updateLesson(id, request); @@ -126,6 +131,7 @@ public class TeacherLessonController { } @Operation(summary = "开始上课") + @Log(module = LogModule.LESSON, type = LogOperationType.OTHER, description = "开始上课") @PostMapping("/{id}/start") public Result startLesson(@PathVariable Long id) { lessonService.startLesson(id); @@ -133,6 +139,7 @@ public class TeacherLessonController { } @Operation(summary = "完成课时") + @Log(module = LogModule.LESSON, type = LogOperationType.OTHER, description = "完成课时") @PostMapping("/{id}/complete") public Result completeLesson(@PathVariable Long id) { lessonService.completeLesson(id); @@ -140,6 +147,7 @@ public class TeacherLessonController { } @Operation(summary = "取消课时") + @Log(module = LogModule.LESSON, type = LogOperationType.OTHER, description = "取消课时") @PostMapping("/{id}/cancel") public Result cancelLesson(@PathVariable Long id) { lessonService.cancelLesson(id); @@ -164,6 +172,7 @@ public class TeacherLessonController { } @Operation(summary = "保存学生记录") + @Log(module = LogModule.STUDENT_RECORD, type = LogOperationType.CREATE, description = "保存学生记录") @PostMapping("/{id}/students/{studentId}/record") public Result saveStudentRecord( @PathVariable Long id, @@ -174,6 +183,7 @@ public class TeacherLessonController { } @Operation(summary = "批量保存学生记录") + @Log(module = LogModule.STUDENT_RECORD, type = LogOperationType.CREATE, description = "批量保存学生记录") @PostMapping("/{id}/students/batch-records") public Result> batchSaveStudentRecords( @PathVariable Long id, @@ -192,6 +202,7 @@ public class TeacherLessonController { } @Operation(summary = "提交课时反馈") + @Log(module = LogModule.LESSON_FEEDBACK, type = LogOperationType.CREATE, description = "提交课时反馈") @PostMapping("/{id}/feedback") public Result submitFeedback( @PathVariable Long id, @@ -202,6 +213,7 @@ public class TeacherLessonController { } @Operation(summary = "保存课时进度") + @Log(module = LogModule.LESSON, type = LogOperationType.UPDATE, description = "保存课时进度") @PutMapping("/{id}/progress") public Result saveLessonProgress( @PathVariable Long id, @@ -235,6 +247,7 @@ public class TeacherLessonController { } @Operation(summary = "从排课开始上课") + @Log(module = LogModule.LESSON, type = LogOperationType.OTHER, description = "从排课开始上课") @PostMapping("/from-schedule/{schedulePlanId}/start") public Result startLessonFromSchedule(@PathVariable Long schedulePlanId) { Long teacherId = SecurityUtils.getCurrentUserId(); @@ -249,6 +262,7 @@ public class TeacherLessonController { } @Operation(summary = "从排课创建课时") + @Log(module = LogModule.LESSON, type = LogOperationType.CREATE, description = "从排课创建课时") @PostMapping("/from-schedule/{schedulePlanId}") public Result createLessonFromSchedule(@PathVariable Long schedulePlanId) { Long teacherId = SecurityUtils.getCurrentUserId(); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherNotificationController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherNotificationController.java index 71a4fad..601c040 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherNotificationController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherNotificationController.java @@ -1,5 +1,8 @@ package com.reading.platform.controller.teacher; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.reading.platform.common.response.PageResult; import com.reading.platform.common.response.Result; @@ -37,6 +40,7 @@ public class TeacherNotificationController { } @Operation(summary = "标记通知为已读") + @Log(module = LogModule.NOTIFICATION, type = LogOperationType.OTHER, description = "标记通知为已读") @PostMapping("/{id}/read") public Result markAsRead(@PathVariable Long id) { notificationService.markAsRead(id); @@ -44,6 +48,7 @@ public class TeacherNotificationController { } @Operation(summary = "标记所有通知为已读") + @Log(module = LogModule.NOTIFICATION, type = LogOperationType.OTHER, description = "标记所有通知为已读") @PostMapping("/read-all") public Result markAllAsRead() { Long userId = SecurityUtils.getCurrentUserId(); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherScheduleController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherScheduleController.java index dc0514f..895e668 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherScheduleController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherScheduleController.java @@ -2,6 +2,9 @@ package com.reading.platform.controller.teacher; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.reading.platform.common.annotation.RequireRole; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.response.PageResult; import com.reading.platform.common.response.Result; @@ -81,6 +84,7 @@ public class TeacherScheduleController { @PostMapping @Operation(summary = "创建排课") + @Log(module = LogModule.SCHEDULE, type = LogOperationType.CREATE, description = "创建排课") public Result createSchedule(@Valid @RequestBody SchedulePlanCreateRequest request) { Long teacherId = SecurityUtils.getCurrentUserId(); Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -90,6 +94,7 @@ public class TeacherScheduleController { @PutMapping("/{id}") @Operation(summary = "更新排课") + @Log(module = LogModule.SCHEDULE, type = LogOperationType.UPDATE, description = "更新排课") public Result updateSchedule( @PathVariable Long id, @RequestBody SchedulePlanUpdateRequest request) { @@ -99,6 +104,7 @@ public class TeacherScheduleController { @DeleteMapping("/{id}") @Operation(summary = "取消排课") + @Log(module = LogModule.SCHEDULE, type = LogOperationType.DELETE, description = "取消排课") public Result cancelSchedule(@PathVariable Long id) { teacherScheduleService.cancelSchedule(id); return Result.success(); diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherTaskController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherTaskController.java index 9d546f9..25ef0aa 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherTaskController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherTaskController.java @@ -1,6 +1,9 @@ package com.reading.platform.controller.teacher; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.mapper.TaskMapper; import com.reading.platform.common.response.PageResult; import com.reading.platform.common.response.Result; @@ -33,6 +36,7 @@ public class TeacherTaskController { private final TaskFeedbackService taskFeedbackService; @Operation(summary = "创建任务") + @Log(module = LogModule.TASK, type = LogOperationType.CREATE, description = "创建任务") @PostMapping public Result createTask(@Valid @RequestBody TaskCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); @@ -42,6 +46,7 @@ public class TeacherTaskController { } @Operation(summary = "更新任务") + @Log(module = LogModule.TASK, type = LogOperationType.UPDATE, description = "更新任务") @PutMapping("/{id}") public Result updateTask(@PathVariable Long id, @RequestBody TaskUpdateRequest request) { Task task = taskService.updateTask(id, request); @@ -77,6 +82,7 @@ public class TeacherTaskController { } @Operation(summary = "删除任务") + @Log(module = LogModule.TASK, type = LogOperationType.DELETE, description = "删除任务") @DeleteMapping("/{id}") public Result deleteTask(@PathVariable Long id) { taskService.deleteTask(id); @@ -106,6 +112,7 @@ public class TeacherTaskController { } @Operation(summary = "提交评价") + @Log(module = LogModule.TASK_FEEDBACK, type = LogOperationType.CREATE, description = "提交任务评价") @PostMapping("/completions/{completionId}/feedback") public Result submitFeedback( @PathVariable Long completionId, @@ -116,6 +123,7 @@ public class TeacherTaskController { } @Operation(summary = "修改评价") + @Log(module = LogModule.TASK_FEEDBACK, type = LogOperationType.UPDATE, description = "修改任务评价") @PutMapping("/completions/{completionId}/feedback") public Result updateFeedback( @PathVariable Long completionId, diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherTaskTemplateController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherTaskTemplateController.java index 1aefe38..64fa31a 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherTaskTemplateController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/teacher/TeacherTaskTemplateController.java @@ -2,6 +2,9 @@ package com.reading.platform.controller.teacher; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.reading.platform.common.annotation.RequireRole; +import com.reading.platform.common.annotation.Log; +import com.reading.platform.common.enums.LogModule; +import com.reading.platform.common.enums.LogOperationType; import com.reading.platform.common.enums.UserRole; import com.reading.platform.common.mapper.TaskTemplateMapper; import com.reading.platform.common.response.PageResult; @@ -65,6 +68,7 @@ public class TeacherTaskTemplateController { @PostMapping @Operation(summary = "创建模板") + @Log(module = LogModule.TASK_TEMPLATE, type = LogOperationType.CREATE, description = "创建任务模板") public Result createTemplate(@Valid @RequestBody TaskTemplateCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); Long userId = SecurityUtils.getCurrentUserId(); @@ -74,6 +78,7 @@ public class TeacherTaskTemplateController { @PostMapping("/from-template") @Operation(summary = "从模板创建任务") + @Log(module = LogModule.TASK_TEMPLATE, type = LogOperationType.CREATE, description = "从模板创建任务") public Result createFromTemplate(@Valid @RequestBody CreateTaskFromTemplateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); Long userId = SecurityUtils.getCurrentUserId(); @@ -83,6 +88,7 @@ public class TeacherTaskTemplateController { @PutMapping("/{id}") @Operation(summary = "更新模板") + @Log(module = LogModule.TASK_TEMPLATE, type = LogOperationType.UPDATE, description = "更新任务模板") public Result updateTemplate( @PathVariable Long id, @RequestBody TaskTemplateCreateRequest request) { @@ -92,6 +98,7 @@ public class TeacherTaskTemplateController { @DeleteMapping("/{id}") @Operation(summary = "删除模板") + @Log(module = LogModule.TASK_TEMPLATE, type = LogOperationType.DELETE, description = "删除任务模板") public Result deleteTemplate(@PathVariable Long id) { taskTemplateService.deleteTemplate(id); return Result.success(); diff --git a/reading-platform-java/src/main/java/com/reading/platform/dto/request/TenantUpdateRequest.java b/reading-platform-java/src/main/java/com/reading/platform/dto/request/TenantUpdateRequest.java index b2a79a8..7e59293 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/dto/request/TenantUpdateRequest.java +++ b/reading-platform-java/src/main/java/com/reading/platform/dto/request/TenantUpdateRequest.java @@ -51,5 +51,4 @@ public class TenantUpdateRequest { @Schema(description = "结束日期") private LocalDate expireDate; - } diff --git a/reading-platform-java/src/main/java/com/reading/platform/entity/OperationLog.java b/reading-platform-java/src/main/java/com/reading/platform/entity/OperationLog.java index c71e89b..c01dc74 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/entity/OperationLog.java +++ b/reading-platform-java/src/main/java/com/reading/platform/entity/OperationLog.java @@ -23,7 +23,7 @@ public class OperationLog extends BaseEntity { @Schema(description = "用户角色") private String userRole; - @Schema(description = "操作类型") + @Schema(description = "操作类型(CREATE/UPDATE/DELETE/QUERY/EXPORT/IMPORT/OTHER)") private String action; @Schema(description = "操作模块") @@ -44,4 +44,7 @@ public class OperationLog extends BaseEntity { @Schema(description = "用户代理") private String userAgent; + @Schema(description = "请求参数(JSON 格式,不返回给前端)") + private String requestParams; + } diff --git a/reading-platform-java/src/main/java/com/reading/platform/service/OperationLogService.java b/reading-platform-java/src/main/java/com/reading/platform/service/OperationLogService.java index db194ed..8370d66 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/service/OperationLogService.java +++ b/reading-platform-java/src/main/java/com/reading/platform/service/OperationLogService.java @@ -15,7 +15,7 @@ public interface OperationLogService extends IService { * 分页查询日志列表(按租户隔离) */ Page getLogPage(Long tenantId, Integer pageNum, Integer pageSize, - String module, String operator); + String module, String action); /** * 获取日志统计(按租户隔离) diff --git a/reading-platform-java/src/main/java/com/reading/platform/service/impl/AuthServiceImpl.java b/reading-platform-java/src/main/java/com/reading/platform/service/impl/AuthServiceImpl.java index 255dc24..3056376 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/service/impl/AuthServiceImpl.java +++ b/reading-platform-java/src/main/java/com/reading/platform/service/impl/AuthServiceImpl.java @@ -64,7 +64,7 @@ public class AuthServiceImpl implements AuthService { if (adminUser != null) { if (!passwordEncoder.matches(password, adminUser.getPassword())) { log.warn("登录失败:密码错误,用户名:{}", username); - throw new BusinessException(ErrorCode.LOGIN_FAILED); + throw new BusinessException(ErrorCode.INCORRECT_PASSWORD); } if (!GenericStatus.isActive(adminUser.getStatus())) { log.warn("登录失败:账户已禁用,用户名:{}", username); @@ -104,7 +104,7 @@ public class AuthServiceImpl implements AuthService { if (teacher != null) { if (!passwordEncoder.matches(password, teacher.getPassword())) { log.warn("登录失败:密码错误,用户名:{}", username); - throw new BusinessException(ErrorCode.LOGIN_FAILED); + throw new BusinessException(ErrorCode.INCORRECT_PASSWORD); } if (!GenericStatus.isActive(teacher.getStatus())) { log.warn("登录失败:账户已禁用,用户名:{}", username); @@ -150,7 +150,7 @@ public class AuthServiceImpl implements AuthService { if (parent != null) { if (!passwordEncoder.matches(password, parent.getPassword())) { log.warn("登录失败:密码错误,用户名:{}", username); - throw new BusinessException(ErrorCode.LOGIN_FAILED); + throw new BusinessException(ErrorCode.INCORRECT_PASSWORD); } if (!GenericStatus.isActive(parent.getStatus())) { log.warn("登录失败:账户已禁用,用户名:{}", username); @@ -190,7 +190,7 @@ public class AuthServiceImpl implements AuthService { if (tenant != null) { if (!passwordEncoder.matches(password, tenant.getPassword())) { log.warn("登录失败:密码错误,用户名:{}", username); - throw new BusinessException(ErrorCode.LOGIN_FAILED); + throw new BusinessException(ErrorCode.INCORRECT_PASSWORD); } if (!TenantStatus.ACTIVE.getCode().equalsIgnoreCase(tenant.getStatus())) { log.warn("登录失败:账户已禁用,用户名:{}", username); @@ -220,8 +220,8 @@ public class AuthServiceImpl implements AuthService { .build(); } - log.warn("登录失败:用户不存在,用户名:{}", username); - throw new BusinessException(ErrorCode.LOGIN_FAILED); + log.warn("登录失败:账号不存在,用户名:{}", username); + throw new BusinessException(ErrorCode.ACCOUNT_NOT_FOUND); } private LoginResponse loginWithRole(String username, String password, String role) { @@ -232,9 +232,13 @@ public class AuthServiceImpl implements AuthService { AdminUser adminUser = adminUserMapper.selectOne( new LambdaQueryWrapper().eq(AdminUser::getUsername, username) ); - if (adminUser == null || !passwordEncoder.matches(password, adminUser.getPassword())) { - log.warn("登录失败:用户不存在或密码错误,用户名:{}", username); - throw new BusinessException(ErrorCode.LOGIN_FAILED); + if (adminUser == null) { + log.warn("登录失败:账号不存在,用户名:{}", username); + throw new BusinessException(ErrorCode.ACCOUNT_NOT_FOUND); + } + if (!passwordEncoder.matches(password, adminUser.getPassword())) { + log.warn("登录失败:密码错误,用户名:{}", username); + throw new BusinessException(ErrorCode.INCORRECT_PASSWORD); } if (!GenericStatus.isActive(adminUser.getStatus())) { log.warn("登录失败:账户已禁用,用户名:{}", username); @@ -269,9 +273,13 @@ public class AuthServiceImpl implements AuthService { Tenant tenant = tenantMapper.selectOne( new LambdaQueryWrapper().eq(Tenant::getUsername, username) ); - if (tenant == null || !passwordEncoder.matches(password, tenant.getPassword())) { - log.warn("登录失败:用户不存在或密码错误,用户名:{}", username); - throw new BusinessException(ErrorCode.LOGIN_FAILED); + if (tenant == null) { + log.warn("登录失败:账号不存在,用户名:{}", username); + throw new BusinessException(ErrorCode.ACCOUNT_NOT_FOUND); + } + if (!passwordEncoder.matches(password, tenant.getPassword())) { + log.warn("登录失败:密码错误,用户名:{}", username); + throw new BusinessException(ErrorCode.INCORRECT_PASSWORD); } if (!GenericStatus.isActive(tenant.getStatus())) { log.warn("登录失败:账户已禁用,用户名:{}", username); @@ -303,9 +311,13 @@ public class AuthServiceImpl implements AuthService { Teacher teacher = teacherMapper.selectOne( new LambdaQueryWrapper().eq(Teacher::getUsername, username) ); - if (teacher == null || !passwordEncoder.matches(password, teacher.getPassword())) { - log.warn("登录失败:用户不存在或密码错误,用户名:{}", username); - throw new BusinessException(ErrorCode.LOGIN_FAILED); + if (teacher == null) { + log.warn("登录失败:账号不存在,用户名:{}", username); + throw new BusinessException(ErrorCode.ACCOUNT_NOT_FOUND); + } + if (!passwordEncoder.matches(password, teacher.getPassword())) { + log.warn("登录失败:密码错误,用户名:{}", username); + throw new BusinessException(ErrorCode.INCORRECT_PASSWORD); } if (!GenericStatus.isActive(teacher.getStatus())) { log.warn("登录失败:账户已禁用,用户名:{}", username); @@ -346,9 +358,13 @@ public class AuthServiceImpl implements AuthService { Parent parent = parentMapper.selectOne( new LambdaQueryWrapper().eq(Parent::getUsername, username) ); - if (parent == null || !passwordEncoder.matches(password, parent.getPassword())) { - log.warn("登录失败:用户不存在或密码错误,用户名:{}", username); - throw new BusinessException(ErrorCode.LOGIN_FAILED); + if (parent == null) { + log.warn("登录失败:账号不存在,用户名:{}", username); + throw new BusinessException(ErrorCode.ACCOUNT_NOT_FOUND); + } + if (!passwordEncoder.matches(password, parent.getPassword())) { + log.warn("登录失败:密码错误,用户名:{}", username); + throw new BusinessException(ErrorCode.INCORRECT_PASSWORD); } if (!GenericStatus.isActive(parent.getStatus())) { log.warn("登录失败:账户已禁用,用户名:{}", username); @@ -379,7 +395,7 @@ public class AuthServiceImpl implements AuthService { .tenantId(parent.getTenantId()) .build(); } - default -> throw new BusinessException(ErrorCode.LOGIN_FAILED); + default -> throw new BusinessException(ErrorCode.ACCOUNT_NOT_FOUND); } } diff --git a/reading-platform-java/src/main/java/com/reading/platform/service/impl/OperationLogServiceImpl.java b/reading-platform-java/src/main/java/com/reading/platform/service/impl/OperationLogServiceImpl.java index b020b01..be85ad6 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/service/impl/OperationLogServiceImpl.java +++ b/reading-platform-java/src/main/java/com/reading/platform/service/impl/OperationLogServiceImpl.java @@ -15,7 +15,9 @@ import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * 操作日志服务实现类 @@ -28,7 +30,7 @@ public class OperationLogServiceImpl extends ServiceImpl getLogPage(Long tenantId, Integer pageNum, Integer pageSize, - String module, String operator) { + String module, String action) { log.debug("分页查询日志列表,页码:{},每页数量:{},租户 ID:{}", pageNum, pageSize, tenantId); int current = pageNum != null && pageNum > 0 ? pageNum : 1; @@ -43,8 +45,8 @@ public class OperationLogServiceImpl extends ServiceImpl allLogs = this.list( + new LambdaQueryWrapper() + .eq(OperationLog::getTenantId, tenantId) + .select(OperationLog::getModule) + ); + + Map byModuleMap = allLogs.stream() + .collect(Collectors.groupingBy( + OperationLog::getModule, + Collectors.counting() + )); + + // 转换为前端期望的格式:Map + Map byModule = byModuleMap.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> entry.getValue().intValue() + )); + Map stats = new HashMap<>(); stats.put("totalLogs", totalLogs); - stats.put("byModule", new HashMap<>()); + stats.put("byModule", byModule); stats.put("byOperator", new HashMap<>()); return stats; diff --git a/reading-platform-java/src/main/resources/db/migration/V27__extend_schedule_plan_table.sql b/reading-platform-java/src/main/resources/db/migration/V27__extend_schedule_plan_table.sql index c7bccb7..937e3ec 100644 --- a/reading-platform-java/src/main/resources/db/migration/V27__extend_schedule_plan_table.sql +++ b/reading-platform-java/src/main/resources/db/migration/V27__extend_schedule_plan_table.sql @@ -15,7 +15,3 @@ ALTER TABLE `schedule_plan` ADD COLUMN `lesson_type` VARCHAR(50) COMMENT '课程类型: INTRODUCTION/COLLECTIVE/LANGUAGE/SOCIETY/SCIENCE/ART/HEALTH', ADD INDEX `idx_lesson_type` (`lesson_type`); --- 添加外键约束 -ALTER TABLE `schedule_plan` -ADD CONSTRAINT `fk_schedule_plan_course_package` -FOREIGN KEY (`course_package_id`) REFERENCES `course_package`(`id`); diff --git a/reading-platform-java/src/main/resources/db/migration/V48__add_request_params_to_operation_log.sql b/reading-platform-java/src/main/resources/db/migration/V48__add_request_params_to_operation_log.sql new file mode 100644 index 0000000..5b20bc8 --- /dev/null +++ b/reading-platform-java/src/main/resources/db/migration/V48__add_request_params_to_operation_log.sql @@ -0,0 +1,19 @@ +-- ===================================================== +-- 操作日志表添加请求参数字段 +-- 版本:V48 +-- 创建时间:2026-03-23 +-- 描述:在 operation_log 表中添加 request_params 字段,用于记录请求参数 +-- ===================================================== + +-- ----------------------------------------------------- +-- 1. 添加 request_params 字段 +-- ----------------------------------------------------- +ALTER TABLE `operation_log` + ADD COLUMN `request_params` TEXT COMMENT '请求参数(JSON 格式)' AFTER `user_agent`; + +-- ----------------------------------------------------- +-- 说明: +-- - request_params 字段用于存储请求参数的 JSON 表示 +-- - 该字段仅在 Service 层和数据库层面使用,不通过 API 返回给前端 +-- - 参数记录由 LogAspect 自动完成,当 @Log 注解的 recordParams() = true 时生效 +-- -----------------------------------------------------