获取专项练习

文章目录

1.sun-club-practice-api

1.vo构建
1.SpecialPracticeVO.java
java 复制代码
package com.sunxiansheng.practice.api.vo;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/25 16:36
 * @Version 1.0
 */
@Data
public class SpecialPracticeVO implements Serializable {

    /**
     * 一级分类的名字
     */
    private String primaryCategoryName;

    /**
     * 一级分类的id
     */
    private Long primaryCategoryId;

    /**
     * 一级分类下二级分类的列表
     */
    private List<SpecialPracticeCategoryVO> categoryList;

}
2.SpecialPracticeCategoryVO.java
java 复制代码
package com.sunxiansheng.practice.api.vo;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/25 16:36
 * @Version 1.0
 */
@Data
public class SpecialPracticeCategoryVO implements Serializable {

    /**
     * 二级分类的名字
     */
    private String categoryName;

    /**
     * 二级分类的id
     */
    private Long categoryId;

    /**
     * 二级分类关联的标签列表
     */
    private List<SpecialPracticeLabelVO> labelList;

}
3.SpecialPracticeLabelVO.java
java 复制代码
package com.sunxiansheng.practice.api.vo;

import lombok.Data;

import java.io.Serializable;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/25 16:36
 * @Version 1.0
 */
@Data
public class SpecialPracticeLabelVO implements Serializable {

    /**
     * 标签id
     */
    private Long id;

    /**
     * 分类id-标签id,作为这个标签的唯一标识
     */
    private String assembleId;

    /**
     * 标签名字
     */
    private String labelName;

}
2.SubjectInfoTypeEnum.java
java 复制代码
package com.sunxiansheng.practice.api.enums;

import lombok.Getter;

/**
 * Description: 题目类型枚举
 * @Author sun
 * @Create 2024/5/24 9:53
 * @Version 1.0
 */
@Getter
public enum SubjectInfoTypeEnum {
    RADIO(1,"单选"),
    MULTIPLE(2,"多选"),
    JUDGE(3,"判断"),
    BRIEF(4,"简答");

    public int code;
    public String desc;

    SubjectInfoTypeEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    /**
     * 根据code获取枚举
     * @param code
     * @return
     */
    public static SubjectInfoTypeEnum getByCode(int code) {
        for (SubjectInfoTypeEnum value : values()) {
            if (value.code == code) {
                return value;
            }
        }
        return null;
    }
}

2.sun-club-practice-server

1.PracticeSetController.java
java 复制代码
package com.sunxiansheng.practice.server.controller;

import com.alibaba.fastjson.JSON;
import com.sunxiansheng.practice.api.common.Result;
import com.sunxiansheng.practice.api.vo.SpecialPracticeVO;
import com.sunxiansheng.practice.server.service.PracticeSetService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * Description: 练习套卷controller
 * @Author sun
 * @Create 2024/6/25 15:38
 * @Version 1.0
 */
@RestController
@RequestMapping("/practice/set")
@Slf4j
public class PracticeSetController {

    @Resource
    private PracticeSetService practiceSetService;

    @RequestMapping("getSpecialPracticeContent")
    public Result<List<SpecialPracticeVO>> getSpecialPracticeContent() {
        try {
            List<SpecialPracticeVO> res = practiceSetService.getSpecialPracticeContent();
            if (log.isInfoEnabled()) {
                // 打日志
                log.info("getSpecialPracticeContent res:{}", JSON.toJSONString(res));
            }
            return Result.ok(res);
        } catch (Exception e) {
            log.error("getSpecialPracticeContent error", e.getMessage(), e);
            return Result.fail("获取练习套卷内容失败");
        }
    }

}
2.service
1.PracticeSetService.java
java 复制代码
package com.sunxiansheng.practice.server.service;

import com.sunxiansheng.practice.api.vo.SpecialPracticeVO;

import java.util.List;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/25 16:57
 * @Version 1.0
 */
