|
|
|
@ -15,6 +15,7 @@ import com.ibeetl.jlw.dao.CourseInfoDao;
|
|
|
|
|
import com.ibeetl.jlw.dao.ResourcesQuestionDao;
|
|
|
|
|
import com.ibeetl.jlw.entity.*;
|
|
|
|
|
import com.ibeetl.jlw.entity.dto.QuestionSettingDTO;
|
|
|
|
|
import com.ibeetl.jlw.entity.vo.ImportQuestionByWordTemplateResultVO;
|
|
|
|
|
import com.ibeetl.jlw.entity.vo.QuestionTypeCountVO;
|
|
|
|
|
import com.ibeetl.jlw.enums.AddTypeEnum;
|
|
|
|
|
import com.ibeetl.jlw.enums.ResourcesQuestionTypeEnum;
|
|
|
|
@ -22,6 +23,7 @@ import com.ibeetl.jlw.service.strategy.StrategyContext;
|
|
|
|
|
import com.ibeetl.jlw.validator.QuestionValidator;
|
|
|
|
|
import com.ibeetl.jlw.web.query.CourseInfoQuery;
|
|
|
|
|
import com.ibeetl.jlw.web.query.ResourcesQuestionQuery;
|
|
|
|
|
import lombok.Cleanup;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.apache.logging.log4j.util.Strings;
|
|
|
|
@ -53,6 +55,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
import java.util.concurrent.CopyOnWriteArrayList;
|
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
|
import java.util.function.Consumer;
|
|
|
|
|
import java.util.function.Function;
|
|
|
|
|
import java.util.regex.Matcher;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
@ -798,20 +801,18 @@ public class ResourcesQuestionService extends CoreBaseService<ResourcesQuestion>
|
|
|
|
|
* @Author: lx
|
|
|
|
|
* @Date: 2023/1/8 22:49
|
|
|
|
|
*/
|
|
|
|
|
public JsonResult importQuestionByWordTemplate(@NotEmpty List<FileEntity> fileEntityList, CoreUser coreUser) {
|
|
|
|
|
public ImportQuestionByWordTemplateResultVO importQuestionByWordTemplate(@NotEmpty List<FileEntity> fileEntityList, CoreUser coreUser) {
|
|
|
|
|
/** 找出段落, 逐段落处理 */
|
|
|
|
|
AtomicReference<FileInputStream> inputStream = new AtomicReference<>();
|
|
|
|
|
AtomicReference<XWPFDocument> xDocument = new AtomicReference<>();
|
|
|
|
|
|
|
|
|
|
//装结果 key:卷子访问地址 value:{标题,题目List}
|
|
|
|
|
Map<String,Object[]> resultMap = new HashMap<>();
|
|
|
|
|
ImportQuestionByWordTemplateResultVO resultVO = new ImportQuestionByWordTemplateResultVO();
|
|
|
|
|
/** 仅用于存放标题 */
|
|
|
|
|
final String[] title = { Strings.EMPTY };
|
|
|
|
|
/** 标题暂存,可能是多个 */
|
|
|
|
|
final StringBuilder titleStb = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
/** 循环文件集合 */
|
|
|
|
|
fileEntityList.forEach(fileEntity -> {
|
|
|
|
|
for (FileEntity fileEntity: fileEntityList) {
|
|
|
|
|
/** 上传文件的临时路径 */
|
|
|
|
|
String importPath = fileEntity.getAbsoluteUrl();
|
|
|
|
|
/** 新建文件夹绝对路径 */
|
|
|
|
@ -820,8 +821,8 @@ public class ResourcesQuestionService extends CoreBaseService<ResourcesQuestion>
|
|
|
|
|
String absolutePath = absoluteDirPath + fileEntity.getTempName();
|
|
|
|
|
//各种流
|
|
|
|
|
try {
|
|
|
|
|
inputStream.set(new FileInputStream(importPath));
|
|
|
|
|
xDocument.set(new XWPFDocument(inputStream.get()));
|
|
|
|
|
@Cleanup FileInputStream fileInputStream = new FileInputStream(importPath);
|
|
|
|
|
xDocument.set(new XWPFDocument(fileInputStream));
|
|
|
|
|
/** 集合拷贝 */
|
|
|
|
|
List<MyXWPFParagraph> myParagraphs = BeanCopyUtil.copyListProperties(xDocument.get().getParagraphs() , MyXWPFParagraph::new, (t, d) -> {
|
|
|
|
|
d.setXwpfParagraph(t);
|
|
|
|
@ -844,35 +845,39 @@ public class ResourcesQuestionService extends CoreBaseService<ResourcesQuestion>
|
|
|
|
|
/** 题干计数 */
|
|
|
|
|
AtomicInteger recordsCount = new AtomicInteger();
|
|
|
|
|
/** 遍历所有段落 */
|
|
|
|
|
myParagraphs.forEach(e -> {
|
|
|
|
|
for (MyXWPFParagraph myParagraph : myParagraphs) {
|
|
|
|
|
/** 策略中的参数设置 */
|
|
|
|
|
strategyContext.setText(e.getText(absoluteDirPath, fileEntity.getTempName())).start(c -> {
|
|
|
|
|
Consumer<Map<StrategyContext.QuestionParagraphTypeEnum, String>> mapConsumer = item -> {
|
|
|
|
|
/** 第一行 */
|
|
|
|
|
if (recordsCount.get() == 1 && StringUtils.isBlank(title[0])) {
|
|
|
|
|
if (recordsCount.get() == 1 && StringUtils.isBlank(title[0])) {
|
|
|
|
|
/** 暴力取值 */
|
|
|
|
|
titleStb.append(title[0] = myParagraphs.get(0).getText(absoluteDirPath, fileEntity.getTempName()));
|
|
|
|
|
}
|
|
|
|
|
/** k 策略枚举:v 处理后的段落文字 */
|
|
|
|
|
c.forEach((k, v) -> {
|
|
|
|
|
item.forEach((k, v) -> {
|
|
|
|
|
/** 记录段落类型, 未查询类型之外的类型 */
|
|
|
|
|
if (!k.equals(OTHER)) {paragraphTypeEnum.set(k);}
|
|
|
|
|
switch(k) {
|
|
|
|
|
if (!k.equals(OTHER)) {
|
|
|
|
|
paragraphTypeEnum.set(k);
|
|
|
|
|
}
|
|
|
|
|
switch (k) {
|
|
|
|
|
/** 未匹配到的段落 */
|
|
|
|
|
case OTHER: {
|
|
|
|
|
/** 如果非标题字符,可能是前一个段落的副行。需要追加到相应的段落中 */
|
|
|
|
|
insertCorrespondingParagraph(typeConcatEnum, paragraphTypeEnum.get() ,v, question, questionStem, questionAnswer);
|
|
|
|
|
} break;
|
|
|
|
|
insertCorrespondingParagraph(typeConcatEnum, paragraphTypeEnum.get(), v, question, questionStem, questionAnswer);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
/** 题目类型,分值,该类型的总分 */
|
|
|
|
|
case TYPE: {
|
|
|
|
|
/** 题目类型作用域 */
|
|
|
|
|
String[] sp = v.split(",");
|
|
|
|
|
typeConcatEnum.set(StrategyContext.QuestionTypeConcatEnum.matchText(sp[2]));
|
|
|
|
|
questionScore.set(NumberUtil.toBigDecimal(sp[0]).setScale(1, RoundingMode.HALF_UP));
|
|
|
|
|
} break;
|
|
|
|
|
questionScore.set(NumberUtil.toBigDecimal(sp[0]).setScale(1, RoundingMode.HALF_UP));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
/** 题干 */
|
|
|
|
|
case STEM: {
|
|
|
|
|
final String numStartRegex = "^\\d+[\\.\\、\\.]";
|
|
|
|
|
if(ReUtil.contains(numStartRegex, v)) {
|
|
|
|
|
if (ReUtil.contains(numStartRegex, v)) {
|
|
|
|
|
/** 题干的编号需要移除掉 */
|
|
|
|
|
questionStem.set(v.replaceFirst(numStartRegex, Strings.EMPTY).trim());
|
|
|
|
|
/** 题数++ */
|
|
|
|
@ -890,37 +895,36 @@ public class ResourcesQuestionService extends CoreBaseService<ResourcesQuestion>
|
|
|
|
|
resourcesQuestion.setUserId(coreUser.getId());
|
|
|
|
|
resourcesQuestion.setOrgId(coreUser.getOrgId());
|
|
|
|
|
|
|
|
|
|
if (StringUtils.isNotBlank(questionStem.get())){
|
|
|
|
|
resourcesQuestion.setQuestionStem(questionStem.get().replace("<","<").replace(">",">"));
|
|
|
|
|
}else {
|
|
|
|
|
if (StringUtils.isNotBlank(questionStem.get())) {
|
|
|
|
|
resourcesQuestion.setQuestionStem(questionStem.get().replace("<", "<").replace(">", ">"));
|
|
|
|
|
} else {
|
|
|
|
|
resourcesQuestion.setQuestionStem(questionStem.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
question.set(resourcesQuestion);
|
|
|
|
|
questionList.add(question.get());
|
|
|
|
|
}
|
|
|
|
|
} break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
/** 选项 */
|
|
|
|
|
case OPTION: {
|
|
|
|
|
putQuestionOption(v, question.get());
|
|
|
|
|
} break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
/** 答案 questionAnswer不包含答案: 字样 */
|
|
|
|
|
case ANSWER: {
|
|
|
|
|
questionAnswer.set(questionAnswer.get().concat(v));
|
|
|
|
|
// questionAnswer.get() 默认不包含 【答案】 字样
|
|
|
|
|
questionAnswer.set(secondFormat(questionAnswer.get(), typeConcatEnum.get()));
|
|
|
|
|
question.get().setQuestionAnswer(questionAnswer.get());
|
|
|
|
|
} break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
titleStb.append("</br><font size=\"0.5\" color=\"blue\">解析结果:");
|
|
|
|
|
titleStb.append(recordsCount.get());
|
|
|
|
|
titleStb.append(" 道题目</font>");
|
|
|
|
|
|
|
|
|
|
String finalTitle = titleStb.toString();
|
|
|
|
|
strategyContext.setText(myParagraph.getText(absoluteDirPath, fileEntity.getTempName())).start(mapConsumer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 最后检测属性, 并行处理,没有向外部非线程安全的变量写入东西,无需担心丢数据 */
|
|
|
|
|
questionList.parallelStream().forEach(item -> {
|
|
|
|
@ -932,15 +936,18 @@ public class ResourcesQuestionService extends CoreBaseService<ResourcesQuestion>
|
|
|
|
|
checkLocalQuestionsUnique(questionList);
|
|
|
|
|
|
|
|
|
|
/** 拼成前端需要的数据 */
|
|
|
|
|
resultMap.put(fileEntity.getUrl(), new Object[]{ finalTitle, questionList });
|
|
|
|
|
resultVO.setTitle(titleStb.toString());
|
|
|
|
|
resultVO.setOtherMsg(Collections.emptyList());
|
|
|
|
|
resultVO.setQuestionCount(recordsCount.get());
|
|
|
|
|
resultVO.setQuestionList(questionList);
|
|
|
|
|
|
|
|
|
|
} catch (Exception ex) { ex.printStackTrace(); }
|
|
|
|
|
finally {
|
|
|
|
|
try {inputStream.get().close(); xDocument.get().close(); }
|
|
|
|
|
try {xDocument.get().close(); }
|
|
|
|
|
catch (Exception ioe) { ioe.printStackTrace(); }
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return JsonResult.success(resultMap);
|
|
|
|
|
}
|
|
|
|
|
return resultVO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 取选项的正则 */
|
|
|
|
@ -960,10 +967,10 @@ public class ResourcesQuestionService extends CoreBaseService<ResourcesQuestion>
|
|
|
|
|
if(matcher.find()){
|
|
|
|
|
String questionOption = text.substring(2);
|
|
|
|
|
// 在现有的列表中添加
|
|
|
|
|
if(null != question.getQuestionOptionList()){
|
|
|
|
|
List<String> questionOptionList = question.getQuestionOptionList();
|
|
|
|
|
questionOptionList.add(questionOption);
|
|
|
|
|
question.putQuestionOptionList(questionOptionList);
|
|
|
|
|
List<String> optionList = question.getResourcesQuestionOptionList();
|
|
|
|
|
if(null != optionList){
|
|
|
|
|
optionList.add(questionOption);
|
|
|
|
|
question.putQuestionOptionList(optionList);
|
|
|
|
|
}
|
|
|
|
|
// 新建
|
|
|
|
|
else {
|
|
|
|
|