Ver Fonte

Merge branch 'dev' of http://192.168.1.245:11111/jinjilong/onlineEducation-fwd into dev

honorfire há 6 meses atrás
pai
commit
aa1934e685
18 ficheiros alterados com 321 adições e 36 exclusões
  1. 7 0
      snowy-plugin/snowy-plugin-disk/snowy-plugin-disk-func/src/main/java/vip/xiaonuo/disk/controller/CourseChapterController.java
  2. 4 0
      snowy-plugin/snowy-plugin-disk/snowy-plugin-disk-func/src/main/java/vip/xiaonuo/disk/mapper/CourseChapterKnowledgeMapper.java
  3. 10 0
      snowy-plugin/snowy-plugin-disk/snowy-plugin-disk-func/src/main/java/vip/xiaonuo/disk/mapper/mapping/CourseChapterKnowledgeMapper.xml
  4. 1 0
      snowy-plugin/snowy-plugin-disk/snowy-plugin-disk-func/src/main/java/vip/xiaonuo/disk/service/CourseChapterKnowledgeService.java
  5. 8 2
      snowy-plugin/snowy-plugin-disk/snowy-plugin-disk-func/src/main/java/vip/xiaonuo/disk/service/impl/CourseChapterKnowledgeServiceImpl.java
  6. 7 10
      snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/controller/student/ExamPaperAnswerController.java
  7. 1 1
      snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/mapper/TExamMapper.java
  8. 5 5
      snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/mapper/mapping/TExamMapper.xml
  9. 5 9
      snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/service/impl/ExamPaperAnswerServiceImpl.java
  10. 1 1
      snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/service/impl/ExamPaperServiceImpl.java
  11. 0 7
      snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/service/impl/QuestionServiceImpl.java
  12. 1 0
      snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/service/impl/TExamServiceImpl.java
  13. 11 0
      snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/vo/TExamVo.java
  14. 22 1
      snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/controller/ForumPostInfoController.java
  15. 35 0
      snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/mapper/ForumPostInfoMapper.java
  16. 90 0
      snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/mapper/mapping/ForumPostInfoMapper.xml
  17. 16 0
      snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/service/ForumPostInfoService.java
  18. 97 0
      snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/service/impl/ForumPostInfoServiceImpl.java

+ 7 - 0
snowy-plugin/snowy-plugin-disk/snowy-plugin-disk-func/src/main/java/vip/xiaonuo/disk/controller/CourseChapterController.java

@@ -118,6 +118,7 @@ public class CourseChapterController {
                 }
             }
 
+
             chapter.put("classHours", chapterClassHours);
         }
 //        //按chapterId分组课程
@@ -182,7 +183,13 @@ public class CourseChapterController {
                 }
             }
 
+            //根据章节,获得的知识点
+            List<String> knowledegeList=courseChapterKnowledgeService.selectknowledge(req.getParameter("courseId"),chapterId);
+            //章节对应知识点
             chapter.put("classHours", chapterClassHours);
+
+            chapter.put("knowledeges", knowledegeList);
+
         }
 //        //按chapterId分组课程
 //        Map<String, List<Map<String, Object>>> classHourByChapter = classHourList.stream()

+ 4 - 0
snowy-plugin/snowy-plugin-disk/snowy-plugin-disk-func/src/main/java/vip/xiaonuo/disk/mapper/CourseChapterKnowledgeMapper.java

@@ -13,8 +13,11 @@
 package vip.xiaonuo.disk.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
 import vip.xiaonuo.disk.domain.CourseChapterKnowledge;
 
+import java.util.List;
+
 
 /**
  * COURSE_CHAPTER_KNOWLEDGEMapper接口
@@ -23,4 +26,5 @@ import vip.xiaonuo.disk.domain.CourseChapterKnowledge;
  * @date  2025/08/04 17:14
  **/
 public interface CourseChapterKnowledgeMapper extends BaseMapper<CourseChapterKnowledge> {
+    List<String> selectknowledge(@Param("courseId")String courseId, @Param("chapterId") String chapterId);
 }

+ 10 - 0
snowy-plugin/snowy-plugin-disk/snowy-plugin-disk-func/src/main/java/vip/xiaonuo/disk/mapper/mapping/CourseChapterKnowledgeMapper.xml

@@ -1,5 +1,15 @@
 <?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="vip.xiaonuo.disk.mapper.CourseChapterKnowledgeMapper">
+      <select id="selectknowledge" resultType="java.lang.String">
+          SELECT
+
+              KNOWLEDGE_ID
+          FROM
+              ONLINEEDU.COURSE_CHAPTER_KNOWLEDGE
+          WHERE
+              COURSE_ID = #{courseId}
+            AND CHAPTER_ID = #{chapterId}
+      </select>
 
 </mapper>

+ 1 - 0
snowy-plugin/snowy-plugin-disk/snowy-plugin-disk-func/src/main/java/vip/xiaonuo/disk/service/CourseChapterKnowledgeService.java

@@ -78,4 +78,5 @@ public interface CourseChapterKnowledgeService extends IService<CourseChapterKno
      **/
     CourseChapterKnowledge queryEntity(String id);
 
+    List<String> selectknowledge(String courseId, String chapterId);
 }

+ 8 - 2
snowy-plugin/snowy-plugin-disk/snowy-plugin-disk-func/src/main/java/vip/xiaonuo/disk/service/impl/CourseChapterKnowledgeServiceImpl.java

@@ -32,6 +32,7 @@ import vip.xiaonuo.disk.param.konwledge.CourseChapterKnowledgeIdParam;
 import vip.xiaonuo.disk.param.konwledge.CourseChapterKnowledgePageParam;
 import vip.xiaonuo.disk.service.CourseChapterKnowledgeService;
 
+import javax.annotation.Resource;
 import java.util.List;
 
 /**
@@ -42,8 +43,8 @@ import java.util.List;
  **/
 @Service
 public class CourseChapterKnowledgeServiceImpl extends ServiceImpl<CourseChapterKnowledgeMapper, CourseChapterKnowledge> implements CourseChapterKnowledgeService {
-
-
+    @Resource
+    private CourseChapterKnowledgeMapper courseChapterKnowledgeMapper;
     @Override
     public Page<CourseChapterKnowledge> page(CourseChapterKnowledgePageParam courseChapterKnowledgePageParam) {
         QueryWrapper<CourseChapterKnowledge> queryWrapper = new QueryWrapper<>();
@@ -93,4 +94,9 @@ public class CourseChapterKnowledgeServiceImpl extends ServiceImpl<CourseChapter
         return courseChapterKnowledge;
     }
 
+    @Override
+    public List<String> selectknowledge(String courseId, String chapterId) {
+        return courseChapterKnowledgeMapper.selectknowledge(courseId,chapterId);
+    }
+
 }

+ 7 - 10
snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/controller/student/ExamPaperAnswerController.java

@@ -2,13 +2,16 @@ package vip.xiaonuo.exam.controller.student;
 
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.web.bind.annotation.*;
 import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser;
 import vip.xiaonuo.common.pojo.CommonResult;
 import vip.xiaonuo.exam.base.BaseApiController;
-import vip.xiaonuo.exam.base.RestResponse;
-
-import vip.xiaonuo.exam.domain.*;
+import vip.xiaonuo.exam.domain.ExamPaperAnswer;
+import vip.xiaonuo.exam.domain.ExamPaperAnswerInfo;
+import vip.xiaonuo.exam.domain.Subject;
+import vip.xiaonuo.exam.domain.UserEventLog;
 import vip.xiaonuo.exam.domain.enums.ExamPaperAnswerStatusEnum;
 import vip.xiaonuo.exam.event.CalculateExamPaperAnswerCompleteEvent;
 import vip.xiaonuo.exam.event.UserEvent;
@@ -17,16 +20,10 @@ import vip.xiaonuo.exam.service.ExamPaperService;
 import vip.xiaonuo.exam.service.SubjectService;
 import vip.xiaonuo.exam.utility.DateTimeUtil;
 import vip.xiaonuo.exam.utility.ExamUtil;
-import vip.xiaonuo.exam.utility.PageInfoHelper;
 import vip.xiaonuo.exam.viewmodel.admin.exam.ExamPaperEditRequestVM;
 import vip.xiaonuo.exam.viewmodel.student.exam.ExamPaperReadVM;
 import vip.xiaonuo.exam.viewmodel.student.exam.ExamPaperSubmitVM;
-import vip.xiaonuo.exam.viewmodel.student.exampaper.ExamPaperAnswerPageResponseVM;
 import vip.xiaonuo.exam.viewmodel.student.exampaper.ExamPaperAnswerPageVM;
-import com.github.pagehelper.PageInfo;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
 import java.util.Date;

+ 1 - 1
snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/mapper/TExamMapper.java

@@ -35,5 +35,5 @@ public interface TExamMapper extends BaseMapper<TExam> {
 
     List<TExamPaperStastic> stasticByPaperId(String paperId);
 
-    Page<TExamVo> queryStudentList(Page<Object> objectPage, TExamPageParam tExamPageParam);
+    Page<TExamVo> queryStudentList(@Param("page") Page<Object> objectPage,@Param("tExamPageParam") TExamPageParam tExamPageParam);
 }

+ 5 - 5
snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/mapper/mapping/TExamMapper.xml

@@ -65,17 +65,17 @@
         a.EXAM_TYPE examType,
         a.SEMESTER_ID semesterId,
         c.name semesterName,
-        a.course_id courseId
+        a.course_id courseId,
+        NVL(d.status, 0) AS status,
+        d.id answerId
         FROM
         ONLINEEDU.T_EXAM a
         LEFT JOIN  SEMESTER c ON a.SEMESTER_ID =c.ID
+        LEFT JOIN t_exam_paper_answer d ON d.exam_paper_id = a.PAPER_ID AND d.create_user = #{tExamPageParam.userId}
         <where>
             <if test="tExamPageParam.examName != null and tExamPageParam.examName != ''">
                 a.EXAM_NAME like '%'||#{tExamPageParam.examName}||'%'
             </if>
-            <if test="tExamPageParam.examStatus != null and tExamPageParam.examStatus != ''">
-                and a.EXAM_STATUS = #{tExamPageParam.examStatus}
-            </if>
             <if test="tExamPageParam.semesterId != null and tExamPageParam.semesterId != ''">
                 and a.SEMESTER_ID = #{tExamPageParam.semesterId}
             </if>
@@ -85,7 +85,7 @@
             <if test="tExamPageParam.createUser != null and tExamPageParam.createUser != ''">
                 and a.STUDENT_IDS like concat('%',#{tExamPageParam.createUser},'%')
             </if>
-            and  a.DELETED=0
+            and  a.DELETED=0  and  a.EXAM_STATUS=1
         </where>
         order by a.CREATE_TIME desc
     </select>

+ 5 - 9
snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/service/impl/ExamPaperAnswerServiceImpl.java

@@ -1,18 +1,20 @@
 package vip.xiaonuo.exam.service.impl;
 
-import cn.hutool.json.JSONString;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser;
 import vip.xiaonuo.exam.domain.*;
 import vip.xiaonuo.exam.domain.enums.ExamPaperAnswerStatusEnum;
 import vip.xiaonuo.exam.domain.enums.ExamPaperTypeEnum;
 import vip.xiaonuo.exam.domain.enums.QuestionTypeEnum;
 import vip.xiaonuo.exam.domain.exam.ExamPaperTitleItemObject;
-import vip.xiaonuo.exam.domain.other.KeyValue;
 import vip.xiaonuo.exam.domain.other.ExamPaperAnswerUpdate;
+import vip.xiaonuo.exam.domain.other.KeyValue;
 import vip.xiaonuo.exam.domain.task.TaskItemAnswerObject;
 import vip.xiaonuo.exam.mapper.ExamPaperAnswerMapper;
 import vip.xiaonuo.exam.mapper.ExamPaperMapper;
@@ -28,12 +30,6 @@ import vip.xiaonuo.exam.viewmodel.admin.paper.ExamPaperAnswerPageRequestVM;
 import vip.xiaonuo.exam.viewmodel.student.exam.ExamPaperSubmitItemVM;
 import vip.xiaonuo.exam.viewmodel.student.exam.ExamPaperSubmitVM;
 import vip.xiaonuo.exam.viewmodel.student.exampaper.ExamPaperAnswerPageVM;
-import com.github.pagehelper.PageHelper;
-import com.github.pagehelper.PageInfo;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
 import java.util.Date;
@@ -193,7 +189,7 @@ public class ExamPaperAnswerServiceImpl extends BaseServiceImpl<ExamPaperAnswer>
         ExamPaperAnswer examPaperAnswer = examPaperAnswerMapper.selectByPrimaryKey(id);
         examPaperSubmitVM.setId(examPaperAnswer.getId());
         examPaperSubmitVM.setDoTime(examPaperAnswer.getDoTime());
-        examPaperSubmitVM.setScore(ExamUtil.scoreToVM(examPaperAnswer.getUserScore()));
+        examPaperSubmitVM.setScore(String.valueOf(examPaperAnswer.getUserScore()));
         List<ExamPaperQuestionCustomerAnswer> examPaperQuestionCustomerAnswers = examPaperQuestionCustomerAnswerService.selectListByPaperAnswerId(examPaperAnswer.getId());
         TextContent textContent = textContentService.selectById(examPaperQuestionCustomerAnswers.get(0).getTextContentId());
         List<ExamPaperSubmitItemVM> examPaperSubmitItemVMS = examPaperQuestionCustomerAnswers.stream()

+ 1 - 1
snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/service/impl/ExamPaperServiceImpl.java

@@ -149,7 +149,7 @@ public class ExamPaperServiceImpl extends BaseServiceImpl<ExamPaper> implements
             return tTitleVM;
         }).collect(Collectors.toList());
         vm.setTitleItems(examPaperTitleItemVMS);
-        vm.setScore(ExamUtil.scoreToVM(examPaper.getScore()));
+        vm.setScore(String.valueOf(examPaper.getScore()));
         if (ExamPaperTypeEnum.TimeLimit == ExamPaperTypeEnum.fromCode(examPaper.getPaperType())) {
             List<String> limitDateTime = Arrays.asList(DateTimeUtil.dateFormat(examPaper.getLimitStartTime()), DateTimeUtil.dateFormat(examPaper.getLimitEndTime()));
             vm.setLimitDateTime(limitDateTime);

+ 0 - 7
snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/service/impl/QuestionServiceImpl.java

@@ -15,7 +15,6 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser;
 import vip.xiaonuo.dev.api.DevDictApi;
-import vip.xiaonuo.disk.domain.Major;
 import vip.xiaonuo.disk.domain.Semester;
 import vip.xiaonuo.disk.mapper.MajorMapper;
 import vip.xiaonuo.disk.mapper.SemesterMapper;
@@ -109,7 +108,6 @@ public class QuestionServiceImpl extends BaseServiceImpl<Question> implements Qu
         question.setBankType(model.getBankType());
         question.setCreateUser(userId);
         question.setDeleted(false);
-        question.setMajorId(model.getMajorId());
         question.setCourseId(model.getCourseId());
         question.setSemesterId(model.getSemesterId());
         questionMapper.insertSelective(question);
@@ -127,7 +125,6 @@ public class QuestionServiceImpl extends BaseServiceImpl<Question> implements Qu
         if(model.getBankType() != null){
             question.setBankType(model.getBankType());
         }
-        question.setMajorId(model.getMajorId());
         question.setCourseId(model.getCourseId());
         question.setSemesterId(model.getSemesterId());
         questionMapper.updateByPrimaryKeySelective(question);
@@ -188,10 +185,6 @@ public class QuestionServiceImpl extends BaseServiceImpl<Question> implements Qu
             return questionEditItemVM;
         }).collect(Collectors.toList());
         questionEditRequestVM.setItems(editItems);
-        if(ObjectUtil.isNotEmpty(question.getMajorId())){
-            Major major = majorMapper.selectById(question.getMajorId());
-            questionEditRequestVM.setMajorName(major.getMajorName());
-        }
         if(ObjectUtil.isNotEmpty(question.getSemesterId())){
             Semester semester = semesterMapper.selectById(question.getSemesterId());
             questionEditRequestVM.setSemesterName(semester.getName());

+ 1 - 0
snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/service/impl/TExamServiceImpl.java

@@ -98,6 +98,7 @@ public class TExamServiceImpl extends ServiceImpl<TExamMapper, TExam> implements
         if(!StpLoginUserUtil.getLoginUser().getAccount().equals("superAdmin")){
             tExamPageParam.setCreateUser(StpLoginUserUtil.getLoginUser().getAccount());
         }
+        tExamPageParam.setUserId(StpLoginUserUtil.getLoginUser().getId());
         Page<TExamVo> page = tExamMapper.queryStudentList(CommonPageRequest.defaultPage(), tExamPageParam);
         return page;
     }