public interface PracticeSetService {

    /**
     * 获取练习套卷内容
     * @return
     */
    List<SpecialPracticeVO> getSpecialPracticeContent();

}
2.PracticeSetServiceImpl.java
java 复制代码
package com.sunxiansheng.practice.server.service.impl;

import com.sunxiansheng.practice.api.enums.SubjectInfoTypeEnum;
import com.sunxiansheng.practice.api.vo.SpecialPracticeCategoryVO;
import com.sunxiansheng.practice.api.vo.SpecialPracticeLabelVO;
import com.sunxiansheng.practice.api.vo.SpecialPracticeVO;
import com.sunxiansheng.practice.server.dao.SubjectCategoryDao;
import com.sunxiansheng.practice.server.dao.SubjectLabelDao;
import com.sunxiansheng.practice.server.dao.SubjectMappingDao;
import com.sunxiansheng.practice.server.entity.dto.CategoryDTO;
import com.sunxiansheng.practice.server.entity.po.*;
import com.sunxiansheng.practice.server.service.PracticeSetService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/25 17:08
 * @Version 1.0
 */
@Service
@Slf4j
public class PracticeSetServiceImpl implements PracticeSetService {

    @Resource
    private SubjectCategoryDao subjectCategoryDao;

    @Resource
    private SubjectMappingDao subjectMappingDao;

    @Resource
    private SubjectLabelDao subjectLabelDao;

    @Override
    public List<SpecialPracticeVO> getSpecialPracticeContent() {
        // 构建要返回的对象
        List<SpecialPracticeVO> specialPracticeVOList = new LinkedList<>();
        // 构建一个查询的DTO
        CategoryDTO categoryDTO = new CategoryDTO();
        // 第一步:查询所有的一级分类的名字和id,遍历结果,将每一个结果map成一个SpecialPracticeVO然后收集成一个specialPracticeVOList
        // 根据题目的类型,查询二级分类中有题的,并且题目类型是单选,多选,判断的,的一级分类id
        List<Integer> subjectTypeList = new LinkedList<>();
        subjectTypeList.add(SubjectInfoTypeEnum.RADIO.getCode());
        subjectTypeList.add(SubjectInfoTypeEnum.MULTIPLE.getCode());
        subjectTypeList.add(SubjectInfoTypeEnum.JUDGE.getCode());
        categoryDTO.setSubjectTypeList(subjectTypeList);
        List<PrimaryCategoryPO> poList = subjectCategoryDao.getPrimaryCategoryHasSubject(categoryDTO);
        if (CollectionUtils.isEmpty(poList)) {
            return specialPracticeVOList;
        }
        // 此时poList中的id为一级分类的id
        // 将一级分类的每一个元素map成一个SpecialPracticeVO并最终收集成一个list
        List<SpecialPracticeVO> res = poList.stream().map(
                primaryCategoryPO -> {
                    // 要构建的SpecialPracticeVO
                    SpecialPracticeVO specialPracticeVO = new SpecialPracticeVO();
                    // ==========映射过程==========

                    // 取出每个一级分类的id,映射成一个SpecialPracticeVO
                    Long primaryCategoryId = primaryCategoryPO.getId();
                    specialPracticeVO.setPrimaryCategoryId(primaryCategoryId);
                    // 根据primaryCategoryId 查询出primaryCategoryName
                    CategoryPO categoryPO = subjectCategoryDao.selectById(primaryCategoryId);
                    specialPracticeVO.setPrimaryCategoryName(categoryPO.getCategoryName());
                    // 组装specialPracticeCategoryVOList
                    List<SpecialPracticeCategoryVO> specialPracticeCategoryVOList = new LinkedList<>();
                    // 根据primaryCategoryId查询出所有二级分类的categoryName和categoryId
                    List<SecondCategoryPO> secondCategoryPOList = subjectCategoryDao.getSecondCategoryByPrimaryId(primaryCategoryId);
                    // 遍历每一个secondCategoryPO,将其map成一个SpecialPracticeCategoryVO,然后收集成specialPracticeCategoryVOList
                    List<SpecialPracticeCategoryVO> categoryList = secondCategoryPOList.stream().map(
                            secondCategoryPO -> {
                                // 映射成SpecialPracticeCategoryVO
                                SpecialPracticeCategoryVO specialPracticeCategoryVO = new SpecialPracticeCategoryVO();
                                specialPracticeCategoryVO.setCategoryName(secondCategoryPO.getCategoryName());
                                specialPracticeCategoryVO.setCategoryId(secondCategoryPO.getId());
                                // 构建labelList
                                // 根据分类id查询所有标签的id和labelName
                                List<LabelCountPO> labelIdAndName = subjectMappingDao.getLabelIdAndName(secondCategoryPO.getId(), subjectTypeList);
                                List<SpecialPracticeLabelVO> labelList = labelIdAndName.stream().map(
                                        labelCountPO -> {
                                            SpecialPracticeLabelVO specialPracticeLabelVO = new SpecialPracticeLabelVO();
                                            // 映射
                                            specialPracticeLabelVO.setId(labelCountPO.getLabelId());
                                            specialPracticeLabelVO.setLabelName(labelCountPO.getLabelName());
                                            specialPracticeLabelVO.setAssembleId(secondCategoryPO.getId() + "-" + labelCountPO.getLabelId());
                                            return specialPracticeLabelVO;
                                        }
                                ).collect(Collectors.toList());
                                specialPracticeCategoryVO.setLabelList(labelList);
                                return specialPracticeCategoryVO;
                            }
                    ).collect(Collectors.toList());
                    specialPracticeVO.setCategoryList(categoryList);
                    // ==========映射过程==========
                    // 映射成一个SpecialPracticeVO
                    return specialPracticeVO;
                }
        ).collect(Collectors.toList());
        return res;
    }


}
3.dao
1.SubjectCategoryDao.java
java 复制代码
package com.sunxiansheng.practice.server.dao;


