diff --git a/app/api/playedu-ai/src/main/java/xyz/playedu/ai/config/AIPlatformConfig.java b/app/api/playedu-ai/src/main/java/xyz/playedu/ai/config/AIPlatformConfig.java index 82cb4b2..91b31d1 100644 --- a/app/api/playedu-ai/src/main/java/xyz/playedu/ai/config/AIPlatformConfig.java +++ b/app/api/playedu-ai/src/main/java/xyz/playedu/ai/config/AIPlatformConfig.java @@ -12,4 +12,5 @@ import org.springframework.stereotype.Component; public class AIPlatformConfig { private String host; private String api_key; + private String profile; } diff --git a/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/jc/KnowledgeController.java b/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/jc/KnowledgeController.java index 345a7e9..3b5c2c3 100644 --- a/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/jc/KnowledgeController.java +++ b/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/jc/KnowledgeController.java @@ -1,5 +1,6 @@ package xyz.playedu.api.controller.backend.jc; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import xyz.playedu.common.annotation.Log; @@ -7,6 +8,7 @@ import xyz.playedu.common.constant.BusinessTypeConstant; import xyz.playedu.common.types.JsonResponse; import xyz.playedu.common.types.paginate.PaginationResult; import xyz.playedu.jc.domain.Knowledge; +import xyz.playedu.jc.param.KnowledgeParam; import xyz.playedu.jc.service.IKnowledgeService; import java.util.HashMap; @@ -22,48 +24,52 @@ public class KnowledgeController { @Autowired private IKnowledgeService knowledgeService; - /** 分页列表 */ - @GetMapping("/index") - public JsonResponse index(@RequestParam HashMap params) { - PaginationResult result = knowledgeService.paginate(params); - return JsonResponse.data(result); + + /** + * 获取知识点卡片列表 + */ + @GetMapping("/list") + public JsonResponse list(KnowledgeParam param) { + List list = knowledgeService.listVo(param); + return JsonResponse.data(list); } - /** 全量列表 */ - @GetMapping("/list") - public JsonResponse list() { - List list = knowledgeService.list(); + + + + /** + * 获取知识点树结构 + */ + @GetMapping("/treeList") + public JsonResponse treeList(KnowledgeParam param) { + List list = knowledgeService.treeList(param); return JsonResponse.data(list); } /** 详情 */ @GetMapping("/{id}") public JsonResponse detail(@PathVariable("id") Integer id) { - Knowledge one = knowledgeService.getById(id); - return JsonResponse.data(one); + return JsonResponse.data( knowledgeService.getByIdVo(id)); } /** 新增 */ @Log(title = "新增知识点", businessType = BusinessTypeConstant.INSERT) - @PostMapping - public JsonResponse store(@RequestBody Knowledge knowledge) { - knowledgeService.save(knowledge); + @PostMapping("/saveOrUpdateVo") + public JsonResponse saveOrUpdateVo(@RequestBody Knowledge knowledge) { + knowledgeService.saveOrUpdateVo(knowledge); return JsonResponse.success(); } - /** 修改 */ - @Log(title = "修改知识点", businessType = BusinessTypeConstant.UPDATE) - @PutMapping - public JsonResponse update(@RequestBody Knowledge knowledge) { - knowledgeService.updateById(knowledge); - return JsonResponse.success(); - } + /** 删除 */ @Log(title = "删除知识点", businessType = BusinessTypeConstant.DELETE) @DeleteMapping("/{id}") public JsonResponse destroy(@PathVariable("id") Integer id) { - knowledgeService.removeById(id); + Knowledge byId = knowledgeService.getById(id); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.likeRight(Knowledge::getKnowledgeCode, byId.getKnowledgeCode()); + knowledgeService.remove(queryWrapper); return JsonResponse.success(); } } diff --git a/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/system/LocalFileController.java b/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/system/LocalFileController.java new file mode 100644 index 0000000..31e7d28 --- /dev/null +++ b/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/system/LocalFileController.java @@ -0,0 +1,60 @@ +package xyz.playedu.api.controller.backend.system; + + +import com.alibaba.fastjson.JSONObject; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import xyz.playedu.common.config.PlatformConfig; +import xyz.playedu.common.config.ServerConfig; +import xyz.playedu.common.types.JsonResponse; +import xyz.playedu.common.util.FileUploadUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * 通用请求处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/common") +public class LocalFileController { + private static final Logger log = LoggerFactory.getLogger(LocalFileController.class); + private static final String FILE_DELIMETER = ","; + @Autowired + private ServerConfig serverConfig; + + /** + * 通用上传请求(单个) + */ + @PostMapping("/upload") + public JsonResponse uploadFile(MultipartFile file) throws Exception { + // 上传文件路径 + String filePath = PlatformConfig.getUploadPath(); + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + try { + String url = serverConfig.getUrl() + fileName; + JSONObject ajax = new JSONObject(); + ajax.put("url", url); + ajax.put("path", fileName); + ajax.put("newFileName", FileUploadUtils.getName(fileName)); + ajax.put("originalFilename", file.getOriginalFilename()); + return JsonResponse.data(ajax); + } catch (Exception e) { + return JsonResponse.error(e.getMessage()); + } + } + +} diff --git a/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/system/UploadController.java b/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/system/UploadController.java index 92a02aa..a5db20e 100644 --- a/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/system/UploadController.java +++ b/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/backend/system/UploadController.java @@ -54,6 +54,8 @@ public class UploadController { @Autowired private AppConfigService appConfigService; + + @PostMapping("/minio") @Log(title = "上传-MinIO", businessType = BusinessTypeConstant.UPLOAD) public JsonResponse uploadMinio( diff --git a/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/frontend/KnowledgeController.java b/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/frontend/KnowledgeController.java new file mode 100644 index 0000000..6871bdf --- /dev/null +++ b/app/api/playedu-api/src/main/java/xyz/playedu/api/controller/frontend/KnowledgeController.java @@ -0,0 +1,49 @@ +package xyz.playedu.api.controller.frontend; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import xyz.playedu.common.annotation.Log; +import xyz.playedu.common.constant.BusinessTypeConstant; +import xyz.playedu.common.types.JsonResponse; +import xyz.playedu.jc.domain.Knowledge; +import xyz.playedu.jc.param.KnowledgeParam; +import xyz.playedu.jc.service.IKnowledgeService; + +import java.util.List; + +/** + * 知识点管理 + */ +@RestController +@RequestMapping("/api/v1/jc/knowledge") +public class KnowledgeController { + + @Autowired + private IKnowledgeService knowledgeService; + + + /** + * 获取知识点卡片列表 + */ + @GetMapping("/list") + public JsonResponse list(KnowledgeParam param) { + List list = knowledgeService.listVo(param); + return JsonResponse.data(list); + } + + /** + * 获取知识点树结构 + */ + @GetMapping("/treeList") + public JsonResponse treeList(KnowledgeParam param) { + List list = knowledgeService.treeList(param); + return JsonResponse.data(list); + } + + /** 详情 */ + @GetMapping("/getDetail") + public JsonResponse detail(@RequestParam("id") Integer id) { + return JsonResponse.data( knowledgeService.stuGetByIdVo(id)); + } +} diff --git a/app/api/playedu-api/src/main/resources/application.yml b/app/api/playedu-api/src/main/resources/application.yml index 0c98465..6b1cf89 100644 --- a/app/api/playedu-api/src/main/resources/application.yml +++ b/app/api/playedu-api/src/main/resources/application.yml @@ -3,10 +3,14 @@ server: tomcat: max-swallow-size: 10000MB connection-timeout: 600000 + ai: platform: host: "http://localhost:9380/" api-key: "ragflow-VlZWVjMDg0ZjAzMTExZWZhZDhkZTU5ZD" +platform: + config: + profile: D:/ruoyi/uploadPath spring: profiles: active: kafka,quartz,dev diff --git a/app/api/playedu-common/src/main/java/xyz/playedu/common/config/PlatformConfig.java b/app/api/playedu-common/src/main/java/xyz/playedu/common/config/PlatformConfig.java new file mode 100644 index 0000000..dd0a2be --- /dev/null +++ b/app/api/playedu-common/src/main/java/xyz/playedu/common/config/PlatformConfig.java @@ -0,0 +1,50 @@ +package xyz.playedu.common.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + + +@Component +@ConfigurationProperties(prefix = "platform.config") +public class PlatformConfig { + + private static String profile; + + + public static String getProfile() { + return profile; + } + + + + public void setProfile(String profile) { + PlatformConfig.profile = profile; + } + /** + * 获取导入上传路径 + */ + public static String getImportPath() { + return getProfile() + "/import"; + } + + /** + * 获取头像上传路径 + */ + public static String getAvatarPath() { + return getProfile() + "/avatar"; + } + + /** + * 获取下载路径 + */ + public static String getDownloadPath() { + return getProfile() + "/download/"; + } + + /** + * 获取上传路径 + */ + public static String getUploadPath() { + return getProfile() + "/upload"; + } +} diff --git a/app/api/playedu-common/src/main/java/xyz/playedu/common/config/ServerConfig.java b/app/api/playedu-common/src/main/java/xyz/playedu/common/config/ServerConfig.java new file mode 100644 index 0000000..572f9ae --- /dev/null +++ b/app/api/playedu-common/src/main/java/xyz/playedu/common/config/ServerConfig.java @@ -0,0 +1,31 @@ +package xyz.playedu.common.config; + + +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Component; +import xyz.playedu.common.util.ServletUtils; + + +/** + * 服务相关配置 + * + * @author ruoyi + */ +@Component +public class ServerConfig { + public static String getDomain(HttpServletRequest request) { + StringBuffer url = request.getRequestURL(); + String contextPath = request.getServletContext().getContextPath(); + return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString(); + } + + /** + * 获取完整的请求路径,包括:域名,端口,上下文访问路径 + * + * @return 服务地址 + */ + public String getUrl() { + HttpServletRequest request = ServletUtils.getRequest(); + return getDomain(request); + } +} diff --git a/app/api/playedu-common/src/main/java/xyz/playedu/common/util/FileUploadUtils.java b/app/api/playedu-common/src/main/java/xyz/playedu/common/util/FileUploadUtils.java new file mode 100644 index 0000000..3e37e51 --- /dev/null +++ b/app/api/playedu-common/src/main/java/xyz/playedu/common/util/FileUploadUtils.java @@ -0,0 +1,171 @@ +package xyz.playedu.common.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Objects; + +import org.apache.commons.io.FilenameUtils; + +import org.springframework.web.multipart.MultipartFile; +import xyz.playedu.common.config.PlatformConfig; + + +/** + * 文件上传工具类 + * + * @author ruoyi + */ +public class FileUploadUtils { + /** + * 默认大小 50M + */ + public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L; + + /** + * 默认的文件名最大长度 100 + */ + public static final int DEFAULT_FILE_NAME_LENGTH = 100; + + /** + * 默认上传的地址 + */ + private static String defaultBaseDir = PlatformConfig.getProfile(); + public static final String RESOURCE_PREFIX = "/profile"; + + public static String getDefaultBaseDir() { + return defaultBaseDir; + } + + public static void setDefaultBaseDir(String defaultBaseDir) { + FileUploadUtils.defaultBaseDir = defaultBaseDir; + } + + /** + * 以默认配置进行文件上传 + * + * @param file 上传的文件 + * @return 文件名称 + * @throws Exception + */ + public static final String upload(MultipartFile file) throws IOException { + try { + return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 根据文件路径上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @return 文件名称 + * @throws IOException + */ + public static final String upload(String baseDir, MultipartFile file) throws IOException { + try { + return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + } catch (Exception e) { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 文件上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @param allowedExtension 上传文件类型 + * @return 返回上传成功的文件名 + * @throws IOException 比如读写文件出错时 + */ + public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) + throws Exception { + int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length(); + if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) { + throw new Exception("文件名过长"+FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); + } + + + String fileName = extractFilename(file); + + String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath(); + file.transferTo(Paths.get(absPath)); + return getPathFileName(baseDir, fileName); + } + + /** + * 编码文件名 + */ + public static final String extractFilename(MultipartFile file) { + return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), + FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file)); + } + + public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException { + File desc = new File(uploadDir + File.separator + fileName); + + if (!desc.exists()) { + if (!desc.getParentFile().exists()) { + desc.getParentFile().mkdirs(); + } + } + return desc; + } + + public static final String getPathFileName(String uploadDir, String fileName) throws IOException { + int dirLastIndex = PlatformConfig.getProfile().length() + 1; + String currentDir = StringUtils.substring(uploadDir, dirLastIndex); + return RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; + } + + + /** + * 判断MIME类型是否是允许的MIME类型 + * + * @param extension + * @param allowedExtension + * @return + */ + public static final boolean isAllowedExtension(String extension, String[] allowedExtension) { + for (String str : allowedExtension) { + if (str.equalsIgnoreCase(extension)) { + return true; + } + } + return false; + } + + /** + * 获取文件名的后缀 + * + * @param file 表单文件 + * @return 后缀名 + */ + public static final String getExtension(MultipartFile file) { + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + if (StringUtils.isEmpty(extension)) { + extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType())); + } + return extension; + } + + + /** + * 获取文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png + * + * @param fileName 路径名称 + * @return 没有文件路径的名称 + */ + public static String getName(String fileName) { + if (fileName == null) { + return null; + } + int lastUnixPos = fileName.lastIndexOf('/'); + int lastWindowsPos = fileName.lastIndexOf('\\'); + int index = Math.max(lastUnixPos, lastWindowsPos); + return fileName.substring(index + 1); + } +} diff --git a/app/api/playedu-common/src/main/java/xyz/playedu/common/util/MimeTypeUtils.java b/app/api/playedu-common/src/main/java/xyz/playedu/common/util/MimeTypeUtils.java new file mode 100644 index 0000000..86fe8ad --- /dev/null +++ b/app/api/playedu-common/src/main/java/xyz/playedu/common/util/MimeTypeUtils.java @@ -0,0 +1,56 @@ +package xyz.playedu.common.util; + +/** + * 媒体类型工具类 + * + * @author ruoyi + */ +public class MimeTypeUtils { + public static final String IMAGE_PNG = "image/png"; + + public static final String IMAGE_JPG = "image/jpg"; + + public static final String IMAGE_JPEG = "image/jpeg"; + + public static final String IMAGE_BMP = "image/bmp"; + + public static final String IMAGE_GIF = "image/gif"; + + public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"}; + + public static final String[] FLASH_EXTENSION = {"swf", "flv"}; + + public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", + "asf", "rm", "rmvb"}; + + public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"}; + + public static final String[] DEFAULT_ALLOWED_EXTENSION = { + // 图片 + "bmp", "gif", "jpg", "jpeg", "png", + // word excel powerpoint + "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", + // 压缩文件 + "rar", "zip", "gz", "bz2", + // 视频格式 + "mp4", "avi", "rmvb", + // pdf + "pdf"}; + + public static String getExtension(String prefix) { + switch (prefix) { + case IMAGE_PNG: + return "png"; + case IMAGE_JPG: + return "jpg"; + case IMAGE_JPEG: + return "jpeg"; + case IMAGE_BMP: + return "bmp"; + case IMAGE_GIF: + return "gif"; + default: + return ""; + } + } +} diff --git a/app/api/playedu-common/src/main/java/xyz/playedu/common/util/Seq.java b/app/api/playedu-common/src/main/java/xyz/playedu/common/util/Seq.java new file mode 100644 index 0000000..a10eb2a --- /dev/null +++ b/app/api/playedu-common/src/main/java/xyz/playedu/common/util/Seq.java @@ -0,0 +1,76 @@ +package xyz.playedu.common.util; + +import cn.hutool.core.date.DateUtil; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author ruoyi 序列生成类 + */ +public class Seq { + // 通用序列类型 + public static final String commSeqType = "COMMON"; + + // 上传序列类型 + public static final String uploadSeqType = "UPLOAD"; + // 机器标识 + private static final String machineCode = "A"; + // 通用接口序列数 + private static AtomicInteger commSeq = new AtomicInteger(1); + // 上传接口序列数 + private static AtomicInteger uploadSeq = new AtomicInteger(1); + + /** + * 获取通用序列号 + * + * @return 序列值 + */ + public static String getId() { + return getId(commSeqType); + } + + /** + * 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串 + * + * @return 序列值 + */ + public static String getId(String type) { + AtomicInteger atomicInt = commSeq; + if (uploadSeqType.equals(type)) { + atomicInt = uploadSeq; + } + return getId(atomicInt, 3); + } + + /** + * 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串 + * + * @param atomicInt 序列数 + * @param length 数值长度 + * @return 序列值 + */ + public static String getId(AtomicInteger atomicInt, int length) { + String result = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss"); + result += machineCode; + result += getSeq(atomicInt, length); + return result; + } + + /** + * 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数 + * + * @return 序列值 + */ + private synchronized static String getSeq(AtomicInteger atomicInt, int length) { + // 先取值再+1 + int value = atomicInt.getAndIncrement(); + + // 如果更新后值>=10 的 (length)幂次方则重置为1 + int maxSeq = (int) Math.pow(10, length); + if (atomicInt.get() >= maxSeq) { + atomicInt.set(1); + } + // 转字符串,用0左补齐 + return StringUtils.padl(value, length); + } +} diff --git a/app/api/playedu-common/src/main/java/xyz/playedu/common/util/ServletUtils.java b/app/api/playedu-common/src/main/java/xyz/playedu/common/util/ServletUtils.java new file mode 100644 index 0000000..8a6ac4a --- /dev/null +++ b/app/api/playedu-common/src/main/java/xyz/playedu/common/util/ServletUtils.java @@ -0,0 +1,72 @@ +package xyz.playedu.common.util; + + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * 客户端工具类 + * + * @author ruoyi + */ +public class ServletUtils { + + + + /** + * 获取request + */ + public static HttpServletRequest getRequest() { + return getRequestAttributes().getRequest(); + } + + /** + * 获取response + */ + public static HttpServletResponse getResponse() { + return getRequestAttributes().getResponse(); + } + + /** + * 获取session + */ + public static HttpSession getSession() { + return getRequest().getSession(); + } + + public static ServletRequestAttributes getRequestAttributes() { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + + /** + * 将字符串渲染到客户端 + * + * @param response 渲染对象 + * @param string 待渲染的字符串 + */ + public static void renderString(HttpServletResponse response, String string) { + try { + response.setStatus(200); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().print(string); + } catch (IOException e) { + e.printStackTrace(); + } + } + + +} diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookChapter.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookChapter.java index c16ec2c..db12941 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookChapter.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookChapter.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import xyz.playedu.framework.tenant.core.db.TenantBaseDO; import java.util.Date; @@ -14,7 +15,7 @@ import java.util.Date; */ @Data @TableName("jc_book_chapter") -public class BookChapter { +public class BookChapter extends TenantBaseDO { @TableId(type = IdType.AUTO) private Integer id; @@ -34,23 +35,11 @@ public class BookChapter { /** 章节名 */ @TableField("name") private String name; + /** 层级 */ + private Integer level; /** 排序 */ @TableField("sort") private Integer sort; - @TableField("create_time") - private Date createTime; - - @TableField("update_time") - private Date updateTime; - - @TableField("creator") - private String creator; - - @TableField("updater") - private String updater; - - @TableField("tenant_id") - private String tenantId; -} \ No newline at end of file +} diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookDepartmentUser.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookDepartmentUser.java index e387e4a..84f1272 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookDepartmentUser.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookDepartmentUser.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import xyz.playedu.framework.tenant.core.db.TenantBaseDO; import java.util.Date; @@ -14,7 +15,7 @@ import java.util.Date; */ @Data @TableName("jc_book_department_user") -public class BookDepartmentUser { +public class BookDepartmentUser extends TenantBaseDO { /** 教材ID */ @TableField("book_id") @@ -28,18 +29,4 @@ public class BookDepartmentUser { @TableField("type") private Integer type; - @TableField("creator") - private String creator; - - @TableField("updater") - private String updater; - - @TableField("create_time") - private Date createTime; - - @TableField("update_time") - private Date updateTime; - - @TableField("tenant_id") - private String tenantId; -} \ No newline at end of file +} diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookPaper.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookPaper.java index 001e75d..7ecd39e 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookPaper.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/BookPaper.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import xyz.playedu.framework.tenant.core.db.TenantBaseDO; import java.util.Date; @@ -14,7 +15,7 @@ import java.util.Date; */ @Data @TableName("jc_book_paper") -public class BookPaper { +public class BookPaper extends TenantBaseDO { @TableId(type = IdType.AUTO) private Integer id; @@ -32,18 +33,4 @@ public class BookPaper { @TableField("extra") private String extra; - @TableField("creator") - private String creator; - - @TableField("updater") - private String updater; - - @TableField("create_time") - private Date createTime; - - @TableField("update_time") - private Date updateTime; - - @TableField("tenant_id") - private String tenantId; -} \ No newline at end of file +} diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/ChapterContent.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/ChapterContent.java index 96205e8..f812867 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/ChapterContent.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/ChapterContent.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import xyz.playedu.framework.tenant.core.db.TenantBaseDO; import java.util.Date; @@ -15,7 +16,7 @@ import java.util.Date; */ @Data @TableName("jc_chapter_content") -public class ChapterContent { +public class ChapterContent extends TenantBaseDO { @TableId(type = IdType.AUTO) private Integer id; @@ -34,28 +35,9 @@ public class ChapterContent { @TableField("type") private String type; -// /** 关联资源ID(逗号分隔) */ -// @TableField("resource_ids") -// private String resourceIds; -// -// /** 关联知识点ID(逗号分隔) */ -// @TableField("knowledge_ids") -// private String knowledgeIds; + private String knowledgeCode; - /** 创建人 */ - @TableField("creator") - private String creator; - - /** 更新人 */ - @TableField("updater") - private String updater; - - @TableField("create_time") - private Date createTime; - - @TableField("update_time") - private Date updateTime; - - @TableField("tenant_id") - private String tenantId; -} \ No newline at end of file + /** 章节名称 */ + @TableField(exist = false) + private String chapterName; +} diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Discussion.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Discussion.java index 2f5a3dc..eef06c6 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Discussion.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Discussion.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import xyz.playedu.framework.tenant.core.db.TenantBaseDO; import java.util.Date; @@ -14,7 +15,7 @@ import java.util.Date; */ @Data @TableName("jc_discussion") -public class Discussion { +public class Discussion extends TenantBaseDO { @TableId(type = IdType.AUTO) private Integer id; @@ -51,20 +52,12 @@ public class Discussion { @TableField("status") private Integer status; - /** 创建人(可以是用户名) */ - @TableField("creator") - private String creator; + /** 知识点编码 */ + @TableField(exist = false) + private String knowledgeCode; + @TableField(exist = false) + private String chapterName; + @TableField(exist = false) + private String orderType; - /** 更新人 */ - @TableField("updater") - private String updater; - - @TableField("create_time") - private Date createTime; - - @TableField("update_time") - private Date updateTime; - - @TableField("tenant_id") - private String tenantId; } diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/DiscussionDetail.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/DiscussionDetail.java index 804198a..0449158 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/DiscussionDetail.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/DiscussionDetail.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import xyz.playedu.framework.tenant.core.db.TenantBaseDO; import java.util.Date; @@ -14,7 +15,7 @@ import java.util.Date; */ @Data @TableName("jc_discussion_detail") -public class DiscussionDetail { +public class DiscussionDetail extends TenantBaseDO { @TableId(type = IdType.AUTO) private Integer id; @@ -46,19 +47,4 @@ public class DiscussionDetail { /** 讨论内容 */ @TableField("content") private String content; - - @TableField("create_time") - private Date createTime; - - @TableField("update_time") - private Date updateTime; - - @TableField("creator") - private String creator; - - @TableField("updater") - private String updater; - - @TableField("tenant_id") - private String tenantId; } diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/JCResource.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/JCResource.java index 938c58b..1db3b6e 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/JCResource.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/JCResource.java @@ -31,8 +31,8 @@ public class JCResource { @TableField("name") private String name; - @TableField("konwledge_code") - private String konwledgeCode; + @TableField("knowledge_code") + private String knowledgeCode; /** 文本描述 AI分析或自动填入 */ @@ -75,4 +75,4 @@ public class JCResource { @TableField("tenant_id") private String tenantId; -} \ No newline at end of file +} diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Knowledge.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Knowledge.java index 50f4d89..eb5214a 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Knowledge.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Knowledge.java @@ -5,8 +5,10 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import xyz.playedu.framework.tenant.core.db.TenantBaseDO; import java.util.Date; +import java.util.List; /** * 知识点表 @@ -14,7 +16,7 @@ import java.util.Date; */ @Data @TableName("jc_knowledge") -public class Knowledge { +public class Knowledge extends TenantBaseDO { @TableId(type = IdType.AUTO) private Integer id; @@ -31,9 +33,9 @@ public class Knowledge { @TableField("name") private String name; - /** 知识点code(字段名拼写为 konwledge_code) */ - @TableField("konwledge_code") - private String konwledgeCode; + /** 知识点code(字段名拼写为 knowledge_code) */ + @TableField("knowledge_code") + private String knowledgeCode; /** 知识点介绍 */ @TableField("desc") @@ -41,11 +43,14 @@ public class Knowledge { /** 层级 */ @TableField("level") - private String level; + private Integer level; /** 知识点类型 */ @TableField("type") private String type; + /** 是否是真实知识点 */ + @TableField("is_real") + private String isReal; /** 当前层级排序 */ @TableField("order_num") @@ -54,19 +59,7 @@ public class Knowledge { /** 预留JSON */ @TableField("extra_json") private String extraJson; - - @TableField("create_time") - private Date createTime; - - @TableField("update_time") - private Date updateTime; - - @TableField("creator") - private String creator; - - @TableField("updater") - private String updater; - - @TableField("tenant_id") - private String tenantId; + //子节点 + @TableField(exist = false) + private List children; } diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Note.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Note.java index e445c2b..34a883d 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Note.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Note.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import xyz.playedu.framework.tenant.core.db.TenantBaseDO; import java.util.Date; @@ -14,7 +15,7 @@ import java.util.Date; */ @Data @TableName("jc_note") -public class Note { +public class Note extends TenantBaseDO { @TableId(type = IdType.AUTO) private Integer id; @@ -50,19 +51,11 @@ public class Note { /** 存储笔记信息的JSON(位置信息等) */ @TableField("extra_json") private String extraJson; - - @TableField("create_time") - private Date createTime; - - @TableField("update_time") - private Date updateTime; - - @TableField("creator") - private String creator; - - @TableField("updater") - private String updater; - - @TableField("tenant_id") - private String tenantId; + /** 知识点编码 */ + @TableField(exist = false) + private String knowledgeCode; + @TableField(exist = false) + private String chapterName; + @TableField(exist = false) + private String orderType; } diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Textbook.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Textbook.java index d4ce03b..1fc97aa 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Textbook.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/domain/Textbook.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import xyz.playedu.framework.tenant.core.db.TenantBaseDO; import java.util.Date; @@ -14,7 +15,7 @@ import java.util.Date; */ @Data @TableName("jc_textbook") -public class Textbook { +public class Textbook extends TenantBaseDO { @TableId(type = IdType.AUTO) private Integer id; @@ -54,20 +55,4 @@ public class Textbook { @TableField("publish_time") private Date publishTime; - /** 创建人 */ - @TableField("creator") - private String creator; - - /** 更新人 */ - @TableField("updater") - private String updater; - - @TableField("create_time") - private Date createTime; - - @TableField("update_time") - private Date updateTime; - - @TableField("tenant_id") - private String tenantId; -} \ No newline at end of file +} diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/mapper/DiscussionMapper.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/mapper/DiscussionMapper.java index 61d47b1..35df955 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/mapper/DiscussionMapper.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/mapper/DiscussionMapper.java @@ -1,10 +1,15 @@ package xyz.playedu.jc.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; import xyz.playedu.jc.domain.Discussion; +import xyz.playedu.jc.domain.Note; + +import java.util.List; /** * 讨论 Mapper */ public interface DiscussionMapper extends BaseMapper { + List listVo(@Param("param") Discussion note); } diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/mapper/NoteMapper.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/mapper/NoteMapper.java index f7b8781..01a3814 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/mapper/NoteMapper.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/mapper/NoteMapper.java @@ -1,10 +1,14 @@ package xyz.playedu.jc.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; import xyz.playedu.jc.domain.Note; +import java.util.List; + /** * 笔记 Mapper */ public interface NoteMapper extends BaseMapper { + List listVo(@Param("param") Note note); } diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/param/KnowledgeParam.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/param/KnowledgeParam.java new file mode 100644 index 0000000..ba6d923 --- /dev/null +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/param/KnowledgeParam.java @@ -0,0 +1,13 @@ +package xyz.playedu.jc.param; + +import lombok.Data; + +@Data +public class KnowledgeParam { + //书本id + private Integer bookId; + //知识点名称 + private String name; + //知识点code + private String knowledgeCode; +} diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/service/IKnowledgeService.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/service/IKnowledgeService.java index c1d9430..dbf4149 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/service/IKnowledgeService.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/service/IKnowledgeService.java @@ -1,15 +1,24 @@ package xyz.playedu.jc.service; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.service.IService; import xyz.playedu.common.types.paginate.PaginationResult; import xyz.playedu.jc.domain.Knowledge; +import xyz.playedu.jc.param.KnowledgeParam; import java.util.HashMap; +import java.util.List; /** * 知识点 Service */ public interface IKnowledgeService extends IService { + List listVo(KnowledgeParam param); + + List treeList(KnowledgeParam param); + void saveOrUpdateVo(Knowledge data); + JSONObject getByIdVo(Integer id); + JSONObject stuGetByIdVo(Integer id); + - PaginationResult paginate(HashMap params); } diff --git a/app/api/playedu-course/src/main/java/xyz/playedu/jc/service/impl/KnowledgeServiceImpl.java b/app/api/playedu-course/src/main/java/xyz/playedu/jc/service/impl/KnowledgeServiceImpl.java index 77cc5cd..3c39430 100644 --- a/app/api/playedu-course/src/main/java/xyz/playedu/jc/service/impl/KnowledgeServiceImpl.java +++ b/app/api/playedu-course/src/main/java/xyz/playedu/jc/service/impl/KnowledgeServiceImpl.java @@ -1,75 +1,255 @@ package xyz.playedu.jc.service.impl; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.MapUtils; +import org.checkerframework.checker.units.qual.A; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import xyz.playedu.common.context.FCtx; +import xyz.playedu.common.domain.User; import xyz.playedu.common.types.paginate.PaginationResult; -import xyz.playedu.jc.domain.Knowledge; -import xyz.playedu.jc.mapper.KnowledgeMapper; +import xyz.playedu.jc.domain.*; +import xyz.playedu.jc.mapper.*; +import xyz.playedu.jc.param.KnowledgeParam; import xyz.playedu.jc.service.IKnowledgeService; +import xyz.playedu.jc.service.ITextbookService; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; /** * 知识点 Service 实现 */ @Slf4j @Service -public class KnowledgeServiceImpl - extends ServiceImpl - implements IKnowledgeService { +public class KnowledgeServiceImpl extends ServiceImpl implements IKnowledgeService { + @Autowired + private ChapterContentMapper contentMapper; + @Autowired + private JCResourceMapper resourceMapper; + @Autowired + private BookChapterMapper chapterMapper; + @Autowired + private NoteMapper noteMapper; + @Autowired + private DiscussionMapper discussionMapper; + + @Override - public PaginationResult paginate(HashMap params) { - try { - Integer page = MapUtils.getInteger(params, "page", 1); - Integer size = MapUtils.getInteger(params, "size", 10); + public List listVo(KnowledgeParam param) { + //获取知识点卡片 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Knowledge::getBookId, param.getBookId()) + .eq(Knowledge::getIsReal,"1").orderByAsc(Knowledge::getOrderNum); + return list(queryWrapper); + } + @Override + public JSONObject getByIdVo(Integer id) { + JSONObject res = new JSONObject(); + Knowledge knowledge = this.getById(id); + res.put("knowledge", knowledge); + //获取各个板块该知识点下的资源 + LambdaQueryWrapper contentWrapper = new LambdaQueryWrapper<>(); + contentWrapper.select(ChapterContent::getId,ChapterContent::getChapterId).like(ChapterContent::getKnowledgeCode, knowledge.getKnowledgeCode()).eq(ChapterContent::getBookId, knowledge.getBookId()); + List contents = contentMapper.selectList(contentWrapper); + for (ChapterContent content : contents) { + BookChapter bookChapter = chapterMapper.selectById(content.getChapterId()); + content.setChapterName(bookChapter.getName()); + } + res.put("contents", contents); + LambdaQueryWrapper resourceWrapper = new LambdaQueryWrapper<>(); + resourceWrapper.like(JCResource::getKnowledgeCode, knowledge.getKnowledgeCode()).eq(JCResource::getBookId, knowledge.getBookId()); + res.put("resources", resourceMapper.selectList(resourceWrapper)); + return res; + } - Page pageParam = new Page<>(page, size); - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + @Override + public JSONObject stuGetByIdVo(Integer id) { + Knowledge knowledge = this.getById(id); + //获取当前学生信息 + User user = FCtx.getUser(); + JSONObject res = this.getByIdVo(id); + //获取笔记信息 + Note param = new Note(); + param.setBookId(knowledge.getBookId()); + param.setKnowledgeCode(knowledge.getKnowledgeCode()); + param.setUserId(user.getId()); + List notes = noteMapper.listVo(param); + res.put("notes", notes); + //获取讨论信息 + Discussion discussion = new Discussion(); + discussion.setBookId(knowledge.getBookId()); + discussion.setKnowledgeCode(knowledge.getKnowledgeCode()); + discussion.setUserId(user.getId()); + List discussions = discussionMapper.listVo(discussion); + res.put("discussions", discussions); + return res; + } - Integer bookId = MapUtils.getInteger(params, "bookId"); - if (bookId != null) { - queryWrapper.eq(Knowledge::getBookId, bookId); - } + @Override + public List treeList(KnowledgeParam param) { + //获取全部知识点 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Knowledge::getBookId, param.getBookId()).orderByAsc(Knowledge::getOrderNum); + List allKnowledges = this.list(queryWrapper); + // 处理为树结构 + return buildTree(allKnowledges); + } - Integer parentId = MapUtils.getInteger(params, "parentId"); - if (parentId != null) { - queryWrapper.eq(Knowledge::getParentId, parentId); - } - - String name = MapUtils.getString(params, "name"); - if (name != null && !name.isEmpty()) { - queryWrapper.like(Knowledge::getName, name); - } - - queryWrapper.orderByAsc(Knowledge::getOrderNum); - - IPage pageResult = this.page(pageParam, queryWrapper); - - Long total = pageResult.getTotal(); - PaginationResult result = new PaginationResult<>(); - result.setData(pageResult.getRecords()); - result.setTotal(total); - result.setCurrent(page); - result.setSize(size); - result.setPages((total + size - 1) / size); - - return result; - } catch (Exception e) { - log.error("分页查询知识点失败,参数:{}", params, e); - PaginationResult emptyResult = new PaginationResult<>(); - emptyResult.setData(new ArrayList<>()); - emptyResult.setTotal(0L); - emptyResult.setCurrent(MapUtils.getInteger(params, "page", 1)); - emptyResult.setSize(MapUtils.getInteger(params, "size", 10)); - emptyResult.setPages(0L); - return emptyResult; + @Override + public void saveOrUpdateVo(Knowledge data) { + if (ObjectUtil.isEmpty(data.getId())){ + Knowledge knowledge = this.getById(data.getId()); + knowledge.setDesc(data.getDesc()); + knowledge.setName(data.getName()); + knowledge.setType(data.getType()); + this.updateById(knowledge); + return; + } + if (ObjectUtil.isNotEmpty(data.getParentId())||data.getParentId()==0){ + data.setLevel(1); + data.setKnowledgeCode(generateKnowledgeCode(data.getParentId())); + this.save(data); + }else { + Knowledge byId = this.getById(data.getParentId()); + data.setLevel(byId.getLevel()+1); + data.setKnowledgeCode(generateKnowledgeCode(data.getParentId())); + this.save(data); } } + + + + private List buildTree(List knowledges) { + // 创建一个map来存储id到对象的映射,方便快速查找 + HashMap knowledgeMap = new HashMap<>(); + for (Knowledge knowledge : knowledges) { + knowledgeMap.put(knowledge.getId(), knowledge); + } + + // 存储最终的根节点 + List rootNodes = new ArrayList<>(); + + for (Knowledge knowledge : knowledges) { + Integer parentId = knowledge.getParentId(); + if (parentId == null || parentId == 0) { // 假设没有父节点的是根节点 + rootNodes.add(knowledge); + } else { + Knowledge parent = knowledgeMap.get(parentId); + if (parent != null) { + if (parent.getChildren() == null) { + parent.setChildren(new ArrayList<>()); + } + parent.getChildren().add(knowledge); + } + } + } + + return rootNodes; + } + + + /** + * 生成知识点编码 + * @param parentId 父节点ID,0或null代表顶级节点 + * @return 知识点编码,如A01、A01A01等 + */ + public String generateKnowledgeCode(Integer parentId) { + if (parentId == null || parentId == 0) { + // 顶级节点编码生成逻辑 + // 查询当前最大的顶级节点编码 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.isNull(Knowledge::getParentId).or().eq(Knowledge::getParentId, 0); + queryWrapper.orderByDesc(Knowledge::getId); + List topKnowledges = this.list(queryWrapper); + + if (topKnowledges.isEmpty()) { + return "A01"; + } + + // 获取最后一个顶级节点的编码 + String lastCode = topKnowledges.get(0).getKnowledgeCode(); + if (lastCode == null || lastCode.isEmpty()) { + return "A01"; + } + + // 解析并递增编码 + return incrementCode(lastCode, 3); // 顶级节点固定3位编码 + } else { + // 子节点编码生成逻辑 + Knowledge parent = this.getById(parentId); + if (parent == null || parent.getKnowledgeCode() == null) { + throw new RuntimeException("父节点不存在或无编码"); + } + + String parentCode = parent.getKnowledgeCode(); + // 查询该父节点下的所有子节点 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Knowledge::getParentId, parentId); + queryWrapper.orderByDesc(Knowledge::getId); + List childKnowledges = this.list(queryWrapper); + + if (childKnowledges.isEmpty()) { + // 第一个子节点 + return parentCode + "A01"; + } + + // 获取最后一个子节点的编码 + String lastChildCode = childKnowledges.get(0).getKnowledgeCode(); + if (lastChildCode == null || lastChildCode.length() <= parentCode.length()) { + return parentCode + "A01"; + } + + // 提取子节点部分并递增 + String childPart = lastChildCode.substring(parentCode.length()); + String newChildPart = incrementCode(childPart, 3); // 子节点部分固定3位编码 + + return parentCode + newChildPart; + } + } + + /** + * 递增编码 + * @param code 当前编码 + * @param length 编码长度 + * @return 递增后的编码 + */ + private String incrementCode(String code, int length) { + if (code == null || code.isEmpty()) { + return "A01"; + } + + // 分离字母和数字部分 + StringBuilder letters = new StringBuilder(); + StringBuilder digits = new StringBuilder(); + + for (char c : code.toCharArray()) { + if (Character.isLetter(c)) { + letters.append(c); + } else if (Character.isDigit(c)) { + digits.append(c); + } + } + + if (digits.isEmpty()) { + return "A01"; + } + + // 递增数字部分 + int num = Integer.parseInt(digits.toString()); + num++; + + // 格式化回固定长度 + String format = "%0" + length + "d"; + return letters.toString() + String.format(format, num); + } + } diff --git a/app/api/playedu-course/src/main/resources/mapper/jc/DiscussionMapper.xml b/app/api/playedu-course/src/main/resources/mapper/jc/DiscussionMapper.xml index c3847f1..be1008f 100644 --- a/app/api/playedu-course/src/main/resources/mapper/jc/DiscussionMapper.xml +++ b/app/api/playedu-course/src/main/resources/mapper/jc/DiscussionMapper.xml @@ -5,9 +5,34 @@ - + diff --git a/app/api/playedu-course/src/main/resources/mapper/jc/KnowledgeMapper.xml b/app/api/playedu-course/src/main/resources/mapper/jc/KnowledgeMapper.xml index a187dab..3dfcbc8 100644 --- a/app/api/playedu-course/src/main/resources/mapper/jc/KnowledgeMapper.xml +++ b/app/api/playedu-course/src/main/resources/mapper/jc/KnowledgeMapper.xml @@ -4,40 +4,6 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - - - - - - - - - - - - - - - - - - - id, - book_id, - parent_id, - name, - konwledge_code, - `desc`, - `level`, - `type`, - order_num, - extra_json, - create_time, - update_time, - creator, - updater, - tenant_id - diff --git a/app/api/playedu-course/src/main/resources/mapper/jc/NoteMapper.xml b/app/api/playedu-course/src/main/resources/mapper/jc/NoteMapper.xml index 8902f42..65ef4da 100644 --- a/app/api/playedu-course/src/main/resources/mapper/jc/NoteMapper.xml +++ b/app/api/playedu-course/src/main/resources/mapper/jc/NoteMapper.xml @@ -4,38 +4,35 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - - - - - - - - - - - - - - - - +