Pārlūkot izejas kodu

1、数字人、课程ai问答加上问题提示
2、添加问卷添加试题管理功能
3、去除后台上传大小
4、评估报告管理
5、保存进度接口(视频进度、问题互动、ai问答)
6、前端接口去除免登录、免租户

liyanbo 9 mēneši atpakaļ
vecāks
revīzija
5e05da84f7
49 mainītis faili ar 2062 papildinājumiem un 27 dzēšanām
  1. 3 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/courseconfig/vo/CourseConfigPageReqVO.java
  2. 3 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/courseconfig/vo/CourseConfigRespVO.java
  3. 3 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/courseconfig/vo/CourseConfigSaveReqVO.java
  4. 144 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/questionnaire/QuestionnaireController.java
  5. 44 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/questionnaire/vo/ConfigQuestionRespVO.java
  6. 38 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/questionnaire/vo/QuestionnairePageReqVO.java
  7. 47 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/questionnaire/vo/QuestionnaireRespVO.java
  8. 35 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/questionnaire/vo/QuestionnaireSaveReqVO.java
  9. 105 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/reportmanage/ReportManageController.java
  10. 44 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/reportmanage/vo/ReportManagePageReqVO.java
  11. 55 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/reportmanage/vo/ReportManageRespVO.java
  12. 39 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/reportmanage/vo/ReportManageSaveReqVO.java
  13. 6 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/dal/dataobject/courseconfig/CourseConfigDO.java
  14. 55 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/dal/dataobject/questionnaire/QuestionnaireDO.java
  15. 63 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/dal/dataobject/reportmanage/ReportManageDO.java
  16. 51 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/dal/mysql/questionnaire/QuestionnaireMapper.java
  17. 32 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/dal/mysql/reportmanage/ReportManageMapper.java
  18. 9 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/enums/ErrorCodeConstants.java
  19. 8 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/coursequestion/CourseQuestionService.java
  20. 5 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/coursequestion/CourseQuestionServiceImpl.java
  21. 94 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/questionnaire/QuestionnaireService.java
  22. 125 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/questionnaire/QuestionnaireServiceImpl.java
  23. 63 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/reportmanage/ReportManageService.java
  24. 90 0
      byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/reportmanage/ReportManageServiceImpl.java
  25. 2 1
      byzs-course/src/main/resources/mapper/courseconfig/CourseConfigMapper.xml
  26. 87 0
      byzs-course/src/main/resources/mapper/questionnaire/QuestionnaireMapper.xml
  27. 7 0
      byzs-course/src/main/resources/mapper/reportmanage/ReportManageMapper.xml
  28. 3 0
      byzs-module-ai/src/main/java/cn/iocoder/byzs/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java
  29. 3 0
      byzs-module-ai/src/main/java/cn/iocoder/byzs/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java
  30. 3 0
      byzs-module-ai/src/main/java/cn/iocoder/byzs/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java
  31. 3 0
      byzs-module-ai/src/main/java/cn/iocoder/byzs/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java
  32. 5 0
      byzs-module-ai/src/main/java/cn/iocoder/byzs/module/ai/dal/dataobject/model/AiChatRoleDO.java
  33. 4 4
      byzs-module-infra/src/main/java/cn/iocoder/byzs/module/infra/controller/admin/file/FileController.java
  34. 2 2
      byzs-server/src/main/resources/application-local.yaml
  35. 0 12
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/ai/WebAiController.java
  36. 3 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/ai/vo/WebAiChatRoleVO.java
  37. 0 8
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/course/WebCourseController.java
  38. 52 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/questionnaire/WebQuestionnaireController.java
  39. 66 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/questionnaire/vo/WebQuestionnaireResultVo.java
  40. 66 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/questionnaire/vo/WebQuestionnaireVo.java
  41. 61 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/reportprogress/WebReportProgressController.java
  42. 65 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/reportprogress/vo/WebReportProgressDO.java
  43. 48 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/reportprogress/vo/WebReportProgressDTO.java
  44. 70 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/reportprogress/vo/WebReportProgressVO.java
  45. 17 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/dal/mysql/questionnaire/WebQuestionnaireMapper.java
  46. 19 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/dal/mysql/reportprogress/WebReportProgressMapper.java
  47. 93 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/service/questionnaire/WebQuestionnaireServiceImpl.java
  48. 204 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/service/reportprogress/WebReportProgressServiceImpl.java
  49. 18 0
      byzs-web/src/main/resources/mapper/reportprogress/ReportProgressMapper.xml

+ 3 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/courseconfig/vo/CourseConfigPageReqVO.java