+ 11 - 0
snowy-plugin/snowy-plugin-exam/snowy-plugin-exam-func/src/main/java/vip/xiaonuo/exam/vo/TExamVo.java

@@ -89,4 +89,15 @@ public class TExamVo {
     @ApiModelProperty(value = "课程id", position = 15)
     private String courseId;
 
+    /**
+     * 试卷状态(0 未答题  1待判分 2已完成)
+     */
+    private Integer status;
+    /**
+     * 试卷答案id
+     */
+    private Integer answerId;
+
+
+
 }

+ 22 - 1
snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/controller/ForumPostInfoController.java

@@ -186,14 +186,35 @@ public class ForumPostInfoController {
     }
 
     /**
-     * 统计:根据日期查询发帖和回帖数
+     * 统计:学习进度概览 根据日期查询发帖和回帖数
      */
     @PostMapping("/forum/postinfo/getCountByDate")
     public CommonResult<JSONObject> getCountByDate(@RequestBody JSONObject json) {
         return forumPostInfoService.getCountByDate(json);
     }
 
+    /**
+     * 统计:教学活动分析 讨论互动统计
+     */
+    @PostMapping("/forum/postinfo/getCountByCourseAndDate")
+    public CommonResult<JSONObject> getCountByCourseAndDate(@RequestBody JSONObject json) {
+        return forumPostInfoService.getCountByCourseAndDate(json);
+    }
 
+    /**
+     * 统计:教学活动分析 学员和教员分别统计
+     */
+    @PostMapping("/forum/postinfo/getStudentAndTeacherCount")
+    public CommonResult<JSONObject> getStudentAndTeacherCount(@RequestBody JSONObject json) {
+        return forumPostInfoService.getStudentAndTeacherCount(json);
+    }
 
+    /**
+     * 统计:教学活动分析 课程的讨论主题统计
+     */
+    @PostMapping("/forum/postinfo/getStudentPostInfoList")
+    public CommonResult<JSONObject> getStudentPostInfoList(@RequestBody JSONObject json) {
+        return forumPostInfoService.getStudentPostInfoList(json);
+    }
 
 }

+ 35 - 0
snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/mapper/ForumPostInfoMapper.java

@@ -13,8 +13,12 @@
 package vip.xiaonuo.forum.modular.postinfo.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
 import vip.xiaonuo.forum.modular.postinfo.entity.ForumPostInfo;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * 帖子信息表Mapper接口
  *
@@ -22,4 +26,35 @@ import vip.xiaonuo.forum.modular.postinfo.entity.ForumPostInfo;
  * @date  2025/07/16 08:46
  **/
 public interface ForumPostInfoMapper extends BaseMapper<ForumPostInfo> {
+
+    /**
+     * 根据课程id和时间标识 查询讨论数和回帖数
+     *
+     * @param courseId 课程id
+     * @param dateType 时间标识 1=7天、2=30天、3=90天、4=365天
+     *
+     * @return 讨论数和回帖数
+     */
+    Map<String, Long> getPostCountAndReplyCountByCourse(@Param("courseId") String courseId, @Param("dateType") Integer dateType);
+
+    /**
+     * 根据课程id和时间标识 分别查询学员和教员的讨论数和回帖数
+     *
+     * @param courseId 课程id
+     * @param dateType 时间标识 1=7天、2=30天、3=90天、4=365天
+     *
+     * @return 学员和教员的讨论数和回帖数
+     */
+
+    Map<String, Long> getStudentAndTeacherCount(@Param("courseId") String courseId, @Param("dateType") Integer dateType);
+
+    /**
+     * 根据课程id和时间标识 查询讨论发帖情况
+     *
+     * @param courseId 课程id
+     * @param dateType 时间标识 1=7天、2=30天、3=90天、4=365天
+     *
+     * @return 发帖情况
+     */
+    List<Map<String, String>> getStudentPostInfoList(@Param("courseId") String courseId, @Param("dateType") Integer dateType);
 }

+ 90 - 0
snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/mapper/mapping/ForumPostInfoMapper.xml

@@ -2,4 +2,94 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="vip.xiaonuo.forum.modular.postinfo.mapper.ForumPostInfoMapper">
 
