From 97820eb402f0be945f7b33ad7065ac93e74da7cf Mon Sep 17 00:00:00 2001 From: none Date: Fri, 24 Feb 2023 14:12:51 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=BE=E7=A8=8B=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../playedu/api/bus/CourseCategoryBus.java | 40 ++++++ .../api/checks/AdminPermissionCheck.java | 4 +- .../api/constant/BPermissionConstant.java | 2 + .../backend/CourseCategoryController.java | 104 +++++++++++++++ .../playedu/api/domain/CourseCategory.java | 109 ++++++++++++++++ .../api/event/CourseCategoryDestroyEvent.java | 26 ++++ .../CourseCategoryDestroyListener.java | 14 +++ .../api/mapper/CourseCategoryMapper.java | 20 +++ .../backend/CourseCategoryRequest.java | 31 +++++ .../api/service/CourseCategoryService.java | 26 ++++ .../impl/CourseCategoryServiceImpl.java | 119 ++++++++++++++++++ .../resources/mapper/CourseCategoryMapper.xml | 22 ++++ 12 files changed, 516 insertions(+), 1 deletion(-) create mode 100644 src/main/java/xyz/playedu/api/bus/CourseCategoryBus.java create mode 100644 src/main/java/xyz/playedu/api/controller/backend/CourseCategoryController.java create mode 100644 src/main/java/xyz/playedu/api/domain/CourseCategory.java create mode 100644 src/main/java/xyz/playedu/api/event/CourseCategoryDestroyEvent.java create mode 100644 src/main/java/xyz/playedu/api/listener/CourseCategoryDestroyListener.java create mode 100644 src/main/java/xyz/playedu/api/mapper/CourseCategoryMapper.java create mode 100644 src/main/java/xyz/playedu/api/request/backend/CourseCategoryRequest.java create mode 100644 src/main/java/xyz/playedu/api/service/CourseCategoryService.java create mode 100644 src/main/java/xyz/playedu/api/service/impl/CourseCategoryServiceImpl.java create mode 100644 src/main/resources/mapper/CourseCategoryMapper.xml diff --git a/src/main/java/xyz/playedu/api/bus/CourseCategoryBus.java b/src/main/java/xyz/playedu/api/bus/CourseCategoryBus.java new file mode 100644 index 0000000..9d0283f --- /dev/null +++ b/src/main/java/xyz/playedu/api/bus/CourseCategoryBus.java @@ -0,0 +1,40 @@ +package xyz.playedu.api.bus; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import xyz.playedu.api.domain.CourseCategory; +import xyz.playedu.api.exception.NotFoundException; +import xyz.playedu.api.service.CourseCategoryService; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/2/24 13:57 + */ +@Component +public class CourseCategoryBus { + + @Autowired + private CourseCategoryService categoryService; + + public String compParentChain(Integer parentId) throws NotFoundException { + String parentChain = ""; + if (parentId != 0) { + CourseCategory parentCourseCategory = categoryService.getById(parentId); + if (parentCourseCategory == null) { + throw new NotFoundException("父级分类不存在"); + } + String pc = parentCourseCategory.getParentChain(); + parentChain = pc == null || pc.length() == 0 ? parentId + "" : pc + "," + parentId; + } + return parentChain; + } + + public static String childrenParentChain(CourseCategory CourseCategory) { + String prefix = CourseCategory.getId() + ""; + if (CourseCategory.getParentChain() != null && CourseCategory.getParentChain().length() > 0) { + prefix = CourseCategory.getParentChain() + "," + prefix; + } + return prefix; + } + +} diff --git a/src/main/java/xyz/playedu/api/checks/AdminPermissionCheck.java b/src/main/java/xyz/playedu/api/checks/AdminPermissionCheck.java index 8e71dc3..fc2effd 100644 --- a/src/main/java/xyz/playedu/api/checks/AdminPermissionCheck.java +++ b/src/main/java/xyz/playedu/api/checks/AdminPermissionCheck.java @@ -36,12 +36,14 @@ public class AdminPermissionCheck implements ApplicationRunner { {"部门", "10", "部门-编辑", BPermissionConstant.DEPARTMENT_UPDATE}, {"部门", "15", "部门-删除", BPermissionConstant.DEPARTMENT_DESTROY}, - {"资源分类", "0", "资源分类管理", BPermissionConstant.RESOURCE_CATEGORY}, + {"资源分类", "0", "资源分类", BPermissionConstant.RESOURCE_CATEGORY}, {"学员", "0", "学员-查看", BPermissionConstant.USER_INDEX}, {"学员", "5", "学员-添加", BPermissionConstant.USER_STORE}, {"学员", "10", "学员-编辑", BPermissionConstant.USER_UPDATE}, {"学员", "15", "学员-删除", BPermissionConstant.USER_DESTROY}, + + {"课程分类", "0", "课程分类", BPermissionConstant.COURSE_CATEGORY}, }; @Override diff --git a/src/main/java/xyz/playedu/api/constant/BPermissionConstant.java b/src/main/java/xyz/playedu/api/constant/BPermissionConstant.java index a326962..bfb13ce 100644 --- a/src/main/java/xyz/playedu/api/constant/BPermissionConstant.java +++ b/src/main/java/xyz/playedu/api/constant/BPermissionConstant.java @@ -28,4 +28,6 @@ public class BPermissionConstant { public final static String USER_UPDATE = "user-update"; public final static String USER_DESTROY = "user-destroy"; + public final static String COURSE_CATEGORY = "course—category"; + } diff --git a/src/main/java/xyz/playedu/api/controller/backend/CourseCategoryController.java b/src/main/java/xyz/playedu/api/controller/backend/CourseCategoryController.java new file mode 100644 index 0000000..81fe2fa --- /dev/null +++ b/src/main/java/xyz/playedu/api/controller/backend/CourseCategoryController.java @@ -0,0 +1,104 @@ +package xyz.playedu.api.controller.backend; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import xyz.playedu.api.bus.CourseCategoryBus; +import xyz.playedu.api.constant.BPermissionConstant; +import xyz.playedu.api.domain.CourseCategory; +import xyz.playedu.api.event.CourseCategoryDestroyEvent; +import xyz.playedu.api.exception.NotFoundException; +import xyz.playedu.api.middleware.BackendPermissionMiddleware; +import xyz.playedu.api.request.backend.CourseCategoryRequest; +import xyz.playedu.api.service.CourseCategoryService; +import xyz.playedu.api.types.JsonResponse; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/2/24 13:57 + */ +@RestController +@RequestMapping("/backend/v1/course-category") +public class CourseCategoryController { + + @Autowired + private CourseCategoryService categoryService; + + @Autowired + private ApplicationContext ctx; + + @Autowired + private CourseCategoryBus courseCategoryBus; + + @GetMapping("/index") + public JsonResponse index() { + Map> categories = categoryService.all().stream().collect(Collectors.groupingBy(CourseCategory::getParentId)); + + HashMap data = new HashMap<>(); + data.put("categories", categories); + + return JsonResponse.data(data); + } + + @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE_CATEGORY) + @GetMapping("/create") + public JsonResponse create(@RequestParam(name = "parent_id", defaultValue = "0") Integer parentId) { + List data = categoryService.listByParentId(parentId); + return JsonResponse.data(data); + } + + @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE_CATEGORY) + @PostMapping("/create") + public JsonResponse store(@RequestBody @Validated CourseCategoryRequest request) throws NotFoundException { + String parentChain = ""; + if (request.getParentId() != 0) { + parentChain = courseCategoryBus.compParentChain(request.getParentId()); + } + + CourseCategory category = new CourseCategory(); + category.setName(request.getName()); + category.setParentId(request.getParentId()); + category.setParentChain(parentChain); + category.setSort(request.getSort()); + category.setCreatedAt(new Date()); + category.setUpdatedAt(new Date()); + + categoryService.save(category); + + return JsonResponse.success(); + } + + @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE_CATEGORY) + @GetMapping("/{id}") + public JsonResponse edit(@PathVariable Integer id) throws NotFoundException { + CourseCategory category = categoryService.findOrFail(id); + return JsonResponse.data(category); + } + + @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE_CATEGORY) + @PutMapping("/{id}") + public JsonResponse update(@PathVariable Integer id, @RequestBody CourseCategoryRequest request) throws NotFoundException { + CourseCategory category = categoryService.findOrFail(id); + categoryService.update(category, request.getName(), request.getParentId(), request.getSort()); + return JsonResponse.success(); + } + + @BackendPermissionMiddleware(slug = BPermissionConstant.COURSE_CATEGORY) + @DeleteMapping("/{id}") + public JsonResponse destroy(@PathVariable Integer id) throws NotFoundException { + CourseCategory category = categoryService.findOrFail(id); + categoryService.deleteById(category.getId()); + + ctx.publishEvent(new CourseCategoryDestroyEvent(this, id, new Date())); + + return JsonResponse.success(); + } + +} diff --git a/src/main/java/xyz/playedu/api/domain/CourseCategory.java b/src/main/java/xyz/playedu/api/domain/CourseCategory.java new file mode 100644 index 0000000..49dbd81 --- /dev/null +++ b/src/main/java/xyz/playedu/api/domain/CourseCategory.java @@ -0,0 +1,109 @@ +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 java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * @TableName course_categories + */ +@TableName(value = "course_categories") +@Data +public class CourseCategory implements Serializable { + /** + * + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 部门名 + */ + private String name; + + /** + * 父id + */ + @JsonProperty("parent_id") + private Integer parentId; + + /** + * 父链 + */ + @JsonProperty("parent_chain") + private String parentChain; + + /** + * 升序 + */ + private Integer sort; + + @JsonProperty("created_at") + private Date createdAt; + + @JsonProperty("updated_at") + private Date updatedAt; + + @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; + } + CourseCategory other = (CourseCategory) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName())) + && (this.getParentId() == null ? other.getParentId() == null : this.getParentId().equals(other.getParentId())) + && (this.getParentChain() == null ? other.getParentChain() == null : this.getParentChain().equals(other.getParentChain())) + && (this.getSort() == null ? other.getSort() == null : this.getSort().equals(other.getSort())) + && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt())) + && (this.getUpdatedAt() == null ? other.getUpdatedAt() == null : this.getUpdatedAt().equals(other.getUpdatedAt())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getName() == null) ? 0 : getName().hashCode()); + result = prime * result + ((getParentId() == null) ? 0 : getParentId().hashCode()); + result = prime * result + ((getParentChain() == null) ? 0 : getParentChain().hashCode()); + result = prime * result + ((getSort() == null) ? 0 : getSort().hashCode()); + result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode()); + result = prime * result + ((getUpdatedAt() == null) ? 0 : getUpdatedAt().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(", name=").append(name); + sb.append(", parentId=").append(parentId); + sb.append(", parentChain=").append(parentChain); + sb.append(", sort=").append(sort); + sb.append(", createdAt=").append(createdAt); + sb.append(", updatedAt=").append(updatedAt); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/playedu/api/event/CourseCategoryDestroyEvent.java b/src/main/java/xyz/playedu/api/event/CourseCategoryDestroyEvent.java new file mode 100644 index 0000000..4aaf6e7 --- /dev/null +++ b/src/main/java/xyz/playedu/api/event/CourseCategoryDestroyEvent.java @@ -0,0 +1,26 @@ +package xyz.playedu.api.event; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.context.ApplicationEvent; + +import java.util.Date; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/2/24 14:01 + */ +@Setter +@Getter +public class CourseCategoryDestroyEvent extends ApplicationEvent { + + private Integer categoryId; + private Date at; + + public CourseCategoryDestroyEvent(Object source, Integer categoryId, Date date) { + super(source); + this.categoryId = categoryId; + this.at = date; + } + +} diff --git a/src/main/java/xyz/playedu/api/listener/CourseCategoryDestroyListener.java b/src/main/java/xyz/playedu/api/listener/CourseCategoryDestroyListener.java new file mode 100644 index 0000000..27ba040 --- /dev/null +++ b/src/main/java/xyz/playedu/api/listener/CourseCategoryDestroyListener.java @@ -0,0 +1,14 @@ +package xyz.playedu.api.listener; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/2/24 14:07 + */ +@Component +@Slf4j +public class CourseCategoryDestroyListener { + +} diff --git a/src/main/java/xyz/playedu/api/mapper/CourseCategoryMapper.java b/src/main/java/xyz/playedu/api/mapper/CourseCategoryMapper.java new file mode 100644 index 0000000..f6bf31f --- /dev/null +++ b/src/main/java/xyz/playedu/api/mapper/CourseCategoryMapper.java @@ -0,0 +1,20 @@ +package xyz.playedu.api.mapper; + +import org.apache.ibatis.annotations.Mapper; +import xyz.playedu.api.domain.CourseCategory; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author tengteng +* @description 针对表【course_categories】的数据库操作Mapper +* @createDate 2023-02-24 13:55:19 +* @Entity xyz.playedu.api.domain.CourseCategory +*/ +@Mapper +public interface CourseCategoryMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/xyz/playedu/api/request/backend/CourseCategoryRequest.java b/src/main/java/xyz/playedu/api/request/backend/CourseCategoryRequest.java new file mode 100644 index 0000000..4eaec0e --- /dev/null +++ b/src/main/java/xyz/playedu/api/request/backend/CourseCategoryRequest.java @@ -0,0 +1,31 @@ +package xyz.playedu.api.request.backend; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/2/24 13:56 + */ +@Data +public class CourseCategoryRequest implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + + @NotNull(message = "请输入分类名") + @Length(min = 1, max = 20, message = "分类名长度在1-20个字符之间") + private String name; + + @JsonProperty("parent_id") + @NotNull(message = "请选择上级分类") + private Integer parentId; + + @NotNull(message = "请输入排序值") + private Integer sort; + +} diff --git a/src/main/java/xyz/playedu/api/service/CourseCategoryService.java b/src/main/java/xyz/playedu/api/service/CourseCategoryService.java new file mode 100644 index 0000000..87631b3 --- /dev/null +++ b/src/main/java/xyz/playedu/api/service/CourseCategoryService.java @@ -0,0 +1,26 @@ +package xyz.playedu.api.service; + +import xyz.playedu.api.domain.CourseCategory; +import com.baomidou.mybatisplus.extension.service.IService; +import xyz.playedu.api.exception.NotFoundException; + +import java.util.List; + +/** + * @author tengteng + * @description 针对表【course_categories】的数据库操作Service + * @createDate 2023-02-24 13:55:19 + */ +public interface CourseCategoryService extends IService { + + List listByParentId(Integer id); + + List all(); + + CourseCategory findOrFail(Integer id) throws NotFoundException; + + void deleteById(Integer id) throws NotFoundException; + + void update(CourseCategory category, String name, Integer parentId, Integer sort) throws NotFoundException; + +} diff --git a/src/main/java/xyz/playedu/api/service/impl/CourseCategoryServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/CourseCategoryServiceImpl.java new file mode 100644 index 0000000..1569f3b --- /dev/null +++ b/src/main/java/xyz/playedu/api/service/impl/CourseCategoryServiceImpl.java @@ -0,0 +1,119 @@ +package xyz.playedu.api.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.transaction.annotation.Transactional; +import xyz.playedu.api.bus.CourseCategoryBus; +import xyz.playedu.api.domain.CourseCategory; +import xyz.playedu.api.exception.NotFoundException; +import xyz.playedu.api.service.CourseCategoryService; +import xyz.playedu.api.mapper.CourseCategoryMapper; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author tengteng + * @description 针对表【course_categories】的数据库操作Service实现 + * @createDate 2023-02-24 13:55:19 + */ +@Service +public class CourseCategoryServiceImpl extends ServiceImpl implements CourseCategoryService { + + @Override + public List listByParentId(Integer id) { + return list(query().getWrapper().eq("parent_id", id).orderByAsc("sort")); + } + + @Override + public List all() { + return list(query().getWrapper().orderByAsc("sort")); + } + + @Override + public CourseCategory findOrFail(Integer id) throws NotFoundException { + CourseCategory category = getById(id); + if (category == null) { + throw new NotFoundException("分类不存在"); + } + return category; + } + + @Override + @Transactional + public void deleteById(Integer id) throws NotFoundException { + CourseCategory category = findOrFail(id); + //更新parent_chain + updateParentChain(category.getParentChain(), CourseCategoryBus.childrenParentChain(category)); + //删除记录 + removeById(category.getId()); + } + + @Override + @Transactional + public void update(CourseCategory category, String name, Integer parentId, Integer sort) throws NotFoundException { + String childrenChainPrefix = CourseCategoryBus.childrenParentChain(category); + + CourseCategory data = new CourseCategory(); + data.setId(category.getId()); + + if (!category.getName().equals(name)) { + data.setName(name); + } + + if (!category.getParentId().equals(parentId)) { + data.setParentId(parentId); + if (parentId.equals(0)) { + data.setParentChain(""); + } else { + CourseCategory parentCourseCategory = findOrFail(parentId); + data.setParentChain(CourseCategoryBus.childrenParentChain(parentCourseCategory)); + } + } + if (!category.getSort().equals(sort)) { + data.setSort(sort); + } + + //提交更换 + updateById(data); + + category = getById(category.getId()); + updateParentChain(CourseCategoryBus.childrenParentChain(category), childrenChainPrefix); + } + + private void updateParentChain(String newChildrenPC, String oldChildrenPC) { + List children = list(query().getWrapper().like("parent_chain", oldChildrenPC + "%")); + if (children.size() == 0) { + return; + } + + ArrayList updateRows = new ArrayList<>(); + for (CourseCategory tmpCourseCategory : children) { + CourseCategory tmpUpdateCourseCategory = new CourseCategory(); + tmpUpdateCourseCategory.setId(tmpCourseCategory.getId()); + + // parentChain计算 + String pc = newChildrenPC; + if (!tmpCourseCategory.getParentChain().equals(oldChildrenPC)) { + pc = tmpCourseCategory.getParentChain().replaceFirst(oldChildrenPC + ",", newChildrenPC.length() == 0 ? newChildrenPC : newChildrenPC + ','); + } + tmpUpdateCourseCategory.setParentChain(pc); + + // parentId计算 + int parentId = 0; + if (pc != null && pc.length() > 0) { + String[] parentIds = pc.split(","); + parentId = Integer.parseInt(parentIds[parentIds.length - 1]); + } + tmpUpdateCourseCategory.setParentId(parentId); + + updateRows.add(tmpUpdateCourseCategory); + } + updateBatchById(updateRows); + } + +} + + + + diff --git a/src/main/resources/mapper/CourseCategoryMapper.xml b/src/main/resources/mapper/CourseCategoryMapper.xml new file mode 100644 index 0000000..e6a8933 --- /dev/null +++ b/src/main/resources/mapper/CourseCategoryMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + id,name,parent_id, + parent_chain,sort,created_at, + updated_at + +