@@ -29,6 +29,9 @@ public class CourseConfigPageReqVO extends PageParam {
     @Schema(description = "试题选项")
     private String ccQuestOption;
 
+    @Schema(description = "ai问题提示")
+    private String ccAiQuestTip;
+
     @Schema(description = "ai答案")
     private String ccAiAnswer;
 

+ 3 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/courseconfig/vo/CourseConfigRespVO.java

@@ -38,6 +38,9 @@ public class CourseConfigRespVO {
     @ExcelProperty("试题选项")
     private String ccQuestOption;
 
+    @Schema(description = "ai问题提示")
+    private String ccAiQuestTip;
+
     @Schema(description = "ai答案")
     @ExcelProperty("ai答案")
     private String ccAiAnswer;

+ 3 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/courseconfig/vo/CourseConfigSaveReqVO.java

@@ -27,6 +27,9 @@ public class CourseConfigSaveReqVO {
     @Schema(description = "试题选项")
     private String ccQuestOption;
 
+    @Schema(description = "ai问题提示")
+    private String ccAiQuestTip;
+
     @Schema(description = "ai答案")
     private String ccAiAnswer;
 

+ 144 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/questionnaire/QuestionnaireController.java

@@ -0,0 +1,144 @@
+package cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire;
+
+import org.springframework.web.bind.annotation.*;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import jakarta.validation.constraints.*;
+import jakarta.validation.*;
+import jakarta.servlet.http.*;
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.byzs.framework.common.pojo.PageParam;
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.framework.common.pojo.CommonResult;
+import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
+import static cn.iocoder.byzs.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.byzs.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.byzs.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.byzs.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.*;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.questionnaire.QuestionnaireDO;
+import cn.iocoder.byzs.module.bjdx.service.questionnaire.QuestionnaireService;
+
+@Tag(name = "管理后台 - 问卷")
+@RestController
+@RequestMapping("/bjdx/questionnaire")
+@Validated
+public class QuestionnaireController {
+
+    @Resource
+    private QuestionnaireService questionnaireService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建问卷")
+    @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:create')")
+    public CommonResult<Long> createQuestionnaire(@Valid @RequestBody QuestionnaireSaveReqVO createReqVO) {
+        return success(questionnaireService.createQuestionnaire(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新问卷")
+    @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:update')")
+    public CommonResult<Boolean> updateQuestionnaire(@Valid @RequestBody QuestionnaireSaveReqVO updateReqVO) {
+        questionnaireService.updateQuestionnaire(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除问卷")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:delete')")
+    public CommonResult<Boolean> deleteQuestionnaire(@RequestParam("id") Long id) {
+        questionnaireService.deleteQuestionnaire(id);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete-list")
+    @Parameter(name = "ids", description = "编号", required = true)
+    @Operation(summary = "批量删除问卷")
+                @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:delete')")
+    public CommonResult<Boolean> deleteQuestionnaireList(@RequestParam("ids") List<Long> ids) {
+        questionnaireService.deleteQuestionnaireListByIds(ids);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得问卷")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:query')")
+    public CommonResult<QuestionnaireRespVO> getQuestionnaire(@RequestParam("id") Long id) {
+        QuestionnaireDO questionnaire = questionnaireService.getQuestionnaire(id);
+        return success(BeanUtils.toBean(questionnaire, QuestionnaireRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得问卷分页")
+    @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:query')")
+    public CommonResult<PageResult<QuestionnaireRespVO>> getQuestionnairePage(@Valid QuestionnairePageReqVO pageReqVO) {
+        PageResult<QuestionnaireDO> pageResult = questionnaireService.getQuestionnairePage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, QuestionnaireRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出问卷 Excel")
+    @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportQuestionnaireExcel(@Valid QuestionnairePageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<QuestionnaireDO> list = questionnaireService.getQuestionnairePage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "问卷.xls", "数据", QuestionnaireRespVO.class,
+                        BeanUtils.toBean(list, QuestionnaireRespVO.class));
+    }
+
+
+
+
+
+    @GetMapping("/getConfigQuest")
+    @Operation(summary = "获得问卷配置的试题")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:query')")
+    public CommonResult<PageResult<ConfigQuestionRespVO>> getConfigQuest(@Valid ConfigQuestionRespVO configQuestionRespVO) {
+        PageResult<ConfigQuestionRespVO> configQuestPage = questionnaireService.getConfigQuestPage(configQuestionRespVO);
+        return success(configQuestPage);
+    }
+
+    @GetMapping("/getConfigQuestNo")
+    @Operation(summary = "获得问卷配置的未配置试题")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:query')")
+    public CommonResult<PageResult<ConfigQuestionRespVO>> getConfigQuestNo(@Valid ConfigQuestionRespVO configQuestionRespVO) {
+        PageResult<ConfigQuestionRespVO> configQuestPage = questionnaireService.getConfigQuestNoPage(configQuestionRespVO);
+        return success(configQuestPage);
+    }
+
+    @GetMapping("/addConfigQuest")
+    @Operation(summary = "获得问卷配置的试题")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:query')")
+    public CommonResult<Boolean> addConfigQuest(@Valid ConfigQuestionRespVO configQuestionRespVO) {
+        questionnaireService.addConfigQuest(configQuestionRespVO);
+        return success(true);
+    }
+
+    @GetMapping("/delConfigQuest")
+    @Operation(summary = "获得问卷配置的未配置试题")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('bjdx:questionnaire:query')")
+    public CommonResult<Boolean> delConfigQuest(@Valid ConfigQuestionRespVO configQuestionRespVO) {
+        questionnaireService.delConfigQuest(configQuestionRespVO);
+        return success(true);
+    }
+
+}

+ 44 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/questionnaire/vo/ConfigQuestionRespVO.java

@@ -0,0 +1,44 @@
+package cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo;
+
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.coursequestoption.CourseQuestOptionDO;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 课程-试题 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class ConfigQuestionRespVO {
+
+    @Schema(description = "问卷id", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Long questionnaireId;
+
+    @Schema(description = "课程试题id", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Long id;
+
+    @Schema(description = "课程试题id", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Long[] questionIds;
+
+    @Schema(description = "试题内容")
+    private String cqQuestion;
+
+    @Schema(description = "试题解析")
+    private String cqQuestAnalysis;
+
+    @Schema(description = "试题类型")
+    private String cqQuestType;
+
+    @Schema(description = "试题答案id")
+    private Integer cqQuestAnswerId;
+
+    @Schema(description = "试题排序")
+    private Integer bqOrder;
+
+
+    @Schema(description = "选项列表")
+    private List<CourseQuestOptionDO> courseQuestOptionList;
+
+}

+ 38 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/questionnaire/vo/QuestionnairePageReqVO.java

@@ -0,0 +1,38 @@
+package cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo;
+
+import cn.iocoder.byzs.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.byzs.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 问卷分页 Request VO")
+@Data
+public class QuestionnairePageReqVO extends PageParam {
+
+    @Schema(description = "问卷名称")
+    private String bqQuestionnaire;
+
+    @Schema(description = "问卷介绍")
+    private String bqDetails;
+
+    @Schema(description = "问卷排序")
+    private Integer bqOrder;
+
+    @Schema(description = "问卷开始指导语")
+    private String bqStartInfo;
+
+    @Schema(description = "问卷结束指导语")
+    private String bqEndInfo;
+
+    @Schema(description = "问题id集")
+    private String bqQuestIds;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 47 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/questionnaire/vo/QuestionnaireRespVO.java

@@ -0,0 +1,47 @@
+package cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 问卷 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class QuestionnaireRespVO {
+
+    @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "3832")
+    @ExcelProperty("id")
+    private Long id;
+
+    @Schema(description = "问卷名称", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("问卷名称")
+    private String bqQuestionnaire;
+
+    @Schema(description = "问卷介绍")
+    @ExcelProperty("问卷介绍")
+    private String bqDetails;
+
+    @Schema(description = "问卷排序", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("问卷排序")
+    private Integer bqOrder;
+
+    @Schema(description = "问卷开始指导语")
+    @ExcelProperty("问卷开始指导语")
+    private String bqStartInfo;
+
+    @Schema(description = "问卷结束指导语")
+    @ExcelProperty("问卷结束指导语")
+    private String bqEndInfo;
+
+    @Schema(description = "问题id集")
+    @ExcelProperty("问题id集")
+    private String bqQuestIds;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 35 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/questionnaire/vo/QuestionnaireSaveReqVO.java

@@ -0,0 +1,35 @@
+package cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 问卷新增/修改 Request VO")
+@Data
+public class QuestionnaireSaveReqVO {
+
+    @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "3832")
+    private Long id;
+
+    @Schema(description = "问卷名称", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotEmpty(message = "问卷名称不能为空")
+    private String bqQuestionnaire;
+
+    @Schema(description = "问卷介绍")
+    private String bqDetails;
+
+    @Schema(description = "问卷排序", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "问卷排序不能为空")
+    private Integer bqOrder;
+
+    @Schema(description = "问卷开始指导语")
+    private String bqStartInfo;
+
+    @Schema(description = "问卷结束指导语")
+    private String bqEndInfo;
+
+    @Schema(description = "问题id集")
+    private String bqQuestIds;
+
+}

+ 105 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/reportmanage/ReportManageController.java

@@ -0,0 +1,105 @@
+package cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage;
+
+import cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo.ReportManagePageReqVO;
+import cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo.ReportManageRespVO;
+import cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo.ReportManageSaveReqVO;
+import org.springframework.web.bind.annotation.*;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import jakarta.validation.*;
+import jakarta.servlet.http.*;
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.byzs.framework.common.pojo.PageParam;
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.framework.common.pojo.CommonResult;
+import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
+import static cn.iocoder.byzs.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.byzs.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.byzs.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.byzs.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.reportmanage.ReportManageDO;
+import cn.iocoder.byzs.module.bjdx.service.reportmanage.ReportManageService;
+
+@Tag(name = "管理后台 - 评估报告-评语")
+@RestController
+@RequestMapping("/bjdxReport/manage")
+@Validated
+public class ReportManageController {
+
+    @Resource
+    private ReportManageService manageService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建评估报告-评语")
+    @PreAuthorize("@ss.hasPermission('report:manage:create')")
+    public CommonResult<Long> createManage(@Valid @RequestBody ReportManageSaveReqVO createReqVO) {
+        return success(manageService.createManage(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新评估报告-评语")
+    @PreAuthorize("@ss.hasPermission('report:manage:update')")
+    public CommonResult<Boolean> updateManage(@Valid @RequestBody ReportManageSaveReqVO updateReqVO) {
+        manageService.updateManage(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除评估报告-评语")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('report:manage:delete')")
+    public CommonResult<Boolean> deleteManage(@RequestParam("id") Long id) {
+        manageService.deleteManage(id);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete-list")
+    @Parameter(name = "ids", description = "编号", required = true)
+    @Operation(summary = "批量删除评估报告-评语")
+                @PreAuthorize("@ss.hasPermission('report:manage:delete')")
+    public CommonResult<Boolean> deleteManageList(@RequestParam("ids") List<Long> ids) {
+        manageService.deleteManageListByIds(ids);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得评估报告-评语")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('report:manage:query')")
+    public CommonResult<ReportManageRespVO> getManage(@RequestParam("id") Long id) {
+        ReportManageDO manage = manageService.getManage(id);
+        return success(BeanUtils.toBean(manage, ReportManageRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得评估报告-评语分页")
+    @PreAuthorize("@ss.hasPermission('report:manage:query')")
+    public CommonResult<PageResult<ReportManageRespVO>> getManagePage(@Valid ReportManagePageReqVO pageReqVO) {
+        PageResult<ReportManageDO> pageResult = manageService.getManagePage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, ReportManageRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出评估报告-评语 Excel")
+    @PreAuthorize("@ss.hasPermission('report:manage:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportManageExcel(@Valid ReportManagePageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<ReportManageDO> list = manageService.getManagePage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "评估报告-评语.xls", "数据", ReportManageRespVO.class,
+                        BeanUtils.toBean(list, ReportManageRespVO.class));
+    }
+
+}

+ 44 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/reportmanage/vo/ReportManagePageReqVO.java

@@ -0,0 +1,44 @@
+package cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo;
+
+import cn.iocoder.byzs.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.byzs.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 评估报告-评语分页 Request VO")
+@Data
+public class ReportManagePageReqVO extends PageParam {
+
+    @Schema(description = "开课率最小")
+    private Double brcReportCourseMin;
+
+    @Schema(description = "开课率最大")
+    private Double brcReportCourseMax;
+
+    @Schema(description = "互动最小")
+    private Double brcReportQuestMin;
+
+    @Schema(description = "互动最大")
+    private Double brcReportQuestMax;
+
+    @Schema(description = "ai问答次数最小")
+    private Double brcReportAiCountMin;
+
+    @Schema(description = "ai问答次数最大")
+    private Double brcReportAiCountMax;
+
+    @Schema(description = "等级")
+    private String brcReportLevel;
+
+    @Schema(description = "评语")
+    private String brcReportComment;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 55 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/reportmanage/vo/ReportManageRespVO.java

@@ -0,0 +1,55 @@
+package cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 评估报告-评语 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class ReportManageRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "25358")
+    @ExcelProperty("主键id")
+    private Long brcId;
+
+    @Schema(description = "开课率最小")
+    @ExcelProperty("开课率最小")
+    private Double brcReportCourseMin;
+
+    @Schema(description = "开课率最大")
+    @ExcelProperty("开课率最大")
+    private Double brcReportCourseMax;
+
+    @Schema(description = "互动最小")
+    @ExcelProperty("互动最小")
+    private Double brcReportQuestMin;
+
+    @Schema(description = "互动最大")
+    @ExcelProperty("互动最大")
+    private Double brcReportQuestMax;
+
+    @Schema(description = "ai问答次数最小")
+    @ExcelProperty("ai问答次数最小")
+    private Double brcReportAiCountMin;
+
+    @Schema(description = "ai问答次数最大")
+    @ExcelProperty("ai问答次数最大")
+    private Double brcReportAiCountMax;
+
+    @Schema(description = "等级")
+    @ExcelProperty("等级")
+    private String brcReportLevel;
+
+    @Schema(description = "评语")
+    @ExcelProperty("评语")
+    private String brcReportComment;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 39 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/controller/admin/reportmanage/vo/ReportManageSaveReqVO.java

@@ -0,0 +1,39 @@
+package cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import jakarta.validation.constraints.*;
+
+@Schema(description = "管理后台 - 评估报告-评语新增/修改 Request VO")
+@Data
+public class ReportManageSaveReqVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "25358")
+    private Long brcId;
+
+    @Schema(description = "开课率最小")
+    private Double brcReportCourseMin;
+
+    @Schema(description = "开课率最大")
+    private Double brcReportCourseMax;
+
+    @Schema(description = "互动最小")
+    private Double brcReportQuestMin;
+
+    @Schema(description = "互动最大")
+    private Double brcReportQuestMax;
+
+    @Schema(description = "ai问答次数最小")
+    private Double brcReportAiCountMin;
+
+    @Schema(description = "ai问答次数最大")
+    private Double brcReportAiCountMax;
+
+    @Schema(description = "等级")
+    private String brcReportLevel;
+
+    @Schema(description = "评语")
+    private String brcReportComment;
+
+}

+ 6 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/dal/dataobject/courseconfig/CourseConfigDO.java

@@ -4,6 +4,7 @@ import cn.iocoder.byzs.framework.mybatis.core.dataobject.BaseDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;
 
 /**
@@ -50,6 +51,11 @@ public class CourseConfigDO extends BaseDO {
      */
     private String ccQuestOption;
 
+    /**
+     * ai问题提示
+     */
+    private String ccAiQuestTip;
+
     /**
      * ai答案
      */

+ 55 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/dal/dataobject/questionnaire/QuestionnaireDO.java

@@ -0,0 +1,55 @@
+package cn.iocoder.byzs.module.bjdx.dal.dataobject.questionnaire;
+
+import cn.iocoder.byzs.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+/**
+ * 问卷 DO
+ *
+ * @author lyb
+ */
+@TableName("bjdx_questionnaire")
+@KeySequence("bjdx_questionnaire_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class QuestionnaireDO extends BaseDO {
+
+    /**
+     * id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 问卷名称
+     */
+    private String bqQuestionnaire;
+    /**
+     * 问卷介绍
+     */
+    private String bqDetails;
+    /**
+     * 问卷排序
+     */
+    private Integer bqOrder;
+    /**
+     * 问卷开始指导语
+     */
+    private String bqStartInfo;
+    /**
+     * 问卷结束指导语
+     */
+    private String bqEndInfo;
+    /**
+     * 问题id集
+     */
+    private String bqQuestIds;
+
+
+}

+ 63 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/dal/dataobject/reportmanage/ReportManageDO.java

@@ -0,0 +1,63 @@
+package cn.iocoder.byzs.module.bjdx.dal.dataobject.reportmanage;
+
+import cn.iocoder.byzs.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+/**
+ * 评估报告-评语 DO
+ *
+ * @author lyb
+ */
+@TableName("bjdx_report_manage")
+@KeySequence("bjdx_report_manage_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ReportManageDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long brcId;
+    /**
+     * 开课率最小
+     */
+    private Double brcReportCourseMin;
+    /**
+     * 开课率最大
+     */
+    private Double brcReportCourseMax;
+    /**
+     * 互动最小
+     */
+    private Double brcReportQuestMin;
+    /**
+     * 互动最大
+     */
+    private Double brcReportQuestMax;
+    /**
+     * ai问答次数最小
+     */
+    private Double brcReportAiCountMin;
+    /**
+     * ai问答次数最大
+     */
+    private Double brcReportAiCountMax;
+    /**
+     * 等级
+     */
+    private String brcReportLevel;
+    /**
+     * 评语
+     */
+    private String brcReportComment;
+
+
+}

+ 51 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/dal/mysql/questionnaire/QuestionnaireMapper.java

@@ -0,0 +1,51 @@
+package cn.iocoder.byzs.module.bjdx.dal.mysql.questionnaire;
+
+import java.util.*;
+
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.byzs.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.questionnaire.QuestionnaireDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.*;
+
+/**
+ * 问卷 Mapper
+ *
+ * @author lyb
+ */
+@Mapper
+public interface QuestionnaireMapper extends BaseMapperX<QuestionnaireDO> {
+
+    default PageResult<QuestionnaireDO> selectPage(QuestionnairePageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<QuestionnaireDO>()
+                .likeIfPresent(QuestionnaireDO::getBqQuestionnaire, reqVO.getBqQuestionnaire())
+                .eqIfPresent(QuestionnaireDO::getBqDetails, reqVO.getBqDetails())
+                .eqIfPresent(QuestionnaireDO::getBqOrder, reqVO.getBqOrder())
+                .eqIfPresent(QuestionnaireDO::getBqStartInfo, reqVO.getBqStartInfo())
+                .eqIfPresent(QuestionnaireDO::getBqEndInfo, reqVO.getBqEndInfo())
+                .eqIfPresent(QuestionnaireDO::getBqQuestIds, reqVO.getBqQuestIds())
+                .betweenIfPresent(QuestionnaireDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(QuestionnaireDO::getId));
+    }
+
+    List<ConfigQuestionRespVO> selectConfigQuestionList(ConfigQuestionRespVO configQuestionRespVO);
+
+    List<ConfigQuestionRespVO> selectConfigQuestionNoList(ConfigQuestionRespVO configQuestionRespVO);
+
+
+    /**
+     * 添加问卷试题配置
+     *
+     * @param configQuestionRespVO 编号
+     */
+    void addConfigQuest(ConfigQuestionRespVO configQuestionRespVO);
+
+    /**
+     * 删除问卷试题配置
+     *
+     * @param configQuestionRespVO 编号
+     */
+    void delConfigQuest(ConfigQuestionRespVO configQuestionRespVO);
+
+}

+ 32 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/dal/mysql/reportmanage/ReportManageMapper.java

@@ -0,0 +1,32 @@
+package cn.iocoder.byzs.module.bjdx.dal.mysql.reportmanage;
+
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.byzs.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo.ReportManagePageReqVO;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.reportmanage.ReportManageDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 评估报告-评语 Mapper
+ *
+ * @author lyb
+ */
+@Mapper
+public interface ReportManageMapper extends BaseMapperX<ReportManageDO> {
+
+    default PageResult<ReportManageDO> selectPage(ReportManagePageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<ReportManageDO>()
+                .eqIfPresent(ReportManageDO::getBrcReportCourseMin, reqVO.getBrcReportCourseMin())
+                .eqIfPresent(ReportManageDO::getBrcReportCourseMax, reqVO.getBrcReportCourseMax())
+                .eqIfPresent(ReportManageDO::getBrcReportQuestMin, reqVO.getBrcReportQuestMin())
+                .eqIfPresent(ReportManageDO::getBrcReportQuestMax, reqVO.getBrcReportQuestMax())
+                .eqIfPresent(ReportManageDO::getBrcReportAiCountMin, reqVO.getBrcReportAiCountMin())
+                .eqIfPresent(ReportManageDO::getBrcReportAiCountMax, reqVO.getBrcReportAiCountMax())
+                .eqIfPresent(ReportManageDO::getBrcReportLevel, reqVO.getBrcReportLevel())
+                .eqIfPresent(ReportManageDO::getBrcReportComment, reqVO.getBrcReportComment())
+                .betweenIfPresent(ReportManageDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(ReportManageDO::getBrcId));
+    }
+
+}

+ 9 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/enums/ErrorCodeConstants.java

@@ -31,4 +31,13 @@ public interface ErrorCodeConstants {
     // ========== 课程-试题-选项 1_060_050_000 ==========
     ErrorCode COURSE_QUEST_OPTION_NOT_EXISTS = new ErrorCode(1_060_050_000, "课程-试题-选项不存在");
 
+    // ========== 问卷 1_070_000_000 ==========
+    ErrorCode QUESTIONNAIRE_NOT_EXISTS = new ErrorCode(1_070_010_000, "问卷不存在");
+
+    // ========== 报告 1_080_000_000 ==========
+    ErrorCode MANAGE_NOT_EXISTS = new ErrorCode(1_080_010_000, "报告不存在");
+
+    // ========== 进度 1_090_000_000 ==========
+    ErrorCode PROGRESS_NOT_EXISTS = new ErrorCode(1_090_010_000, "课程配置id不能为空");
+
 }

+ 8 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/coursequestion/CourseQuestionService.java

@@ -61,4 +61,12 @@ public interface CourseQuestionService {
      */
     PageResult<CourseQuestionDO> getCourseQuestionPage(CourseQuestionPageReqVO pageReqVO);
 
+    /**
+     * 获得课程-试题分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 课程-试题分页
+     */
+    PageResult<CourseQuestionDO> getCourseQuestionNoPage(CourseQuestionPageReqVO pageReqVO);
+
 }

+ 5 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/coursequestion/CourseQuestionServiceImpl.java

@@ -88,4 +88,9 @@ public class CourseQuestionServiceImpl implements CourseQuestionService {
         return courseQuestionMapper.selectPage(pageReqVO);
     }
 
+    @Override
+    public PageResult<CourseQuestionDO> getCourseQuestionNoPage(CourseQuestionPageReqVO pageReqVO) {
+        return courseQuestionMapper.selectPage(pageReqVO);
+    }
+
 }

+ 94 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/questionnaire/QuestionnaireService.java

@@ -0,0 +1,94 @@
+package cn.iocoder.byzs.module.bjdx.service.questionnaire;
+
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.ConfigQuestionRespVO;
+import cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.QuestionnairePageReqVO;
+import cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.QuestionnaireSaveReqVO;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.questionnaire.QuestionnaireDO;
+import jakarta.validation.Valid;
+
+import java.util.List;
+
+/**
+ * 问卷 Service 接口
+ *
+ * @author lyb
+ */
+public interface QuestionnaireService {
+
+    /**
+     * 创建问卷
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createQuestionnaire(@Valid QuestionnaireSaveReqVO createReqVO);
+
+    /**
+     * 更新问卷
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateQuestionnaire(@Valid QuestionnaireSaveReqVO updateReqVO);
+
+    /**
+     * 删除问卷
+     *
+     * @param id 编号
+     */
+    void deleteQuestionnaire(Long id);
+
+    /**
+    * 批量删除问卷
+    *
+    * @param ids 编号
+    */
+    void deleteQuestionnaireListByIds(List<Long> ids);
+
+    /**
+     * 获得问卷
+     *
+     * @param id 编号
+     * @return 问卷
+     */
+    QuestionnaireDO getQuestionnaire(Long id);
+
+    /**
+     * 获得问卷分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 问卷分页
+     */
+    PageResult<QuestionnaireDO> getQuestionnairePage(QuestionnairePageReqVO pageReqVO);
+
+    /**
+     * 获得问卷配置
+     *
+     * @param configQuestionRespVO 分页查询
+     * @return 问卷分页
+     */
+    PageResult<ConfigQuestionRespVO> getConfigQuestPage(ConfigQuestionRespVO configQuestionRespVO);
+
+    /**
+     * 获得问卷配置
+     *
+     * @param configQuestionRespVO 分页查询
+     * @return 问卷分页
+     */
+    PageResult<ConfigQuestionRespVO> getConfigQuestNoPage(ConfigQuestionRespVO configQuestionRespVO);
+
+    /**
+     * 添加问卷试题配置
+     *
+     * @param configQuestionRespVO 编号
+     */
+    void addConfigQuest(ConfigQuestionRespVO configQuestionRespVO);
+
+    /**
+     * 删除问卷试题配置
+     *
+     * @param configQuestionRespVO 编号
+     */
+    void delConfigQuest(ConfigQuestionRespVO configQuestionRespVO);
+
+}

+ 125 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/questionnaire/QuestionnaireServiceImpl.java

@@ -0,0 +1,125 @@
+package cn.iocoder.byzs.module.bjdx.service.questionnaire;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
+import cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.ConfigQuestionRespVO;
+import cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.QuestionnairePageReqVO;
+import cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.QuestionnaireSaveReqVO;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.questionnaire.QuestionnaireDO;
+import cn.iocoder.byzs.module.bjdx.dal.mysql.questionnaire.QuestionnaireMapper;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static cn.iocoder.byzs.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.byzs.module.bjdx.enums.ErrorCodeConstants.QUESTIONNAIRE_NOT_EXISTS;
+
+/**
+ * 问卷 Service 实现类
+ *
+ * @author lyb
+ */
+@Service
+@Validated
+public class QuestionnaireServiceImpl implements QuestionnaireService {
+
+    @Resource
+    private QuestionnaireMapper questionnaireMapper;
+
+    @Override
+    public Long createQuestionnaire(QuestionnaireSaveReqVO createReqVO) {
+        // 插入
+        QuestionnaireDO questionnaire = BeanUtils.toBean(createReqVO, QuestionnaireDO.class);
+        questionnaireMapper.insert(questionnaire);
+        // 返回
+        return questionnaire.getId();
+    }
+
+    @Override
+    public void updateQuestionnaire(QuestionnaireSaveReqVO updateReqVO) {
+        // 校验存在
+        validateQuestionnaireExists(updateReqVO.getId());
+        // 更新
+        QuestionnaireDO updateObj = BeanUtils.toBean(updateReqVO, QuestionnaireDO.class);
+        questionnaireMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteQuestionnaire(Long id) {
+        // 校验存在
+        validateQuestionnaireExists(id);
+        // 删除
+        questionnaireMapper.deleteById(id);
+    }
+
+    @Override
+        public void deleteQuestionnaireListByIds(List<Long> ids) {
+        // 校验存在
+        validateQuestionnaireExists(ids);
+        // 删除
+        questionnaireMapper.deleteByIds(ids);
+        }
+
+    private void validateQuestionnaireExists(List<Long> ids) {
+        List<QuestionnaireDO> list = questionnaireMapper.selectByIds(ids);
+        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
+            throw exception(QUESTIONNAIRE_NOT_EXISTS);
+        }
+    }
+
+    private void validateQuestionnaireExists(Long id) {
+        if (questionnaireMapper.selectById(id) == null) {
+            throw exception(QUESTIONNAIRE_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public QuestionnaireDO getQuestionnaire(Long id) {
+        return questionnaireMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<QuestionnaireDO> getQuestionnairePage(QuestionnairePageReqVO pageReqVO) {
+        return questionnaireMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public PageResult<ConfigQuestionRespVO> getConfigQuestPage(ConfigQuestionRespVO configQuestionRespVO) {
+        List<ConfigQuestionRespVO> configQuestionRespVOList = questionnaireMapper.selectConfigQuestionList(configQuestionRespVO);
+
+        // 调用服务层方法获取分页结果
+        return new PageResult<ConfigQuestionRespVO>(
+                configQuestionRespVOList.stream()
+                        .map(doItem -> BeanUtils.toBean(doItem, ConfigQuestionRespVO.class))
+                        .collect(Collectors.toList()),
+                (long) configQuestionRespVOList.size()
+        );
+    }
+
+    @Override
+    public PageResult<ConfigQuestionRespVO> getConfigQuestNoPage(ConfigQuestionRespVO configQuestionRespVO) {
+        List<ConfigQuestionRespVO> configQuestionRespVOList = questionnaireMapper.selectConfigQuestionNoList(configQuestionRespVO);
+
+        // 调用服务层方法获取分页结果
+        return new PageResult<ConfigQuestionRespVO>(
+                configQuestionRespVOList.stream()
+                        .map(doItem -> BeanUtils.toBean(doItem, ConfigQuestionRespVO.class))
+                        .collect(Collectors.toList()),
+                (long) configQuestionRespVOList.size()
+        );
+    }
+
+    @Override
+    public void addConfigQuest(ConfigQuestionRespVO configQuestionRespVO) {
+        questionnaireMapper.addConfigQuest(configQuestionRespVO);
+    }
+
+    @Override
+    public void delConfigQuest(ConfigQuestionRespVO configQuestionRespVO) {
+        questionnaireMapper.delConfigQuest(configQuestionRespVO);
+    }
+}

+ 63 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/reportmanage/ReportManageService.java

@@ -0,0 +1,63 @@
+package cn.iocoder.byzs.module.bjdx.service.reportmanage;
+
+import java.util.*;
+
+import cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo.ReportManagePageReqVO;
+import cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo.ReportManageSaveReqVO;
+import jakarta.validation.*;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.reportmanage.ReportManageDO;
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+
+/**
+ * 评估报告-评语 Service 接口
+ *
+ * @author lyb
+ */
+public interface ReportManageService {
+
+    /**
+     * 创建评估报告-评语
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createManage(@Valid ReportManageSaveReqVO createReqVO);
+
+    /**
+     * 更新评估报告-评语
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateManage(@Valid ReportManageSaveReqVO updateReqVO);
+
+    /**
+     * 删除评估报告-评语
+     *
+     * @param id 编号
+     */
+    void deleteManage(Long id);
+
+    /**
+    * 批量删除评估报告-评语
+    *
+    * @param ids 编号
+    */
+    void deleteManageListByIds(List<Long> ids);
+
+    /**
+     * 获得评估报告-评语
+     *
+     * @param id 编号
+     * @return 评估报告-评语
+     */
+    ReportManageDO getManage(Long id);
+
+    /**
+     * 获得评估报告-评语分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 评估报告-评语分页
+     */
+    PageResult<ReportManageDO> getManagePage(ReportManagePageReqVO pageReqVO);
+
+}

+ 90 - 0
byzs-course/src/main/java/cn/iocoder/byzs/module/bjdx/service/reportmanage/ReportManageServiceImpl.java

@@ -0,0 +1,90 @@
+package cn.iocoder.byzs.module.bjdx.service.reportmanage;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo.ReportManagePageReqVO;
+import cn.iocoder.byzs.module.bjdx.controller.admin.reportmanage.vo.ReportManageSaveReqVO;
+import org.springframework.stereotype.Service;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.*;
+
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.reportmanage.ReportManageDO;
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
+
+import cn.iocoder.byzs.module.bjdx.dal.mysql.reportmanage.ReportManageMapper;
+
+import static cn.iocoder.byzs.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.byzs.module.bjdx.enums.ErrorCodeConstants.MANAGE_NOT_EXISTS;
+
+/**
+ * 评估报告-评语 Service 实现类
+ *
+ * @author lyb
+ */
+@Service
+@Validated
+public class ReportManageServiceImpl implements ReportManageService {
+
+    @Resource
+    private ReportManageMapper manageMapper;
+
+    @Override
+    public Long createManage(ReportManageSaveReqVO createReqVO) {
+        // 插入
+        ReportManageDO manage = BeanUtils.toBean(createReqVO, ReportManageDO.class);
+        manageMapper.insert(manage);
+        // 返回
+        return manage.getBrcId();
+    }
+
+    @Override
+    public void updateManage(ReportManageSaveReqVO updateReqVO) {
+        // 校验存在
+        validateManageExists(updateReqVO.getBrcId());
+        // 更新
+        ReportManageDO updateObj = BeanUtils.toBean(updateReqVO, ReportManageDO.class);
+        manageMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteManage(Long id) {
+        // 校验存在
+        validateManageExists(id);
+        // 删除
+        manageMapper.deleteById(id);
+    }
+
+    @Override
+        public void deleteManageListByIds(List<Long> ids) {
+        // 校验存在
+        validateManageExists(ids);
+        // 删除
+        manageMapper.deleteByIds(ids);
+        }
+
+    private void validateManageExists(List<Long> ids) {
+        List<ReportManageDO> list = manageMapper.selectByIds(ids);
+        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
+            throw exception(MANAGE_NOT_EXISTS);
+        }
+    }
+
+    private void validateManageExists(Long id) {
+        if (manageMapper.selectById(id) == null) {
+            throw exception(MANAGE_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public ReportManageDO getManage(Long id) {
+        return manageMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<ReportManageDO> getManagePage(ReportManagePageReqVO pageReqVO) {
+        return manageMapper.selectPage(pageReqVO);
+    }
+
+}

+ 2 - 1
byzs-course/src/main/resources/mapper/courseconfig/CourseConfigMapper.xml

@@ -10,7 +10,8 @@
                 cc_quest_option as ccQuestOption,
                 cc_ai_answer as ccAiAnswer,
                 cc_answer as ccAnswer, cc.cc_quest_id as ccQuestId, cc.cc_time as ccTime, cc.cc_answer_judge as ccAnswerJudge,
-               c.course_name as courseName
+               c.course_name as courseName,
+               cc_ai_quest_tip as ccAiQuestTip
         FROM bjdx_course_config cc
         LEFT JOIN bjdx_course c ON cc.cc_course_id = c.id
         <where>

+ 87 - 0
byzs-course/src/main/resources/mapper/questionnaire/QuestionnaireMapper.xml

@@ -0,0 +1,87 @@
+<?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="cn.iocoder.byzs.module.bjdx.dal.mysql.questionnaire.QuestionnaireMapper">
+
+    <select id="selectConfigQuestionList"
+            parameterType="cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.ConfigQuestionRespVO"
+            resultType="cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.ConfigQuestionRespVO">
+        SELECT
+            cq.id,
+            q.id as questionnaireId,
+            cq.cq_quest_type as cqQuestType,
+            cq.cq_question as cqQuestion,
+            cq.cq_quest_analysis as cqQuestAnalysis,
+            cq.cq_quest_answer_id as cqQuestAnswerId,
+            qc.bq_order as bqOrder
+        FROM bjdx_questionnaire_config qc
+        LEFT JOIN bjdx_questionnaire q ON q.id = qc.bqc_questionnaire_id
+        LEFT JOIN bjdx_course_question cq ON qc.bqc_question_id = cq.id
+        WHERE
+            <if test="questionnaireId != null">
+                q.id = #{questionnaireId}
+            </if>
+            <if test="cqQuestType != null">
+                AND cq.cq_quest_type = #{cqQuestType}
+            </if>
+            <if test="cqQuestion != null">
+                AND cq.cq_question LIKE CONCAT('%', #{cqQuestion}, '%')
+            </if>
+    </select>
+
+    <select id="selectConfigQuestionNoList"
+            parameterType="cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.ConfigQuestionRespVO"
+            resultType="cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.ConfigQuestionRespVO">
+        SELECT
+        cq.id,
+        cq.cq_quest_type as cqQuestType,
+        cq.cq_question as cqQuestion,
+        cq.cq_quest_analysis as cqQuestAnalysis,
+        cq.cq_quest_answer_id as cqQuestAnswerId
+        FROM bjdx_course_question cq
+        <!-- 左连接子查询结果,用于判断是否存在关联 -->
+        LEFT JOIN (
+            SELECT qc.bqc_question_id id
+            FROM bjdx_questionnaire q
+            LEFT JOIN bjdx_questionnaire_config qc ON qc.bqc_questionnaire_id = q.id
+            WHERE
+                <if test="questionnaireId != null">
+                    q.id = #{questionnaireId}
+                </if>
+        ) t ON cq.id = t.id
+        WHERE
+            <!-- 当子查询无匹配时,t.id为NULL -->
+            t.id IS NULL
+            <if test="cqQuestType != null">
+                AND cq.cq_quest_type = #{cqQuestType}
+            </if>
+            <if test="cqQuestion != null">
+                AND cq.cq_question LIKE CONCAT('%', #{cqQuestion}, '%')
+            </if>
+    </select>
+
+    <insert id="addConfigQuest" parameterType="cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.ConfigQuestionRespVO">
+        INSERT INTO bjdx_questionnaire_config (bqc_questionnaire_id, bqc_question_id, bq_order)
+        SELECT
+            #{questionnaireId},
+            q.id,
+            @max_order := @max_order + 1
+        FROM (
+            <!-- 使用foreach直接生成所有ID行,无需单独处理第一个元素 -->
+            <foreach collection="questionIds" item="id" index="index" open="" separator="UNION ALL " close="">
+                SELECT #{questionnaireId} AS qn_id, #{id} AS id
+            </foreach>
+        ) AS q
+        CROSS JOIN (SELECT @max_order := COALESCE((
+            SELECT MAX(bq_order)
+            FROM bjdx_questionnaire_config
+            WHERE bqc_questionnaire_id = #{questionnaireId}
+        ), 0)) AS init;
+    </insert>
+
+    <delete id="delConfigQuest" parameterType="cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.ConfigQuestionRespVO">
+        DELETE FROM bjdx_questionnaire_config WHERE bqc_questionnaire_id = #{questionnaireId} AND bqc_question_id IN
+        <foreach collection="questionIds" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 7 - 0
byzs-course/src/main/resources/mapper/reportmanage/ReportManageMapper.xml

@@ -0,0 +1,7 @@
+<?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="cn.iocoder.byzs.module.bjdx.dal.mysql.reportmanage.ReportManageMapper">
+
+
+
+</mapper>

+ 3 - 0
byzs-module-ai/src/main/java/cn/iocoder/byzs/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java

@@ -14,6 +14,9 @@ public class AiChatRolePageReqVO extends PageParam {
     @Schema(description = "角色类别", example = "创作")
     private String category;
 
+    @Schema(description = "问题提示")
+    private String questTip;
+
     @Schema(description = "是否公开", example = "1")
     private Boolean publicStatus;
 

+ 3 - 0
byzs-module-ai/src/main/java/cn/iocoder/byzs/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java

@@ -41,6 +41,9 @@ public class AiChatRoleRespVO implements VO {
     @Schema(description = "角色类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作")
     private String category;
 
+    @Schema(description = "问题提示")
+    private String questTip;
+
     @Schema(description = "角色排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer sort;
 

+ 3 - 0
byzs-module-ai/src/main/java/cn/iocoder/byzs/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java

@@ -43,4 +43,7 @@ public class AiChatRoleSaveMyReqVO {
     @Schema(description = "引用的工具编号列表", example = "1,2,3")
     private List<Long> toolIds;
 
+    @Schema(description = "问题提示")
+    private String questTip;
+
 }

+ 3 - 0
byzs-module-ai/src/main/java/cn/iocoder/byzs/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java

@@ -56,6 +56,9 @@ public class AiChatRoleSaveReqVO {
     @Schema(description = "引用的工具编号列表", example = "1,2,3")
     private List<Long> toolIds;
 
+    @Schema(description = "问题提示")
+    private String questTip;
+
     @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "是否公开不能为空")
     private Boolean publicStatus;

+ 5 - 0
byzs-module-ai/src/main/java/cn/iocoder/byzs/module/ai/dal/dataobject/model/AiChatRoleDO.java

@@ -92,6 +92,11 @@ public class AiChatRoleDO extends BaseDO {
     @TableField(typeHandler = LongListTypeHandler.class)
     private List<Long> toolIds;
 
+    /**
+     * 问题提示
+     */
+    private String questTip;
+
     /**
      * 是否公开
      *

+ 4 - 4
byzs-module-infra/src/main/java/cn/iocoder/byzs/module/infra/controller/admin/file/FileController.java

@@ -46,10 +46,10 @@ public class FileController {
         MultipartFile file = uploadReqVO.getFile();
 
         // 新增:文件大小校验(假设数据库限制 64MB)
-        long maxFileSize = 64 * 1024 * 1024; // 64MB
-        if (file.getSize() > maxFileSize) {
-            throw new IllegalArgumentException("文件大小超过限制,仅支持 200MB 以内的文件(大文件请使用前端直传模式)");
-        }
+//        long maxFileSize = 64 * 1024 * 1024; // 64MB
+//        if (file.getSize() > maxFileSize) {
+//            throw new IllegalArgumentException("文件大小超过限制,仅支持 200MB 以内的文件(大文件请使用前端直传模式)");
+//        }
 
         byte[] content = IoUtil.readBytes(file.getInputStream());
         return success(fileService.createFile(content, file.getOriginalFilename(),

+ 2 - 2
byzs-server/src/main/resources/application-local.yaml

@@ -48,8 +48,8 @@ spring:
       primary: master
       datasource:
         master:
-          url: jdbc:mysql://127.0.0.1:3306/byzs-bjdx?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
-#          url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro-all?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例
+          url: jdbc:mysql://127.0.0.1:3306/byzs-bjdx?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&allowMultiQueries=true # MySQL Connector/J 8.X 连接的示例
+          #          url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro-all?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例
           #          url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
           #          url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
           #          url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer 连接的示例

+ 0 - 12
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/ai/WebAiController.java

@@ -55,8 +55,6 @@ public class WebAiController {
 
     // ================ 智能问答 ================
 
-    @PermitAll
-    @TenantIgnore
     @Operation(summary = "创建智能问答")
     @PostMapping("/create-dialogue")
     public CommonResult<Long> createChatConversationMy(@RequestBody @Valid AiChatConversationCreateMyReqVO createReqVO) {
@@ -72,8 +70,6 @@ public class WebAiController {
 //        return success(BeanUtils.toBean(list, AiChatConversationRespVO.class));
 //    }
 
-    @PermitAll
-    @TenantIgnore
     @Operation(summary = "智能问答-发送消息(流式)", description = "流式返回,响应较快")
     @PostMapping(value = "/dialogue-send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
     public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(@Valid @RequestBody AiChatMessageSendReqVO sendReqVO) {
@@ -82,16 +78,12 @@ public class WebAiController {
 
     // ================ 绘图管理 ================
 
-    @PermitAll
-    @TenantIgnore
     @Operation(summary = "生成图片")
     @PostMapping("/create-painting")
     public CommonResult<Long> drawImage(@Valid @RequestBody AiImageDrawReqVO drawReqVO) {
         return success(imageService.drawImage(userId, drawReqVO));
     }
 
-    @PermitAll
-    @TenantIgnore
     @GetMapping("/painting-get-my")
     @Operation(summary = "绘画-获取绘图记录")
     public CommonResult<AiImageRespVO> getImageMy(@RequestParam("id") Long id) {
@@ -102,8 +94,6 @@ public class WebAiController {
         return success(BeanUtils.toBean(image, AiImageRespVO.class));
     }
 
-    @PermitAll
-    @TenantIgnore
     @GetMapping("/painting-get-mys")
     @Operation(summary = "获取【我的】绘图记录列表")
     @Parameter(name = "ids", required = true, description = "绘画编号数组", example = "1024,2048")
@@ -114,8 +104,6 @@ public class WebAiController {
     }
 
 
-    @PermitAll
-    @TenantIgnore
     @GetMapping("/selectRoleModel")
     @Operation(summary = "获得聊天角色分页")
     public CommonResult<PageResult<WebAiChatRoleVO>> selectRoleModel(@Valid AiChatRolePageReqVO pageReqVO) {

+ 3 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/ai/vo/WebAiChatRoleVO.java

@@ -41,4 +41,7 @@ public class WebAiChatRoleVO implements VO {
 
     @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED)
     private String systemMessage;
+
+    @Schema(description = "问题提示")
+    private String questTip;
 }

+ 0 - 8
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/course/WebCourseController.java

@@ -29,8 +29,6 @@ import static cn.iocoder.byzs.framework.common.pojo.CommonResult.success;
 @RestController
 @RequestMapping("/bjdxWeb/course")
 @Validated
-@PermitAll
-@TenantIgnore
 public class WebCourseController {
 
     @Resource
@@ -41,8 +39,6 @@ public class WebCourseController {
     private CourseTypeService courseTypeService;
 
 
-    @PermitAll
-    @TenantIgnore
     @GetMapping("/getCourseByTypeId")
     @Operation(summary = "根据类型获得课程列表")
     @Parameter(name = "typeId", description = "编号", required = true, example = "1024")
@@ -53,8 +49,6 @@ public class WebCourseController {
         return success(courseVoList);
     }
 
-    @PermitAll
-    @TenantIgnore
     @GetMapping("/getTypeGrade")
     @Operation(summary = "获得课程-年级")
     public CommonResult<List<CourseTypeRespVO>> getTypeGrade() {
@@ -64,8 +58,6 @@ public class WebCourseController {
         return success(listVo);
     }
 
-    @PermitAll
-    @TenantIgnore
     @GetMapping("/getTypeByGradeId")
     @Operation(summary = "获得课程-年级大纲")
     public CommonResult<List<CourseTypeRespVO>> getTypeByGradeId(@RequestParam("id") Integer id) {

+ 52 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/questionnaire/WebQuestionnaireController.java

@@ -0,0 +1,52 @@
+package cn.iocoder.byzs.module.web.controller.admin.questionnaire;
+
+import cn.iocoder.byzs.framework.common.pojo.CommonResult;
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.QuestionnairePageReqVO;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.questionnaire.QuestionnaireDO;
+import cn.iocoder.byzs.module.bjdx.service.questionnaire.QuestionnaireService;
+import cn.iocoder.byzs.module.web.controller.admin.questionnaire.vo.WebQuestionnaireVo;
+import cn.iocoder.byzs.module.web.service.questionnaire.WebQuestionnaireServiceImpl;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import static cn.iocoder.byzs.framework.common.pojo.CommonResult.success;
+
+
+@Tag(name = "Web-前端接口")
+@RestController
+@RequestMapping("/bjdxWeb/questionnaire")
+@Validated
+public class WebQuestionnaireController {
+
+    @Resource
+    private WebQuestionnaireServiceImpl webQuestionnaireService;
+    @Resource
+    private QuestionnaireService questionnaireService;
+
+    @GetMapping("/selectQuestionnaire")
+    @Operation(summary = "取问卷列表")
+    public CommonResult<PageResult<QuestionnaireDO>> selectQuestionnaire(@Valid QuestionnairePageReqVO questionnairePageReqVO) {
+        PageResult<QuestionnaireDO> pageResult = questionnaireService.getQuestionnairePage(questionnairePageReqVO);
+        return success(pageResult);
+    }
+
+    @GetMapping("/getQuestionVoList")
+    @Operation(summary = "取问卷列表")
+    public CommonResult<WebQuestionnaireVo> getQuestionVoList(@RequestParam("qrId") Long qrId) {
+        WebQuestionnaireVo webQuestionnaireVo = webQuestionnaireService.getQuestionVoList(qrId);
+        return success(webQuestionnaireVo);
+    }
+
+    @PostMapping("/saveQuestionResult")
+    @Operation(summary = "保存试卷结果")
+    public CommonResult<Boolean> getQuestionnaire(@Valid QuestionnairePageReqVO questionnairePageReqVO) {
+
+        return success(true);
+    }
+
+}

+ 66 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/questionnaire/vo/WebQuestionnaireResultVo.java

@@ -0,0 +1,66 @@
+package cn.iocoder.byzs.module.web.controller.admin.questionnaire.vo;
+
+import cn.iocoder.byzs.framework.common.pojo.PageParam;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+public class WebQuestionnaireResultVo extends PageParam {
+    //问卷id
+    private Long qrId;
+
+    //问卷名称
+    private String qrName;
+
+    //问卷介绍
+    private String qrDetails;
+
+    //问卷排序
+    private Integer qrOrder;
+
+    //问卷开始指导语
+    private String qrStartInfo;
+
+    //问卷结束指导语
+    private String qrEndInfo;
+
+    //问题id集(后期改成问题条数)
+    private String qrQuestIds;
+
+    //问题列表
+    private List<WebQuestion> questionList;
+
+    @Data
+    public static class WebQuestion{
+        //问题id
+        private Long qId;
+        //问题类型
+        private String qType;
+        //问题内容
+        private String qContent;
+        //问题内容
+        private String qAnalysis;
+        //问题内容
+        private Integer qOrder;
+
+        //问题选项
+        private List<WebQuestOption> questionOptionsList;
+
+        @Data
+        public static class WebQuestOption{
+            //选项
+            private Long oId;
+            //选项
+            private String oValue;
+            //选项内容
+            private String oName;
+            //分值
+            private Double oSorce;
+            //是否答案
+            private String oIsAnswer;
+        }
+    }
+}

+ 66 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/questionnaire/vo/WebQuestionnaireVo.java

@@ -0,0 +1,66 @@
+package cn.iocoder.byzs.module.web.controller.admin.questionnaire.vo;
+
+import cn.iocoder.byzs.framework.common.pojo.PageParam;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+public class WebQuestionnaireVo extends PageParam {
+    //问卷id
+    private Long qrId;
+
+    //问卷名称
+    private String qrName;
+
+    //问卷介绍
+    private String qrDetails;
+
+    //问卷排序
+    private Integer qrOrder;
+
+    //问卷开始指导语
+    private String qrStartInfo;
+
+    //问卷结束指导语
+    private String qrEndInfo;
+
+    //问题id集(后期改成问题条数)
+    private String qrQuestIds;
+
+    //问题列表
+    private List<WebQuestion> questionList;
+
+    @Data
+    public static class WebQuestion{
+        //问题id
+        private Long qId;
+        //问题类型
+        private String qType;
+        //问题内容
+        private String qContent;
+        //问题内容
+        private String qAnalysis;
+        //问题内容
+        private Integer qOrder;
+
+        //问题选项
+        private List<WebQuestOption> questionOptionsList;
+
+        @Data
+        public static class WebQuestOption{
+            //选项
+            private Long oId;
+            //选项
+            private String oValue;
+            //选项内容
+            private String oName;
+            //分值
+            private Double oSorce;
+            //是否答案
+            private String oIsAnswer;
+        }
+    }
+}

+ 61 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/reportprogress/WebReportProgressController.java

@@ -0,0 +1,61 @@
+package cn.iocoder.byzs.module.web.controller.admin.reportprogress;
+
+import cn.iocoder.byzs.framework.common.pojo.CommonResult;
+import cn.iocoder.byzs.framework.tenant.core.aop.TenantIgnore;
+import cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressDO;
+import cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressVO;
+import cn.iocoder.byzs.module.web.service.reportprogress.WebReportProgressServiceImpl;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.annotation.security.PermitAll;
+import jakarta.validation.Valid;
+import jodd.util.StringUtil;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Objects;
+
+import static cn.iocoder.byzs.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.byzs.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.byzs.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+import static cn.iocoder.byzs.module.bjdx.enums.ErrorCodeConstants.PROGRESS_NOT_EXISTS;
+
+
+@Tag(name = "管理后台 - 评估报告-课程开课率")
+@RestController
+@RequestMapping("/bjdxReport/progress")
+@Validated
+public class WebReportProgressController {
+
+    @Resource
+    private WebReportProgressServiceImpl progressService;
+
+    @PermitAll
+    @TenantIgnore
+    @PostMapping("/saveReportProgress")
+    @Operation(summary = "保存评估报告进度")
+    public CommonResult<Boolean> saveReportProgress(@Valid @RequestBody WebReportProgressDO reportProgressDO) {
+        // 校验
+        if (StringUtil.isBlank(reportProgressDO.getBrpType()) ||reportProgressDO.getBrpType().equals("courseQuest") && Objects.isNull(reportProgressDO.getBrpCourseConfigId())) {
+            throw exception(PROGRESS_NOT_EXISTS);
+        }
+        //用户id
+        reportProgressDO.setBrpUserId(getLoginUserId());
+        // 插入
+        progressService.saveReportProgress(reportProgressDO);
+        return success(true);
+    }
+
+    @PermitAll
+    @TenantIgnore
+    @GetMapping("/getReportProgress")
+    @Operation(summary = "取评估报告进度")
+    public WebReportProgressVO getReportProgress(@Valid WebReportProgressDO reportProgressDO) {
+        //用户id
+        reportProgressDO.setBrpUserId(getLoginUserId());
+        // 插入
+        return progressService.getReportProgress(reportProgressDO);
+    }
+
+}

+ 65 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/reportprogress/vo/WebReportProgressDO.java

@@ -0,0 +1,65 @@
+package cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo;
+
+import cn.iocoder.byzs.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+import lombok.experimental.Accessors;
+
+/**
+ * 评估报告-课程开课率 DO
+ *
+ * @author lyb
+ */
+@TableName("bjdx_report_progress")
+@KeySequence("bjdx_report_progress_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class WebReportProgressDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long brpId;
+    /**
+     * 用户id
+     */
+    private Long brpUserId;
+    /**
+     * 年级id
+     */
+    @NonNull
+    private Long brpNjId;
+    /**
+     * 课程类型id
+     */
+    @NonNull
+    private Long brpCtId;
+    /**
+     * 课程id
+     */
+    @NonNull
+    private Long brpCourseId;
+    /**
+     * 课程配置id
+     */
+    private Long brpCourseConfigId;
+    /**
+     * 进度分类
+     */
+    @NonNull
+    private String brpType;
+    /**
+     * 进度(课程开课率、课程互动率、ai问答次数)
+     */
+    private Double brpProgress;
+
+
+}

+ 48 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/reportprogress/vo/WebReportProgressDTO.java

@@ -0,0 +1,48 @@
+package cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.*;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * 评估报告-课程开课率 VO
+ *
+ * @author lyb
+ */
+@Data
+@Accessors(chain = true)
+public class WebReportProgressDTO {
+
+    /**
+     /**
+     * 用户id
+     */
+    private String userName;
+    /**
+     * 年级名称
+     */
+    private String njName;
+    /**
+     * 课程类型名称
+     */
+    private String kcflName;
+    /**
+     * 课程名称
+     */
+    private String courseName;
+    /**
+     * 课程配置id
+     */
+    private Long courseConfigId;
+    /**
+     * 进度分类
+     */
+    private String progressType;
+    /**
+     * 进度(课程开课率、课程互动率、ai问答次数)
+     */
+    private Double progress;
+
+}

+ 70 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/reportprogress/vo/WebReportProgressVO.java

@@ -0,0 +1,70 @@
+package cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * 评估报告-课程开课率 DO
+ *
+ * @author lyb
+ */
+@Data
+@Accessors(chain = true)
+public class WebReportProgressVO {
+
+    /**
+     /**
+     * 用户id
+     */
+//    private String userName;
+    /**
+     * 年级名称
+     */
+//    private String njName;
+    /**
+     * 年级课程开课率
+     */
+    private Double njCourseProgress;
+    /**
+     * 年级课程互动率
+     */
+    private Double njCourseConfigProgress;
+
+    /**
+     * ai问答次数
+     */
+    private Integer aiCount;
+
+    /**
+     * 评语
+     */
+    private String comment;
+
+    /**
+     * 课程开课率
+     */
+    private List<ReportProgressVo> reportCourseProgressList;
+
+    /**
+     * 课程互动率
+     */
+    private List<ReportProgressVo> reportCourseConfigProgressList;
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class ReportProgressVo {
+
+        /**
+         * 课程类型名称
+         */
+        private String kcflName;
+        /**
+         * 进度(课程开课率、课程互动率、ai问答次数)
+         */
+        private Double progress;
+    }
+
+}

+ 17 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/dal/mysql/questionnaire/WebQuestionnaireMapper.java

@@ -0,0 +1,17 @@
+package cn.iocoder.byzs.module.web.dal.mysql.questionnaire;
+
+import cn.iocoder.byzs.module.bjdx.controller.admin.course.vo.CoursePageReqVO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 课程 Mapper
+ *
+ * @author lyb
+ */
+@Mapper
+public interface WebQuestionnaireMapper{
+
+    List<CoursePageReqVO> getQuestionnaire(CoursePageReqVO reqVO);
+}

+ 19 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/dal/mysql/reportprogress/WebReportProgressMapper.java

@@ -0,0 +1,19 @@
+package cn.iocoder.byzs.module.web.dal.mysql.reportprogress;
+
+import cn.iocoder.byzs.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressDO;
+import cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressDTO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 评估报告-课程开课率 Mapper
+ *
+ * @author lyb
+ */
+@Mapper
+public interface WebReportProgressMapper extends BaseMapperX<WebReportProgressDO> {
+
+    List<WebReportProgressDTO> selectProgres(WebReportProgressDO reportProgressDO);
+}

+ 93 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/service/questionnaire/WebQuestionnaireServiceImpl.java

@@ -0,0 +1,93 @@
+package cn.iocoder.byzs.module.web.service.questionnaire;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.byzs.module.bjdx.controller.admin.questionnaire.vo.ConfigQuestionRespVO;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.coursequestoption.CourseQuestOptionDO;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.questionnaire.QuestionnaireDO;
+import cn.iocoder.byzs.module.bjdx.dal.mysql.coursequestion.CourseQuestionMapper;
+import cn.iocoder.byzs.module.bjdx.dal.mysql.coursequestoption.CourseQuestOptionMapper;
+import cn.iocoder.byzs.module.bjdx.dal.mysql.questionnaire.QuestionnaireMapper;
+import cn.iocoder.byzs.module.bjdx.service.questionnaire.QuestionnaireService;
+import cn.iocoder.byzs.module.web.controller.admin.questionnaire.vo.WebQuestionnaireVo;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * web课程 Service 实现类
+ *
+ * @author lyb
+ */
+@Service
+@Validated
+public class WebQuestionnaireServiceImpl {
+
+    @Resource
+    private QuestionnaireService questionnaireService;
+    @Resource
+    private QuestionnaireMapper questionnaireMapper;
+    @Resource
+    private CourseQuestionMapper courseQuestionMapper;
+    @Resource
+    private CourseQuestOptionMapper courseQuestOptionMapper;
+
+    public WebQuestionnaireVo getQuestionVoList(Long qrId) {
+        // 问卷信息填充(未修改部分)
+        QuestionnaireDO questionnaire = questionnaireService.getQuestionnaire(qrId);
+        WebQuestionnaireVo questionnaireVo = new WebQuestionnaireVo();
+        questionnaireVo.setQrId(questionnaire.getId());
+        questionnaireVo.setQrName(questionnaire.getBqQuestionnaire());
+        questionnaireVo.setQrDetails(questionnaire.getBqDetails());
+        questionnaireVo.setQrOrder(questionnaire.getBqOrder());
+        questionnaireVo.setQrStartInfo(questionnaire.getBqStartInfo());
+        questionnaireVo.setQrEndInfo(questionnaire.getBqEndInfo());
+        questionnaireVo.setQrQuestIds(questionnaire.getBqQuestIds());
+
+        // 问题列表处理
+        List<ConfigQuestionRespVO> configQuestionRespVOList = questionnaireMapper.selectConfigQuestionList(new ConfigQuestionRespVO().setQuestionnaireId(qrId));
+        if (CollUtil.isNotEmpty(configQuestionRespVOList)) {
+            Set<Long> qustionIdSet = configQuestionRespVOList.stream().map(ConfigQuestionRespVO::getId).collect(Collectors.toSet());
+
+            // 选项列表处理
+            List<CourseQuestOptionDO> questOptionDOList = courseQuestOptionMapper.selectListByQuestId(qustionIdSet);
+            if (CollUtil.isNotEmpty(questOptionDOList)) {
+                Map<Long, List<CourseQuestOptionDO>> questionOptionMap = questOptionDOList.stream().collect(Collectors.groupingBy(CourseQuestOptionDO::getCqoQuestId));
+
+                List<WebQuestionnaireVo.WebQuestion> questionList = new ArrayList<>();
+                configQuestionRespVOList.forEach(configQuestionRespVO -> {
+                    WebQuestionnaireVo.WebQuestion webQuestion = new WebQuestionnaireVo.WebQuestion();
+                    webQuestion.setQId(configQuestionRespVO.getId());
+                    webQuestion.setQType(configQuestionRespVO.getCqQuestType());
+                    webQuestion.setQContent(configQuestionRespVO.getCqQuestion());
+                    webQuestion.setQAnalysis(configQuestionRespVO.getCqQuestAnalysis());
+                    webQuestion.setQOrder(configQuestionRespVO.getBqOrder());
+
+                    List<CourseQuestOptionDO> questOptionDOMapList = questionOptionMap.get(webQuestion.getQId());
+                    if (CollUtil.isNotEmpty(questOptionDOMapList)) {
+                        List<WebQuestionnaireVo.WebQuestion.WebQuestOption> questOptionList = new ArrayList<>();
+                        questOptionDOMapList.forEach(questOptionDO -> {
+                            WebQuestionnaireVo.WebQuestion.WebQuestOption webQuestOption = new WebQuestionnaireVo.WebQuestion.WebQuestOption();
+                            webQuestOption.setOId(questOptionDO.getId());
+                            webQuestOption.setOValue(questOptionDO.getCqoValue());
+                            webQuestOption.setOName(questOptionDO.getCqoOption());
+                            webQuestOption.setOSorce(questOptionDO.getCqoSocre());
+                            webQuestOption.setOIsAnswer(questOptionDO.getCqoIsAnswer());
+                            questOptionList.add(webQuestOption);
+                        });
+                        // 新增:选项按 oValue 升序排序
+                        questOptionList.sort(Comparator.comparing(WebQuestionnaireVo.WebQuestion.WebQuestOption::getOValue));
+                        webQuestion.setQuestionOptionsList(questOptionList);
+                    }
+                    questionList.add(webQuestion);
+                });
+                // 新增:问题列表按 qOrder 升序排序(假设 qOrder 是整数类型)
+                questionList.sort(Comparator.comparingInt(WebQuestionnaireVo.WebQuestion::getQOrder));
+                questionnaireVo.setQuestionList(questionList);
+            }
+        }
+        return questionnaireVo;
+    }
+}

+ 204 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/service/reportprogress/WebReportProgressServiceImpl.java

@@ -0,0 +1,204 @@
+package cn.iocoder.byzs.module.web.service.reportprogress;
+
+import cn.iocoder.byzs.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.byzs.module.bjdx.controller.admin.coursetype.vo.CourseTypeListReqVO;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.coursetype.CourseTypeDO;
+import cn.iocoder.byzs.module.bjdx.dal.dataobject.reportmanage.ReportManageDO;
+import cn.iocoder.byzs.module.bjdx.dal.mysql.coursetype.CourseTypeMapper;
+import cn.iocoder.byzs.module.bjdx.dal.mysql.reportmanage.ReportManageMapper;
+import cn.iocoder.byzs.module.web.controller.admin.course.vo.WebCourseVO;
+import cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressDO;
+import cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressDTO;
+import cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressVO;
+import cn.iocoder.byzs.module.web.dal.mysql.reportprogress.WebReportProgressMapper;
+import cn.iocoder.byzs.module.web.service.course.WebCourseServiceImpl;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 评估报告-课程开课率 Service 实现类
+ *
+ * @author lyb
+ */
+@Service
+@Validated
+public class WebReportProgressServiceImpl {
+
+    @Resource
+    private WebReportProgressMapper progressMapper;
+    @Resource
+    private ReportManageMapper reportManageMapper;
+    @Resource
+    private CourseTypeMapper courseTypeMapper;
+    @Resource
+    private WebCourseServiceImpl webCourseService;
+
+    public void saveReportProgress(WebReportProgressDO progress) {
+
+        LambdaQueryWrapperX<WebReportProgressDO> progressLambdaQueryWrapperX = new LambdaQueryWrapperX<WebReportProgressDO>()
+                .eqIfPresent(WebReportProgressDO::getBrpUserId, progress.getBrpUserId())
+                .eqIfPresent(WebReportProgressDO::getBrpType, progress.getBrpType())
+                .eqIfPresent(WebReportProgressDO::getBrpNjId, progress.getBrpNjId());
+
+        switch (progress.getBrpType()) {
+            case "course":// 课程开课率
+                progressLambdaQueryWrapperX
+                        .eqIfPresent(WebReportProgressDO::getBrpCtId, progress.getBrpCtId())
+                        .eqIfPresent(WebReportProgressDO::getBrpCourseId, progress.getBrpCourseId());
+                WebReportProgressDO courseProgressDo = progressMapper.selectOne(progressLambdaQueryWrapperX);
+                if (courseProgressDo == null) {
+                    progressMapper.insert(progress);
+                }else if (progress.getBrpProgress() > courseProgressDo.getBrpProgress()) {
+                    courseProgressDo.setBrpProgress(progress.getBrpProgress());
+                    progressMapper.updateById(courseProgressDo);
+                }
+                break;
+
+            case "courseQuest":// 课程互动率
+                progressLambdaQueryWrapperX
+                        .eqIfPresent(WebReportProgressDO::getBrpCtId, progress.getBrpCtId())
+                        .eqIfPresent(WebReportProgressDO::getBrpCourseId, progress.getBrpCourseId())
+                        .eqIfPresent(WebReportProgressDO::getBrpCourseConfigId, progress.getBrpCourseConfigId());
+                WebReportProgressDO courseConfigProgressDo = progressMapper.selectOne(progressLambdaQueryWrapperX);
+
+                if (courseConfigProgressDo == null) {
+                    progressMapper.insert(progress);
+                }
+                break;
+
+            case "aiCount":// ai问答次数
+                WebReportProgressDO aiCountProgressDo = progressMapper.selectOne(progressLambdaQueryWrapperX);
+
+                if (aiCountProgressDo == null) {
+                    progressMapper.insert(progress);
+                }else {
+                    aiCountProgressDo.setBrpProgress(aiCountProgressDo.getBrpProgress()+1);
+                    progressMapper.updateById(aiCountProgressDo);
+                }
+                break;
+        }
+    }
+
+    public WebReportProgressVO getReportProgress(WebReportProgressDO progress) {
+        //前端数据封装
+        WebReportProgressVO webReportProgressVO = new WebReportProgressVO();
+        List<WebReportProgressVO.ReportProgressVo> courseProgressVoList = new ArrayList<>();
+        List<WebReportProgressVO.ReportProgressVo> courseConfigProgressVoList = new ArrayList<>();
+
+        //年级下的课程列表
+        Map<String, List<Map<String, Integer>>> courseAllMap = new HashMap<>();
+        List<CourseTypeDO> courseTypeDOS = courseTypeMapper.selectList(new CourseTypeListReqVO().setCtParentId(Math.toIntExact(progress.getBrpNjId())).setCtTypeNode("1"));
+        courseTypeDOS.forEach(courseTypeDO -> {
+            List<WebCourseVO> courseVoList = webCourseService.getCourseVoByTypeId(courseTypeDO.getId());
+            List<Map<String, Integer>> courseCountMapList = new ArrayList<>();
+            courseVoList.forEach(webCourseVO -> {
+                Map<String, Integer> courseCountMap = new HashMap<>();
+                courseCountMap.put(webCourseVO.getCourseName(), webCourseVO.getCourseConfigList().size());
+                courseCountMapList.add(courseCountMap);
+            });
+            String sort = courseTypeDO.getCtTypeSort() > 9 ? "" : "0";
+            courseAllMap.put(sort + courseTypeDO.getCtTypeSort() + " " + courseTypeDO.getCtType(), courseCountMapList);
+        });
+
+        //取进度
+        List<WebReportProgressDTO> webReportProgressDOList = progressMapper.selectProgres(progress);
+        Map<String, List<WebReportProgressDTO>> progressTypeMap = webReportProgressDOList.stream().collect(Collectors.groupingBy(WebReportProgressDTO::getProgressType));
+
+        courseAllMap.forEach((kcflName, courseMap)->{
+
+            //解析数据进度
+            progressTypeMap.keySet().forEach(progressType -> {
+                List<WebReportProgressDTO> progressDOList = progressTypeMap.get(progressType);
+                Map<String, List<WebReportProgressDTO>> progressKcflMap = progressDOList.stream().collect(Collectors.groupingBy(WebReportProgressDTO::getKcflName));
+                switch (progressType) {
+                    case "course":
+
+                        //计算课程大纲进度
+                        progressKcflMap.forEach((kcflNameData, progressDTOList) -> {
+                            //课程开课率
+                            WebReportProgressVO.ReportProgressVo courseProgressVo = new WebReportProgressVO.ReportProgressVo();
+                            courseProgressVo.setKcflName(kcflName);
+                            double sum = progressDTOList.stream().collect(Collectors.summarizingDouble(WebReportProgressDTO::getProgress)).getSum();
+                            courseProgressVo.setProgress(delTwo(sum / courseAllMap.get(kcflName).size()));
+                            courseProgressVoList.add(courseProgressVo);
+                        });
+                        break;
+
+                    case "courseQuest":
+
+                        //计算课程大纲进度
+                        progressKcflMap.forEach((kcflNameData, progressDTOList) -> {
+                            //课程互动率
+                            WebReportProgressVO.ReportProgressVo courseConfigProgressVoConfig = new WebReportProgressVO.ReportProgressVo();
+                            courseConfigProgressVoConfig.setKcflName(kcflName);
+
+                            // 新增:计算courseMap所有value的总和(每个Map的value是课程配置数量)
+                            int totalConfigCount = courseMap.stream()
+                                .flatMap(map -> map.values().stream())  // 展开所有Map的value值
+                                .mapToInt(Integer::intValue)            // 转换为int流
+                                .sum();                                 // 求和
+
+                            double sum = progressDTOList.size();
+                            // 注意:这里可能需要根据实际业务调整分母(示例保持原逻辑)
+                            courseConfigProgressVoConfig.setProgress(delTwo(sum / totalConfigCount * 100));  // 调整为使用总和计算进度
+                            courseConfigProgressVoList.add(courseConfigProgressVoConfig);  // 修正集合添加对象
+                        });
+                        break;
+
+                    case "aiCount":
+                        if (!progressDOList.isEmpty()) {
+                            Double sum = progressDOList.stream().collect(Collectors.summarizingDouble(WebReportProgressDTO::getProgress)).getSum();
+                            webReportProgressVO.setAiCount(sum.intValue());
+                        }
+                        break;
+                }
+            });
+        });
+
+        // 原有总和计算逻辑(位置不变)
+        double courseProgressSum = courseProgressVoList.stream().collect(Collectors.summarizingDouble(WebReportProgressVO.ReportProgressVo::getProgress)).getSum();
+        double courseConfigProgressSum = courseConfigProgressVoList.stream().collect(Collectors.summarizingDouble(WebReportProgressVO.ReportProgressVo::getProgress)).getSum();
+        webReportProgressVO.setNjCourseProgress(delTwo(courseProgressSum / courseProgressVoList.size()));
+        webReportProgressVO.setNjCourseConfigProgress(delTwo(courseConfigProgressSum / courseConfigProgressVoList.size()));
+
+        // 按kcflName字段排序(自然顺序)
+        courseProgressVoList.sort(Comparator.comparing(WebReportProgressVO.ReportProgressVo::getKcflName));
+        courseConfigProgressVoList.sort(Comparator.comparing(WebReportProgressVO.ReportProgressVo::getKcflName));
+        webReportProgressVO.setReportCourseProgressList(courseProgressVoList);
+        webReportProgressVO.setReportCourseConfigProgressList(courseConfigProgressVoList);
+
+        //
+        Double njCourseProgress = webReportProgressVO.getNjCourseProgress();
+        Double njCourseConfigProgress = webReportProgressVO.getNjCourseConfigProgress();
+        Integer aiCount = webReportProgressVO.getAiCount();
+        List<ReportManageDO> reportManageDOList = reportManageMapper.selectList();
+        StringBuffer comment = new StringBuffer();
+        reportManageDOList.forEach(reportManageDO -> {
+            if (reportManageDO.getBrcReportAiCountMin() <= njCourseProgress && reportManageDO.getBrcReportAiCountMax() >= njCourseProgress){
+                comment.append(reportManageDO.getBrcReportComment());
+            }
+            if (reportManageDO.getBrcReportQuestMin() <= njCourseConfigProgress && reportManageDO.getBrcReportQuestMax() >= njCourseConfigProgress){
+                comment.append(reportManageDO.getBrcReportComment());
+            }
+            if (reportManageDO.getBrcReportAiCountMin() <= aiCount && reportManageDO.getBrcReportAiCountMax() >= aiCount){
+                comment.append(reportManageDO.getBrcReportComment());
+            }
+        });
+        webReportProgressVO.setComment(comment.toString());
+        return webReportProgressVO;
+    }
+
+    public double delTwo(Double num){
+        if (Double.isInfinite(num))return 0;
+        BigDecimal two = new BigDecimal(num);
+        double newNum = two.setScale(0, RoundingMode.HALF_UP).doubleValue();
+        newNum = newNum > 100 ? 100 : newNum;
+        return newNum;
+    }
+}

+ 18 - 0
byzs-web/src/main/resources/mapper/reportprogress/ReportProgressMapper.xml

@@ -0,0 +1,18 @@
+<?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="cn.iocoder.byzs.module.web.dal.mysql.reportprogress.WebReportProgressMapper">
+
+    <select id="selectProgres" parameterType="cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressDO"
+            resultType="cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressDTO">
+        SELECT
+            u.nickname as userName,
+            fl.ct_type as kcflName,
+            c.course_name as courseName,
+            rp.brp_progress as progress,
+            rp.brp_type as progressType
+        FROM bjdx_report_progress rp
+        LEFT JOIN bjdx_course_type fl ON rp.brp_ct_id =fl.id
+        LEFT JOIN bjdx_course c ON rp.brp_course_id = c.id
+        LEFT JOIN system_users u ON rp.brp_user_id = u.id
+    </select>
+</mapper>