+    <select id="getPostCountAndReplyCountByCourse" resultType="java.util.Map">
+        SELECT
+        COUNT(CASE WHEN reply.PARENT_ID = '-1' THEN 1 END) AS postCount,
+        COUNT(CASE WHEN reply.PARENT_ID != '-1' THEN 1 END) AS replyCount
+        FROM FORUM_POST_REPLY reply
+        LEFT JOIN FORUM_CHAPTER_DISCUSSION chapter
+        ON reply.POST_ID = chapter.POST_ID
+        WHERE reply.POST_TYPE = 3
+        AND reply.CREATE_TIME >= CASE
+        WHEN #{dateType} = 1 THEN TRUNC(SYSDATE) - 6
+        WHEN #{dateType} = 2 THEN TRUNC(SYSDATE) - 29
+        WHEN #{dateType} = 3 THEN TRUNC(SYSDATE) - 89
+        WHEN #{dateType} = 4 THEN TRUNC(SYSDATE) - 364
+        ELSE TO_DATE('1970-01-01','YYYY-MM-DD') -- 默认值
+        END
+        AND reply.CREATE_TIME &lt; TRUNC(SYSDATE) + 1
+        <if test="courseId != null and courseId != ''">
+            AND chapter.COURSE_ID = #{courseId}
+        </if>
+    </select>
+
+    <select id="getStudentAndTeacherCount" resultType="java.util.Map">
+        SELECT
+        COUNT(CASE WHEN reply.PARENT_ID = '-1' AND reply.USER_EDU_IDENTITY = 1 THEN 1 END) AS studentPostCount,
+        COUNT(CASE WHEN reply.PARENT_ID != '-1' AND reply.USER_EDU_IDENTITY = 1 THEN 1 END) AS studentReplyCount,
+        COUNT(CASE WHEN reply.PARENT_ID = '-1' AND reply.USER_EDU_IDENTITY = 2 THEN 1 END) AS teacherPostCount,
+        COUNT(CASE WHEN reply.PARENT_ID != '-1' AND reply.USER_EDU_IDENTITY = 2 THEN 1 END) AS teacherReplyCount
+        FROM FORUM_POST_REPLY reply
+        LEFT JOIN FORUM_CHAPTER_DISCUSSION chapter
+        ON reply.POST_ID = chapter.POST_ID
+        WHERE reply.POST_TYPE = 3
+        AND reply.CREATE_TIME >= CASE
+        WHEN #{dateType} = 1 THEN TRUNC(SYSDATE) - 6
+        WHEN #{dateType} = 2 THEN TRUNC(SYSDATE) - 29
+        WHEN #{dateType} = 3 THEN TRUNC(SYSDATE) - 89
+        WHEN #{dateType} = 4 THEN TRUNC(SYSDATE) - 364
+        ELSE TO_DATE('1970-01-01','YYYY-MM-DD') -- 默认值
+        END
+        AND reply.CREATE_TIME &lt; TRUNC(SYSDATE) + 1
+        <if test="courseId != null and courseId != ''">
+            AND chapter.COURSE_ID = #{courseId}
+        </if>
+    </select>
+
+    <select id="getStudentPostInfoList" resultType="java.util.Map">
+        SELECT
+        reply.USER_ID,
+        MAX(reply.POST_ID) AS latest_post_id,
+        MAX(reply.PARENT_ID) AS latest_parent_id,
+        MAX(reply.REPLY_CONTENT) AS latest_content,
+        MAX(DATE_FORMAT(reply.CREATE_TIME, '%Y-%m-%d %H:%i:%s')) AS latest_create_time,
+        MAX(sysuser.NAME) AS userName,
+        MAX(post.POST_TITLE) AS postTitle,
+        COUNT(*) AS total_replies,
+        COALESCE(MAX(sub_reply.replyCount), 0) AS total_child_replies,
+        MAX(sub_reply.lastReplyTime) AS last_child_reply_time
+        FROM
+        FORUM_POST_REPLY as reply
+        LEFT JOIN SYS_USER as sysuser ON reply.USER_ID = sysuser.ID
+        LEFT JOIN FORUM_POST_INFO as post ON reply.POST_ID = post.POST_ID
+        LEFT JOIN FORUM_CHAPTER_DISCUSSION chapter ON reply.POST_ID = chapter.POST_ID
+        LEFT JOIN (
+        SELECT
+        PARENT_ID,
+        COUNT(*) as replyCount,
+        DATE_FORMAT(MAX(CREATE_TIME), '%Y-%m-%d %H:%i:%s') as lastReplyTime
+        FROM FORUM_POST_REPLY
+        GROUP BY PARENT_ID
+        ) sub_reply ON reply.REPLY_ID = sub_reply.PARENT_ID
+        WHERE
+        reply.POST_TYPE = 3
+        AND reply.CREATE_TIME >= CASE
+        WHEN #{dateType} = 1 THEN TRUNC(SYSDATE) - 6
+        WHEN #{dateType} = 2 THEN TRUNC(SYSDATE) - 29
+        WHEN #{dateType} = 3 THEN TRUNC(SYSDATE) - 89
+        WHEN #{dateType} = 4 THEN TRUNC(SYSDATE) - 364
+        ELSE TO_DATE('1970-01-01','YYYY-MM-DD')
+        END
+        AND reply.CREATE_TIME &lt; TRUNC(SYSDATE) + 1
+        <if test="courseId != null and courseId != ''">
+            AND chapter.COURSE_ID = #{courseId}
+        </if>
+        GROUP BY
+        reply.USER_ID
+        ORDER BY
+        latest_create_time DESC
+        LIMIT 5
+    </select>
+
+
 </mapper>