import com.sunxiansheng.practice.server.entity.dto.CategoryDTO;
import com.sunxiansheng.practice.server.entity.po.CategoryPO;
import com.sunxiansheng.practice.server.entity.po.PrimaryCategoryPO;
import com.sunxiansheng.practice.server.entity.po.SecondCategoryPO;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * 题目分类(SubjectCategory)表数据库访问层
 *
 * @author makejava
 * @since 2024-05-23 19:06:49
 */
@Mapper
public interface SubjectCategoryDao {

    List<PrimaryCategoryPO> getPrimaryCategory(CategoryDTO categoryDTO);

    CategoryPO selectById(Long id);

    List<CategoryPO> selectList(CategoryDTO categoryDTOTemp);

    /**
     * 查询一级分类下有题目的分类id
     * @param categoryDTO
     * @return
     */
    List<PrimaryCategoryPO> getPrimaryCategoryHasSubject(CategoryDTO categoryDTO);

    /**
     * 根据一级分类id查询二级分类
     * @param primaryCategoryId
     * @return
     */
    List<SecondCategoryPO> getSecondCategoryByPrimaryId(Long primaryCategoryId);
}
2.SubjectLabelDao.java
java 复制代码
package com.sunxiansheng.practice.server.dao;


import com.sunxiansheng.practice.server.entity.po.SubjectLabelPO;

/**
 * 题目标签表(SubjectLabel)表数据库访问层
 *
 * @author makejava
 * @since 2024-05-25 16:43:49
 */
public interface SubjectLabelDao {

    SubjectLabelPO queryById(Long id);

}
3.SubjectMappingDao.java
java 复制代码
package com.sunxiansheng.practice.server.dao;

