Parcourir la source

Merge branch 'master' of http://49.234.186.218:9000/root/ieplus

mingfu il y a 1 mois
Parent
commit
ce011bc688

+ 80 - 10
back-ui/src/utils/imageHelper.js

@@ -25,6 +25,35 @@ export function getImageProxyUrl(imageUrl) {
     return imageUrl
 }
 
+/**
+ * 转义HTML特殊字符
+ * @param {string} text - 需要转义的文本
+ * @returns {string} 转义后的文本
+ */
+function escapeHtml(text) {
+    if (!text) return ''
+    const map = {
+        '&': '&',
+        '<': '&lt;',
+        '>': '&gt;',
+        '"': '&quot;',
+        "'": '&#039;'
+    }
+    return text.replace(/[&<>"']/g, m => map[m])
+}
+
+/**
+ * 检查内容是否包含有效的HTML标签
+ * @param {string} content - 需要检查的内容
+ * @returns {boolean} 是否包含HTML标签
+ */
+function containsHtmlTags(content) {
+    // 检查是否包含完整的HTML标签(必须有开始和结束,或者自闭合标签)
+    // 匹配常见的HTML标签模式:<tag>、</tag>、<tag/>、<tag attr="value">
+    const htmlTagRegex = /<\/?[a-z][a-z0-9]*(\s+[^>]*)?\/?>/i
+    return htmlTagRegex.test(content)
+}
+
 /**
  * 格式化内容,将图片URL转换为img标签
  * 处理HTML中的图片标签和纯文本中的图片URL
@@ -34,6 +63,9 @@ export function getImageProxyUrl(imageUrl) {
 export function formatContentWithImages(content) {
     if (!content) return ''
 
+    // 检查内容是否包含HTML标签
+    const isHtmlContent = containsHtmlTags(content)
+
     // 如果内容已经是HTML格式(包含img标签),需要处理其中的图片URL
     if (content.includes('<img') || content.includes('<IMG')) {
         // 提取所有img标签中的src属性
@@ -66,29 +98,67 @@ export function formatContentWithImages(content) {
 
     // 将纯文本的图片URL转换为img标签
     let formattedContent = content
-    const matches = content.match(imageUrlRegex)
+    const urlPositions = []
+
+    // 使用exec方法获取所有图片URL的位置信息
+    let match
+    const regex = new RegExp(imageUrlRegex)
+    while ((match = regex.exec(content)) !== null) {
+        urlPositions.push({
+            url: match[0],
+            startIndex: match.index,
+            endIndex: match.index + match[0].length
+        })
+    }
+
+    // 如果是纯文本内容(不包含HTML标签),需要转义HTML特殊字符
+    if (!isHtmlContent) {
+        // 从前往后处理,分段转义
+        let result = ''
+        let lastIndex = 0
 
-    if (matches) {
-        matches.forEach(url => {
-            // 确保URL是完整的
+        // 处理每个图片URL
+        urlPositions.forEach(({ url, startIndex, endIndex }) => {
+            // 转义URL之前的内容
+            result += escapeHtml(content.substring(lastIndex, startIndex))
+            
+            // 处理图片URL
+            let imageUrl = url.trim()
+            if (imageUrl.startsWith('//')) {
+                imageUrl = 'https:' + imageUrl
+            }
+
+            const proxyUrl = getImageProxyUrl(imageUrl)
+            const finalUrl = proxyUrl !== imageUrl ? proxyUrl : imageUrl
+            const crossOriginAttr = proxyUrl === imageUrl ? 'crossorigin="anonymous" referrerpolicy="no-referrer"' : ''
+
+            const imgTag = `<img src="${finalUrl}" ${crossOriginAttr} alt="图片" style="max-width: 100%; height: auto; display: block; margin: 10px 0;" onerror="this.onerror=null; this.src='${imageUrl}'; this.style.border='1px solid #ddd'; this.alt='图片加载失败,点击查看原图'; this.style.cursor='pointer'; this.title='点击查看原图'; this.onclick='window.open(this.src)';" />`
+            result += imgTag
+            
+            lastIndex = endIndex
+        })
+        
+        // 转义剩余内容
+        result += escapeHtml(content.substring(lastIndex))
+        
+        return result
+    } else {
+        // HTML内容,直接替换图片URL
+        urlPositions.forEach(({ url }) => {
             let imageUrl = url.trim()
-            // 如果是以//开头的,添加https:
             if (imageUrl.startsWith('//')) {
                 imageUrl = 'https:' + imageUrl
             }
 
-            // 对于第三方图片,尝试使用代理
             const proxyUrl = getImageProxyUrl(imageUrl)
-            // 如果代理不可用,使用原URL并添加跨域属性
             const finalUrl = proxyUrl !== imageUrl ? proxyUrl : imageUrl
             const crossOriginAttr = proxyUrl === imageUrl ? 'crossorigin="anonymous" referrerpolicy="no-referrer"' : ''
 
-            // 将URL替换为img标签
             const imgTag = `<img src="${finalUrl}" ${crossOriginAttr} alt="图片" style="max-width: 100%; height: auto; display: block; margin: 10px 0;" onerror="this.onerror=null; this.src='${imageUrl}'; this.style.border='1px solid #ddd'; this.alt='图片加载失败,点击查看原图'; this.style.cursor='pointer'; this.title='点击查看原图'; this.onclick='window.open(this.src)';" />`
             formattedContent = formattedContent.replace(url, imgTag)
         })
+        
+        return formattedContent
     }
-
-    return formattedContent
 }
 

+ 21 - 1
back-ui/src/views/system/bBusiWishUniversitiesEnrollBrochure/index.vue

@@ -320,7 +320,26 @@
 <!--          <el-input v-model="form.metaDescription" placeholder="请输入元数据描述" />-->
 <!--        </el-form-item>-->
         <el-form-item label="内容">
-          <editor v-model="form.content" :min-height="192"/>
+          <div style="width: 100%;">
+            <div style="margin-bottom: 10px;">
+              <el-radio-group v-model="editorMode" size="small">
+                <el-radio-button label="rich">富文本编辑</el-radio-button>
+                <el-radio-button label="source">源代码编辑</el-radio-button>
+              </el-radio-group>
+              <span style="margin-left: 10px; color: #909399; font-size: 12px;">
+                {{ editorMode === 'source' ? '源代码模式可保持原始HTML格式' : '富文本模式可能改变HTML格式' }}
+              </span>
+            </div>
+            <editor v-if="editorMode === 'rich'" v-model="form.content" :min-height="192"/>
+            <el-input 
+              v-else 
+              v-model="form.content" 
+              type="textarea" 
+              :autosize="{ minRows: 10, maxRows: 30 }" 
+              placeholder="请输入HTML内容"
+              style="font-family: monospace;"
+            />
+          </div>
         </el-form-item>
 <!--        <el-form-item label="tags" prop="tags">-->
 <!--          <el-input v-model="form.tags" placeholder="请输入tags" />-->
@@ -404,6 +423,7 @@ const total = ref(0)
 const title = ref("")
 const collegeList = ref([])
 const brochureTypeList = ref([])
+const editorMode = ref("source") // 默认使用源代码模式,保持原始格式
 
 /** 导入参数 */
 const upload = reactive({

+ 1 - 4
ie-admin/src/main/java/com/ruoyi/web/controller/front/FrontUniversitiesController.java

@@ -359,9 +359,6 @@ public class FrontUniversitiesController extends BaseController {
         return AjaxResult.success(data);
     }
 
-
-
-
     @GetMapping("getUniversitiesEnrollBrochure")
     @ApiOperation("03 招生简章")
     public TableDataInfo getUniversitiesEnrollBrochure(@ApiParam("学校code") @RequestParam String code,
@@ -369,7 +366,7 @@ public class FrontUniversitiesController extends BaseController {
         BBusiWishUniversitiesEnrollBrochure query = new BBusiWishUniversitiesEnrollBrochure();
         query.setCollegeCode(code);
         query.setTitle(title);
-        startPage();
+//        startPage();
         List<BBusiWishUniversitiesEnrollBrochure> list = universitiesEnrollBrochureService.selectBBusiWishUniversitiesEnrollBrochureList(query);
         return getDataTable(list);
     }

+ 4 - 1
ie-admin/src/main/java/com/ruoyi/web/controller/ie/FrontHollandController.java

@@ -1,5 +1,6 @@
 package com.ruoyi.web.controller.ie;
 
+import com.ruoyi.common.annotation.Anonymous;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.page.TableDataInfo;
@@ -35,6 +36,7 @@ public class FrontHollandController extends BaseController {
     private CommService commService;
     @GetMapping("steps")
     @ApiOperation("01 测试步骤")
+    @Anonymous
     public AjaxResult steps() {
         BBusiHollandSteps exam = new BBusiHollandSteps();
         exam.setStatus(1);
@@ -44,8 +46,9 @@ public class FrontHollandController extends BaseController {
 
     @GetMapping("questions")
     @ApiOperation("02 步骤题目")
+    @Anonymous
     public TableDataInfo question(@ApiParam("stepId") @RequestParam Long stepId) {
-        commService.requireVip();
+//        commService.requireVip();
 
         List<BBusiHollandQuestions> arr = questionsService.selectQuestionsByStepId(stepId);
         for (int i = 0; i < arr.size(); i++) {

+ 16 - 1
ie-admin/src/main/java/com/ruoyi/web/controller/learn/LearnTeacherController.java

@@ -271,7 +271,8 @@ public class LearnTeacherController extends BaseController {
         req.setBuildType("FullIntelligent");
         req.setDirectType(false);
         if(null == req.getSubjectId()) {
-            AjaxResult.error("未选择科目");
+//            AjaxResult.error("未选择科目");
+            req.setSubjectId(11L);
         }
         req.setTeacherId(getTeacherId());
         return AjaxResult.success(learnTeacherService.buildPapersFull(req));
@@ -306,6 +307,20 @@ public class LearnTeacherController extends BaseController {
         return AjaxResult.success(learnTeacherService.buildPapersFull(req));
     }
 
+    @PreAuthorize("@ss.hasPermi('learn:test_paper:add')")
+    @PostMapping("/build/fullKnowledgeIntelligent")
+    @ApiOperation("全量知识点智能")
+    public AjaxResult buildFullKnowledgeIntelligent(@RequestBody TestPaperVO.TestPaperBuildReq req)
+    {
+        req.setBuildType("FullIntelligent");
+        req.setDirectType(false);
+        if(null == req.getSubjectId()) {
+            AjaxResult.error("未选择科目");
+        }
+        req.setTeacherId(getTeacherId());
+        return AjaxResult.success(learnTeacherService.buildPapersFullByKnowledge(req));
+    }
+
     @GetMapping("/universities")
     @ApiOperation("院校列表")
     public AjaxResult universities(@ApiParam("批次ID") Long batchId, @RequestParam @ApiParam("考生类型") ExamType examType)

+ 79 - 27
ie-admin/src/main/java/com/ruoyi/web/service/LearnTeacherService.java

@@ -347,33 +347,7 @@ public class LearnTeacherService {
         List<LearnTestPaper> learnTestPaperList = learnTestPaperMapper.selectByBatchAndUniversityIds(req.getBuildType(), req.getBatchId(), req.getSubjectId(),req.getTeacherId(), null);
         LearnTestPaper learnTestPaper;
         if(CollectionUtils.isEmpty(learnTestPaperList)) {
-            LearnPaper paper = new LearnPaper();
-            paper.setSubjectId(req.getSubjectId());
-            String paperName = StringUtils.isBlank(req.getName()) ? learnTest.getName() + "_" + dzSubject.getSubjectName() : req.getName();
-            paper.setPaperName(paperName.length() > 254 ? paperName.substring(0, 254) : paperName);
-            paper.setYear(Calendar.getInstance().get(Calendar.YEAR)); // TODO  年度
-            paper.setPaperType(PaperType.Test.name());
-            paper.setDirectKey("");
-            paper.setStatus(PaperStatus.Valid.getVal());
-            paper.setRelateId(req.getBatchId().longValue());
-            paper.setFenshu(0);
-            if("FullHand".equals(req.getBuildType())) {
-                saveHandPaper(paper, req.getQuestions());
-            } else {
-                Pair<LearnPaper, List<LearnPaperQuestion>> paperResult = paperService.buildPaper(null, paper, req.getPaperDef());
-                paperService.savePaper(paperResult.getKey(), paperResult.getValue());
-            }
-            LearnTestPaper testPaper = new LearnTestPaper();
-            testPaper.setBuildType(req.getBuildType());
-            testPaper.setBatchId(req.getBatchId());
-            testPaper.setExamType(req.getExamType());
-            testPaper.setSubjectId(req.getSubjectId());
-            testPaper.setDirectKey("");
-            testPaper.setPaperId(paper.getId());
-            testPaper.setConditions(JSONObject.toJSONString(req));
-            testPaper.setCreatorId(SecurityUtils.getUserId());
-            testPaper.setTeacherId(req.getTeacherId());
-            learnTestPaperMapper.insertLearnTestPaper(testPaper);
+            LearnTestPaper testPaper = getPaper( req, dzSubject, learnTest);
             learnTestPaper = testPaper;
         } else {
             learnTestPaper = learnTestPaperList.get(0);
@@ -652,4 +626,82 @@ public class LearnTeacherService {
             return false;
         }
     }
+
+    private LearnTestPaper getPaper(TestPaperVO.TestPaperBuildReq req,DzSubject dzSubject,LearnTest learnTest){
+        LearnPaper paper = new LearnPaper();
+        paper.setSubjectId(req.getSubjectId());
+        String paperName = StringUtils.isBlank(req.getName()) ? learnTest.getName() + "_" + (null==dzSubject?"":dzSubject.getSubjectName()) : req.getName();
+        paper.setPaperName(paperName.length() > 254 ? paperName.substring(0, 254) : paperName);
+        paper.setYear(Calendar.getInstance().get(Calendar.YEAR)); // TODO  年度
+        paper.setPaperType(PaperType.Test.name());
+        paper.setDirectKey("");
+        paper.setStatus(PaperStatus.Valid.getVal());
+        paper.setRelateId(req.getBatchId().longValue());
+        paper.setFenshu(0);
+        if("FullHand".equals(req.getBuildType())) {
+            saveHandPaper(paper, req.getQuestions());
+        } else {
+            Pair<LearnPaper, List<LearnPaperQuestion>> paperResult = paperService.buildPaper(null, paper, req.getPaperDef());
+            paperService.savePaper(paperResult.getKey(), paperResult.getValue());
+        }
+        LearnTestPaper testPaper = new LearnTestPaper();
+        testPaper.setBuildType(req.getBuildType());
+        testPaper.setBatchId(req.getBatchId());
+        testPaper.setExamType(req.getExamType());
+        testPaper.setSubjectId(req.getSubjectId());
+        testPaper.setDirectKey("");
+        testPaper.setPaperId(paper.getId());
+        testPaper.setConditions(JSONObject.toJSONString(req));
+        testPaper.setCreatorId(SecurityUtils.getUserId());
+        testPaper.setTeacherId(req.getTeacherId());
+        learnTestPaperMapper.insertLearnTestPaper(testPaper);
+        return testPaper;
+    }
+
+    /**
+     * 根据知识点自由组卷
+     * @param req
+     * @return
+     */
+    public String buildPapersFullByKnowledge(TestPaperVO.TestPaperBuildReq req) {
+
+        DzSubject dzSubject = dzSubjectService.selectDzSubjectBySubjectId(req.getSubjectId());
+        LearnTest learnTest = learnTestService.selectLearnTestByBatchId(req.getBatchId());
+        // 生成试卷
+        LearnTestPaper testPaper = getPaper( req, dzSubject, learnTest);
+
+        updateBuildInfo(req.getTeacherId(), new TestRecordCond(req.getBuildType(), req.getBatchId(), req.getClassId(), req.getSubjectId(), null, null));
+        return "";
+    }
+
+    /**
+     * 发送试卷给学生
+     * @param req
+     * @param paperId
+     * @return
+     */
+    public String sendPaper(TestPaperVO.TestPaperBuildReq req,Long paperId) {
+        List<LearnStudent> studentList = learnStudentMapper.selectLearnStudentsByMap(req.toMap());
+        if(CollectionUtils.isEmpty(studentList)) {
+            throw new ValidationException("无学生可发布");
+        }
+
+//        LearnTestPaper learnTestPaper = learnTestPaperMapper.selectLearnTestPaperByPaperId(paperId);
+        for(LearnStudent student : studentList) {
+            LearnTestStudent lts = new LearnTestStudent();
+            lts.setBatchId(req.getBatchId());
+            lts.setStudentId(student.getStudentId());
+            lts.setBuildType(req.getBuildType());
+            lts.setSubjectId(req.getSubjectId());
+            lts.setDirectKey("");
+            lts.setPaperId(paperId);
+            lts.setCampusId(student.getCampusId());
+            lts.setSchoolId(student.getSchoolId());
+            lts.setClassId(student.getClassId());
+            lts.setStatus(ExamineeStatus.Sign.getVal());
+            lts.setCreatorId(SecurityUtils.getUserId());
+            learnTestStudentMapper.insertLearnTestStudent(lts);
+        }
+        return "";
+    }
 }

+ 10 - 9
ie-system/src/main/java/com/ruoyi/learn/mapper/LearnTestPaperMapper.java

@@ -7,25 +7,26 @@ import org.apache.ibatis.annotations.Param;
 
 /**
  * 批次测试卷Mapper接口
- * 
+ *
  * @author ruoyi
  * @date 2025-09-18
  */
-public interface LearnTestPaperMapper 
+public interface LearnTestPaperMapper
 {
     public List<LearnTestPaper> selectByBatchAndUniversityIds(@Param("buildType") String buildType, @Param("batchId") Integer batchId, @Param("subjectId") Long subjectId, @Param("teacherId") Long teacherId, @Param("universityIds") Collection<Long> universityIds);
 
     /**
      * 查询批次测试卷
-     * 
+     *
      * @param id 批次测试卷主键
      * @return 批次测试卷
      */
     public LearnTestPaper selectLearnTestPaperById(String id);
+    public LearnTestPaper selectLearnTestPaperByPaperId(Long paperId);
 
     /**
      * 查询批次测试卷列表
-     * 
+     *
      * @param learnTestPaper 批次测试卷
      * @return 批次测试卷集合
      */
@@ -33,7 +34,7 @@ public interface LearnTestPaperMapper
 
     /**
      * 新增批次测试卷
-     * 
+     *
      * @param learnTestPaper 批次测试卷
      * @return 结果
      */
@@ -41,7 +42,7 @@ public interface LearnTestPaperMapper
 
     /**
      * 修改批次测试卷
-     * 
+     *
      * @param learnTestPaper 批次测试卷
      * @return 结果
      */
@@ -49,7 +50,7 @@ public interface LearnTestPaperMapper
 
     /**
      * 删除批次测试卷
-     * 
+     *
      * @param id 批次测试卷主键
      * @return 结果
      */
@@ -57,7 +58,7 @@ public interface LearnTestPaperMapper
 
     /**
      * 批量删除批次测试卷
-     * 
+     *
      * @param ids 需要删除的数据主键集合
      * @return 结果
      */
@@ -65,7 +66,7 @@ public interface LearnTestPaperMapper
 
     /**
      * 查询试卷列表(关联查询)
-     * 
+     *
      * @param params 查询参数(creatorId, buildType)
      * @return 试卷列表
      */

+ 9 - 8
ie-system/src/main/java/com/ruoyi/learn/service/ILearnTestPaperService.java

@@ -5,23 +5,24 @@ import com.ruoyi.learn.domain.LearnTestPaper;
 
 /**
  * 批次测试卷Service接口
- * 
+ *
  * @author ruoyi
  * @date 2025-09-18
  */
-public interface ILearnTestPaperService 
+public interface ILearnTestPaperService
 {
     /**
      * 查询批次测试卷
-     * 
+     *
      * @param id 批次测试卷主键
      * @return 批次测试卷
      */
     public LearnTestPaper selectLearnTestPaperById(String id);
+    public LearnTestPaper selectLearnTestPaperByPaperId(Long paperId);
 
     /**
      * 查询批次测试卷列表
-     * 
+     *
      * @param learnTestPaper 批次测试卷
      * @return 批次测试卷集合
      */
@@ -29,7 +30,7 @@ public interface ILearnTestPaperService
 
     /**
      * 新增批次测试卷
-     * 
+     *
      * @param learnTestPaper 批次测试卷
      * @return 结果
      */
@@ -37,7 +38,7 @@ public interface ILearnTestPaperService
 
     /**
      * 修改批次测试卷
-     * 
+     *
      * @param learnTestPaper 批次测试卷
      * @return 结果
      */
@@ -45,7 +46,7 @@ public interface ILearnTestPaperService
 
     /**
      * 批量删除批次测试卷
-     * 
+     *
      * @param ids 需要删除的批次测试卷主键集合
      * @return 结果
      */
@@ -53,7 +54,7 @@ public interface ILearnTestPaperService
 
     /**
      * 删除批次测试卷信息
-     * 
+     *
      * @param id 批次测试卷主键
      * @return 结果
      */

+ 13 - 8
ie-system/src/main/java/com/ruoyi/learn/service/impl/LearnTestPaperServiceImpl.java

@@ -10,19 +10,19 @@ import com.ruoyi.learn.service.ILearnTestPaperService;
 
 /**
  * 批次测试卷Service业务层处理
- * 
+ *
  * @author ruoyi
  * @date 2025-09-18
  */
 @Service
-public class LearnTestPaperServiceImpl implements ILearnTestPaperService 
+public class LearnTestPaperServiceImpl implements ILearnTestPaperService
 {
     @Autowired
     private LearnTestPaperMapper learnTestPaperMapper;
 
     /**
      * 查询批次测试卷
-     * 
+     *
      * @param id 批次测试卷主键
      * @return 批次测试卷
      */
@@ -32,9 +32,14 @@ public class LearnTestPaperServiceImpl implements ILearnTestPaperService
         return learnTestPaperMapper.selectLearnTestPaperById(id);
     }
 
+    @Override
+    public LearnTestPaper selectLearnTestPaperByPaperId(Long paperId) {
+        return learnTestPaperMapper.selectLearnTestPaperByPaperId(paperId);
+    }
+
     /**
      * 查询批次测试卷列表
-     * 
+     *
      * @param learnTestPaper 批次测试卷
      * @return 批次测试卷
      */
@@ -46,7 +51,7 @@ public class LearnTestPaperServiceImpl implements ILearnTestPaperService
 
     /**
      * 新增批次测试卷
-     * 
+     *
      * @param learnTestPaper 批次测试卷
      * @return 结果
      */
@@ -59,7 +64,7 @@ public class LearnTestPaperServiceImpl implements ILearnTestPaperService
 
     /**
      * 修改批次测试卷
-     * 
+     *
      * @param learnTestPaper 批次测试卷
      * @return 结果
      */
@@ -71,7 +76,7 @@ public class LearnTestPaperServiceImpl implements ILearnTestPaperService
 
     /**
      * 批量删除批次测试卷
-     * 
+     *
      * @param ids 需要删除的批次测试卷主键
      * @return 结果
      */
@@ -83,7 +88,7 @@ public class LearnTestPaperServiceImpl implements ILearnTestPaperService
 
     /**
      * 删除批次测试卷信息
-     * 
+     *
      * @param id 批次测试卷主键
      * @return 结果
      */

+ 4 - 0
ie-system/src/main/resources/mapper/learn/LearnTestPaperMapper.xml

@@ -51,6 +51,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectLearnTestPaperVo"/>
         where id = #{id}
     </select>
+    <select id="selectLearnTestPaperByPaperId" parameterType="Long" resultMap="LearnTestPaperResult">
+        <include refid="selectLearnTestPaperVo"/>
+        where paper_id = #{paperId}
+    </select>
 
     <insert id="insertLearnTestPaper" parameterType="LearnTestPaper" useGeneratedKeys="true" keyProperty="id">
         insert into learn_test_paper