+ 16 - 0
snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/service/ForumPostInfoService.java

@@ -119,4 +119,20 @@ public interface ForumPostInfoService extends IService<ForumPostInfo> {
      * 统计:根据日期查询发帖和回帖数
      */
     CommonResult<JSONObject> getCountByDate(JSONObject json);
+
+    /**
+     * 统计:讨论互动统计
+     */
+    CommonResult<JSONObject> getCountByCourseAndDate(JSONObject json);
+
+    /**
+     * 统计:教学活动分析 学员和教员分别统计
+     */
+    CommonResult<JSONObject> getStudentAndTeacherCount(JSONObject json);
+
+    /**
+     * 统计:教学活动分析 学员课程的讨论主题统计
+     */
+    CommonResult<JSONObject> getStudentPostInfoList(JSONObject json);
+
 }

+ 97 - 0
snowy-plugin/snowy-plugin-forum/snowy-plugin-forum-func/src/main/java/vip/xiaonuo/forum/modular/postinfo/service/impl/ForumPostInfoServiceImpl.java

@@ -55,11 +55,15 @@ import vip.xiaonuo.forum.modular.supportenv.mapper.ForumSupportEnvMapper;
 import vip.xiaonuo.sys.api.SysUserApi;
 
 import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -100,6 +104,9 @@ public class ForumPostInfoServiceImpl extends ServiceImpl<ForumPostInfoMapper, F
     @Resource
     private ForumChapterDiscussionMapper forumChapterDiscussionMapper;
 
+    @Resource
+    private ForumPostInfoMapper forumPostInfoMapper;
+
 
     @Override
     public Page<ForumPostInfo> page(ForumPostInfoPageParam forumPostInfoPageParam) {
@@ -730,6 +737,96 @@ public class ForumPostInfoServiceImpl extends ServiceImpl<ForumPostInfoMapper, F
         return CommonResult.data(result);
     }
 