import com.sunxiansheng.practice.server.entity.po.LabelCountPO;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 题目分类关系表(SubjectMapping)表数据库访问层
 *
 * @author makejava
 * @since 2024-05-26 14:05:02
 */
public interface SubjectMappingDao {

    List<LabelCountPO> getLabelSubjectCount(@Param("categoryId") Long categoryId, @Param("subjectTypeList") List<Integer> subjectTypeList);

    // 根据分类id和题目类型查询标签的id和labelName
    List<LabelCountPO> getLabelIdAndName(@Param("categoryId") Long categoryId, @Param("subjectTypeList") List<Integer> subjectTypeList);
}
4.mapper.xml
1.SubjectCategoryDao.xml
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sunxiansheng.practice.server.dao.SubjectCategoryDao">
    <select id="getPrimaryCategory" resultType="com.sunxiansheng.practice.server.entity.po.PrimaryCategoryPO">
        select count(distinct a.subject_id) as subjectCount,
               b.parent_id                  as parentId
        from subject_mapping a,
             subject_category b,
             subject_info c
        where a.category_id = b.id
          and a.subject_id = c.id
          and a.is_deleted = 0
          and b.is_deleted = 0
          and c.is_deleted = 0
          and c.subject_type in
        <foreach collection="subjectTypeList" item="item" open="(" close=")" separator=",">
            #{item}
        </foreach>
        group by b.parent_id
    </select>

    <select id="selectById" resultType="com.sunxiansheng.practice.server.entity.po.CategoryPO">
        select category_name as categoryName
        from subject_category
        where is_deleted = 0
          and id = #{id}
    </select>

    <select id="selectList" resultType="com.sunxiansheng.practice.server.entity.po.CategoryPO">
        select id,
               category_name as categoryName,
               category_type as categoryType,
               parent_id     as parentId
        from subject_category
        where is_deleted = 0
          and parent_id = #{parentId}
          and category_type = #{categoryType}
    </select>

    <select id="getPrimaryCategoryHasSubject" resultType="com.sunxiansheng.practice.server.entity.po.PrimaryCategoryPO">
        select distinct parent_id as id
        from subject_category a,
             subject_mapping b,
             subject_info c
        where a.id = b.category_id
          and c.id = b.subject_id
          and a.is_deleted = 0
          and b.is_deleted = 0
          and c.is_deleted = 0
          and category_type = 2
          and subject_type in
        <foreach collection="subjectTypeList" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>

    <select id="getSecondCategoryByPrimaryId" resultType="com.sunxiansheng.practice.server.entity.po.SecondCategoryPO">
        select distinct category_id as id,
        category_name as categoryName
        from subject_mapping a,
             subject_category b
        where a.category_id = b.id
          and a.is_deleted = 0
          and b.is_deleted = 0
        and parent_id = #{primaryCategoryId}
    </select>
</mapper>
2.SubjectLabelDao.xml
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sunxiansheng.practice.server.dao.SubjectLabelDao">
    <resultMap id="SubjectLabelPOResultMap" type="com.sunxiansheng.practice.server.entity.po.SubjectLabelPO">
        <id column="id" property="id"/>
        <result column="label_name" property="labelName"/>
        <result column="sort_num" property="sortNum"/>
        <result column="category_id" property="categoryId"/>
        <result column="created_by" property="createdBy"/>
        <result column="created_time" property="createdTime"/>
        <result column="update_by" property="updateBy"/>
        <result column="update_time" property="updateTime"/>
        <result column="is_deleted" property="isDeleted"/>
    </resultMap>
    <select id="queryById" resultMap="SubjectLabelPOResultMap">
        select id,
               label_name,
               category_id,
               sort_num,
               created_by,
               created_time,
               update_by,
               is_deleted,
               update_time
        from subject_label
        where id = #{id}
    </select>
