Compare commits
2 Commits
2d9856edac
...
b715c9a31c
| Author | SHA1 | Date | |
|---|---|---|---|
| b715c9a31c | |||
| 8aaa8cdd94 |
@ -3,7 +3,8 @@
|
||||
"allow": [
|
||||
"Bash(mvn compile:*)",
|
||||
"Bash(sed:*)",
|
||||
"Bash(grep:*)"
|
||||
"Bash(grep:*)",
|
||||
"Bash(export:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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<string, number>; byOperator: Record<string, number> }>('/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<OperationLog>(`/v1/school/operation-logs/${id}`);
|
||||
|
||||
/**
|
||||
* 获取可用模块列表
|
||||
* 用于操作日志页面的模块筛选下拉框
|
||||
*/
|
||||
export const getOperationLogModules = () =>
|
||||
http.get<string[]>('/v1/school/operation-logs/modules');
|
||||
|
||||
// ==================== 任务模板 API ====================
|
||||
|
||||
export interface TaskTemplate {
|
||||
|
||||
21
reading-platform-frontend/src/constants/logOperationType.ts
Normal file
21
reading-platform-frontend/src/constants/logOperationType.ts
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 操作类型映射(后端 code → 前端中文描述)
|
||||
* 对应后端 LogOperationType 枚举
|
||||
*/
|
||||
export const LOG_OPERATION_TYPE_LABELS: Record<string, string> = {
|
||||
CREATE: '新增',
|
||||
UPDATE: '修改',
|
||||
DELETE: '删除',
|
||||
QUERY: '查询',
|
||||
EXPORT: '导出',
|
||||
IMPORT: '导入',
|
||||
OTHER: '其他',
|
||||
};
|
||||
|
||||
/**
|
||||
* 操作类型选项(用于下拉选择)
|
||||
*/
|
||||
export const LOG_OPERATION_TYPE_OPTIONS = Object.entries(LOG_OPERATION_TYPE_LABELS).map(([code, label]) => ({
|
||||
code,
|
||||
label,
|
||||
}));
|
||||
@ -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) {
|
||||
|
||||
@ -490,10 +490,10 @@ export function translateResourceType(type: string): string {
|
||||
|
||||
// 通用状态映射(用于 Student、Teacher、Parent、Class 等实体的 active/ACTIVE 状态)
|
||||
export const GENERIC_STATUS_MAP: Record<string, string> = {
|
||||
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" },
|
||||
};
|
||||
|
||||
|
||||
@ -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('修改成功')
|
||||
@ -25,8 +25,8 @@
|
||||
style="width: 150px"
|
||||
@change="loadLogs"
|
||||
>
|
||||
<a-select-option v-for="action in actions" :key="action" :value="action">
|
||||
{{ action }}
|
||||
<a-select-option v-for="option in actions" :key="option.code" :value="option.code">
|
||||
{{ option.label }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
<a-range-picker
|
||||
@ -135,7 +135,8 @@ import { message } from 'ant-design-vue';
|
||||
import type { TableProps } from 'ant-design-vue';
|
||||
import dayjs, { type Dayjs } from 'dayjs';
|
||||
import { SearchOutlined } from '@ant-design/icons-vue';
|
||||
import { getOperationLogs, getOperationLogStats } from '@/api/school';
|
||||
import { getOperationLogs, getOperationLogStats, getOperationLogModules } from '@/api/school';
|
||||
import { LOG_OPERATION_TYPE_OPTIONS } from '@/constants/logOperationType';
|
||||
|
||||
interface OperationLog {
|
||||
id: number;
|
||||
@ -155,8 +156,8 @@ interface OperationLog {
|
||||
// 数据
|
||||
const loading = ref(false);
|
||||
const logs = ref<OperationLog[]>([]);
|
||||
const modules = ref<string[]>(['排课管理', '教师管理', '学生管理', '班级管理', '课程管理']);
|
||||
const actions = ref<string[]>(['创建', '更新', '删除', '创建排课', '批量创建排课', '取消排课']);
|
||||
const modules = ref<string[]>([]);
|
||||
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();
|
||||
});
|
||||
|
||||
@ -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 {
|
||||
* 例如:用户管理、课程管理、学校管理等
|
||||
* </p>
|
||||
*/
|
||||
String module() default "";
|
||||
LogModule module() default LogModule.OTHER;
|
||||
|
||||
/**
|
||||
* 操作类型
|
||||
@ -30,7 +33,7 @@ public @interface Log {
|
||||
* 例如:新增、修改、删除、查询、导出等
|
||||
* </p>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对请求参数进行脱敏处理(密码字段)
|
||||
* <p>
|
||||
* 注意:DTO 类中的密码字段使用 @JsonIgnore 注解,序列化时会自动忽略
|
||||
* 本方法主要处理 String 类型的直接参数(如 oldPassword, newPassword)
|
||||
* </p>
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -0,0 +1,177 @@
|
||||
package com.reading.platform.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 日志操作模块枚举
|
||||
* <p>
|
||||
* 用于 @Log 注解的 module 参数赋值,统一管理操作日志的模块名称
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package com.reading.platform.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 日志操作类型枚举
|
||||
* <p>
|
||||
* 用于 @Log 注解的 type 参数赋值
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,6 +95,7 @@ public class Result<T> implements Serializable {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 错误响应(默认 500)
|
||||
*/
|
||||
|
||||
@ -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<LoginResponse> 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<Void> 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<Void> 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<UpdateProfileResponse> updateProfile(
|
||||
@Valid @RequestBody UpdateProfileRequest request) {
|
||||
|
||||
@ -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<Map<String, Object>> 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<Map<String, Object>> deleteFile(@RequestBody Map<String, String> request) {
|
||||
String filePath = request.get("filePath");
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<CourseCollectionResponse> 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<CourseCollectionResponse> 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<Void> 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<Void> 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<Void> 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<Void> 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<Void> 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<Void> 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<Void> 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<Void> reject(@PathVariable Long id, @Valid @RequestBody CourseCollectionRejectRequest request) {
|
||||
collectionService.rejectCollection(id, request.getComment());
|
||||
|
||||
@ -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<CourseResponse> 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<CourseResponse> 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<Void> 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<Void> 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<Void> 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<Void> 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<Void> rejectCourse(@PathVariable Long id, @Valid @RequestBody CourseRejectRequest request) {
|
||||
courseService.rejectCourse(id, request.getComment());
|
||||
|
||||
@ -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<CourseLessonResponse> 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<CourseLessonResponse> 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<Void> 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<Void> 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<LessonStepResponse> 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<LessonStepResponse> 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<Void> 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<Void> reorderSteps(
|
||||
@PathVariable Long courseId,
|
||||
|
||||
@ -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<ResourceLibraryResponse> 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<ResourceLibraryResponse> 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<Void> 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<ResourceItemResponse> 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<ResourceItemResponse> 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<Void> 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<Void> batchDeleteItems(@RequestBody List<String> ids) {
|
||||
resourceLibraryService.batchDeleteItems(ids);
|
||||
|
||||
@ -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;
|
||||
@ -39,6 +42,7 @@ public class AdminTenantController {
|
||||
private final CourseCollectionMapper collectionMapper;
|
||||
|
||||
@Operation(summary = "Create tenant")
|
||||
@Log(module = LogModule.TENANT, type = LogOperationType.CREATE, description = "创建租户")
|
||||
@PostMapping
|
||||
public Result<TenantResponse> createTenant(@Valid @RequestBody TenantCreateRequest request) {
|
||||
Tenant tenant = tenantService.createTenant(request);
|
||||
@ -46,6 +50,7 @@ public class AdminTenantController {
|
||||
}
|
||||
|
||||
@Operation(summary = "Update tenant")
|
||||
@Log(module = LogModule.TENANT, type = LogOperationType.UPDATE, description = "修改租户")
|
||||
@PutMapping("/{id}")
|
||||
public Result<TenantResponse> updateTenant(@PathVariable Long id, @RequestBody TenantUpdateRequest request) {
|
||||
Tenant tenant = tenantService.updateTenant(id, request);
|
||||
@ -78,6 +83,7 @@ public class AdminTenantController {
|
||||
}
|
||||
|
||||
@Operation(summary = "Delete tenant")
|
||||
@Log(module = LogModule.TENANT, type = LogOperationType.DELETE, description = "删除租户")
|
||||
@DeleteMapping("/{id}")
|
||||
public Result<Void> deleteTenant(@PathVariable Long id) {
|
||||
tenantService.deleteTenant(id);
|
||||
@ -105,6 +111,7 @@ public class AdminTenantController {
|
||||
}
|
||||
|
||||
@Operation(summary = "更新租户配额")
|
||||
@Log(module = LogModule.TENANT, type = LogOperationType.UPDATE, description = "更新租户配额")
|
||||
@PutMapping("/{id}/quota")
|
||||
public Result<TenantResponse> updateTenantQuota(
|
||||
@PathVariable Long id,
|
||||
@ -118,6 +125,7 @@ public class AdminTenantController {
|
||||
}
|
||||
|
||||
@Operation(summary = "更新租户状态")
|
||||
@Log(module = LogModule.TENANT, type = LogOperationType.UPDATE, description = "更新租户状态")
|
||||
@PutMapping("/{id}/status")
|
||||
public Result<TenantResponse> updateTenantStatus(@PathVariable Long id, @RequestBody Map<String, Object> status) {
|
||||
String newStatus = (String) status.get("status");
|
||||
@ -127,6 +135,7 @@ public class AdminTenantController {
|
||||
}
|
||||
|
||||
@Operation(summary = "重置租户密码")
|
||||
@Log(module = LogModule.TENANT, type = LogOperationType.UPDATE, description = "重置租户密码")
|
||||
@PostMapping("/{id}/reset-password")
|
||||
public Result<Map<String, String>> resetTenantPassword(@PathVariable Long id) {
|
||||
String tempPassword = tenantService.resetPasswordAndReturnTemp(id);
|
||||
|
||||
@ -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<ThemeResponse> 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<ThemeResponse> 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<Void> 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<Void> reorder(@RequestBody List<Long> ids) {
|
||||
themeService.reorder(ids);
|
||||
|
||||
@ -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<Void> 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<Void> markAllAsRead() {
|
||||
Long userId = SecurityUtils.getCurrentUserId();
|
||||
|
||||
@ -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<TaskCompletionDetailResponse> 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<TaskCompletionDetailResponse> 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<Void> completeTask(
|
||||
@PathVariable Long id,
|
||||
|
||||
@ -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<ClassResponse> 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<ClassResponse> 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<Void> 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<Void> assignTeachers(@PathVariable Long id, @RequestBody List<Long> 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<Void> assignStudents(@PathVariable Long id, @RequestBody List<Long> 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<Void> 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<Void> removeClassTeacher(
|
||||
@PathVariable Long id,
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<GrowthRecordResponse> 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<GrowthRecordResponse> 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<Void> deleteGrowthRecord(@PathVariable Long id) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
|
||||
@ -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<OperationLog> 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<List<String>> getAvailableModules() {
|
||||
// 从枚举获取所有模块描述
|
||||
List<String> modules = Arrays.stream(LogModule.values())
|
||||
.map(LogModule::toString)
|
||||
.collect(Collectors.toList());
|
||||
return Result.success(modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entity 转 Response
|
||||
*/
|
||||
|
||||
@ -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;
|
||||
@ -65,6 +68,7 @@ public class SchoolPackageController {
|
||||
|
||||
@PostMapping("/{collectionId}/renew")
|
||||
@Operation(summary = "续费课程套餐")
|
||||
@Log(module = LogModule.PACKAGE, type = LogOperationType.UPDATE, description = "续费课程套餐")
|
||||
@RequireRole(UserRole.SCHOOL)
|
||||
public Result<Void> renewCollection(
|
||||
@PathVariable Long collectionId,
|
||||
|
||||
@ -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<ParentResponse> 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<ParentResponse> 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<Void> 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<java.util.Map<String, String>> resetPassword(@PathVariable Long id) {
|
||||
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<Void> 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<Void> 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<Void> 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<Void> removeChild(@PathVariable Long parentId, @PathVariable Long studentId) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
|
||||
@ -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<List<SchedulePlanResponse>> createSchedule(@Valid @RequestBody SchedulePlanCreateRequest request) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
List<SchedulePlan> 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<SchedulePlanResponse> 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<Void> 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<List<SchedulePlanResponse>> 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<List<SchedulePlanResponse>> createSchedulesByClasses(
|
||||
@Valid @RequestBody ScheduleCreateByClassesRequest request) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
|
||||
@ -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<SchoolSettingsResponse> 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<BasicSettingsResponse> 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<NotificationSettingsResponse> 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<SecuritySettingsResponse> updateSecuritySettings(@RequestBody SecuritySettingsUpdateRequest request) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
// TODO: 实现安全设置更新,根据 tenantId 更新
|
||||
|
||||
@ -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;
|
||||
@ -33,6 +36,7 @@ public class SchoolStudentController {
|
||||
private final StudentMapper studentMapper;
|
||||
|
||||
@Operation(summary = "Create student")
|
||||
@Log(module = LogModule.STUDENT, type = LogOperationType.CREATE, description = "创建学生")
|
||||
@PostMapping
|
||||
public Result<StudentResponse> createStudent(@Valid @RequestBody StudentCreateRequest request) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
@ -43,6 +47,7 @@ public class SchoolStudentController {
|
||||
}
|
||||
|
||||
@Operation(summary = "Update student")
|
||||
@Log(module = LogModule.STUDENT, type = LogOperationType.UPDATE, description = "修改学生")
|
||||
@PutMapping("/{id}")
|
||||
public Result<StudentResponse> updateStudent(@PathVariable Long id, @RequestBody StudentUpdateRequest request) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
@ -92,6 +97,7 @@ public class SchoolStudentController {
|
||||
}
|
||||
|
||||
@Operation(summary = "Delete student")
|
||||
@Log(module = LogModule.STUDENT, type = LogOperationType.DELETE, description = "删除学生")
|
||||
@DeleteMapping("/{id}")
|
||||
public Result<Void> deleteStudent(@PathVariable Long id) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
|
||||
@ -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<TaskTemplateResponse> 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<TaskTemplateResponse> 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<Void> deleteTemplate(@PathVariable Long id) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
TaskTemplate template = taskTemplateService.getTemplateById(id);
|
||||
|
||||
@ -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<TeacherResponse> 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<TeacherResponse> 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<Void> 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<java.util.Map<String, String>> resetPassword(@PathVariable Long id) {
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<GrowthRecordResponse> 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<GrowthRecordResponse> 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<Void> deleteGrowthRecord(@PathVariable Long id) {
|
||||
growthRecordService.deleteGrowthRecord(id);
|
||||
|
||||
@ -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<LessonResponse> 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<LessonResponse> 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<Void> 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<Void> 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<Void> 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<StudentRecordResponse> 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<List<StudentRecordResponse>> 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<LessonFeedback> 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<Void> 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<LessonResponse> 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<LessonResponse> createLessonFromSchedule(@PathVariable Long schedulePlanId) {
|
||||
Long teacherId = SecurityUtils.getCurrentUserId();
|
||||
|
||||
@ -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<Void> 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<Void> markAllAsRead() {
|
||||
Long userId = SecurityUtils.getCurrentUserId();
|
||||
|
||||
@ -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<SchedulePlanResponse> 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<SchedulePlanResponse> 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<Void> cancelSchedule(@PathVariable Long id) {
|
||||
teacherScheduleService.cancelSchedule(id);
|
||||
return Result.success();
|
||||
|
||||
@ -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<TaskResponse> 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<TaskResponse> 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<Void> 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<TaskFeedbackResponse> 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<TaskFeedbackResponse> updateFeedback(
|
||||
@PathVariable Long completionId,
|
||||
|
||||
@ -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<TaskTemplateResponse> 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<Task> 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<TaskTemplateResponse> 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<Void> deleteTemplate(@PathVariable Long id) {
|
||||
taskTemplateService.deleteTemplate(id);
|
||||
return Result.success();
|
||||
|
||||
@ -51,5 +51,4 @@ public class TenantUpdateRequest {
|
||||
@Schema(description = "结束日期")
|
||||
private LocalDate expireDate;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ public interface OperationLogService extends IService<OperationLog> {
|
||||
* 分页查询日志列表(按租户隔离)
|
||||
*/
|
||||
Page<OperationLog> getLogPage(Long tenantId, Integer pageNum, Integer pageSize,
|
||||
String module, String operator);
|
||||
String module, String action);
|
||||
|
||||
/**
|
||||
* 获取日志统计(按租户隔离)
|
||||
|
||||
@ -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<AdminUser>().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<Tenant>().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<Teacher>().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<Parent>().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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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<OperationLogMapper, Ope
|
||||
|
||||
@Override
|
||||
public Page<OperationLog> 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<OperationLogMapper, Ope
|
||||
if (StringUtils.hasText(module)) {
|
||||
wrapper.eq(OperationLog::getModule, module);
|
||||
}
|
||||
if (StringUtils.hasText(operator)) {
|
||||
wrapper.like(OperationLog::getAction, operator);
|
||||
if (StringUtils.hasText(action)) {
|
||||
wrapper.like(OperationLog::getAction, action);
|
||||
}
|
||||
|
||||
wrapper.orderByDesc(OperationLog::getCreatedAt);
|
||||
@ -62,9 +64,29 @@ public class OperationLogServiceImpl extends ServiceImpl<OperationLogMapper, Ope
|
||||
.eq(OperationLog::getTenantId, tenantId)
|
||||
);
|
||||
|
||||
// 按模块分组统计
|
||||
List<OperationLog> allLogs = this.list(
|
||||
new LambdaQueryWrapper<OperationLog>()
|
||||
.eq(OperationLog::getTenantId, tenantId)
|
||||
.select(OperationLog::getModule)
|
||||
);
|
||||
|
||||
Map<String, Long> byModuleMap = allLogs.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
OperationLog::getModule,
|
||||
Collectors.counting()
|
||||
));
|
||||
|
||||
// 转换为前端期望的格式:Map<String, Integer>
|
||||
Map<String, Integer> byModule = byModuleMap.entrySet().stream()
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().intValue()
|
||||
));
|
||||
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
stats.put("totalLogs", totalLogs);
|
||||
stats.put("byModule", new HashMap<>());
|
||||
stats.put("byModule", byModule);
|
||||
stats.put("byOperator", new HashMap<>());
|
||||
|
||||
return stats;
|
||||
|
||||
@ -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`);
|
||||
|
||||
@ -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 时生效
|
||||
-- -----------------------------------------------------
|
||||
Loading…
Reference in New Issue
Block a user