+    @Override
+    public CommonResult<com.alibaba.fastjson.JSONObject> getCountByCourseAndDate(com.alibaba.fastjson.JSONObject json) {
+        // 取出课程id,查询日期类型 最近7天、最近30天、最近90天、最近一年
+        String courseId = json.getString("courseId");
+        Integer dateType = json.getInteger("dateType");
+        // 查询讨论总数、回帖总数、平均回帖数
+        Map<String, Long> postCountAndReplyCount = forumPostInfoMapper.getPostCountAndReplyCountByCourse(courseId, dateType);
+        com.alibaba.fastjson.JSONObject result = new com.alibaba.fastjson.JSONObject();
+        Long replyCount = postCountAndReplyCount.getOrDefault("replyCount", 0L);
+        Long postCount = postCountAndReplyCount.getOrDefault("postCount", 0L);
+        result.put("postCount", postCount);
+        result.put("replyCount", replyCount);
+        // 计算平均回帖数 回帖数除以发帖数 并四舍五入后面只留一位小数
+        double avgReplyCount = 0.0;
+        if (postCount > 0) {
+            // 使用BigDecimal保证计算精度
+            BigDecimal reply = new BigDecimal(replyCount);
+            BigDecimal post = new BigDecimal(postCount);
+            avgReplyCount = reply.divide(post, 2, RoundingMode.HALF_UP).setScale(1, RoundingMode.HALF_UP).doubleValue();
+        }
+        result.put("avgReplyCount", avgReplyCount);
+        return CommonResult.data(result);
+    }
+
+    @Override
+    public CommonResult<com.alibaba.fastjson.JSONObject> getStudentAndTeacherCount(com.alibaba.fastjson.JSONObject json) {
+        // 取出课程id,查询日期类型 最近7天、最近30天、最近90天、最近一年
+        String courseId = json.getString("courseId");
+        Integer dateType = json.getInteger("dateType");
+        // 分别查询学员和教员的讨论总数、回帖总数
+        Map<String, Long> studentAndTeacher = forumPostInfoMapper.getStudentAndTeacherCount(courseId, dateType);
+        // 封装参数
+        com.alibaba.fastjson.JSONObject result = new com.alibaba.fastjson.JSONObject();
+        // 学员
+        Long studentPostCount = studentAndTeacher.getOrDefault("studentPostCount", 0L);
+        Long studentReplyCount = studentAndTeacher.getOrDefault("studentReplyCount", 0L);
+        // 计算学员日均回帖数
+        double studentAvgReplyCount = 0.0;
+        if (studentPostCount > 0) {
+            // 使用BigDecimal保证计算精度
+            BigDecimal reply = new BigDecimal(studentReplyCount);
+            BigDecimal post = new BigDecimal(studentPostCount);
+            studentAvgReplyCount = reply.divide(post, 2, RoundingMode.HALF_UP).setScale(1, RoundingMode.HALF_UP).doubleValue();
+        }
+        // 教员
+        Long teacherPostCount = studentAndTeacher.getOrDefault("teacherPostCount", 0L);
+        Long teacherReplyCount = studentAndTeacher.getOrDefault("teacherReplyCount", 0L);
+        // 计算教员日均回帖数
+        double teacherAvgReplyCount = 0.0;
+        if (teacherPostCount > 0) {
+            // 使用BigDecimal保证计算精度
+            BigDecimal reply = new BigDecimal(teacherReplyCount);
+            BigDecimal post = new BigDecimal(teacherPostCount);
+            teacherAvgReplyCount = reply.divide(post, 2, RoundingMode.HALF_UP).setScale(1, RoundingMode.HALF_UP).doubleValue();
+        }
+        result.put("studentPostCount", studentPostCount);
+        result.put("studentReplyCount", studentReplyCount);
+        result.put("studentAvgReplyCount", studentAvgReplyCount);
+        result.put("teacherPostCount", teacherPostCount);
+        result.put("teacherReplyCount", teacherReplyCount);
+        result.put("teacherAvgReplyCount", teacherAvgReplyCount);
+        return CommonResult.data(result);
+    }
+
+    @Override
+    public CommonResult<com.alibaba.fastjson.JSONObject> getStudentPostInfoList(com.alibaba.fastjson.JSONObject json) {
+        com.alibaba.fastjson.JSONObject result = new com.alibaba.fastjson.JSONObject();
+        // 取出课程id,查询日期类型 最近7天、最近30天、最近90天、最近一年
+        String courseId = json.getString("courseId");
+        Integer dateType = json.getInteger("dateType");
+        // 根据课程id查询出 讨论的用户
+        List<Map<String, String>> studentAndTeacher = forumPostInfoMapper.getStudentPostInfoList(courseId, dateType);
+        // 封装参数
+        JSONArray jsonArray = new JSONArray();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        if (studentAndTeacher.size() > 0) {
+            for (Map<String, String> dataMap : studentAndTeacher) {
+                com.alibaba.fastjson.JSONObject info = new com.alibaba.fastjson.JSONObject();
+                info.put("postTitle", dataMap.getOrDefault("postTitle", ""));
+                info.put("userName", dataMap.getOrDefault("userName", ""));
+                info.put("createTime", dataMap.getOrDefault("latest_create_time", ""));
+                info.put("replyCount", dataMap.getOrDefault("total_replies", "0"));
+                info.put("lastReplyTime", dataMap.getOrDefault("last_child_reply_time", ""));
+                jsonArray.add(info);
+            }
+        }
+        result.put("list", jsonArray);
+        return CommonResult.data(result);
+    }
+
     /**
      * 自动创建章节讨论类型的帖子
      */