</mapper>
3.SubjectMappingDao.xml
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sunxiansheng.practice.server.dao.SubjectMappingDao">

    <select id="getLabelSubjectCount" resultType="com.sunxiansheng.practice.server.entity.po.LabelCountPO">
        select count(distinct a.subject_id) as count,
               a.label_id                   as labelId
        from subject_mapping a,
             subject_info b
        where a.subject_id = b.id
          and a.is_deleted = 0
          and b.is_deleted = 0
          and a.category_id = #{categoryId}
          and b.subject_type in
        <foreach collection="subjectTypeList" item="item" open="(" close=")" separator=",">
            #{item}
        </foreach>
        group by a.label_id
    </select>

    <select id="getLabelIdAndName" resultType="com.sunxiansheng.practice.server.entity.po.LabelCountPO">
        select label_id         as labelId,
               c.label_name as labelName
        from subject_mapping a,
             subject_category b,
             subject_label c,
             subject_info d
        where a.category_id = b.id
          and a.label_id = c.id
          and a.subject_id = d.id
          and a.is_deleted = 0
          and b.is_deleted = 0
          and c.is_deleted = 0
          and d.is_deleted = 0
          and subject_type in
        <foreach collection="subjectTypeList" item="item" open="(" close=")" separator=",">
            #{item}
        </foreach>
        and a.category_id = #{categoryId}
        group by label_id, label_name
    </select>
</mapper>
5.entity
1.dto
CategoryDTO.java
java 复制代码
package com.sunxiansheng.practice.server.entity.dto;

import lombok.Data;

import java.util.List;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/25 17:15
 * @Version 1.0
 */
@Data
public class CategoryDTO {

    private Long id;

    private List<Integer> subjectTypeList;

    private Integer categoryType;

    private Long parentId;

}
2.po
1.CategoryPO.java
java 复制代码
package com.sunxiansheng.practice.server.entity.po;

import lombok.Data;

/**
 * Description: 大类PO,对应DB中的字段
 * @Author sun
 * @Create 2024/6/25 17:28
 * @Version 1.0
 */
@Data
public class CategoryPO {

    private Long id;

    private String categoryName;

    private Integer categoryType;

    private Long parentId;
}
2.LabelCountPO.java
java 复制代码
package com.sunxiansheng.practice.server.entity.po;

import lombok.Data;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/26 14:40
 * @Version 1.0
 */
@Data
public class LabelCountPO {

    private Long labelId;

    private Integer count;

    private String labelName;

}
3.PrimaryCategoryPO.java
java 复制代码
package com.sunxiansheng.practice.server.entity.po;

import lombok.Data;

/**
 * Description: 大类PO,对应DB中的字段
 * @Author sun
 * @Create 2024/6/25 17:28
 * @Version 1.0
 */
@Data
public class PrimaryCategoryPO {

    private Long id;

    private String categoryName;

    private Integer categoryType;

    private Long parentId;

}
4.SecondCategoryPO.java
java 复制代码
package com.sunxiansheng.practice.server.entity.po;

import lombok.Data;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/26 17:46
 * @Version 1.0
 */
@Data
public class SecondCategoryPO {

    private String categoryName;

    private Long id;

}
5.SubjectLabelPO.java
java 复制代码
package com.sunxiansheng.practice.server.entity.po;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * 题目标签表(SubjectLabel)实体类
 *
 * @author makejava
 * @since 2024-05-25 16:43:50
 */
@Data
public class SubjectLabelPO implements Serializable {
    /**
     * 主键
     */
    private Long id;
    /**
     * 标签分类
     */
    private String labelName;
    /**
     * 排序
     */
    private Integer sortNum;

    private String categoryId;
    /**
     * 创建人
     */
    private String createdBy;
    /**
     * 创建时间
     */
    private Date createdTime;
    /**
     * 更新人
     */
    private String updateBy;
    /**
     * 更新时间
     */
    private Date updateTime;

    private Integer isDeleted;


}

3.测试

1.接口设计
2.测试请求