diff --git a/databases/v1.0-beta.1.sql b/databases/v1.0-beta.1.sql index 9af13f5..1ef2170 100644 --- a/databases/v1.0-beta.1.sql +++ b/databases/v1.0-beta.1.sql @@ -27,10 +27,16 @@ CREATE TABLE `admin_logs` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `admin_id` int(11) NOT NULL DEFAULT '0' COMMENT '管理员ID', `module` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '模块', - `opt` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '操作指令', - `remark` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '备注', + `title` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求方法标题', + `opt` int(2) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 0 COMMENT '操作指令(0其它 1新增 2修改 3删除 4查询 5登录 6退出登录)', + `method` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求方法', + `request_method` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求方式POST,GET,PUT,DELETE', + `url` varchar(266) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求URL', + `param` text COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '请求参数', + `result` text COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '返回参数', `ip` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT 'ip', `ip_area` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '地址', + `error_msg` varchar(2000) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '错误消息', `created_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `a_m_o` (`admin_id`,`module`,`opt`) diff --git a/databases/v1.2.sql b/databases/v1.2.sql new file mode 100644 index 0000000..f30163e --- /dev/null +++ b/databases/v1.2.sql @@ -0,0 +1,47 @@ +drop table admin_logs; + +CREATE TABLE `admin_logs` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `admin_id` int(11) NOT NULL DEFAULT '0' COMMENT '管理员ID', + `module` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '模块', + `title` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求方法标题', + `opt` int(2) NOT NULL DEFAULT '0' COMMENT '操作指令(0其它 1新增 2修改 3删除 4登录 5退出登录)', + `method` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求方法', + `request_method` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求方式POST,GET,PUT,DELETE', + `url` varchar(266) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求URL', + `param` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '请求参数', + `result` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '返回参数', + `ip` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT 'ip', + `ip_area` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '地址', + `error_msg` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '错误消息', + `created_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `a_m_o` (`admin_id`,`module`,`opt`) +) ENGINE=InnoDB AUTO_INCREMENT=515 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `course_attachment` +( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `course_id` int(11) NOT NULL DEFAULT '0' COMMENT '课程ID', + `sort` int(11) NOT NULL DEFAULT '0' COMMENT '升序', + `title` varchar(255) NOT NULL DEFAULT '' COMMENT '附件名', + `type` varchar(20) NOT NULL DEFAULT '' COMMENT '附件类型', + `rid` int(11) NOT NULL DEFAULT '0' COMMENT '资源id', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `course_id` (`course_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `course_attachment_download_log` +( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL DEFAULT '0' COMMENT '学员ID', + `course_id` int(11) NOT NULL DEFAULT '0' COMMENT '课程ID', + `title` varchar(255) NOT NULL DEFAULT '' COMMENT '课程标题', + `courser_attachment_id` int(11) NOT NULL DEFAULT '0' COMMENT '课程附件id', + `rid` int(11) NOT NULL DEFAULT '0' COMMENT '资源id', + `ip` varchar(45) NOT NULL DEFAULT '' COMMENT '下载ip', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/src/main/java/xyz/playedu/api/annotation/Log.java b/src/main/java/xyz/playedu/api/annotation/Log.java new file mode 100644 index 0000000..948f35a --- /dev/null +++ b/src/main/java/xyz/playedu/api/annotation/Log.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.annotation; + +import xyz.playedu.api.constant.BusinessType; + +import java.lang.annotation.*; + +@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Log { + /** 标题 */ + public String title() default ""; + + /** 功能 */ + public BusinessType businessType() default BusinessType.OTHER; +} diff --git a/src/main/java/xyz/playedu/api/aspectj/AdminLogAspect.java b/src/main/java/xyz/playedu/api/aspectj/AdminLogAspect.java new file mode 100644 index 0000000..828ea8c --- /dev/null +++ b/src/main/java/xyz/playedu/api/aspectj/AdminLogAspect.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.aspectj; + +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; + +import jakarta.servlet.http.HttpServletRequest; + +import lombok.extern.slf4j.Slf4j; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.*; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import xyz.playedu.api.annotation.Log; +import xyz.playedu.api.domain.AdminLog; +import xyz.playedu.api.service.AdminLogService; +import xyz.playedu.api.service.BackendAuthService; +import xyz.playedu.api.util.IpUtil; +import xyz.playedu.api.util.RequestUtil; +import xyz.playedu.api.util.StringUtil; + +import java.lang.reflect.Method; +import java.util.Date; +import java.util.Map; + +@Aspect +@Component +@Slf4j +public class AdminLogAspect { + + @Autowired private BackendAuthService authService; + + @Autowired private AdminLogService adminLogService; + + /** 排除敏感属性字段 */ + public static final String[] EXCLUDE_PROPERTIES = { + "password", "oldPassword", "newPassword", "confirmPassword", "token" + }; + + /** Controller层切点 注解拦截 */ + @Pointcut("@annotation(xyz.playedu.api.annotation.Log)") + public void logPointCut() {} + + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) { + handleLog(joinPoint, null, jsonResult); + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "logPointCut()", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Exception e) { + handleLog(joinPoint, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) { + try { + // 获取注解信息 + Log controllerLog = getAnnotationLog(joinPoint); + if (null == controllerLog) { + return; + } + + // 日志 + AdminLog adminLog = new AdminLog(); + adminLog.setAdminId(authService.userId()); + adminLog.setModule("BACKEND"); + adminLog.setTitle(controllerLog.title()); + adminLog.setOpt(controllerLog.businessType().ordinal()); + + // 设置方法名称 + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + adminLog.setMethod(className + "." + methodName + "()"); + + HttpServletRequest request = RequestUtil.handler(); + if (null == request) { + return; + } + adminLog.setRequestMethod(request.getMethod()); + adminLog.setUrl(request.getRequestURL().toString()); + String params = ""; + Map parameterMap = request.getParameterMap(); + if (StringUtil.isNotEmpty(parameterMap)) { + params = JSONUtil.toJsonStr(parameterMap); + } else { + Object[] args = joinPoint.getArgs(); + if (StringUtil.isNotNull(args)) { + params = StringUtil.arrayToString(args); + } + } + if (StringUtil.isNotEmpty(params)) { + JSONObject paramObj = excludeProperties(params); + adminLog.setParam(JSONUtil.toJsonStr(paramObj)); + } + if (null != jsonResult) { + jsonResult = excludeProperties(JSONUtil.toJsonStr(jsonResult)); + adminLog.setResult(JSONUtil.toJsonStr(jsonResult)); + } + + adminLog.setIp(IpUtil.getIpAddress()); + adminLog.setIpArea(IpUtil.getRealAddressByIP(IpUtil.getIpAddress())); + + if (null != e) { + adminLog.setErrorMsg(e.getMessage()); + } + adminLog.setCreatedAt(new Date()); + // 保存数据库 + adminLogService.save(adminLog); + } catch (Exception exp) { + // 记录本地异常日志 + log.error("异常信息:" + exp.getMessage(), e); + } + } + + /** 是否存在注解,如果存在就获取 */ + private Log getAnnotationLog(JoinPoint joinPoint) throws Exception { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + + if (method != null) { + return method.getAnnotation(Log.class); + } + return null; + } + + public JSONObject excludeProperties(String jsonData) { + JSONObject jsonObjectResult = new JSONObject(); + // 把传入String类型转换成JSONObject对象 + if (JSONUtil.isTypeJSONObject(jsonData)) { + JSONObject jsonObject = JSONUtil.parseObj(jsonData); + for (Map.Entry entry : jsonObject.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (StringUtil.isNotNull(value)) { + // 如果value依旧是json类型的话继续递归解析 + if (JSONUtil.isTypeJSONObject(value.toString())) { + jsonObjectResult.put(key, excludeProperties(entry.getValue().toString())); + } else { + // 如果value是单纯的数据,执行脱敏操作 + for (String i : EXCLUDE_PROPERTIES) { + if (key.equals(i)) { + jsonObjectResult.put(key, "******"); + } + } + } + } + } + } + return jsonObjectResult; + } +} diff --git a/src/main/java/xyz/playedu/api/checks/AdminPermissionCheck.java b/src/main/java/xyz/playedu/api/checks/AdminPermissionCheck.java index 4486128..5299aa8 100644 --- a/src/main/java/xyz/playedu/api/checks/AdminPermissionCheck.java +++ b/src/main/java/xyz/playedu/api/checks/AdminPermissionCheck.java @@ -71,6 +71,18 @@ public class AdminPermissionCheck implements ApplicationRunner { } }, }); + // 管理员日志 + put( + "管理员日志", + new AdminPermission[] { + new AdminPermission() { + { + setSort(0); + setName("列表"); + setSlug(BPermissionConstant.ADMIN_LOG); + } + }, + }); // 部门 put( "部门", diff --git a/src/main/java/xyz/playedu/api/constant/BPermissionConstant.java b/src/main/java/xyz/playedu/api/constant/BPermissionConstant.java index 96a0918..a4e3a7f 100644 --- a/src/main/java/xyz/playedu/api/constant/BPermissionConstant.java +++ b/src/main/java/xyz/playedu/api/constant/BPermissionConstant.java @@ -27,6 +27,8 @@ public class BPermissionConstant { public static final String ADMIN_ROLE = "admin-role"; + public static final String ADMIN_LOG = "admin-log"; + public static final String DEPARTMENT_CUD = "department-cud"; public static final String DEPARTMENT_USER_LEARN = "department-user-learn"; diff --git a/src/main/java/xyz/playedu/api/constant/BackendConstant.java b/src/main/java/xyz/playedu/api/constant/BackendConstant.java index 8b7600d..1701091 100644 --- a/src/main/java/xyz/playedu/api/constant/BackendConstant.java +++ b/src/main/java/xyz/playedu/api/constant/BackendConstant.java @@ -35,6 +35,25 @@ public class BackendConstant { public static final String RESOURCE_TYPE_PDF = "PDF"; public static final String RESOURCE_TYPE_WORD = "WORD"; public static final String RESOURCE_TYPE_PPT = "PPT"; + public static final String RESOURCE_TYPE_EXCEL = "EXCEL"; + public static final String RESOURCE_TYPE_ZIP = "ZIP"; + public static final String RESOURCE_TYPE_RAR = "RAR"; + public static final String RESOURCE_TYPE_TXT = "TXT"; + + public static final String RESOURCE_TYPE_ATTACHMENT = + RESOURCE_TYPE_PDF + + "," + + RESOURCE_TYPE_TXT + + "," + + RESOURCE_TYPE_ZIP + + "," + + RESOURCE_TYPE_RAR + + "," + + RESOURCE_TYPE_WORD + + "," + + RESOURCE_TYPE_PPT + + "," + + RESOURCE_TYPE_EXCEL; public static final HashMap RESOURCE_EXT_2_CONTENT_TYPE = new HashMap<>() { @@ -53,6 +72,13 @@ public class BackendConstant { put( "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"); + put("xls", "application/vnd.ms-excel"); + put( + "xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + put("txt", "text/plain"); + put("zip", "application/zip"); + put("rar", "application/x-rar"); } }; public static final HashMap RESOURCE_EXT_2_TYPE = @@ -68,6 +94,11 @@ public class BackendConstant { put("docx", RESOURCE_TYPE_WORD); put("ppt", RESOURCE_TYPE_PPT); put("pptx", RESOURCE_TYPE_PPT); + put("xls", RESOURCE_TYPE_EXCEL); + put("xlsx", RESOURCE_TYPE_EXCEL); + put("txt", RESOURCE_TYPE_TXT); + put("zip", RESOURCE_TYPE_ZIP); + put("rar", RESOURCE_TYPE_RAR); } }; public static final HashMap RESOURCE_TYPE_2_DIR = @@ -78,6 +109,10 @@ public class BackendConstant { put(RESOURCE_TYPE_PDF, UPLOAD_PDF_DIR); put(RESOURCE_TYPE_WORD, UPLOAD_WORD_DIR); put(RESOURCE_TYPE_PPT, UPLOAD_PPT_DIR); + put(RESOURCE_TYPE_EXCEL, UPLOAD_EXCEL_DIR); + put(RESOURCE_TYPE_TXT, UPLOAD_TXT_DIR); + put(RESOURCE_TYPE_ZIP, UPLOAD_ZIP_DIR); + put(RESOURCE_TYPE_RAR, UPLOAD_RAR_DIR); } }; @@ -91,6 +126,10 @@ public class BackendConstant { public static final String UPLOAD_PDF_DIR = "pdf/"; public static final String UPLOAD_WORD_DIR = "word/"; public static final String UPLOAD_PPT_DIR = "word/"; + public static final String UPLOAD_EXCEL_DIR = "excel/"; + public static final String UPLOAD_TXT_DIR = "txt/"; + public static final String UPLOAD_ZIP_DIR = "zip/"; + public static final String UPLOAD_RAR_DIR = "rar/"; public static final String PRIVACY_FIELD_TYPE_EMAIL = "email"; public static final String PRIVACY_FIELD_TYPE_PHONE = "phone"; diff --git a/src/main/java/xyz/playedu/api/constant/BusinessType.java b/src/main/java/xyz/playedu/api/constant/BusinessType.java new file mode 100644 index 0000000..1f46c6c --- /dev/null +++ b/src/main/java/xyz/playedu/api/constant/BusinessType.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.constant; + +public enum BusinessType { + /** 其它 */ + OTHER, + + /** 新增 */ + INSERT, + + /** 修改 */ + UPDATE, + + /** 删除 */ + DELETE, + + /** 查询 */ + GET, + + /** 登录 */ + LOGIN, + + /** 退出登录 */ + LOGOUT, + + /** 上传 */ + UPLOAD +} diff --git a/src/main/java/xyz/playedu/api/controller/backend/AdminLogController.java b/src/main/java/xyz/playedu/api/controller/backend/AdminLogController.java new file mode 100644 index 0000000..7c92cfc --- /dev/null +++ b/src/main/java/xyz/playedu/api/controller/backend/AdminLogController.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.controller.backend; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.collections4.MapUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; +import xyz.playedu.api.bus.BackendBus; +import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.constant.BusinessType; +import xyz.playedu.api.domain.*; +import xyz.playedu.api.middleware.BackendPermissionMiddleware; +import xyz.playedu.api.service.AdminLogService; +import xyz.playedu.api.service.AdminUserService; +import xyz.playedu.api.types.JsonResponse; +import xyz.playedu.api.types.paginate.AdminLogPaginateFiler; +import xyz.playedu.api.types.paginate.PaginationResult; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RestController +@Slf4j +@RequestMapping("/backend/v1/admin/log") +public class AdminLogController { + + @Autowired private AdminLogService adminLogService; + + @Autowired private AdminUserService adminUserService; + + @Autowired private BackendBus backendBus; + + @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_LOG) + @GetMapping("/index") + @Log(title = "管理员日志-列表", businessType = BusinessType.GET) + public JsonResponse index(@RequestParam HashMap params) { + Integer page = MapUtils.getInteger(params, "page", 1); + Integer size = MapUtils.getInteger(params, "size", 10); + String sortField = MapUtils.getString(params, "sort_field"); + String sortAlgo = MapUtils.getString(params, "sort_algo"); + + Integer adminId = MapUtils.getInteger(params, "admin_id"); + String module = MapUtils.getString(params, "module"); + String title = MapUtils.getString(params, "title"); + Integer opt = MapUtils.getInteger(params, "opt"); + String startTime = MapUtils.getString(params, "start_time"); + String endTime = MapUtils.getString(params, "end_time"); + + AdminLogPaginateFiler filter = new AdminLogPaginateFiler(); + if (backendBus.isSuperAdmin()) { + filter.setAdminId(adminId); + } else { + filter.setAdminId(BCtx.getId()); + } + filter.setModule(module); + filter.setTitle(title); + filter.setOpt(opt); + filter.setStartTime(startTime); + filter.setEndTime(endTime); + filter.setSortField(sortField); + filter.setSortAlgo(sortAlgo); + + PaginationResult result = adminLogService.paginate(page, size, filter); + if(result.getTotal() > 0){ + List adminUsers = adminUserService.chunks(result.getData().stream().map(AdminLog::getAdminId).toList()); + if(null != adminUsers && adminUsers.size() > 0){ + Map adminUserMap = adminUsers.stream().collect(Collectors.toMap(AdminUser::getId, AdminUser::getName)); + result.getData() + .forEach( + adminLog -> { + adminLog.setAdminName(adminUserMap.get(adminLog.getAdminId())); + }); + } + } + + HashMap data = new HashMap<>(); + data.put("data", result.getData()); + data.put("total", result.getTotal()); + + return JsonResponse.data(data); + } +} diff --git a/src/main/java/xyz/playedu/api/controller/backend/AdminRoleController.java b/src/main/java/xyz/playedu/api/controller/backend/AdminRoleController.java index b5abc18..24e0d42 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/AdminRoleController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/AdminRoleController.java @@ -21,8 +21,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BPermissionConstant; import xyz.playedu.api.constant.BackendConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.AdminPermission; import xyz.playedu.api.domain.AdminRole; import xyz.playedu.api.exception.NotFoundException; @@ -48,6 +50,7 @@ public class AdminRoleController { @Autowired private AdminPermissionService permissionService; @GetMapping("/index") + @Log(title = "管理员角色-列表", businessType = BusinessType.GET) public JsonResponse index() { List data = roleService.list(); return JsonResponse.data(data); @@ -55,6 +58,7 @@ public class AdminRoleController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_ROLE) @GetMapping("/create") + @Log(title = "管理员角色-新建", businessType = BusinessType.GET) public JsonResponse create() { List permissions = permissionService.listOrderBySortAsc(); @@ -68,6 +72,7 @@ public class AdminRoleController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_ROLE) @PostMapping("/create") + @Log(title = "管理员角色-新建", businessType = BusinessType.INSERT) public JsonResponse store(@RequestBody @Validated AdminRoleRequest request) { roleService.createWithPermissionIds(request.getName(), request.getPermissionIds()); return JsonResponse.success(); @@ -75,6 +80,7 @@ public class AdminRoleController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_ROLE) @GetMapping("/{id}") + @Log(title = "管理员角色-编辑", businessType = BusinessType.GET) public JsonResponse edit(@PathVariable(name = "id") Integer id) throws NotFoundException { AdminRole role = roleService.findOrFail(id); @@ -108,6 +114,7 @@ public class AdminRoleController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_ROLE) @PutMapping("/{id}") + @Log(title = "管理员角色-编辑", businessType = BusinessType.UPDATE) public JsonResponse update( @PathVariable(name = "id") Integer id, @RequestBody @Validated AdminRoleRequest request) throws NotFoundException { @@ -123,6 +130,7 @@ public class AdminRoleController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_ROLE) @DeleteMapping("/{id}") + @Log(title = "管理员角色-删除", businessType = BusinessType.DELETE) public JsonResponse destroy(@PathVariable(name = "id") Integer id) throws NotFoundException { AdminRole role = roleService.findOrFail(id); diff --git a/src/main/java/xyz/playedu/api/controller/backend/AdminUserController.java b/src/main/java/xyz/playedu/api/controller/backend/AdminUserController.java index f31aa96..bc1f7d9 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/AdminUserController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/AdminUserController.java @@ -22,7 +22,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.AdminRole; import xyz.playedu.api.domain.AdminUser; import xyz.playedu.api.exception.NotFoundException; @@ -51,6 +53,7 @@ public class AdminUserController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_USER_INDEX) @GetMapping("/index") + @Log(title = "管理员-列表", businessType = BusinessType.GET) public JsonResponse Index(@RequestParam HashMap params) { Integer page = MapUtils.getInteger(params, "page", 1); Integer size = MapUtils.getInteger(params, "size", 10); @@ -83,6 +86,7 @@ public class AdminUserController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_USER_CUD) @GetMapping("/create") + @Log(title = "管理员-新建", businessType = BusinessType.GET) public JsonResponse create() { List roles = roleService.list(); @@ -94,9 +98,10 @@ public class AdminUserController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_USER_CUD) @PostMapping("/create") + @Log(title = "管理员-新建", businessType = BusinessType.INSERT) public JsonResponse store(@RequestBody @Validated AdminUserRequest req) throws ServiceException { - if (req.getPassword() == null || req.getPassword().length() == 0) { + if (req.getPassword().length() == 0) { return JsonResponse.error("请输入密码"); } @@ -112,6 +117,7 @@ public class AdminUserController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_USER_CUD) @GetMapping("/{id}") + @Log(title = "管理员-编辑", businessType = BusinessType.GET) public JsonResponse edit(@PathVariable Integer id) throws NotFoundException { AdminUser adminUser = adminUserService.findOrFail(id); List roleIds = adminUserService.getRoleIdsByUserId(adminUser.getId()); @@ -125,6 +131,7 @@ public class AdminUserController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_USER_CUD) @PutMapping("/{id}") + @Log(title = "管理员-编辑", businessType = BusinessType.UPDATE) public JsonResponse update( @PathVariable Integer id, @RequestBody @Validated AdminUserRequest req) throws NotFoundException, ServiceException { @@ -141,6 +148,7 @@ public class AdminUserController { @BackendPermissionMiddleware(slug = BPermissionConstant.ADMIN_USER_CUD) @DeleteMapping("/{id}") + @Log(title = "管理员-删除", businessType = BusinessType.DELETE) public JsonResponse destroy(@PathVariable Integer id) { adminUserService.removeWithRoleIds(id); return JsonResponse.success(); diff --git a/src/main/java/xyz/playedu/api/controller/backend/AppConfigController.java b/src/main/java/xyz/playedu/api/controller/backend/AppConfigController.java index 5838782..80080a9 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/AppConfigController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/AppConfigController.java @@ -18,7 +18,9 @@ package xyz.playedu.api.controller.backend; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.constant.SystemConstant; import xyz.playedu.api.domain.AppConfig; import xyz.playedu.api.middleware.BackendPermissionMiddleware; @@ -30,11 +32,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -/** - * @Author 杭州白书科技有限公司 - * - * @create 2023/3/9 11:14 - */ @RestController @RequestMapping("/backend/v1/app-config") public class AppConfigController { @@ -43,6 +40,7 @@ public class AppConfigController { @BackendPermissionMiddleware(slug = BPermissionConstant.SYSTEM_CONFIG) @GetMapping("") + @Log(title = "系统配置-读取", businessType = BusinessType.GET) public JsonResponse index() { List configs = configService.allShow(); List data = new ArrayList<>(); @@ -57,6 +55,7 @@ public class AppConfigController { @BackendPermissionMiddleware(slug = BPermissionConstant.SYSTEM_CONFIG) @PutMapping("") + @Log(title = "系统配置-保存", businessType = BusinessType.UPDATE) public JsonResponse save(@RequestBody AppConfigRequest req) { HashMap data = new HashMap<>(); req.getData() diff --git a/src/main/java/xyz/playedu/api/controller/backend/CourseAttachmentController.java b/src/main/java/xyz/playedu/api/controller/backend/CourseAttachmentController.java new file mode 100644 index 0000000..b21e677 --- /dev/null +++ b/src/main/java/xyz/playedu/api/controller/backend/CourseAttachmentController.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.controller.backend; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import xyz.playedu.api.annotation.Log; +import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.constant.BackendConstant; +import xyz.playedu.api.constant.BusinessType; +import xyz.playedu.api.domain.CourseAttachment; +import xyz.playedu.api.exception.NotFoundException; +import xyz.playedu.api.middleware.BackendPermissionMiddleware; +import xyz.playedu.api.request.backend.CourseAttachmentMultiRequest; +import xyz.playedu.api.request.backend.CourseAttachmentRequest; +import xyz.playedu.api.request.backend.CourseAttachmentSortRequest; +import xyz.playedu.api.service.CourseAttachmentService; +import xyz.playedu.api.types.JsonResponse; + +import java.util.*; + +@RestController +@Slf4j +@RequestMapping("/backend/v1/course/{courseId}/attachment") +public class CourseAttachmentController { + + @Autowired private CourseAttachmentService attachmentService; + + @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) + @PostMapping("/create") + @Log(title = "线上课-附件-新建", businessType = BusinessType.INSERT) + public JsonResponse store( + @PathVariable(name = "courseId") Integer courseId, + @RequestBody @Validated CourseAttachmentRequest req) + throws NotFoundException { + // 附件类型校验 + String type = req.getType(); + if (!BackendConstant.RESOURCE_TYPE_ATTACHMENT.contains(type)) { + return JsonResponse.error("附件类型不支持"); + } + + // 课时重复添加校验 + List existsRids = attachmentService.getRidsByCourseId(courseId); + if (existsRids != null) { + if (existsRids.contains(req.getRid())) { + return JsonResponse.error("附件已存在"); + } + } + + CourseAttachment courseAttachment = + attachmentService.create( + courseId, req.getSort(), req.getTitle(), type, req.getRid()); + return JsonResponse.success(); + } + + @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) + @PostMapping("/create-batch") + @Transactional + @Log(title = "线上课-附件-批量新建", businessType = BusinessType.INSERT) + public JsonResponse storeMulti( + @PathVariable(name = "courseId") Integer courseId, + @RequestBody @Validated CourseAttachmentMultiRequest req) { + if (req.getAttachments().size() == 0) { + return JsonResponse.error("参数为空"); + } + + List existsRids = attachmentService.getRidsByCourseId(courseId); + + List attachments = new ArrayList<>(); + Date now = new Date(); + + for (CourseAttachmentMultiRequest.AttachmentItem item : req.getAttachments()) { + if (existsRids.contains(item.getRid())) { + return JsonResponse.error("附件《" + item.getTitle() + "》已存在"); + } + + attachments.add( + new CourseAttachment() { + { + setCourseId(courseId); + setSort(item.getSort()); + setType(item.getType()); + setRid(item.getRid()); + setTitle(item.getTitle()); + setCreatedAt(now); + } + }); + } + + attachmentService.saveBatch(attachments); + return JsonResponse.success(); + } + + @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) + @GetMapping("/{id}") + @Log(title = "线上课-附件-编辑", businessType = BusinessType.GET) + public JsonResponse edit( + @PathVariable(name = "courseId") Integer courseId, + @PathVariable(name = "id") Integer id) + throws NotFoundException { + CourseAttachment courseAttachment = attachmentService.findOrFail(id, courseId); + return JsonResponse.data(courseAttachment); + } + + @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) + @PutMapping("/{id}") + @Log(title = "线上课-附件-编辑", businessType = BusinessType.UPDATE) + public JsonResponse update( + @PathVariable(name = "courseId") Integer courseId, + @PathVariable(name = "id") Integer id, + @RequestBody @Validated CourseAttachmentRequest req) + throws NotFoundException { + CourseAttachment courseAttachment = attachmentService.findOrFail(id, courseId); + attachmentService.update(courseAttachment, req.getSort(), req.getTitle()); + return JsonResponse.success(); + } + + @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) + @DeleteMapping("/{id}") + @Log(title = "线上课-附件-删除", businessType = BusinessType.DELETE) + public JsonResponse destroy( + @PathVariable(name = "courseId") Integer courseId, + @PathVariable(name = "id") Integer id) + throws NotFoundException { + CourseAttachment courseAttachment = attachmentService.findOrFail(id, courseId); + attachmentService.removeById(courseAttachment.getId()); + return JsonResponse.success(); + } + + @PutMapping("/update/sort") + @Log(title = "线上课-附件-排序调整", businessType = BusinessType.UPDATE) + public JsonResponse updateSort( + @PathVariable(name = "courseId") Integer courseId, + @RequestBody @Validated CourseAttachmentSortRequest req) { + attachmentService.updateSort(req.getIds(), courseId); + return JsonResponse.success(); + } +} diff --git a/src/main/java/xyz/playedu/api/controller/backend/CourseAttachmentDownloadLogController.java b/src/main/java/xyz/playedu/api/controller/backend/CourseAttachmentDownloadLogController.java new file mode 100644 index 0000000..69a05fd --- /dev/null +++ b/src/main/java/xyz/playedu/api/controller/backend/CourseAttachmentDownloadLogController.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.controller.backend; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.collections4.MapUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import xyz.playedu.api.annotation.Log; +import xyz.playedu.api.constant.BusinessType; +import xyz.playedu.api.domain.*; +import xyz.playedu.api.service.*; +import xyz.playedu.api.types.JsonResponse; +import xyz.playedu.api.types.paginate.CourseAttachmentDownloadLogPaginateFiler; +import xyz.playedu.api.types.paginate.PaginationResult; + +import java.util.*; + +@RestController +@Slf4j +@RequestMapping("/backend/v1/course/attachment/download/log") +public class CourseAttachmentDownloadLogController { + + @Autowired private CourseAttachmentDownloadLogService courseAttachmentDownloadLogService; + + @GetMapping("/index") + @Log(title = "学员下载课件记录-列表", businessType = BusinessType.GET) + public JsonResponse index(@RequestParam HashMap params) { + Integer page = MapUtils.getInteger(params, "page", 1); + Integer size = MapUtils.getInteger(params, "size", 10); + String sortField = MapUtils.getString(params, "sort_field"); + String sortAlgo = MapUtils.getString(params, "sort_algo"); + + Integer userId = MapUtils.getInteger(params, "user_id"); + Integer courseId = MapUtils.getInteger(params, "course_id"); + String title = MapUtils.getString(params, "title"); + Integer courserAttachmentId = MapUtils.getInteger(params, "courser_attachment_id"); + Integer rid = MapUtils.getInteger(params, "rid"); + + CourseAttachmentDownloadLogPaginateFiler filter = + new CourseAttachmentDownloadLogPaginateFiler(); + filter.setUserId(userId); + filter.setCourseId(courseId); + filter.setTitle(title); + filter.setCourserAttachmentId(courserAttachmentId); + filter.setRid(rid); + filter.setSortField(sortField); + filter.setSortAlgo(sortAlgo); + + PaginationResult result = + courseAttachmentDownloadLogService.paginate(page, size, filter); + + HashMap data = new HashMap<>(); + data.put("data", result.getData()); + data.put("total", result.getTotal()); + + return JsonResponse.data(data); + } +} diff --git a/src/main/java/xyz/playedu/api/controller/backend/CourseChapterController.java b/src/main/java/xyz/playedu/api/controller/backend/CourseChapterController.java index 9b1489f..fcee8ba 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/CourseChapterController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/CourseChapterController.java @@ -21,7 +21,9 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.CourseChapter; import xyz.playedu.api.event.CourseChapterDestroyEvent; import xyz.playedu.api.exception.NotFoundException; @@ -32,11 +34,6 @@ import xyz.playedu.api.service.CourseChapterService; import xyz.playedu.api.service.CourseHourService; import xyz.playedu.api.types.JsonResponse; -/** - * @Author 杭州白书科技有限公司 - * - * @create 2023/2/26 17:28 - */ @RestController @RequestMapping("/backend/v1/course/{courseId}/chapter") public class CourseChapterController { @@ -49,6 +46,7 @@ public class CourseChapterController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @PostMapping("/create") + @Log(title = "线上课-章节-新建", businessType = BusinessType.GET) public JsonResponse store( @PathVariable(name = "courseId") Integer courseId, @RequestBody @Validated CourseChapterRequest req) { @@ -58,6 +56,7 @@ public class CourseChapterController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @GetMapping("/{id}") + @Log(title = "线上课-章节-编辑", businessType = BusinessType.GET) public JsonResponse edit( @PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id) @@ -68,6 +67,7 @@ public class CourseChapterController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @PutMapping("/{id}") + @Log(title = "线上课-章节-编辑", businessType = BusinessType.UPDATE) public JsonResponse update( @PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id, @@ -80,6 +80,7 @@ public class CourseChapterController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @DeleteMapping("/{id}") + @Log(title = "线上课-章节-删除", businessType = BusinessType.DELETE) public JsonResponse destroy( @PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id) @@ -96,6 +97,7 @@ public class CourseChapterController { } @PutMapping("/update/sort") + @Log(title = "线上课-章节-更新排序", businessType = BusinessType.UPDATE) public JsonResponse updateSort( @PathVariable(name = "courseId") Integer courseId, @RequestBody @Validated CourseChapterSortRequest req) { diff --git a/src/main/java/xyz/playedu/api/controller/backend/CourseController.java b/src/main/java/xyz/playedu/api/controller/backend/CourseController.java index b67efd3..0c3b765 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/CourseController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/CourseController.java @@ -25,7 +25,9 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.*; import xyz.playedu.api.event.CourseDestroyEvent; import xyz.playedu.api.exception.NotFoundException; @@ -53,11 +55,16 @@ public class CourseController { @Autowired private CourseHourService hourService; + @Autowired private CourseAttachmentService attachmentService; + + @Autowired private ResourceService resourceService; + @Autowired private DepartmentService departmentService; @Autowired private ApplicationContext ctx; @GetMapping("/index") + @Log(title = "线上课-列表", businessType = BusinessType.GET) public JsonResponse index(@RequestParam HashMap params) { Integer page = MapUtils.getInteger(params, "page", 1); Integer size = MapUtils.getInteger(params, "size", 10); @@ -103,8 +110,9 @@ public class CourseController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @PostMapping("/create") @Transactional + @Log(title = "线上课-新建", businessType = BusinessType.INSERT) public JsonResponse store(@RequestBody @Validated CourseRequest req) throws ParseException { - if (req.getShortDesc() != null && req.getShortDesc().length() > 200) { + if (req.getShortDesc().length() > 200) { return JsonResponse.error("课程简短介绍不能超过200字"); } Course course = @@ -143,7 +151,7 @@ public class CourseController { classHourCount = insertHours.size(); } } else { - if (req.getChapters() == null || req.getChapters().size() == 0) { + if (req.getChapters().size() == 0) { return JsonResponse.error("请配置课时"); } @@ -191,17 +199,53 @@ public class CourseController { courseService.updateClassHour(course.getId(), classHourCount); } + // 课程附件 + if (null != req.getAttachments() && req.getAttachments().size() > 0) { + List insertAttachments = new ArrayList<>(); + final Integer[] sort = {0}; + for (CourseRequest.AttachmentItem attachmentItem : req.getAttachments()) { + insertAttachments.add( + new CourseAttachment() { + { + setCourseId(course.getId()); + setSort(sort[0]++); + setTitle(attachmentItem.getName()); + setType(attachmentItem.getType()); + setRid(attachmentItem.getRid()); + setCreatedAt(now); + } + }); + } + if (insertAttachments.size() > 0) { + attachmentService.saveBatch(insertAttachments); + } + } + return JsonResponse.success(); } @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @GetMapping("/{id}") + @Log(title = "线上课-编辑", businessType = BusinessType.GET) public JsonResponse edit(@PathVariable(name = "id") Integer id) throws NotFoundException { Course course = courseService.findOrFail(id); List depIds = courseService.getDepIdsByCourseId(course.getId()); List categoryIds = courseService.getCategoryIdsByCourseId(course.getId()); List chapters = chapterService.getChaptersByCourseId(course.getId()); List hours = hourService.getHoursByCourseId(course.getId()); + List attachments = + attachmentService.getAttachmentsByCourseId(course.getId()); + if (null != attachments && attachments.size() > 0) { + Map resourceMap = + resourceService + .chunks(attachments.stream().map(CourseAttachment::getRid).toList()) + .stream() + .collect(Collectors.toMap(Resource::getId, Resource::getUrl)); + attachments.forEach( + courseAttachment -> { + courseAttachment.setUrl(resourceMap.get(courseAttachment.getRid())); + }); + } HashMap data = new HashMap<>(); data.put("course", course); @@ -209,13 +253,14 @@ public class CourseController { data.put("category_ids", categoryIds); // 已关联的分类 data.put("chapters", chapters); data.put("hours", hours.stream().collect(Collectors.groupingBy(CourseHour::getChapterId))); - + data.put("attachments", attachments); return JsonResponse.data(data); } @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @PutMapping("/{id}") @Transactional + @Log(title = "线上课-编辑", businessType = BusinessType.UPDATE) public JsonResponse update( @PathVariable(name = "id") Integer id, @RequestBody @Validated CourseRequest req) throws NotFoundException { @@ -234,6 +279,7 @@ public class CourseController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @DeleteMapping("/{id}") + @Log(title = "线上课-删除", businessType = BusinessType.DELETE) public JsonResponse destroy(@PathVariable(name = "id") Integer id) { courseService.removeById(id); ctx.publishEvent(new CourseDestroyEvent(this, BCtx.getId(), id)); diff --git a/src/main/java/xyz/playedu/api/controller/backend/CourseHourController.java b/src/main/java/xyz/playedu/api/controller/backend/CourseHourController.java index 5ea5218..e4ca5ec 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/CourseHourController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/CourseHourController.java @@ -24,8 +24,10 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BPermissionConstant; import xyz.playedu.api.constant.BackendConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.CourseChapter; import xyz.playedu.api.domain.CourseHour; import xyz.playedu.api.event.CourseHourCreatedEvent; @@ -60,6 +62,7 @@ public class CourseHourController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @GetMapping("/create") + @Log(title = "线上课-课时-新建", businessType = BusinessType.GET) public JsonResponse create(@PathVariable(name = "courseId") Integer courseId) { // 课时类型 List> typeItems = new ArrayList<>(); @@ -83,6 +86,7 @@ public class CourseHourController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @PostMapping("/create") + @Log(title = "线上课-课时-新建", businessType = BusinessType.INSERT) public JsonResponse store( @PathVariable(name = "courseId") Integer courseId, @RequestBody @Validated CourseHourRequest req) @@ -127,6 +131,7 @@ public class CourseHourController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @PostMapping("/create-batch") @Transactional + @Log(title = "线上课-课时-批量导入", businessType = BusinessType.INSERT) public JsonResponse storeMulti( @PathVariable(name = "courseId") Integer courseId, @RequestBody @Validated CourseHourMultiRequest req) { @@ -177,6 +182,7 @@ public class CourseHourController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @GetMapping("/{id}") + @Log(title = "线上课-课时-编辑", businessType = BusinessType.GET) public JsonResponse edit( @PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id) @@ -187,6 +193,7 @@ public class CourseHourController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @PutMapping("/{id}") + @Log(title = "线上课-课时-编辑", businessType = BusinessType.UPDATE) public JsonResponse update( @PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id, @@ -203,6 +210,7 @@ public class CourseHourController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE) @DeleteMapping("/{id}") + @Log(title = "线上课-课时-删除", businessType = BusinessType.DELETE) public JsonResponse destroy( @PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id) @@ -220,6 +228,7 @@ public class CourseHourController { } @PutMapping("/update/sort") + @Log(title = "线上课-课时-更新排序", businessType = BusinessType.UPDATE) public JsonResponse updateSort( @PathVariable(name = "courseId") Integer courseId, @RequestBody @Validated CourseHourSortRequest req) { diff --git a/src/main/java/xyz/playedu/api/controller/backend/CourseUserController.java b/src/main/java/xyz/playedu/api/controller/backend/CourseUserController.java index 7ef7b51..42f3bf2 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/CourseUserController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/CourseUserController.java @@ -24,7 +24,9 @@ import org.springframework.context.ApplicationContext; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.User; import xyz.playedu.api.domain.UserCourseRecord; import xyz.playedu.api.event.UserCourseRecordDestroyEvent; @@ -66,6 +68,7 @@ public class CourseUserController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE_USER) @GetMapping("/index") @SneakyThrows + @Log(title = "线上课-学习记录-列表", businessType = BusinessType.GET) public JsonResponse index( @PathVariable(name = "courseId") Integer courseId, @RequestParam HashMap params) { @@ -140,6 +143,7 @@ public class CourseUserController { @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE_USER_DESTROY) @PostMapping("/destroy") + @Log(title = "线上课-学习记录-删除", businessType = BusinessType.DELETE) public JsonResponse destroy( @PathVariable(name = "courseId") Integer courseId, @RequestBody @Validated CourseUserDestroyRequest req) { diff --git a/src/main/java/xyz/playedu/api/controller/backend/DashboardController.java b/src/main/java/xyz/playedu/api/controller/backend/DashboardController.java index 6a701b3..f6b55ae 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/DashboardController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/DashboardController.java @@ -20,7 +20,9 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BackendConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.constant.SystemConstant; import xyz.playedu.api.domain.User; import xyz.playedu.api.domain.UserLearnDurationStats; @@ -57,6 +59,7 @@ public class DashboardController { @Autowired private UserLearnDurationStatsService userLearnDurationStatsService; @GetMapping("/index") + @Log(title = "主面板", businessType = BusinessType.GET) public JsonResponse index() { HashMap data = new HashMap<>(); data.put("version", SystemConstant.VERSION); diff --git a/src/main/java/xyz/playedu/api/controller/backend/DepartmentController.java b/src/main/java/xyz/playedu/api/controller/backend/DepartmentController.java index b19a623..25afe5f 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/DepartmentController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/DepartmentController.java @@ -24,7 +24,9 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.Course; import xyz.playedu.api.domain.Department; import xyz.playedu.api.domain.User; @@ -60,6 +62,7 @@ public class DepartmentController { @Autowired private ApplicationContext ctx; @GetMapping("/index") + @Log(title = "部门-列表", businessType = BusinessType.GET) public JsonResponse index() { HashMap data = new HashMap<>(); data.put("departments", departmentService.groupByParent()); @@ -69,6 +72,7 @@ public class DepartmentController { } @GetMapping("/departments") + @Log(title = "部门-全部部门", businessType = BusinessType.GET) public JsonResponse index( @RequestParam(name = "parent_id", defaultValue = "0") Integer parentId) { List departments = departmentService.listByParentId(parentId); @@ -77,6 +81,7 @@ public class DepartmentController { @BackendPermissionMiddleware(slug = BPermissionConstant.DEPARTMENT_CUD) @GetMapping("/create") + @Log(title = "部门-新建", businessType = BusinessType.GET) public JsonResponse create() { HashMap data = new HashMap<>(); data.put("departments", departmentService.groupByParent()); @@ -85,6 +90,7 @@ public class DepartmentController { @BackendPermissionMiddleware(slug = BPermissionConstant.DEPARTMENT_CUD) @PostMapping("/create") + @Log(title = "部门-新建", businessType = BusinessType.INSERT) public JsonResponse store(@RequestBody @Validated DepartmentRequest req) throws NotFoundException { departmentService.create(req.getName(), req.getParentId(), req.getSort()); @@ -93,6 +99,7 @@ public class DepartmentController { @BackendPermissionMiddleware(slug = BPermissionConstant.DEPARTMENT_CUD) @GetMapping("/{id}") + @Log(title = "部门-编辑", businessType = BusinessType.GET) public JsonResponse edit(@PathVariable Integer id) throws NotFoundException { Department department = departmentService.findOrFail(id); return JsonResponse.data(department); @@ -100,6 +107,7 @@ public class DepartmentController { @BackendPermissionMiddleware(slug = BPermissionConstant.DEPARTMENT_CUD) @PutMapping("/{id}") + @Log(title = "部门-编辑", businessType = BusinessType.UPDATE) public JsonResponse update(@PathVariable Integer id, @RequestBody DepartmentRequest req) throws NotFoundException { Department department = departmentService.findOrFail(id); @@ -109,6 +117,7 @@ public class DepartmentController { @BackendPermissionMiddleware(slug = BPermissionConstant.DEPARTMENT_CUD) @GetMapping("/{id}/destroy") + @Log(title = "部门-批量删除", businessType = BusinessType.DELETE) public JsonResponse preDestroy(@PathVariable Integer id) { List courseIds = departmentService.getCourseIdsByDepId(id); List userIds = departmentService.getUserIdsByDepId(id); @@ -149,6 +158,7 @@ public class DepartmentController { @BackendPermissionMiddleware(slug = BPermissionConstant.DEPARTMENT_CUD) @DeleteMapping("/{id}") + @Log(title = "部门-删除", businessType = BusinessType.DELETE) public JsonResponse destroy(@PathVariable Integer id) throws NotFoundException { Department department = departmentService.findOrFail(id); departmentService.destroy(department.getId()); @@ -158,6 +168,7 @@ public class DepartmentController { @BackendPermissionMiddleware(slug = BPermissionConstant.DEPARTMENT_CUD) @PutMapping("/update/sort") + @Log(title = "部门-更新排序", businessType = BusinessType.UPDATE) public JsonResponse resort(@RequestBody @Validated DepartmentSortRequest req) { departmentService.resetSort(req.getIds()); return JsonResponse.success(); @@ -165,6 +176,7 @@ public class DepartmentController { @BackendPermissionMiddleware(slug = BPermissionConstant.DEPARTMENT_CUD) @PutMapping("/update/parent") + @Log(title = "部门-更新父级", businessType = BusinessType.UPDATE) public JsonResponse updateParent(@RequestBody @Validated DepartmentParentRequest req) throws NotFoundException { departmentService.changeParent(req.getId(), req.getParentId(), req.getIds()); @@ -173,6 +185,7 @@ public class DepartmentController { @BackendPermissionMiddleware(slug = BPermissionConstant.DEPARTMENT_USER_LEARN) @GetMapping("/{id}/users") + @Log(title = "部门-学员", businessType = BusinessType.GET) public JsonResponse users( @PathVariable(name = "id") Integer id, @RequestParam HashMap params) { Integer page = MapUtils.getInteger(params, "page", 1); diff --git a/src/main/java/xyz/playedu/api/controller/backend/LoginController.java b/src/main/java/xyz/playedu/api/controller/backend/LoginController.java index bb6c95b..0630fe7 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/LoginController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/LoginController.java @@ -21,9 +21,11 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.bus.BackendBus; import xyz.playedu.api.config.PlayEduConfig; import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.AdminUser; import xyz.playedu.api.event.AdminUserLoginEvent; import xyz.playedu.api.middleware.BackendPermissionMiddleware; @@ -57,6 +59,7 @@ public class LoginController { @Autowired private PlayEduConfig playEduConfig; @PostMapping("/login") + @Log(title = "管理员-登录", businessType = BusinessType.LOGIN) public JsonResponse login(@RequestBody @Validated LoginRequest loginRequest) { AdminUser adminUser = adminUserService.findByEmail(loginRequest.email); if (adminUser == null) { @@ -100,12 +103,14 @@ public class LoginController { } @PostMapping("/logout") + @Log(title = "管理员-登出", businessType = BusinessType.LOGOUT) public JsonResponse logout() { authService.logout(); return JsonResponse.success("success"); } @GetMapping("/detail") + @Log(title = "管理员-详情", businessType = BusinessType.GET) public JsonResponse detail() { AdminUser user = BCtx.getAdminUser(); HashMap permissions = backendBus.adminUserPermissions(user.getId()); @@ -119,6 +124,7 @@ public class LoginController { @BackendPermissionMiddleware(slug = BPermissionConstant.PASSWORD_CHANGE) @PutMapping("/password") + @Log(title = "管理员-密码修改", businessType = BusinessType.UPDATE) public JsonResponse changePassword(@RequestBody @Validated PasswordChangeRequest req) { AdminUser user = BCtx.getAdminUser(); String password = HelperUtil.MD5(req.getOldPassword() + user.getSalt()); diff --git a/src/main/java/xyz/playedu/api/controller/backend/ResourceCategoryController.java b/src/main/java/xyz/playedu/api/controller/backend/ResourceCategoryController.java index 7f6bfa4..c3a7e46 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/ResourceCategoryController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/ResourceCategoryController.java @@ -21,8 +21,10 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BPermissionConstant; import xyz.playedu.api.constant.BackendConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.Resource; import xyz.playedu.api.domain.ResourceCategory; import xyz.playedu.api.event.ResourceCategoryDestroyEvent; @@ -57,6 +59,7 @@ public class ResourceCategoryController { @Autowired private ApplicationContext ctx; @GetMapping("/index") + @Log(title = "资源-分类-列表", businessType = BusinessType.GET) public JsonResponse index() { HashMap data = new HashMap<>(); data.put("categories", categoryService.groupByParent()); @@ -64,6 +67,7 @@ public class ResourceCategoryController { } @GetMapping("/categories") + @Log(title = "资源-分类-全部分类", businessType = BusinessType.GET) public JsonResponse index( @RequestParam(name = "parent_id", defaultValue = "0") Integer parentId) { List categories = categoryService.listByParentId(parentId); @@ -71,6 +75,7 @@ public class ResourceCategoryController { } @GetMapping("/create") + @Log(title = "资源-分类-新建", businessType = BusinessType.GET) public JsonResponse create() { HashMap data = new HashMap<>(); data.put("categories", categoryService.groupByParent()); @@ -79,6 +84,7 @@ public class ResourceCategoryController { @BackendPermissionMiddleware(slug = BPermissionConstant.RESOURCE_CATEGORY) @PostMapping("/create") + @Log(title = "资源-分类-新建", businessType = BusinessType.INSERT) public JsonResponse store(@RequestBody @Validated ResourceCategoryRequest req) throws NotFoundException { categoryService.create(req.getName(), req.getParentId(), req.getSort()); @@ -87,6 +93,7 @@ public class ResourceCategoryController { @BackendPermissionMiddleware(slug = BPermissionConstant.RESOURCE_CATEGORY) @GetMapping("/{id}") + @Log(title = "资源-分类-编辑", businessType = BusinessType.GET) public JsonResponse edit(@PathVariable Integer id) throws NotFoundException { ResourceCategory category = categoryService.findOrFail(id); return JsonResponse.data(category); @@ -94,6 +101,7 @@ public class ResourceCategoryController { @BackendPermissionMiddleware(slug = BPermissionConstant.RESOURCE_CATEGORY) @PutMapping("/{id}") + @Log(title = "资源-分类-编辑", businessType = BusinessType.UPDATE) public JsonResponse update(@PathVariable Integer id, @RequestBody ResourceCategoryRequest req) throws NotFoundException { ResourceCategory category = categoryService.findOrFail(id); @@ -103,6 +111,7 @@ public class ResourceCategoryController { @BackendPermissionMiddleware(slug = BPermissionConstant.RESOURCE_CATEGORY) @GetMapping("/{id}/destroy") + @Log(title = "资源-分类-批量删除", businessType = BusinessType.DELETE) public JsonResponse preDestroy(@PathVariable Integer id) { List courseIds = categoryService.getCourseIdsById(id); List rids = categoryService.getRidsById(id); @@ -151,6 +160,7 @@ public class ResourceCategoryController { @BackendPermissionMiddleware(slug = BPermissionConstant.RESOURCE_CATEGORY) @DeleteMapping("/{id}") + @Log(title = "资源-分类-删除", businessType = BusinessType.DELETE) public JsonResponse destroy(@PathVariable Integer id) throws NotFoundException { ResourceCategory category = categoryService.findOrFail(id); categoryService.deleteById(category.getId()); @@ -159,12 +169,14 @@ public class ResourceCategoryController { } @PutMapping("/update/sort") + @Log(title = "资源-分类-更新排序", businessType = BusinessType.UPDATE) public JsonResponse resort(@RequestBody @Validated ResourceCategorySortRequest req) { categoryService.resetSort(req.getIds()); return JsonResponse.success(); } @PutMapping("/update/parent") + @Log(title = "资源-分类-更新父级", businessType = BusinessType.UPDATE) public JsonResponse updateParent(@RequestBody @Validated ResourceCategoryParentRequest req) throws NotFoundException { categoryService.changeParent(req.getId(), req.getParentId(), req.getIds()); diff --git a/src/main/java/xyz/playedu/api/controller/backend/ResourceController.java b/src/main/java/xyz/playedu/api/controller/backend/ResourceController.java index 98385b1..5608462 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/ResourceController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/ResourceController.java @@ -24,8 +24,10 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.bus.BackendBus; import xyz.playedu.api.constant.BackendConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.AdminUser; import xyz.playedu.api.domain.Resource; import xyz.playedu.api.domain.ResourceVideo; @@ -59,6 +61,7 @@ public class ResourceController { @Autowired private BackendBus backendBus; @GetMapping("/index") + @Log(title = "资源-列表", businessType = BusinessType.GET) public JsonResponse index(@RequestParam HashMap params) { Integer page = MapUtils.getInteger(params, "page", 1); Integer size = MapUtils.getInteger(params, "size", 10); @@ -109,12 +112,18 @@ public class ResourceController { data.put("admin_users", adminUsers); } + if (!type.equals(BackendConstant.RESOURCE_TYPE_VIDEO) + && !type.equals(BackendConstant.RESOURCE_TYPE_IMAGE)) { + filter.setType(BackendConstant.RESOURCE_TYPE_ATTACHMENT); + data.put("existing_types", resourceService.paginateType(filter)); + } return JsonResponse.data(data); } @DeleteMapping("/{id}") @Transactional @SneakyThrows + @Log(title = "资源-删除", businessType = BusinessType.DELETE) public JsonResponse destroy(@PathVariable(name = "id") Integer id) throws NotFoundException { Resource resource = resourceService.findOrFail(id); @@ -137,6 +146,7 @@ public class ResourceController { @PostMapping("/destroy-multi") @SneakyThrows + @Log(title = "资源-批量列表", businessType = BusinessType.DELETE) public JsonResponse multiDestroy(@RequestBody ResourceDestroyMultiRequest req) { if (req.getIds() == null || req.getIds().size() == 0) { return JsonResponse.error("请选择需要删除的资源"); @@ -169,6 +179,7 @@ public class ResourceController { @GetMapping("/{id}") @SneakyThrows + @Log(title = "资源-编辑", businessType = BusinessType.GET) public JsonResponse edit(@PathVariable(name = "id") Integer id) { Resource resource = resourceService.findOrFail(id); @@ -186,6 +197,7 @@ public class ResourceController { @PutMapping("/{id}") @SneakyThrows + @Log(title = "资源-编辑", businessType = BusinessType.UPDATE) public JsonResponse update( @RequestBody @Validated ResourceUpdateRequest req, @PathVariable(name = "id") Integer id) { diff --git a/src/main/java/xyz/playedu/api/controller/backend/SystemController.java b/src/main/java/xyz/playedu/api/controller/backend/SystemController.java index c197630..13523ec 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/SystemController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/SystemController.java @@ -22,6 +22,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.constant.CConfig; import xyz.playedu.api.types.JsonResponse; import xyz.playedu.api.util.RequestUtil; @@ -37,6 +39,7 @@ import java.util.Map; public class SystemController { @GetMapping("/config") + @Log(title = "其它-系统配置", businessType = BusinessType.GET) public JsonResponse config() { Map configData = BCtx.getConfig(); diff --git a/src/main/java/xyz/playedu/api/controller/backend/UploadController.java b/src/main/java/xyz/playedu/api/controller/backend/UploadController.java index 32755a3..f65b2e4 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/UploadController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/UploadController.java @@ -24,10 +24,12 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BackendConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.domain.Resource; import xyz.playedu.api.exception.ServiceException; -import xyz.playedu.api.request.backend.UploadVideoMergeRequest; +import xyz.playedu.api.request.backend.UploadFileMergeRequest; import xyz.playedu.api.service.MinioService; import xyz.playedu.api.service.ResourceService; import xyz.playedu.api.service.UploadService; @@ -47,6 +49,7 @@ public class UploadController { @Autowired private ResourceService resourceService; @PostMapping("/minio") + @Log(title = "上传-MinIO", businessType = BusinessType.UPLOAD) public JsonResponse uploadMinio( @RequestParam HashMap params, MultipartFile file) throws ServiceException { @@ -56,6 +59,7 @@ public class UploadController { } @GetMapping("/minio/upload-id") + @Log(title = "上传-MinIO-uploadId", businessType = BusinessType.UPLOAD) public JsonResponse minioUploadId(@RequestParam HashMap params) { String extension = MapUtils.getString(params, "extension"); if (extension == null || extension.trim().length() == 0) { @@ -79,6 +83,7 @@ public class UploadController { } @GetMapping("/minio/pre-sign-url") + @Log(title = "上传-MinIO-签名URL", businessType = BusinessType.UPLOAD) public JsonResponse minioPreSignUrl(@RequestParam HashMap params) { String uploadId = MapUtils.getString(params, "upload_id"); Integer partNumber = MapUtils.getInteger(params, "part_number"); @@ -92,8 +97,9 @@ public class UploadController { return JsonResponse.data(data); } - @PostMapping("/minio/merge-video") - public JsonResponse minioMergeVideo(@RequestBody @Validated UploadVideoMergeRequest req) + @PostMapping("/minio/merge-file") + @Log(title = "上传-MinIO-文件合并", businessType = BusinessType.UPLOAD) + public JsonResponse minioMergeFile(@RequestBody @Validated UploadFileMergeRequest req) throws ServiceException { String type = BackendConstant.RESOURCE_EXT_2_TYPE.get(req.getExtension()); if (type == null) { @@ -102,10 +108,10 @@ public class UploadController { String extension = req.getExtension(); String originalFilename = req.getOriginalFilename().replaceAll("(?i)." + extension, ""); - // 合并视频文件 + // 合并资源文件 String url = minioService.merge(req.getFilename(), req.getUploadId()); - // 视频素材保存 + // 资源素材保存 Resource videoResource = resourceService.create( BCtx.getId(), @@ -118,14 +124,18 @@ public class UploadController { "", req.getFilename(), url); - // 视频封面素材保存 - Resource posterResource = - uploadService.storeBase64Image(BCtx.getId(), req.getPoster(), null); - // 视频的封面素材改为[隐藏 && 属于视频的子素材] - resourceService.changeParentId(posterResource.getId(), videoResource.getId()); - // 视频信息 - resourceService.storeResourceVideo( - videoResource.getId(), req.getDuration(), posterResource.getUrl()); + + // 视频资源特殊处理--视频封面资源 + if (BackendConstant.RESOURCE_TYPE_VIDEO.equals(type)) { + // 视频封面素材保存 + Resource posterResource = + uploadService.storeBase64Image(BCtx.getId(), req.getPoster(), null); + // 视频的封面素材改为[隐藏 && 属于视频的子素材] + resourceService.changeParentId(posterResource.getId(), videoResource.getId()); + // 视频信息 + resourceService.storeResourceVideo( + videoResource.getId(), req.getDuration(), posterResource.getUrl()); + } HashMap data = new HashMap<>(); data.put("url", url); @@ -134,6 +144,7 @@ public class UploadController { } @GetMapping("/minio/merge") + @Log(title = "上传-MinIO-文件合并", businessType = BusinessType.UPLOAD) public JsonResponse minioMerge(@RequestParam HashMap params) { String filename = MapUtils.getString(params, "filename"); String uploadId = MapUtils.getString(params, "upload_id"); diff --git a/src/main/java/xyz/playedu/api/controller/backend/UserController.java b/src/main/java/xyz/playedu/api/controller/backend/UserController.java index 32bc29c..8db89dc 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/UserController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/UserController.java @@ -29,7 +29,9 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import xyz.playedu.api.BCtx; +import xyz.playedu.api.annotation.Log; import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.constant.BusinessType; import xyz.playedu.api.constant.CConfig; import xyz.playedu.api.constant.SystemConstant; import xyz.playedu.api.domain.*; @@ -85,6 +87,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_INDEX) @GetMapping("/index") + @Log(title = "学员-列表", businessType = BusinessType.GET) public JsonResponse index(@RequestParam HashMap params) { Integer page = MapUtils.getInteger(params, "page", 1); Integer size = MapUtils.getInteger(params, "size", 10); @@ -146,12 +149,14 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_STORE) @GetMapping("/create") + @Log(title = "学员-新建", businessType = BusinessType.GET) public JsonResponse create() { return JsonResponse.data(null); } @BackendPermissionMiddleware(slug = BPermissionConstant.USER_STORE) @PostMapping("/create") + @Log(title = "学员-新建", businessType = BusinessType.INSERT) public JsonResponse store(@RequestBody @Validated UserRequest req) { String email = req.getEmail(); if (userService.emailIsExists(email)) { @@ -173,6 +178,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_UPDATE) @GetMapping("/{id}") + @Log(title = "学员-编辑", businessType = BusinessType.GET) public JsonResponse edit(@PathVariable(name = "id") Integer id) throws NotFoundException { User user = userService.findOrFail(id); @@ -188,6 +194,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_UPDATE) @PutMapping("/{id}") @Transactional + @Log(title = "学员-编辑", businessType = BusinessType.UPDATE) public JsonResponse update( @PathVariable(name = "id") Integer id, @RequestBody @Validated UserRequest req) throws NotFoundException { @@ -211,6 +218,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_DESTROY) @DeleteMapping("/{id}") + @Log(title = "学员-删除", businessType = BusinessType.DELETE) public JsonResponse destroy(@PathVariable(name = "id") Integer id) throws NotFoundException { User user = userService.findOrFail(id); userService.removeById(user.getId()); @@ -220,6 +228,7 @@ public class UserController { @PostMapping("/store-batch") @Transactional + @Log(title = "学员-批量导入", businessType = BusinessType.INSERT) public JsonResponse batchStore(@RequestBody @Validated UserImportRequest req) { List users = req.getUsers(); if (users.size() == 0) { @@ -384,6 +393,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_LEARN) @GetMapping("/{id}/learn-hours") @SneakyThrows + @Log(title = "学员-已学习课时列表", businessType = BusinessType.GET) public JsonResponse learnHours( @PathVariable(name = "id") Integer id, @RequestParam HashMap params) { Integer page = MapUtils.getInteger(params, "page", 1); @@ -419,6 +429,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_LEARN) @GetMapping("/{id}/learn-courses") + @Log(title = "学员-已学习课程列表", businessType = BusinessType.GET) public JsonResponse latestLearnCourses( @PathVariable(name = "id") Integer id, @RequestParam HashMap params) { Integer page = MapUtils.getInteger(params, "page", 1); @@ -454,6 +465,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_LEARN) @GetMapping("/{id}/all-courses") + @Log(title = "学员-课程", businessType = BusinessType.GET) public JsonResponse allCourses(@PathVariable(name = "id") Integer id) { // 读取学员关联的部门 List depIds = userService.getDepIdsByUserId(id); @@ -516,6 +528,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_LEARN) @GetMapping("/{id}/learn-course/{courseId}") @SneakyThrows + @Log(title = "学员-单个课程的学习记录", businessType = BusinessType.GET) public JsonResponse learnCourseDetail( @PathVariable(name = "id") Integer id, @PathVariable(name = "courseId") Integer courseId) { @@ -537,6 +550,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_LEARN) @GetMapping("/{id}/learn-stats") @SneakyThrows + @Log(title = "学员-学习统计", businessType = BusinessType.GET) public JsonResponse learn(@PathVariable(name = "id") Integer id) { // 最近一个月的每天学习时长 String todayStr = DateTime.now().toDateStr(); @@ -584,6 +598,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_LEARN_DESTROY) @DeleteMapping("/{id}/learn-course/{courseId}") @SneakyThrows + @Log(title = "学员-线上课学习记录删除", businessType = BusinessType.DELETE) public JsonResponse destroyUserCourse( @PathVariable(name = "id") Integer id, @PathVariable(name = "courseId") Integer courseId) { @@ -595,6 +610,7 @@ public class UserController { @BackendPermissionMiddleware(slug = BPermissionConstant.USER_LEARN_DESTROY) @DeleteMapping("/{id}/learn-course/{courseId}/hour/{hourId}") @SneakyThrows + @Log(title = "学员-线上课课时学习记录删除", businessType = BusinessType.DELETE) public JsonResponse destroyUserHour( @PathVariable(name = "id") Integer id, @PathVariable(name = "courseId") Integer courseId, diff --git a/src/main/java/xyz/playedu/api/controller/frontend/CourseController.java b/src/main/java/xyz/playedu/api/controller/frontend/CourseController.java index 10f0386..67fe56b 100644 --- a/src/main/java/xyz/playedu/api/controller/frontend/CourseController.java +++ b/src/main/java/xyz/playedu/api/controller/frontend/CourseController.java @@ -22,15 +22,16 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import xyz.playedu.api.FCtx; -import xyz.playedu.api.domain.Course; -import xyz.playedu.api.domain.CourseHour; -import xyz.playedu.api.domain.UserCourseHourRecord; +import xyz.playedu.api.domain.*; import xyz.playedu.api.service.*; import xyz.playedu.api.types.JsonResponse; import xyz.playedu.api.types.paginate.CoursePaginateFiler; import xyz.playedu.api.types.paginate.PaginationResult; +import xyz.playedu.api.util.IpUtil; +import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.stream.Collectors; /** @@ -48,10 +49,16 @@ public class CourseController { @Autowired private CourseHourService hourService; + @Autowired private CourseAttachmentService attachmentService; + + @Autowired private ResourceService resourceService; + @Autowired private UserCourseRecordService userCourseRecordService; @Autowired private UserCourseHourRecordService userCourseHourRecordService; + @Autowired private CourseAttachmentDownloadLogService courseAttachmentDownloadLogService; + @GetMapping("/index") public JsonResponse index(@RequestParam HashMap params) { Integer page = MapUtils.getInteger(params, "page", 1); @@ -72,18 +79,49 @@ public class CourseController { public JsonResponse detail(@PathVariable(name = "id") Integer id) { Course course = courseService.findOrFail(id); + List courseHours = hourService.getHoursByCourseId(course.getId()); + + List attachments = + attachmentService.getAttachmentsByCourseId(course.getId()); + HashMap data = new HashMap<>(); data.put("course", course); data.put("chapters", chapterService.getChaptersByCourseId(course.getId())); data.put( "hours", - hourService.getHoursByCourseId(course.getId()).stream() - .collect(Collectors.groupingBy(CourseHour::getChapterId))); + courseHours.stream().collect(Collectors.groupingBy(CourseHour::getChapterId))); data.put("learn_record", userCourseRecordService.find(FCtx.getId(), course.getId())); data.put( "learn_hour_records", userCourseHourRecordService.getRecords(FCtx.getId(), course.getId()).stream() .collect(Collectors.toMap(UserCourseHourRecord::getHourId, e -> e))); + data.put("attachments", attachments); + return JsonResponse.data(data); + } + + @GetMapping("/{courseId}/attach/{id}/download") + @SneakyThrows + public JsonResponse attachmentDownload( + @PathVariable(name = "courseId") Integer courseId, + @PathVariable(name = "id") Integer id) { + CourseAttachment attachment = attachmentService.findOrFail(id, courseId); + Resource resource = resourceService.findOrFail(attachment.getRid()); + + HashMap data = new HashMap<>(); + data.put("download_url", resource.getUrl()); + + courseAttachmentDownloadLogService.save( + new CourseAttachmentDownloadLog() { + { + setUserId(FCtx.getId()); + setCourseId(attachment.getCourseId()); + setCourserAttachmentId(attachment.getId()); + setRid(resource.getId()); + setTitle(attachment.getTitle()); + setIp(IpUtil.getIpAddress()); + setCreatedAt(new Date()); + } + }); return JsonResponse.data(data); } diff --git a/src/main/java/xyz/playedu/api/domain/AdminLog.java b/src/main/java/xyz/playedu/api/domain/AdminLog.java index 214b57e..e51a8cb 100644 --- a/src/main/java/xyz/playedu/api/domain/AdminLog.java +++ b/src/main/java/xyz/playedu/api/domain/AdminLog.java @@ -40,14 +40,34 @@ public class AdminLog implements Serializable { @JsonProperty("admin_id") private Integer adminId; + @TableField(exist = false) + @JsonProperty("admin_name") + private String adminName; + /** 模块 */ private String module; - /** 操作指令 */ - private String opt; + /** 标题 */ + private String title; - /** 备注 */ - private String remark; + /** 操作指令 */ + private Integer opt; + + /** 请求方法 */ + private String method; + + /** 请求方式 POST,GET,PUT,DELETE */ + @JsonProperty("request_method") + private String requestMethod; + + /** 请求URL */ + private String url; + + /** 请求参数 */ + private String param; + + /** 返回参数 */ + private String result; /** ip */ private String ip; @@ -56,6 +76,10 @@ public class AdminLog implements Serializable { @JsonProperty("ip_area") private String ipArea; + /** 备注 */ + @JsonProperty("error_msg") + private String errorMsg; + @JsonProperty("created_at") private Date createdAt; @@ -81,18 +105,36 @@ public class AdminLog implements Serializable { && (this.getModule() == null ? other.getModule() == null : this.getModule().equals(other.getModule())) + && (this.getTitle() == null + ? other.getTitle() == null + : this.getTitle().equals(other.getTitle())) && (this.getOpt() == null ? other.getOpt() == null : this.getOpt().equals(other.getOpt())) - && (this.getRemark() == null - ? other.getRemark() == null - : this.getRemark().equals(other.getRemark())) + && (this.getMethod() == null + ? other.getMethod() == null + : this.getMethod().equals(other.getMethod())) + && (this.getRequestMethod() == null + ? other.getRequestMethod() == null + : this.getRequestMethod().equals(other.getRequestMethod())) + && (this.getUrl() == null + ? other.getUrl() == null + : this.getUrl().equals(other.getUrl())) + && (this.getParam() == null + ? other.getParam() == null + : this.getParam().equals(other.getParam())) + && (this.getResult() == null + ? other.getResult() == null + : this.getResult().equals(other.getResult())) && (this.getIp() == null ? other.getIp() == null : this.getIp().equals(other.getIp())) && (this.getIpArea() == null ? other.getIpArea() == null : this.getIpArea().equals(other.getIpArea())) + && (this.getErrorMsg() == null + ? other.getErrorMsg() == null + : this.getErrorMsg().equals(other.getErrorMsg())) && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt())); @@ -105,10 +147,17 @@ public class AdminLog implements Serializable { result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); result = prime * result + ((getAdminId() == null) ? 0 : getAdminId().hashCode()); result = prime * result + ((getModule() == null) ? 0 : getModule().hashCode()); + result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode()); result = prime * result + ((getOpt() == null) ? 0 : getOpt().hashCode()); - result = prime * result + ((getRemark() == null) ? 0 : getRemark().hashCode()); + result = prime * result + ((getMethod() == null) ? 0 : getMethod().hashCode()); + result = + prime * result + ((getRequestMethod() == null) ? 0 : getRequestMethod().hashCode()); + result = prime * result + ((getUrl() == null) ? 0 : getUrl().hashCode()); + result = prime * result + ((getParam() == null) ? 0 : getParam().hashCode()); + result = prime * result + ((getResult() == null) ? 0 : getResult().hashCode()); result = prime * result + ((getIp() == null) ? 0 : getIp().hashCode()); result = prime * result + ((getIpArea() == null) ? 0 : getIpArea().hashCode()); + result = prime * result + ((getErrorMsg() == null) ? 0 : getErrorMsg().hashCode()); result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode()); return result; } @@ -122,10 +171,16 @@ public class AdminLog implements Serializable { sb.append(", id=").append(id); sb.append(", adminId=").append(adminId); sb.append(", module=").append(module); + sb.append(", title=").append(title); sb.append(", opt=").append(opt); - sb.append(", remark=").append(remark); + sb.append(", method=").append(method); + sb.append(", requestMethod=").append(requestMethod); + sb.append(", url=").append(url); + sb.append(", param=").append(param); + sb.append(", result=").append(result); sb.append(", ip=").append(ip); sb.append(", ipArea=").append(ipArea); + sb.append(", errorMsg=").append(errorMsg); sb.append(", createdAt=").append(createdAt); sb.append(", serialVersionUID=").append(serialVersionUID); sb.append("]"); diff --git a/src/main/java/xyz/playedu/api/domain/CourseAttachment.java b/src/main/java/xyz/playedu/api/domain/CourseAttachment.java new file mode 100644 index 0000000..b9fce75 --- /dev/null +++ b/src/main/java/xyz/playedu/api/domain/CourseAttachment.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @TableName course_attachment + */ +@TableName(value = "course_attachment") +@Data +public class CourseAttachment implements Serializable { + /** */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** 课程ID */ + @JsonProperty("course_id") + private Integer courseId; + + /** 升序 */ + private Integer sort; + + /** 附件名 */ + private String title; + + /** 附件类型 */ + private String type; + + /** 资源id */ + private Integer rid; + + /** 资源url */ + @TableField(exist = false) + private String url; + + /** */ + @JsonIgnore private Date createdAt; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + CourseAttachment other = (CourseAttachment) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getCourseId() == null + ? other.getCourseId() == null + : this.getCourseId().equals(other.getCourseId())) + && (this.getSort() == null + ? other.getSort() == null + : this.getSort().equals(other.getSort())) + && (this.getTitle() == null + ? other.getTitle() == null + : this.getTitle().equals(other.getTitle())) + && (this.getType() == null + ? other.getType() == null + : this.getType().equals(other.getType())) + && (this.getRid() == null + ? other.getRid() == null + : this.getRid().equals(other.getRid())) + && (this.getUrl() == null + ? other.getUrl() == null + : this.getUrl().equals(other.getUrl())) + && (this.getCreatedAt() == null + ? other.getCreatedAt() == null + : this.getCreatedAt().equals(other.getCreatedAt())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getCourseId() == null) ? 0 : getCourseId().hashCode()); + result = prime * result + ((getSort() == null) ? 0 : getSort().hashCode()); + result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode()); + result = prime * result + ((getType() == null) ? 0 : getType().hashCode()); + result = prime * result + ((getRid() == null) ? 0 : getRid().hashCode()); + result = prime * result + ((getUrl() == null) ? 0 : getUrl().hashCode()); + result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", courseId=").append(courseId); + sb.append(", sort=").append(sort); + sb.append(", title=").append(title); + sb.append(", type=").append(type); + sb.append(", rid=").append(rid); + sb.append(", url=").append(url); + sb.append(", createdAt=").append(createdAt); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} diff --git a/src/main/java/xyz/playedu/api/domain/CourseAttachmentDownloadLog.java b/src/main/java/xyz/playedu/api/domain/CourseAttachmentDownloadLog.java new file mode 100644 index 0000000..c62a1ec --- /dev/null +++ b/src/main/java/xyz/playedu/api/domain/CourseAttachmentDownloadLog.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @TableName course_attachment_download_log + */ +@TableName(value = "course_attachment_download_log") +@Data +public class CourseAttachmentDownloadLog implements Serializable { + /** */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 学员ID */ + @JsonProperty("user_id") + private Integer userId; + + /** 课程ID */ + @JsonProperty("course_id") + private Integer courseId; + + /** 标题 */ + private String title; + + /** 课程附件ID */ + @JsonProperty("courser_attachment_id") + private Integer courserAttachmentId; + + /** 资源ID */ + private Integer rid; + + /** IP */ + private String ip; + + @JsonProperty("created_at") + private Date createdAt; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + CourseAttachmentDownloadLog other = (CourseAttachmentDownloadLog) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getUserId() == null + ? other.getUserId() == null + : this.getUserId().equals(other.getUserId())) + && (this.getCourseId() == null + ? other.getCourseId() == null + : this.getCourseId().equals(other.getCourseId())) + && (this.getTitle() == null + ? other.getTitle() == null + : this.getTitle().equals(other.getTitle())) + && (this.getCourserAttachmentId() == null + ? other.getCourserAttachmentId() == null + : this.getCourserAttachmentId().equals(other.getCourserAttachmentId())) + && (this.getRid() == null + ? other.getRid() == null + : this.getRid().equals(other.getRid())) + && (this.getIp() == null + ? other.getIp() == null + : this.getIp().equals(other.getIp())) + && (this.getCreatedAt() == null + ? other.getCreatedAt() == null + : this.getCreatedAt().equals(other.getCreatedAt())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode()); + result = prime * result + ((getCourseId() == null) ? 0 : getCourseId().hashCode()); + result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode()); + result = + prime * result + + ((getCourserAttachmentId() == null) + ? 0 + : getCourserAttachmentId().hashCode()); + result = prime * result + ((getRid() == null) ? 0 : getRid().hashCode()); + result = prime * result + ((getIp() == null) ? 0 : getIp().hashCode()); + result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", userId=").append(userId); + sb.append(", courseId=").append(courseId); + sb.append(", title=").append(title); + sb.append(", courserAttachmentId=").append(courserAttachmentId); + sb.append(", rid=").append(rid); + sb.append(", ip=").append(ip); + sb.append(", createdAt=").append(createdAt); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} diff --git a/src/main/java/xyz/playedu/api/listener/AdminUserLoginListener.java b/src/main/java/xyz/playedu/api/listener/AdminUserLoginListener.java index a4c2a4a..72ce4f5 100644 --- a/src/main/java/xyz/playedu/api/listener/AdminUserLoginListener.java +++ b/src/main/java/xyz/playedu/api/listener/AdminUserLoginListener.java @@ -19,18 +19,11 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.EventListener; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import xyz.playedu.api.constant.BackendLogConstant; -import xyz.playedu.api.domain.AdminLog; import xyz.playedu.api.domain.AdminUser; import xyz.playedu.api.event.AdminUserLoginEvent; -import xyz.playedu.api.service.AdminLogService; import xyz.playedu.api.service.AdminUserService; -import xyz.playedu.api.util.IpUtil; - -import java.util.Date; @Component @Slf4j @@ -38,8 +31,6 @@ public class AdminUserLoginListener { @Autowired private AdminUserService adminUserService; - @Autowired private AdminLogService adminLogService; - @EventListener public void updateLoginInfo(AdminUserLoginEvent event) { AdminUser adminUser = new AdminUser(); @@ -51,20 +42,4 @@ public class AdminUserLoginListener { adminUserService.updateById(adminUser); } - - @Async - @EventListener - public void log(AdminUserLoginEvent event) { - String area = IpUtil.getRealAddressByIP(event.getIp()); - - AdminLog adminLog = new AdminLog(); - adminLog.setAdminId(event.getAdminId()); - adminLog.setModule(BackendLogConstant.MODULE_LOGIN); - adminLog.setOpt(BackendLogConstant.OPT_LOGIN); - adminLog.setIp(event.getIp()); - adminLog.setIpArea(area); - adminLog.setCreatedAt(new Date()); - - adminLogService.save(adminLog); - } } diff --git a/src/main/java/xyz/playedu/api/listener/CourseDestroyListener.java b/src/main/java/xyz/playedu/api/listener/CourseDestroyListener.java index 7d45007..c9ece1e 100644 --- a/src/main/java/xyz/playedu/api/listener/CourseDestroyListener.java +++ b/src/main/java/xyz/playedu/api/listener/CourseDestroyListener.java @@ -20,6 +20,7 @@ import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import xyz.playedu.api.event.CourseDestroyEvent; +import xyz.playedu.api.service.CourseAttachmentService; import xyz.playedu.api.service.CourseDepartmentService; import xyz.playedu.api.service.UserCourseHourRecordService; import xyz.playedu.api.service.UserCourseRecordService; @@ -41,6 +42,8 @@ public class CourseDestroyListener { @Autowired private UserCourseHourRecordService userCourseHourRecordService; + @Autowired private CourseAttachmentService courseAttachmentService; + @EventListener public void departmentRelateRemove(CourseDestroyEvent event) { courseDepartmentService.removeByCourseId(event.getCourseId()); @@ -51,6 +54,11 @@ public class CourseDestroyListener { courseCategoryService.removeByCourseId(event.getCourseId()); } + @EventListener + public void attachmentRelateRemove(CourseDestroyEvent event) { + courseAttachmentService.remove(event.getCourseId()); + } + @EventListener public void removeUserRecords(CourseDestroyEvent event) { userCourseRecordService.removeByCourseId(event.getCourseId()); diff --git a/src/main/java/xyz/playedu/api/mapper/AdminLogMapper.java b/src/main/java/xyz/playedu/api/mapper/AdminLogMapper.java index 96072f5..d60713c 100644 --- a/src/main/java/xyz/playedu/api/mapper/AdminLogMapper.java +++ b/src/main/java/xyz/playedu/api/mapper/AdminLogMapper.java @@ -20,6 +20,9 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import xyz.playedu.api.domain.AdminLog; +import xyz.playedu.api.types.paginate.AdminLogPaginateFiler; + +import java.util.List; /** * @author tengteng @@ -27,4 +30,8 @@ import xyz.playedu.api.domain.AdminLog; * @createDate 2023-02-17 15:40:31 @Entity xyz.playedu.api.domain.AdminLog */ @Mapper -public interface AdminLogMapper extends BaseMapper {} +public interface AdminLogMapper extends BaseMapper { + List paginate(AdminLogPaginateFiler filer); + + Long paginateCount(AdminLogPaginateFiler filer); +} diff --git a/src/main/java/xyz/playedu/api/mapper/CourseAttachmentDownloadLogMapper.java b/src/main/java/xyz/playedu/api/mapper/CourseAttachmentDownloadLogMapper.java new file mode 100644 index 0000000..882c47d --- /dev/null +++ b/src/main/java/xyz/playedu/api/mapper/CourseAttachmentDownloadLogMapper.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import org.apache.ibatis.annotations.Mapper; + +import xyz.playedu.api.domain.CourseAttachmentDownloadLog; +import xyz.playedu.api.types.paginate.CourseAttachmentDownloadLogPaginateFiler; + +import java.util.List; + +@Mapper +public interface CourseAttachmentDownloadLogMapper extends BaseMapper { + + List paginate(CourseAttachmentDownloadLogPaginateFiler filer); + + Long paginateCount(CourseAttachmentDownloadLogPaginateFiler filer); +} diff --git a/src/main/java/xyz/playedu/api/mapper/CourseAttachmentMapper.java b/src/main/java/xyz/playedu/api/mapper/CourseAttachmentMapper.java new file mode 100644 index 0000000..9b3b183 --- /dev/null +++ b/src/main/java/xyz/playedu/api/mapper/CourseAttachmentMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import org.apache.ibatis.annotations.Mapper; + +import xyz.playedu.api.domain.CourseAttachment; + +@Mapper +public interface CourseAttachmentMapper extends BaseMapper {} diff --git a/src/main/java/xyz/playedu/api/mapper/ResourceMapper.java b/src/main/java/xyz/playedu/api/mapper/ResourceMapper.java index 9755104..1e6f459 100644 --- a/src/main/java/xyz/playedu/api/mapper/ResourceMapper.java +++ b/src/main/java/xyz/playedu/api/mapper/ResourceMapper.java @@ -35,4 +35,6 @@ public interface ResourceMapper extends BaseMapper { List paginate(ResourcePaginateFilter filter); Long paginateCount(ResourcePaginateFilter filter); + + List paginateType(ResourcePaginateFilter filter); } diff --git a/src/main/java/xyz/playedu/api/request/backend/CourseAttachmentMultiRequest.java b/src/main/java/xyz/playedu/api/request/backend/CourseAttachmentMultiRequest.java new file mode 100644 index 0000000..ce27437 --- /dev/null +++ b/src/main/java/xyz/playedu/api/request/backend/CourseAttachmentMultiRequest.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.request.backend; + +import jakarta.validation.constraints.NotNull; + +import lombok.Data; + +import java.util.List; + +@Data +public class CourseAttachmentMultiRequest { + @Data + public static class AttachmentItem { + private String title; + private Integer sort; + private String type; + private Integer rid; + } + + @NotNull(message = "attachments参数不存在") + private List attachments; +} diff --git a/src/main/java/xyz/playedu/api/request/backend/CourseAttachmentRequest.java b/src/main/java/xyz/playedu/api/request/backend/CourseAttachmentRequest.java new file mode 100644 index 0000000..c2afeb5 --- /dev/null +++ b/src/main/java/xyz/playedu/api/request/backend/CourseAttachmentRequest.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.request.backend; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +import lombok.Data; + +@Data +public class CourseAttachmentRequest { + + @NotBlank(message = "请输入附件名称") + private String title; + + @NotNull(message = "sort参数不存在") + private Integer sort; + + @NotBlank(message = "请选择附件类型") + private String type; + + @NotNull(message = "rid参数不存在") + private Integer rid; +} diff --git a/src/main/java/xyz/playedu/api/request/backend/CourseAttachmentSortRequest.java b/src/main/java/xyz/playedu/api/request/backend/CourseAttachmentSortRequest.java new file mode 100644 index 0000000..83e36ac --- /dev/null +++ b/src/main/java/xyz/playedu/api/request/backend/CourseAttachmentSortRequest.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.request.backend; + +import lombok.Data; + +import java.util.List; + +@Data +public class CourseAttachmentSortRequest { + private List ids; +} diff --git a/src/main/java/xyz/playedu/api/request/backend/CourseRequest.java b/src/main/java/xyz/playedu/api/request/backend/CourseRequest.java index 16d35c1..7833f3b 100644 --- a/src/main/java/xyz/playedu/api/request/backend/CourseRequest.java +++ b/src/main/java/xyz/playedu/api/request/backend/CourseRequest.java @@ -72,6 +72,13 @@ public class CourseRequest { private List hours; } + @Data + public static class AttachmentItem { + private String name; + private String type; + private Integer rid; + } + // 格式 // [ // { @@ -100,4 +107,14 @@ public class CourseRequest { // ] @NotNull(message = "hours参数不存在") private List hours; + + // 格式 + // [ + // { + // 'name' => '附件名', + // 'type' => '附件类型', + // 'rid' => '资源id', + // }... + // ] + private List attachments; } diff --git a/src/main/java/xyz/playedu/api/request/backend/UploadVideoMergeRequest.java b/src/main/java/xyz/playedu/api/request/backend/UploadFileMergeRequest.java similarity index 97% rename from src/main/java/xyz/playedu/api/request/backend/UploadVideoMergeRequest.java rename to src/main/java/xyz/playedu/api/request/backend/UploadFileMergeRequest.java index 6ef5279..4ac9fc6 100644 --- a/src/main/java/xyz/playedu/api/request/backend/UploadVideoMergeRequest.java +++ b/src/main/java/xyz/playedu/api/request/backend/UploadFileMergeRequest.java @@ -28,7 +28,7 @@ import lombok.Data; * @create 2023/3/8 14:49 */ @Data -public class UploadVideoMergeRequest { +public class UploadFileMergeRequest { @NotBlank(message = "请输入课程标题") private String filename; diff --git a/src/main/java/xyz/playedu/api/service/AdminLogService.java b/src/main/java/xyz/playedu/api/service/AdminLogService.java index c255ed6..0b35ed7 100644 --- a/src/main/java/xyz/playedu/api/service/AdminLogService.java +++ b/src/main/java/xyz/playedu/api/service/AdminLogService.java @@ -20,6 +20,8 @@ import com.baomidou.mybatisplus.extension.service.IService; import org.springframework.stereotype.Service; import xyz.playedu.api.domain.AdminLog; +import xyz.playedu.api.types.paginate.AdminLogPaginateFiler; +import xyz.playedu.api.types.paginate.PaginationResult; /** * @author tengteng @@ -27,4 +29,6 @@ import xyz.playedu.api.domain.AdminLog; * @createDate 2023-02-17 15:40:31 */ @Service -public interface AdminLogService extends IService {} +public interface AdminLogService extends IService { + PaginationResult paginate(int page, int size, AdminLogPaginateFiler filter); +} diff --git a/src/main/java/xyz/playedu/api/service/CourseAttachmentDownloadLogService.java b/src/main/java/xyz/playedu/api/service/CourseAttachmentDownloadLogService.java new file mode 100644 index 0000000..89c4b60 --- /dev/null +++ b/src/main/java/xyz/playedu/api/service/CourseAttachmentDownloadLogService.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.service; + +import com.baomidou.mybatisplus.extension.service.IService; + +import org.springframework.stereotype.Service; + +import xyz.playedu.api.domain.CourseAttachmentDownloadLog; +import xyz.playedu.api.types.paginate.CourseAttachmentDownloadLogPaginateFiler; +import xyz.playedu.api.types.paginate.PaginationResult; + +@Service +public interface CourseAttachmentDownloadLogService extends IService { + PaginationResult paginate( + int page, int size, CourseAttachmentDownloadLogPaginateFiler filter); +} diff --git a/src/main/java/xyz/playedu/api/service/CourseAttachmentService.java b/src/main/java/xyz/playedu/api/service/CourseAttachmentService.java new file mode 100644 index 0000000..f55371d --- /dev/null +++ b/src/main/java/xyz/playedu/api/service/CourseAttachmentService.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.service; + +import com.baomidou.mybatisplus.extension.service.IService; + +import xyz.playedu.api.domain.CourseAttachment; +import xyz.playedu.api.exception.NotFoundException; + +import java.util.List; + +public interface CourseAttachmentService extends IService { + + CourseAttachment findOrFail(Integer id, Integer courseId) throws NotFoundException; + + void update(CourseAttachment courseAttachment, Integer sort, String title); + + List getAttachmentsByCourseId(Integer courseId); + + CourseAttachment create(Integer courseId, Integer sort, String title, String type, Integer rid); + + Integer getCountByCourseId(Integer courseId); + + void remove(Integer courseId); + + void updateSort(List ids, Integer cid); + + List getRidsByCourseId(Integer courseId); + + List chunk(List attachmentIds); +} diff --git a/src/main/java/xyz/playedu/api/service/ResourceService.java b/src/main/java/xyz/playedu/api/service/ResourceService.java index a4f42b3..28d4aab 100644 --- a/src/main/java/xyz/playedu/api/service/ResourceService.java +++ b/src/main/java/xyz/playedu/api/service/ResourceService.java @@ -28,6 +28,8 @@ public interface ResourceService extends IService { PaginationResult paginate(int page, int size, ResourcePaginateFilter filter); + List paginateType(ResourcePaginateFilter filter); + Resource create( Integer adminId, String categoryIds, diff --git a/src/main/java/xyz/playedu/api/service/impl/AdminLogServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/AdminLogServiceImpl.java index 3c5b909..81f39b3 100644 --- a/src/main/java/xyz/playedu/api/service/impl/AdminLogServiceImpl.java +++ b/src/main/java/xyz/playedu/api/service/impl/AdminLogServiceImpl.java @@ -22,6 +22,8 @@ import org.springframework.stereotype.Service; import xyz.playedu.api.domain.AdminLog; import xyz.playedu.api.mapper.AdminLogMapper; import xyz.playedu.api.service.AdminLogService; +import xyz.playedu.api.types.paginate.AdminLogPaginateFiler; +import xyz.playedu.api.types.paginate.PaginationResult; /** * @author tengteng @@ -30,4 +32,16 @@ import xyz.playedu.api.service.AdminLogService; */ @Service public class AdminLogServiceImpl extends ServiceImpl - implements AdminLogService {} + implements AdminLogService { + @Override + public PaginationResult paginate(int page, int size, AdminLogPaginateFiler filter) { + filter.setPageStart((page - 1) * size); + filter.setPageSize(size); + + PaginationResult pageResult = new PaginationResult<>(); + pageResult.setData(getBaseMapper().paginate(filter)); + pageResult.setTotal(getBaseMapper().paginateCount(filter)); + + return pageResult; + } +} diff --git a/src/main/java/xyz/playedu/api/service/impl/CourseAttachmentDownloadLogServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/CourseAttachmentDownloadLogServiceImpl.java new file mode 100644 index 0000000..ff25d69 --- /dev/null +++ b/src/main/java/xyz/playedu/api/service/impl/CourseAttachmentDownloadLogServiceImpl.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import org.springframework.stereotype.Service; + +import xyz.playedu.api.domain.CourseAttachmentDownloadLog; +import xyz.playedu.api.mapper.CourseAttachmentDownloadLogMapper; +import xyz.playedu.api.service.CourseAttachmentDownloadLogService; +import xyz.playedu.api.types.paginate.CourseAttachmentDownloadLogPaginateFiler; +import xyz.playedu.api.types.paginate.PaginationResult; + +@Service +public class CourseAttachmentDownloadLogServiceImpl + extends ServiceImpl + implements CourseAttachmentDownloadLogService { + @Override + public PaginationResult paginate( + int page, int size, CourseAttachmentDownloadLogPaginateFiler filter) { + filter.setPageStart((page - 1) * size); + filter.setPageSize(size); + + PaginationResult pageResult = new PaginationResult<>(); + pageResult.setData(getBaseMapper().paginate(filter)); + pageResult.setTotal(getBaseMapper().paginateCount(filter)); + + return pageResult; + } +} diff --git a/src/main/java/xyz/playedu/api/service/impl/ResourceServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/ResourceServiceImpl.java index b55d85b..5d64d85 100644 --- a/src/main/java/xyz/playedu/api/service/impl/ResourceServiceImpl.java +++ b/src/main/java/xyz/playedu/api/service/impl/ResourceServiceImpl.java @@ -60,6 +60,11 @@ public class ResourceServiceImpl extends ServiceImpl return pageResult; } + @Override + public List paginateType(ResourcePaginateFilter filter) { + return getBaseMapper().paginateType(filter); + } + @Override @Transactional public Resource create( diff --git a/src/main/java/xyz/playedu/api/service/impl/internal/CourseAttachmentServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/internal/CourseAttachmentServiceImpl.java new file mode 100644 index 0000000..01be726 --- /dev/null +++ b/src/main/java/xyz/playedu/api/service/impl/internal/CourseAttachmentServiceImpl.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.service.impl.internal; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import org.springframework.stereotype.Service; + +import xyz.playedu.api.domain.CourseAttachment; +import xyz.playedu.api.exception.NotFoundException; +import xyz.playedu.api.mapper.CourseAttachmentMapper; +import xyz.playedu.api.service.CourseAttachmentService; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@Service +public class CourseAttachmentServiceImpl + extends ServiceImpl + implements CourseAttachmentService { + + @Override + public CourseAttachment findOrFail(Integer id, Integer courseId) throws NotFoundException { + CourseAttachment attachment = + getOne(query().getWrapper().eq("id", id).eq("course_id", courseId)); + if (attachment == null) { + throw new NotFoundException("附件不存在"); + } + return attachment; + } + + @Override + public void update(CourseAttachment courseAttachment, Integer sort, String title) { + CourseAttachment attachment = new CourseAttachment(); + attachment.setId(courseAttachment.getId()); + attachment.setSort(sort); + attachment.setTitle(title); + + updateById(attachment); + } + + @Override + public List getAttachmentsByCourseId(Integer courseId) { + return list(query().getWrapper().eq("course_id", courseId).orderByAsc("sort")); + } + + @Override + public CourseAttachment create( + Integer courseId, Integer sort, String title, String type, Integer rid) { + CourseAttachment attachment = new CourseAttachment(); + attachment.setCourseId(courseId); + attachment.setSort(sort); + attachment.setTitle(title); + attachment.setType(type); + attachment.setRid(rid); + attachment.setCreatedAt(new Date()); + + save(attachment); + + return attachment; + } + + @Override + public Integer getCountByCourseId(Integer courseId) { + return Math.toIntExact(count(query().getWrapper().eq("course_id", courseId))); + } + + @Override + public void remove(Integer courseId) { + remove(query().getWrapper().eq("course_id", courseId)); + } + + @Override + public void updateSort(List ids, Integer cid) { + if (ids == null || ids.size() == 0) { + return; + } + List attachments = new ArrayList<>(); + final Integer[] sortVal = {0}; + for (Integer idVal : ids) { + attachments.add( + new CourseAttachment() { + { + setId(idVal); + setCourseId(cid); + setSort(sortVal[0]++); + } + }); + } + updateBatchById(attachments); + } + + @Override + public List getRidsByCourseId(Integer courseId) { + return list(query().getWrapper().eq("course_id", courseId)).stream() + .map(CourseAttachment::getRid) + .toList(); + } + + @Override + public List chunk(List attachmentIds) { + if (attachmentIds == null || attachmentIds.size() == 0) { + return new ArrayList<>(); + } + return list(query().getWrapper().in("id", attachmentIds)); + } +} diff --git a/src/main/java/xyz/playedu/api/types/paginate/AdminLogPaginateFiler.java b/src/main/java/xyz/playedu/api/types/paginate/AdminLogPaginateFiler.java new file mode 100644 index 0000000..bcda5ea --- /dev/null +++ b/src/main/java/xyz/playedu/api/types/paginate/AdminLogPaginateFiler.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.types.paginate; + +import lombok.Data; + +@Data +public class AdminLogPaginateFiler { + + private Integer adminId; + + private String module; + + private String title; + + private Integer opt; + + private String startTime; + + private String endTime; + + private String sortField; + + private String sortAlgo; + + private Integer pageStart; + + private Integer pageSize; +} diff --git a/src/main/java/xyz/playedu/api/types/paginate/CourseAttachmentDownloadLogPaginateFiler.java b/src/main/java/xyz/playedu/api/types/paginate/CourseAttachmentDownloadLogPaginateFiler.java new file mode 100644 index 0000000..093448d --- /dev/null +++ b/src/main/java/xyz/playedu/api/types/paginate/CourseAttachmentDownloadLogPaginateFiler.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2023 杭州白书科技有限公司 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package xyz.playedu.api.types.paginate; + +import lombok.Data; + +@Data +public class CourseAttachmentDownloadLogPaginateFiler { + + private Integer userId; + + private Integer courseId; + + private String title; + + private Integer courserAttachmentId; + + private Integer rid; + + private String sortField; + + private String sortAlgo; + + private Integer pageStart; + + private Integer pageSize; +} diff --git a/src/main/java/xyz/playedu/api/util/StringUtil.java b/src/main/java/xyz/playedu/api/util/StringUtil.java index 7afa0e5..f09603d 100644 --- a/src/main/java/xyz/playedu/api/util/StringUtil.java +++ b/src/main/java/xyz/playedu/api/util/StringUtil.java @@ -15,6 +15,8 @@ */ package xyz.playedu.api.util; +import cn.hutool.json.JSONUtil; + import org.springframework.util.AntPathMatcher; import java.util.*; @@ -527,4 +529,20 @@ public class StringUtil extends org.apache.commons.lang3.StringUtils { sbuf.append(strPattern, handledPosition, strPattern.length()); return sbuf.toString(); } + + public static String arrayToString(Object[] array) { + StringBuilder result = new StringBuilder(); + if (array != null && array.length > 0) { + for (Object o : array) { + if (StringUtil.isNotNull(o)) { + try { + Object jsonObj = JSONUtil.toJsonStr(o); + result.append(jsonObj.toString()); + } catch (Exception e) { + } + } + } + } + return result.toString(); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 4b3e265..b59b660 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -69,4 +69,4 @@ playedu: testing: false limiter: duration: 60 - limit: 240 + limit: 360 diff --git a/src/main/resources/mapper/AdminLogMapper.xml b/src/main/resources/mapper/AdminLogMapper.xml index 7cb1348..4f301e1 100644 --- a/src/main/resources/mapper/AdminLogMapper.xml +++ b/src/main/resources/mapper/AdminLogMapper.xml @@ -8,16 +8,94 @@ - - + + + + + + + + - id,admin_id,module, - opt,remark,ip, - ip_area,created_at + id,admin_id,module,title, + opt,method,request_method,url,param,result, + ip,ip_area,error_msg,created_at + + + + diff --git a/src/main/resources/mapper/CourseAttachmentDownloadLogMapper.xml b/src/main/resources/mapper/CourseAttachmentDownloadLogMapper.xml new file mode 100644 index 0000000..2bb841a --- /dev/null +++ b/src/main/resources/mapper/CourseAttachmentDownloadLogMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + id,user_id,course_id,title, + courser_attachment_id,rid, + ip,created_at + + + + + + diff --git a/src/main/resources/mapper/CourseAttachmentMapper.xml b/src/main/resources/mapper/CourseAttachmentMapper.xml new file mode 100644 index 0000000..77065cd --- /dev/null +++ b/src/main/resources/mapper/CourseAttachmentMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + id,course_id, + sort,title,type, + rid,created_at + + diff --git a/src/main/resources/mapper/ResourceMapper.xml b/src/main/resources/mapper/ResourceMapper.xml index f5db0d9..77d0df5 100644 --- a/src/main/resources/mapper/ResourceMapper.xml +++ b/src/main/resources/mapper/ResourceMapper.xml @@ -61,7 +61,10 @@ AND `resources`.`extension` = #{extension} - AND `resources`.`type` = #{type} + AND `resources`.`type` IN + + #{item} + AND `resources`.`admin_id` = #{adminId} @@ -127,7 +130,52 @@ AND `resources`.`extension` = #{extension} - AND `resources`.`type` = #{type} + AND `resources`.`type` IN + + #{item} + + + + AND `resources`.`admin_id` = #{adminId} + + + +