|
@@ -0,0 +1,620 @@
|
|
|
|
+package com.qmth.jkserver.controller.api;
|
|
|
|
+
|
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
|
+import cn.hutool.http.HttpStatus;
|
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
+import com.google.common.collect.ImmutableMap;
|
|
|
|
+import com.qmth.jkserver.common.UnZipUtils;
|
|
|
|
+import com.qmth.jkserver.constant.SystemConstant;
|
|
|
|
+import com.qmth.jkserver.controller.system.BaseSystemController;
|
|
|
|
+import com.qmth.jkserver.core.annotation.TokenValidate;
|
|
|
|
+import com.qmth.jkserver.core.exception.JkServerException;
|
|
|
|
+import com.qmth.jkserver.dto.wps.*;
|
|
|
|
+import com.qmth.jkserver.enums.TokenPolicy;
|
|
|
|
+import com.qmth.jkserver.service.CommonCacheService;
|
|
|
|
+import com.qmth.jkserver.util.FileStoreUtil;
|
|
|
|
+import com.qmth.jkserver.util.JacksonUtil;
|
|
|
|
+import com.qmth.jkserver.util.ResultUtil;
|
|
|
|
+import com.qmth.jkserver.util.WpsUtil;
|
|
|
|
+import io.swagger.annotations.*;
|
|
|
|
+import org.apache.commons.io.FileUtils;
|
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
|
+import org.jsoup.Jsoup;
|
|
|
|
+import org.jsoup.nodes.Document;
|
|
|
|
+import org.jsoup.nodes.Element;
|
|
|
|
+import org.jsoup.select.Elements;
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
|
+import org.springframework.mock.web.MockMultipartFile;
|
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
+import org.springframework.web.bind.annotation.RequestMethod;
|
|
|
|
+import org.springframework.web.bind.annotation.RequestParam;
|
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
|
+
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
+import javax.validation.constraints.Max;
|
|
|
|
+import javax.validation.constraints.Min;
|
|
|
|
+import java.io.File;
|
|
|
|
+import java.io.FileInputStream;
|
|
|
|
+import java.io.FileOutputStream;
|
|
|
|
+import java.io.IOException;
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+import java.net.URL;
|
|
|
|
+import java.security.NoSuchAlgorithmException;
|
|
|
|
+import java.util.*;
|
|
|
|
+import java.util.regex.Matcher;
|
|
|
|
+import java.util.regex.Pattern;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @Description: 机考wps对接接口
|
|
|
|
+ * @Param:
|
|
|
|
+ * @return:
|
|
|
|
+ * @Author: wangliang
|
|
|
|
+ * @Date: 2024/5/7
|
|
|
|
+ */
|
|
|
|
+@Api(tags = "机考wps对接接口管理Controller")
|
|
|
|
+@RestController
|
|
|
|
+@RequestMapping("/" + SystemConstant.WPS_API_OPEN)
|
|
|
|
+public class WpsController extends BaseSystemController {
|
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(WpsController.class);
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ CommonCacheService commonCacheService;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ FileStoreUtil fileStoreUtil;
|
|
|
|
+
|
|
|
|
+ @ApiOperation(value = "题库列表接口")
|
|
|
|
+ @RequestMapping(value = "/question/list", method = RequestMethod.POST)
|
|
|
|
+ @ApiResponses({@ApiResponse(code = 200, message = "题库列表接口信息", response = Object.class)})
|
|
|
|
+ @TokenValidate(policy = TokenPolicy.IGNORE)
|
|
|
|
+ public Object questionList(@ApiParam(value = "分页页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
|
|
|
|
+ @ApiParam(value = "分页数", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) throws Exception {
|
|
|
|
+ String result = WpsUtil.exection(new JSONObject(ImmutableMap.of("pageNumber", pageNumber, "pageSize", pageSize)).toJSONString(), SystemConstant.QUESTION_LIST);
|
|
|
|
+ Map<String, Object> map = JSONObject.parseObject(result, Map.class);
|
|
|
|
+ Integer code = (Integer) map.get("code");
|
|
|
|
+ if (Objects.nonNull(code) && code.intValue() == HttpStatus.HTTP_OK) {
|
|
|
|
+ Map<String, Object> dataMap = JSONObject.toJavaObject((JSONObject) map.get("data"), Map.class);
|
|
|
|
+ Integer count = (Integer) dataMap.get("count");
|
|
|
|
+ if (Objects.nonNull(count) && count.intValue() > 0) {
|
|
|
|
+ JSONArray jsonArray = (JSONArray) dataMap.get("list");
|
|
|
|
+ this.delFile();
|
|
|
|
+ for (int i = 0; i < jsonArray.size(); i++) {
|
|
|
|
+ this.reWriteJson(jsonArray.getJSONObject(i));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return ResultUtil.ok(result);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @ApiOperation(value = "题库明细接口")
|
|
|
|
+ @RequestMapping(value = "/question/detail", method = RequestMethod.POST)
|
|
|
|
+ @ApiResponses({@ApiResponse(code = 200, message = "题库明细接口信息", response = Object.class)})
|
|
|
|
+ @TokenValidate(policy = TokenPolicy.IGNORE)
|
|
|
|
+ public Object questionDetail(@ApiParam(value = "题库id", required = true) @RequestParam String id) throws IOException, NoSuchAlgorithmException {
|
|
|
|
+ String result = WpsUtil.exection(new JSONObject(Collections.singletonMap("id", id)).toJSONString(), SystemConstant.QUESTION_DETAIL);
|
|
|
|
+ Map<String, Object> map = JSONObject.parseObject(result, Map.class);
|
|
|
|
+ Integer code = (Integer) map.get("code");
|
|
|
|
+ if (Objects.nonNull(code) && code.intValue() == HttpStatus.HTTP_OK) {
|
|
|
|
+ this.reWriteJson((JSONObject) map.get("data"));
|
|
|
|
+ }
|
|
|
|
+ return ResultUtil.ok(result);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @ApiOperation(value = "清除缓存接口")
|
|
|
|
+ @RequestMapping(value = "/delete/cache", method = RequestMethod.POST)
|
|
|
|
+ @ApiResponses({@ApiResponse(code = 200, message = "清除缓存接口信息", response = Object.class)})
|
|
|
|
+ @TokenValidate(policy = TokenPolicy.IGNORE)
|
|
|
|
+ public Object deleteCache(@ApiParam(value = "缓存名称", required = true) @RequestParam String cacheName) throws IOException, NoSuchAlgorithmException {
|
|
|
|
+ commonCacheService.removeSysConfigCache(cacheName);
|
|
|
|
+ return ResultUtil.ok(true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @ApiOperation(value = "读取启明试卷接口")
|
|
|
|
+ @RequestMapping(value = "/read/qm/paper", method = RequestMethod.POST)
|
|
|
|
+ @ApiResponses({@ApiResponse(code = 200, message = "读取启明试卷接口信息", response = Object.class)})
|
|
|
|
+ @TokenValidate(policy = TokenPolicy.IGNORE)
|
|
|
|
+ public Object readQmPaper(@ApiParam(value = "上传文件", required = true) @RequestParam MultipartFile file,
|
|
|
|
+ @ApiParam(value = "题库id", required = true) @RequestParam String id) throws IOException, NoSuchAlgorithmException {
|
|
|
|
+ File zipFile = null;
|
|
|
|
+ Map<String, Object> jsonMap = this.reWriteJson(null);
|
|
|
|
+ if (CollectionUtils.isEmpty(jsonMap)) {
|
|
|
|
+ throw new JkServerException("未找到wps_question.json文件");
|
|
|
|
+ }
|
|
|
|
+ JSONObject json = (JSONObject) jsonMap.get(id);
|
|
|
|
+ Boolean insert = (Boolean) json.get("insert");
|
|
|
|
+ if (Objects.nonNull(insert) && insert) {
|
|
|
|
+ return ResultUtil.ok(true);
|
|
|
|
+ }
|
|
|
|
+ File rootFile = null;
|
|
|
|
+ try {
|
|
|
|
+ String workRoot = null, path = null;
|
|
|
|
+ if (!fileStoreUtil.workIsOss()) {
|
|
|
|
+ workRoot = fileStoreUtil.getWorkRoot();
|
|
|
|
+ path = SystemConstant.WPS + File.separator + DateUtil.format(new Date(), SystemConstant.WPS_DEFAULT_DATE_PATTERN);
|
|
|
|
+ rootFile = new File(new File(workRoot), path + File.separator + SystemConstant.getNanoId() + SystemConstant.ZIP_PREFIX);
|
|
|
|
+ if (!rootFile.exists()) {
|
|
|
|
+ rootFile.createNewFile();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ IOUtils.copy(file.getInputStream(), new FileOutputStream(rootFile));
|
|
|
|
+ File zipChildFile = new File(new File(workRoot), path + File.separator + SystemConstant.getNanoId());
|
|
|
|
+ File zipRootFile = null;
|
|
|
|
+ List<File> fileList = UnZipUtils.doUnZip(rootFile, zipChildFile, rootFile.getPath());
|
|
|
|
+ File dirName = null, answerFile = null;
|
|
|
|
+ Integer mainNumber = null, subNumber = null;
|
|
|
|
+ for (File f : fileList) {
|
|
|
|
+ File temp = f.getParentFile();
|
|
|
|
+ if (Objects.isNull(zipRootFile)) {
|
|
|
|
+ while (!Objects.equals(temp.getParent(), zipChildFile.getAbsolutePath())) {
|
|
|
|
+ temp = temp.getParentFile();
|
|
|
|
+ zipRootFile = temp;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (f.getParent().endsWith("attachment") && Objects.isNull(dirName)) {
|
|
|
|
+ dirName = f.getParentFile();
|
|
|
|
+ } else if (f.getName().endsWith("paper.json")) {
|
|
|
|
+ Map<String, Object> map = this.qmPaperReadAndUpdate(f, id, workRoot, path, dirName, jsonMap);
|
|
|
|
+ if (!CollectionUtils.isEmpty(map)) {
|
|
|
|
+ mainNumber = (Integer) map.get("mainNumber");
|
|
|
|
+ subNumber = (Integer) map.get("subNumber");
|
|
|
|
+ }
|
|
|
|
+ } else if (f.getName().endsWith("answer.json")) {
|
|
|
|
+ answerFile = this.qmAnswerReadAndUpdate(f, id, jsonMap);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (Objects.nonNull(mainNumber) && Objects.nonNull(subNumber) && Objects.nonNull(answerFile)) {
|
|
|
|
+ this.qmAnswerReloadAndUpdate(answerFile, mainNumber, subNumber);
|
|
|
|
+ }
|
|
|
|
+ zipFile = new File(zipChildFile.getAbsolutePath(), zipRootFile.getName() + SystemConstant.ZIP_PREFIX);
|
|
|
|
+ //重新打包
|
|
|
|
+ UnZipUtils.zipFile(zipChildFile.getAbsolutePath(), zipFile.getAbsolutePath(), null);
|
|
|
|
+ log.info("zipFile path:{}", zipFile.getAbsolutePath());
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ } finally {
|
|
|
|
+ if (Objects.nonNull(rootFile)) {
|
|
|
|
+ rootFile.delete();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ MultipartFile multipartFile = null;
|
|
|
|
+ if (Objects.nonNull(zipFile.getAbsolutePath())) {
|
|
|
|
+ for (Map.Entry<String, Object> entry : jsonMap.entrySet()) {
|
|
|
|
+ multipartFile = new MockMultipartFile("file", file.getName(), "application/zip", new FileInputStream(zipFile));
|
|
|
|
+ this.readQmPaper(multipartFile, entry.getKey());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return ResultUtil.ok(true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 启明答案重新修改
|
|
|
|
+ *
|
|
|
|
+ * @param answerFile
|
|
|
|
+ * @param mainNumber
|
|
|
|
+ * @param subNumber
|
|
|
|
+ * @throws IOException
|
|
|
|
+ */
|
|
|
|
+ protected void qmAnswerReloadAndUpdate(File answerFile, Integer mainNumber, Integer subNumber) throws IOException {
|
|
|
|
+ byte[] bytes = IOUtils.toByteArray(new FileInputStream(answerFile));
|
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(new String(bytes, SystemConstant.CHARSET_NAME));
|
|
|
|
+ JSONArray jsonArray = jsonObject.getJSONArray("details");//明细
|
|
|
|
+ JSONArray delJsonArray = new JSONArray(), delJsonOldArray = new JSONArray();
|
|
|
|
+ WpsAnswerVo wpsAnswerVoNew = new WpsAnswerVo(), wpsAnswerVoOld = null;
|
|
|
|
+ for (int i = 0; i < jsonArray.size(); i++) {
|
|
|
|
+ JSONObject jsonObject1 = jsonArray.getJSONObject(i);
|
|
|
|
+ String wpsId = jsonObject1.getString("id");
|
|
|
|
+ Integer number = jsonObject1.getInteger("number");
|
|
|
|
+ if (number.intValue() == mainNumber.intValue()) {
|
|
|
|
+ wpsAnswerVoOld = JSONObject.parseObject(JacksonUtil.parseJson(jsonObject1), WpsAnswerVo.class);
|
|
|
|
+ delJsonOldArray.add(jsonObject1);
|
|
|
|
+ }
|
|
|
|
+ if (Objects.nonNull(wpsId)) {
|
|
|
|
+ WpsAnswerVo wpsAnswerVo = JSONObject.parseObject(JacksonUtil.parseJson(jsonObject1), WpsAnswerVo.class);
|
|
|
|
+ wpsAnswerVo.setNumber(mainNumber);
|
|
|
|
+ wpsAnswerVo.getQuestions().get(0).setNumber(subNumber);
|
|
|
|
+ delJsonArray.add(jsonObject1);
|
|
|
|
+ BeanUtils.copyProperties(wpsAnswerVo, wpsAnswerVoNew);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ jsonArray.removeAll(delJsonArray);
|
|
|
|
+ wpsAnswerVoNew.setId(null);
|
|
|
|
+ if (Objects.isNull(wpsAnswerVoOld)) {
|
|
|
|
+ jsonArray.add(JSONObject.parseObject(JacksonUtil.parseJson(wpsAnswerVoNew)));
|
|
|
|
+ } else {
|
|
|
|
+ jsonArray.removeAll(delJsonOldArray);
|
|
|
|
+ wpsAnswerVoOld.getQuestions().addAll(wpsAnswerVoNew.getQuestions());
|
|
|
|
+ jsonArray.add(JSONObject.parseObject(JacksonUtil.parseJson(wpsAnswerVoOld)));
|
|
|
|
+ }
|
|
|
|
+ IOUtils.write(JacksonUtil.parseJson(jsonObject).getBytes(SystemConstant.CHARSET_NAME), new FileOutputStream(answerFile));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 启明答案修改
|
|
|
|
+ *
|
|
|
|
+ * @param f
|
|
|
|
+ * @param id
|
|
|
|
+ * @param jsonMap
|
|
|
|
+ * @return
|
|
|
|
+ * @throws IOException
|
|
|
|
+ */
|
|
|
|
+ protected File qmAnswerReadAndUpdate(File f, String id, Map<String, Object> jsonMap) throws IOException {
|
|
|
|
+ File answerFile = null;
|
|
|
|
+ byte[] bytes = IOUtils.toByteArray(new FileInputStream(f));
|
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(new String(bytes, SystemConstant.CHARSET_NAME));
|
|
|
|
+ JSONArray jsonArray = jsonObject.getJSONArray("details");//明细
|
|
|
|
+
|
|
|
|
+ JSONObject json = (JSONObject) jsonMap.get(id);
|
|
|
|
+ JSONArray object = json.getJSONArray("answer");
|
|
|
|
+ for (int i = 0; i < object.size(); i++) {
|
|
|
|
+ JSONObject jsonObject1 = object.getJSONObject(i);
|
|
|
|
+ List<WpsBlocksVo> wpsBlocksVoList = JSONArray.parseArray(JacksonUtil.parseJson(jsonObject1.getJSONArray("blocks")), WpsBlocksVo.class);
|
|
|
|
+ WpsSectionsVo wpsSectionsVo = new WpsSectionsVo(wpsBlocksVoList);
|
|
|
|
+ WpsAnswerSectionsVo wpsAnswerSectionsVo = new WpsAnswerSectionsVo(Arrays.asList(wpsSectionsVo));
|
|
|
|
+ List<WpsAnswerQuestionVo> wpsAnswerQuestionVoList = new ArrayList<>();
|
|
|
|
+ wpsAnswerQuestionVoList.add(new WpsAnswerQuestionVo(1, Arrays.asList(wpsAnswerSectionsVo)));
|
|
|
|
+ WpsAnswerVo wpsAnswerVo = new WpsAnswerVo(id, 1, wpsAnswerQuestionVoList);
|
|
|
|
+ jsonArray.add(JSONObject.parseObject(JacksonUtil.parseJson(wpsAnswerVo)));
|
|
|
|
+ }
|
|
|
|
+ IOUtils.write(JacksonUtil.parseJson(jsonObject).getBytes(SystemConstant.CHARSET_NAME), new FileOutputStream(f));
|
|
|
|
+ answerFile = f;
|
|
|
|
+ return answerFile;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 启明试卷修改
|
|
|
|
+ *
|
|
|
|
+ * @param f
|
|
|
|
+ * @param id
|
|
|
|
+ * @param workRoot
|
|
|
|
+ * @param path
|
|
|
|
+ * @param dirName
|
|
|
|
+ * @param jsonMap
|
|
|
|
+ * @return
|
|
|
|
+ * @throws IOException
|
|
|
|
+ */
|
|
|
|
+ protected Map<String, Object> qmPaperReadAndUpdate(File f, String id, String workRoot, String path, File dirName,
|
|
|
|
+ Map<String, Object> jsonMap) throws IOException {
|
|
|
|
+ Integer mainNumber = null, subNumber = null;
|
|
|
|
+ byte[] bytes = IOUtils.toByteArray(new FileInputStream(f));
|
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(new String(bytes, SystemConstant.CHARSET_NAME));
|
|
|
|
+ BigDecimal totalScore = jsonObject.getBigDecimal("totalScore");//全卷总分
|
|
|
|
+ Integer detailCount = jsonObject.getInteger("detailCount");//大题数量
|
|
|
|
+ JSONArray jsonArray = jsonObject.getJSONArray("details");//明细
|
|
|
|
+ JSONObject wpsJson = null;
|
|
|
|
+ for (int i = 0; i < jsonArray.size(); i++) {
|
|
|
|
+ JSONObject json = jsonArray.getJSONObject(i);
|
|
|
|
+ Integer tempMainNumber = json.getInteger("number");
|
|
|
|
+ mainNumber = Objects.isNull(mainNumber) || mainNumber < tempMainNumber ? tempMainNumber : mainNumber;
|
|
|
|
+ JSONArray array = json.getJSONArray("questions");
|
|
|
|
+ for (int y = 0; y < array.size(); y++) {
|
|
|
|
+ JSONObject arrayJSONObject = array.getJSONObject(y);
|
|
|
|
+ Integer type = arrayJSONObject.getInteger("type");
|
|
|
|
+ if (Objects.nonNull(type) && type.intValue() == 200) {
|
|
|
|
+ wpsJson = json;
|
|
|
|
+ Integer tempSubNumber = arrayJSONObject.getInteger("number");
|
|
|
|
+ subNumber = Objects.isNull(subNumber) || subNumber < tempSubNumber ? tempSubNumber : subNumber;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ JSONObject json = (JSONObject) jsonMap.get(id);
|
|
|
|
+ if (Objects.isNull(wpsJson)) {
|
|
|
|
+ subNumber = 1;
|
|
|
|
+ totalScore = this.writeQmPaperStruct(json, id, ++mainNumber, subNumber, workRoot, path, dirName, jsonArray, totalScore, wpsJson);
|
|
|
|
+ detailCount++;
|
|
|
|
+ } else {
|
|
|
|
+ totalScore = this.writeQmPaperStruct(json, id, mainNumber, ++subNumber, workRoot, path, dirName, jsonArray, totalScore, wpsJson);
|
|
|
|
+ }
|
|
|
|
+ jsonObject.put("totalScore", totalScore);
|
|
|
|
+ jsonObject.put("detailCount", detailCount);
|
|
|
|
+ IOUtils.write(JacksonUtil.parseJson(jsonObject).getBytes(SystemConstant.CHARSET_NAME), new FileOutputStream(f));
|
|
|
|
+ json.put("insert", true);
|
|
|
|
+ jsonMap.put(id, json);
|
|
|
|
+ IOUtils.write(JacksonUtil.parseJson(jsonMap).getBytes(SystemConstant.CHARSET_NAME), new FileOutputStream(this.getWpsQuestionJson()));
|
|
|
|
+ return ImmutableMap.of("mainNumber", mainNumber, "subNumber", subNumber);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 写入qm wps试卷结构
|
|
|
|
+ *
|
|
|
|
+ * @param json
|
|
|
|
+ * @param id
|
|
|
|
+ * @param mainNumber
|
|
|
|
+ * @param subNumber
|
|
|
|
+ * @param workRoot
|
|
|
|
+ * @param path
|
|
|
|
+ * @param dirName
|
|
|
|
+ * @param jsonArray
|
|
|
|
+ * @param totalScore
|
|
|
|
+ * @param wpsJson
|
|
|
|
+ * @return
|
|
|
|
+ * @throws IOException
|
|
|
|
+ */
|
|
|
|
+ protected BigDecimal writeQmPaperStruct(JSONObject json, String id,
|
|
|
|
+ Integer mainNumber, Integer subNumber,
|
|
|
|
+ String workRoot, String path, File dirName,
|
|
|
|
+ JSONArray jsonArray, BigDecimal totalScore, JSONObject wpsJson) throws IOException {
|
|
|
|
+ BigDecimal score = json.getBigDecimal("score");
|
|
|
|
+ List<WpsDetailVo> wpsDetailVoList = new ArrayList<>();
|
|
|
|
+ List<WpsQuestionVo> wpsQuestionVoList = new ArrayList<>();
|
|
|
|
+ WpsDetailVo wpsDetailVo = null;
|
|
|
|
+ WpsQuestionVo wpsQuestionVo = new WpsQuestionVo(id, subNumber, score, 200);
|
|
|
|
+ if (subNumber.intValue() == 1) {
|
|
|
|
+ wpsDetailVo = new WpsDetailVo(mainNumber, "WPS操作题", null, score, 1);
|
|
|
|
+ } else {
|
|
|
|
+ wpsDetailVo = JSONObject.parseObject(JacksonUtil.parseJson(wpsJson), WpsDetailVo.class);
|
|
|
|
+ wpsDetailVo.setQuestionCount(wpsDetailVo.getQuestionCount() + 1);
|
|
|
|
+ wpsDetailVo.setTotalScore(wpsDetailVo.getTotalScore().add(score));
|
|
|
|
+ wpsQuestionVoList = wpsDetailVo.getQuestions();
|
|
|
|
+ jsonArray.remove(wpsJson);
|
|
|
|
+ }
|
|
|
|
+ wpsDetailVoList.add(wpsDetailVo);
|
|
|
|
+ wpsQuestionVoList.add(wpsQuestionVo);
|
|
|
|
+
|
|
|
|
+ JSONObject object = json.getJSONObject("body");
|
|
|
|
+ JSONArray sections = object.getJSONArray("sections");
|
|
|
|
+ WpsParamVo wpsParamVo = null;
|
|
|
|
+ for (int i = 0; i < sections.size(); i++) {
|
|
|
|
+ JSONObject obj = sections.getJSONObject(i);
|
|
|
|
+ JSONArray array = obj.getJSONArray("blocks");
|
|
|
|
+ if (array.size() > 0) {
|
|
|
|
+ JSONArray delArray = new JSONArray();
|
|
|
|
+ List<WpsAttachmentVo> wpsOperationFile = new ArrayList<>();
|
|
|
|
+ for (int j = 0; j < array.size(); j++) {
|
|
|
|
+ JSONObject arrayJSONObject = array.getJSONObject(j);
|
|
|
|
+ String type = arrayJSONObject.getString("type");
|
|
|
|
+ String value = arrayJSONObject.getString("value");
|
|
|
|
+ if (Objects.nonNull(type) && Objects.equals(type.trim(), "file")) {
|
|
|
|
+ wpsParamVo = JSONObject.parseObject(value, WpsParamVo.class);
|
|
|
|
+ List<WpsAttachmentVo> attachmentVoList = wpsParamVo.getWpsOperationFile();
|
|
|
|
+ for (WpsAttachmentVo w : attachmentVoList) {
|
|
|
|
+ File sourceFile = new File(new File(workRoot), path + File.separator + w.getValue());
|
|
|
|
+ File destFile = new File(dirName, w.getValue());
|
|
|
|
+ IOUtils.copy(new FileInputStream(sourceFile), new FileOutputStream(destFile));
|
|
|
|
+ wpsOperationFile.add(w);
|
|
|
|
+ }
|
|
|
|
+ delArray.add(arrayJSONObject);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ array.removeAll(delArray);
|
|
|
|
+ if (Objects.nonNull(wpsParamVo)) {
|
|
|
|
+ wpsParamVo.getWpsOperationFile().clear();
|
|
|
|
+ wpsParamVo.setWpsOperationFile(wpsOperationFile);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ wpsQuestionVo.setBody(object);
|
|
|
|
+ wpsQuestionVo.setParam(wpsParamVo);
|
|
|
|
+ wpsDetailVo.setQuestions(wpsQuestionVoList);
|
|
|
|
+ JSONObject newJson = JSONObject.parseObject(JacksonUtil.parseJson(wpsDetailVo));
|
|
|
|
+ jsonArray.add(newJson);
|
|
|
|
+ totalScore = totalScore.add(score);
|
|
|
|
+ return totalScore;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 删除文件
|
|
|
|
+ *
|
|
|
|
+ * @throws Exception
|
|
|
|
+ */
|
|
|
|
+ protected void delFile() throws Exception {
|
|
|
|
+ File rootFile = this.createWpsRootPath(null);
|
|
|
|
+ if (rootFile.exists()) {
|
|
|
|
+ SystemConstant.deleteFolder(rootFile);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 重写json结构
|
|
|
|
+ *
|
|
|
|
+ * @param jsonObject
|
|
|
|
+ * @return
|
|
|
|
+ * @throws IOException
|
|
|
|
+ */
|
|
|
|
+ protected Map<String, Object> reWriteJson(JSONObject jsonObject) throws IOException {
|
|
|
|
+ Map<String, Object> jsonMap = null;
|
|
|
|
+ File rootFile = this.createWpsRootPath(null);
|
|
|
|
+ String dirName = SystemConstant.WPS_QUESTION + SystemConstant.JSON_PREFIX;
|
|
|
|
+ File file = new File(rootFile, dirName);
|
|
|
|
+ jsonMap = new LinkedHashMap<>();
|
|
|
|
+ if (!file.exists()) {
|
|
|
|
+ file.createNewFile();
|
|
|
|
+ } else {
|
|
|
|
+ byte[] bytes = IOUtils.toByteArray(new FileInputStream(file));
|
|
|
|
+ jsonMap = JSONArray.parseObject(new String(bytes, SystemConstant.CHARSET_NAME), Map.class);
|
|
|
|
+ }
|
|
|
|
+ if (Objects.nonNull(jsonObject)) {
|
|
|
|
+ this.writeJson(jsonObject, jsonMap);
|
|
|
|
+ IOUtils.write(JacksonUtil.parseJson(jsonMap).getBytes(SystemConstant.CHARSET_NAME), new FileOutputStream(file));
|
|
|
|
+ }
|
|
|
|
+ return jsonMap;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 写入json信息
|
|
|
|
+ *
|
|
|
|
+ * @param jsonObject
|
|
|
|
+ * @param jsonMap
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ protected Map<String, Object> writeJson(JSONObject jsonObject, Map<String, Object> jsonMap) throws IOException {
|
|
|
|
+ Integer structType = jsonObject.getInteger("structType");
|
|
|
|
+ if (Objects.nonNull(structType) && structType.intValue() == 7) {
|
|
|
|
+ JSONObject json = new JSONObject();
|
|
|
|
+ String id = jsonObject.getString("id");
|
|
|
|
+ BigDecimal score = jsonObject.getBigDecimal("score");
|
|
|
|
+ json.put("score", score);
|
|
|
|
+ json.put("questionCode", jsonObject.get("questionCode"));
|
|
|
|
+ json.put("level", jsonObject.get("level"));
|
|
|
|
+ json.put("structType", structType);
|
|
|
|
+ json.put("questionType", jsonObject.get("questionType"));
|
|
|
|
+ json.put("type", jsonObject.get("type"));
|
|
|
|
+ json.put("status", jsonObject.get("status"));
|
|
|
|
+
|
|
|
|
+ //解析body
|
|
|
|
+ JSONObject object = jsonObject.getJSONObject("body");
|
|
|
|
+ JSONArray jsonArray = object.getJSONArray("sections");
|
|
|
|
+ for (int i = 0; i < jsonArray.size(); i++) {
|
|
|
|
+ JSONObject obj = jsonArray.getJSONObject(i);
|
|
|
|
+ JSONArray array = obj.getJSONArray("blocks");
|
|
|
|
+ List<WpsSectionsVo> wpsSectionsVoList = new ArrayList<>();
|
|
|
|
+ List<WpsBlocksVo> wpsBlocksVoList = new ArrayList<>();
|
|
|
|
+ for (int j = 0; j < array.size(); j++) {
|
|
|
|
+ JSONObject arrayJSONObject = array.getJSONObject(j);
|
|
|
|
+ String type = arrayJSONObject.getString("type");
|
|
|
|
+ String value = arrayJSONObject.getString("value");
|
|
|
|
+ if (Objects.nonNull(type) && Objects.equals(type.trim(), "text")) {
|
|
|
|
+ Set<String> set = this.replaceHtmlTag(value, "p");
|
|
|
|
+ if (CollectionUtils.isEmpty(set)) {
|
|
|
|
+ set.addAll(this.replaceHtmlTag(value, "div"));
|
|
|
|
+ }
|
|
|
|
+ if (CollectionUtils.isEmpty(set)) {
|
|
|
|
+ set.addAll(this.replaceHtmlTag(value, "span"));
|
|
|
|
+ }
|
|
|
|
+ if (!CollectionUtils.isEmpty(set)) {
|
|
|
|
+ set.stream().peek(s -> wpsBlocksVoList.add(new WpsBlocksVo("text", s))).collect(Collectors.toSet());
|
|
|
|
+ } else {
|
|
|
|
+ wpsBlocksVoList.add(new WpsBlocksVo("text", value));
|
|
|
|
+ }
|
|
|
|
+ } else if (Objects.nonNull(type) && Objects.equals(type.trim(), "file")) {
|
|
|
|
+ File rootFile = this.createWpsRootPath(DateUtil.format(new Date(), SystemConstant.WPS_DEFAULT_DATE_PATTERN));
|
|
|
|
+ String fileName = arrayJSONObject.getString("fileName");
|
|
|
|
+ String[] strs = StringUtils.split(fileName, ".");
|
|
|
|
+ File tempFile = new File(rootFile, SystemConstant.getNanoId() + "." + strs[1]);
|
|
|
|
+ FileUtils.copyURLToFile(new URL(value), tempFile);
|
|
|
|
+ List<WpsAttachmentVo> wpsOperationFile = new ArrayList<>();
|
|
|
|
+ wpsOperationFile.add(new WpsAttachmentVo(fileName, tempFile.getName()));
|
|
|
|
+ WpsParamVo wpsParamVo = new WpsParamVo(id, score, wpsOperationFile);
|
|
|
|
+ arrayJSONObject.put("wpsValue", value);
|
|
|
|
+ arrayJSONObject.put("value", wpsParamVo);
|
|
|
|
+ wpsBlocksVoList.add(new WpsBlocksVo("file", JacksonUtil.parseJson(wpsParamVo)));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ wpsSectionsVoList.add(new WpsSectionsVo(wpsBlocksVoList));
|
|
|
|
+ object.put("sections", JSONArray.parseArray(JacksonUtil.parseJson(wpsSectionsVoList)));
|
|
|
|
+ }
|
|
|
|
+ //解析operationDesc
|
|
|
|
+ String operationDesc = jsonObject.getString("operationDesc");
|
|
|
|
+ Set<String> set = this.replaceHtmlTag(operationDesc, "p");
|
|
|
|
+ if (CollectionUtils.isEmpty(set)) {
|
|
|
|
+ set.addAll(this.replaceHtmlTag(operationDesc, "div"));
|
|
|
|
+ }
|
|
|
|
+ if (CollectionUtils.isEmpty(set)) {
|
|
|
|
+ set.addAll(this.replaceHtmlTag(operationDesc, "span"));
|
|
|
|
+ }
|
|
|
|
+ List<WpsBlocksVo> wpsBlocksVoList = new ArrayList<>();
|
|
|
|
+ List<WpsSectionsVo> wpsSectionsVoList = new ArrayList<>();
|
|
|
|
+ wpsSectionsVoList.add(new WpsSectionsVo(wpsBlocksVoList));
|
|
|
|
+ if (!CollectionUtils.isEmpty(set)) {
|
|
|
|
+ set.stream().peek(s -> wpsBlocksVoList.add(new WpsBlocksVo("text", s))).collect(Collectors.toSet());
|
|
|
|
+ } else {
|
|
|
|
+ wpsBlocksVoList.add(new WpsBlocksVo("text", operationDesc));
|
|
|
|
+ }
|
|
|
|
+ json.put("answer", JSONArray.parseArray(JacksonUtil.parseJson(wpsSectionsVoList)));
|
|
|
|
+ json.put("body", object);
|
|
|
|
+ json.put("answers", jsonObject.get("answers"));
|
|
|
|
+ json.put("rightAnswers", jsonObject.get("rightAnswers"));
|
|
|
|
+ json.put("outlineNames", jsonObject.get("outlineNames"));
|
|
|
|
+ json.put("chapterNames", jsonObject.get("chapterNames"));
|
|
|
|
+ json.put("pointNames", jsonObject.get("pointNames"));
|
|
|
|
+ json.put("options", jsonObject.get("options"));
|
|
|
|
+ json.put("operationDesc", operationDesc);
|
|
|
|
+ jsonMap.put(id, json);
|
|
|
|
+ }
|
|
|
|
+ return jsonMap;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+// /**
|
|
|
|
+// * 过滤html和style
|
|
|
|
+// *
|
|
|
|
+// * @param content
|
|
|
|
+// * @return
|
|
|
|
+// */
|
|
|
|
+// protected String replaceHtmlTag(String content) {
|
|
|
|
+// String regExStyle = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
|
|
|
|
+// String regExHtml = "<[^>]+>"; //定义HTML标签的正则表达式
|
|
|
|
+// Pattern pStyle = Pattern.compile(regExStyle, Pattern.CASE_INSENSITIVE);
|
|
|
|
+// Matcher mStyle = pStyle.matcher(content);
|
|
|
|
+// content = mStyle.replaceAll(""); //过滤style标签
|
|
|
|
+// Pattern pHtml = Pattern.compile(regExHtml, Pattern.CASE_INSENSITIVE);
|
|
|
|
+// Matcher mHtml = pHtml.matcher(content);
|
|
|
|
+// content = mHtml.replaceAll(""); //过滤html标签
|
|
|
|
+// content = content.replace(" ", "");
|
|
|
|
+// content = content.replaceAll("\\s*|\t|\r|\n", "");
|
|
|
|
+//// content = content.replace("“", "");
|
|
|
|
+//// content = content.replace("”", "");
|
|
|
|
+// content = content.replaceAll(" ", "");
|
|
|
|
+// return content.trim(); //返回文本字符串
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取wps_question.json
|
|
|
|
+ *
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ protected File getWpsQuestionJson() {
|
|
|
|
+ File rootFile = this.createWpsRootPath(null);
|
|
|
|
+ String dirName = SystemConstant.WPS_QUESTION + SystemConstant.JSON_PREFIX;
|
|
|
|
+ return new File(rootFile, dirName);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 创建wps根目录
|
|
|
|
+ *
|
|
|
|
+ * @param date
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ protected File createWpsRootPath(String date) {
|
|
|
|
+ File rootFile = null;
|
|
|
|
+ if (!fileStoreUtil.workIsOss()) {
|
|
|
|
+ String workRoot = fileStoreUtil.getWorkRoot();
|
|
|
|
+ String path = Objects.nonNull(date) ? SystemConstant.WPS + File.separator + date : SystemConstant.WPS;
|
|
|
|
+ rootFile = new File(new File(workRoot), path);
|
|
|
|
+ if (!rootFile.exists()) {
|
|
|
|
+ rootFile.mkdirs();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return rootFile;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 替换html标签
|
|
|
|
+ *
|
|
|
|
+ * @param content
|
|
|
|
+ * @param cssTag
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ protected Set<String> replaceHtmlTag(String content, String cssTag) {
|
|
|
|
+ Document doc = Jsoup.parse(content);
|
|
|
|
+ Elements elements = doc.select(cssTag);
|
|
|
|
+ Set<String> set = new LinkedHashSet<>(elements.size());
|
|
|
|
+ for (Element e : elements) {
|
|
|
|
+ if (this.containsChinese(e.text())) {
|
|
|
|
+ set.add(e.text());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return set;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 是否包含中文
|
|
|
|
+ *
|
|
|
|
+ * @param content
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ protected boolean containsChinese(String content) {
|
|
|
|
+ // 使用正则表达式匹配中文字符
|
|
|
|
+ String pattern = "[\u4e00-\u9fa5]";
|
|
|
|
+ Pattern p = Pattern.compile(pattern);
|
|
|
|
+ Matcher m = p.matcher(content);
|
|
|
|
+ // 判断是否包含中文字符
|
|
|
|
+ return m.find();
|
|
|
|
+ }
|
|
|
|
+}
|