From 134fe299baa9637b2fc580f0b91da760a6515094 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Thu, 8 Oct 2026 13:59:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B9=B3=E5=8F=B0=E9=A2=98=E5=BA=93?= =?UTF-8?q?=E5=BD=92=E5=B1=9E=E9=A1=B9=E7=9B=AE(=E4=BB=BB=E5=8A=A1)?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E5=8F=AF=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 屏蔽归属任务功能:保存/导入/AI出题不再强制选择归属项目 - task_key 为空时跳过存在性校验,入库存空值;后续归属规则调整(如按学校/项目)预留 --- .../service/PlatformQuestionBankService.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/sztzjy/linkCommerce/service/PlatformQuestionBankService.java b/src/main/java/com/sztzjy/linkCommerce/service/PlatformQuestionBankService.java index 0268c29..668320d 100644 --- a/src/main/java/com/sztzjy/linkCommerce/service/PlatformQuestionBankService.java +++ b/src/main/java/com/sztzjy/linkCommerce/service/PlatformQuestionBankService.java @@ -73,7 +73,7 @@ public class PlatformQuestionBankService { public Map save(JwtUser user, Long id, Map payload) { platformAdminService.requirePlatformAdmin(user); ValidQuestion q = validate(payload); - requireTask(q.taskKey); + if (StringUtils.isNotBlank(q.taskKey)) requireTask(q.taskKey); if (id == null) { jdbc.update("insert into exam_question(school_id,teacher_id,source_type,task_key,question_type,stem,options_json,answer_json,answer_analysis,attachment_name,attachment_url) values(?,?,?,?,?,?,?,?,?,?,?)", PLATFORM, PLATFORM, PLATFORM, q.taskKey, q.type, q.stem, json(q.options), json(q.answer), q.analysis, text(payload.get("attachmentName")), text(payload.get("attachmentUrl"))); @@ -93,8 +93,7 @@ public class PlatformQuestionBankService { public Map aiPreview(JwtUser user, Map request) { platformAdminService.requirePlatformAdmin(user); - String taskKey = required(request, "taskKey", "请选择归属项目"); - requireTask(taskKey); + String taskKey = text(request.get("taskKey")).trim(); String type = required(request, "type", "请选择题型"); validateType(type); int count; try { count = Integer.parseInt(text(request.get("count"))); } catch (Exception e) { throw new IllegalArgumentException("题目数量必须是数字"); } @@ -126,7 +125,7 @@ public class PlatformQuestionBankService { @Transactional public List> importExcel(JwtUser user, MultipartFile file, String taskKey) { - platformAdminService.requirePlatformAdmin(user); requireTask(taskKey); + platformAdminService.requirePlatformAdmin(user); if (StringUtils.isNotBlank(taskKey)) requireTask(taskKey); if (file == null || file.isEmpty()) throw new IllegalArgumentException("请选择Word或Excel文件"); String name = StringUtils.defaultString(file.getOriginalFilename()).toLowerCase(Locale.ROOT); if (name.endsWith(".docx")) return importWord(user, file, taskKey); @@ -158,7 +157,7 @@ public class PlatformQuestionBankService { } catch (IllegalArgumentException e) { throw e; } catch (Exception e) { throw new IllegalArgumentException("Word导入失败,请检查模板"); } } - private ValidQuestion validate(Map p) { String type=required(p,"type","请选择题型"); validateType(type); String stem=required(p,"stem","题干不能为空"); if(StringUtils.isBlank(plain(stem))) throw new IllegalArgumentException("题干不能为空"); List> options=objectMapper.convertValue(p.getOrDefault("options",Collections.emptyList()),new TypeReference>>(){}); Object answer=p.get("answer"); if(type.equals("SINGLE")||type.equals("MULTIPLE")){ if(options.size()<2) throw new IllegalArgumentException("选择题至少需要两个选项"); Set labels=new LinkedHashSet<>(); List> normalized=new ArrayList<>(); for(Map o:options){String label=text(o.get("label")).trim().toUpperCase();String content=text(o.get("content")).trim();if(!label.matches("[A-H]")||StringUtils.isBlank(plain(content))||!labels.add(label)) throw new IllegalArgumentException("选项格式不正确"); normalized.add(map("label",label,"content",content));} List answers=list(answer); if(type.equals("SINGLE")&&answers.size()!=1) throw new IllegalArgumentException("单选题只能设置一个正确答案"); if(answers.isEmpty()||!labels.containsAll(answers)) throw new IllegalArgumentException("正确答案必须来自题目选项"); return new ValidQuestion(type,stem,normalized,answers,text(p.get("analysis")),required(p,"taskKey","请选择归属项目")); } if(type.equals("TRUE_FALSE")){String v=text(answer);if(!"true".equalsIgnoreCase(v)&&!"false".equalsIgnoreCase(v)&&!"正确".equals(v)&&!"错误".equals(v))throw new IllegalArgumentException("判断题答案格式不正确");return new ValidQuestion(type,stem,Collections.emptyList(),"正确".equals(v)||"true".equalsIgnoreCase(v),text(p.get("analysis")),required(p,"taskKey","请选择归属项目"));} if(StringUtils.isBlank(plain(text(answer)))) throw new IllegalArgumentException("参考答案不能为空"); return new ValidQuestion(type,stem,Collections.emptyList(),text(answer),text(p.get("analysis")),required(p,"taskKey","请选择归属项目")); } + private ValidQuestion validate(Map p) { String type=required(p,"type","请选择题型"); validateType(type); String stem=required(p,"stem","题干不能为空"); if(StringUtils.isBlank(plain(stem))) throw new IllegalArgumentException("题干不能为空"); List> options=objectMapper.convertValue(p.getOrDefault("options",Collections.emptyList()),new TypeReference>>(){}); Object answer=p.get("answer"); if(type.equals("SINGLE")||type.equals("MULTIPLE")){ if(options.size()<2) throw new IllegalArgumentException("选择题至少需要两个选项"); Set labels=new LinkedHashSet<>(); List> normalized=new ArrayList<>(); for(Map o:options){String label=text(o.get("label")).trim().toUpperCase();String content=text(o.get("content")).trim();if(!label.matches("[A-H]")||StringUtils.isBlank(plain(content))||!labels.add(label)) throw new IllegalArgumentException("选项格式不正确"); normalized.add(map("label",label,"content",content));} List answers=list(answer); if(type.equals("SINGLE")&&answers.size()!=1) throw new IllegalArgumentException("单选题只能设置一个正确答案"); if(answers.isEmpty()||!labels.containsAll(answers)) throw new IllegalArgumentException("正确答案必须来自题目选项"); return new ValidQuestion(type,stem,normalized,answers,text(p.get("analysis")),text(p.get("taskKey")).trim()); } if(type.equals("TRUE_FALSE")){String v=text(answer);if(!"true".equalsIgnoreCase(v)&&!"false".equalsIgnoreCase(v)&&!"正确".equals(v)&&!"错误".equals(v))throw new IllegalArgumentException("判断题答案格式不正确");return new ValidQuestion(type,stem,Collections.emptyList(),"正确".equals(v)||"true".equalsIgnoreCase(v),text(p.get("analysis")),text(p.get("taskKey")).trim());} if(StringUtils.isBlank(plain(text(answer)))) throw new IllegalArgumentException("参考答案不能为空"); return new ValidQuestion(type,stem,Collections.emptyList(),text(answer),text(p.get("analysis")),text(p.get("taskKey")).trim()); } private Map normalize(Map p){ValidQuestion q=validate(p);return map("type",q.type,"stem",q.stem,"options",q.options,"answer",q.answer,"analysis",q.analysis,"taskKey",q.taskKey);} private void requireTask(String key){if(jdbc.queryForObject("select count(*) from training_task where task_key=?",Integer.class,key)==0)throw new IllegalArgumentException("归属项目不存在");} private Map row(java.sql.ResultSet rs)throws java.sql.SQLException{return map("id",rs.getLong("id"),"type",rs.getString("question_type"),"stem",rs.getString("stem"),"options",parse(rs.getString("options_json")),"answer",parse(rs.getString("answer_json")),"analysis",rs.getString("answer_analysis"),"attachmentName",rs.getString("attachment_name"),"attachmentUrl",rs.getString("attachment_url"),"sourceType",rs.getString("source_type"),"taskKey",rs.getString("task_key"),"projectName",rs.getString("project_name"),"taskName",rs.getString("task_name"),"updatedAt",rs.getTimestamp("update_time"));}