|
@@ -0,0 +1,318 @@
|
|
|
+package com.qmth.eds.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import com.alibaba.excel.EasyExcel;
|
|
|
+import com.alibaba.excel.ExcelWriter;
|
|
|
+import com.alibaba.excel.write.metadata.WriteSheet;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.qmth.boot.api.exception.ApiException;
|
|
|
+import com.qmth.eds.contant.SystemConstant;
|
|
|
+import com.qmth.eds.entity.*;
|
|
|
+import com.qmth.eds.enums.ExceptionResultEnum;
|
|
|
+import com.qmth.eds.enums.TaskResultEnum;
|
|
|
+import com.qmth.eds.enums.TaskStatusEnum;
|
|
|
+import com.qmth.eds.service.*;
|
|
|
+import com.qmth.eds.util.FileUtil;
|
|
|
+import com.qmth.eds.util.WuhanUniversityUtils;
|
|
|
+import org.apache.commons.codec.digest.DigestUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.time.Instant;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 同步服务类
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class DataSyncServiceImpl implements DataSyncService {
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(DataSyncServiceImpl.class);
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private TBSyncTaskService tbSyncTaskService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private WuhanUniversityUtils wuhanUniversityUtils;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ExamSyncStudentService examSyncStudentService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ExamSyncStudentTempService examSyncStudentTempService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ExamSyncTotalService examSyncTotalService;
|
|
|
+
|
|
|
+
|
|
|
+ @Async
|
|
|
+ @Override
|
|
|
+ public void syncWuhanUniversityExamData(ExamScheduleTask examScheduleTask, TBSyncTask tbSyncTask) {
|
|
|
+ // 同步初始参数
|
|
|
+ TaskResultEnum result = null;
|
|
|
+ String errorMessage = "";
|
|
|
+ Long schoolId = examScheduleTask.getSchoolId();
|
|
|
+ String schoolName = examScheduleTask.getSchoolName();
|
|
|
+ Long semesterId = examScheduleTask.getSemesterId();
|
|
|
+ String semesterName = examScheduleTask.getSemesterName();
|
|
|
+ Long examTypeId = examScheduleTask.getExamTypeId();
|
|
|
+ String examTypeName = examScheduleTask.getExamTypeName();
|
|
|
+ File txtFile = null;
|
|
|
+ FileInputStream fis = null;
|
|
|
+ try {
|
|
|
+ // 同步中
|
|
|
+ tbSyncTaskService.updateStatusAndResultById(tbSyncTask.getId(), TaskStatusEnum.RUNNING, null, null);
|
|
|
+ // 获取token
|
|
|
+ String token = wuhanUniversityUtils.getAccessToken();
|
|
|
+ if (StringUtils.isBlank(token)) {
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("获取AccessToken失败");
|
|
|
+ }
|
|
|
+ // 调用接口
|
|
|
+ List<ExamSyncStudentTemp> examSyncStudentTemps = wuhanUniversityUtils.getKwData(token);
|
|
|
+ // 汇总表ID
|
|
|
+ Long examSyncTotalId = SystemConstant.getDbUuid();
|
|
|
+ examSyncStudentTemps.forEach(m -> {
|
|
|
+ m.setId(SystemConstant.getDbUuid());
|
|
|
+ m.setSchoolId(schoolId);
|
|
|
+ m.setExamSyncTotalId(examSyncTotalId);
|
|
|
+ });
|
|
|
+ // 保存临时考务数据
|
|
|
+ examSyncStudentTempService.saveBatch(examSyncStudentTemps);
|
|
|
+
|
|
|
+ // 生成数据文件,用来比较内容是否有变动
|
|
|
+ txtFile = createTxt(schoolId, examSyncStudentTemps);
|
|
|
+ String txtFileMd5 = null;
|
|
|
+
|
|
|
+ if (txtFile != null) {
|
|
|
+ fis = new FileInputStream(txtFile);
|
|
|
+ txtFileMd5 = DigestUtils.md5Hex(fis);
|
|
|
+ }
|
|
|
+ // 校验数据是否变动,若变动,需要新增
|
|
|
+ if (canAddTotal(schoolId, semesterId, examTypeId, examSyncStudentTemps.size(), txtFileMd5)) {
|
|
|
+ // 保存到正式表
|
|
|
+ List<ExamSyncStudent> examSyncStudents = examSyncStudentTemps.stream().map(m -> {
|
|
|
+ ExamSyncStudent examSyncStudent = new ExamSyncStudent();
|
|
|
+ BeanUtil.copyProperties(m, examSyncStudent);
|
|
|
+ examSyncStudent.setId(SystemConstant.getDbUuid());
|
|
|
+ return examSyncStudent;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ examSyncStudentService.saveBatch(examSyncStudents);
|
|
|
+
|
|
|
+ // 将以前数据设置为不可下载
|
|
|
+ examSyncTotalService.updateDownloadStatusBySchoolIdAndSemesterIdAndExamTypeId(schoolId, semesterId, examTypeId);
|
|
|
+
|
|
|
+ // 生成汇总数据
|
|
|
+ ZoneId zone = ZoneId.systemDefault();
|
|
|
+ Instant instant = LocalDate.now().atStartOfDay().atZone(zone).toInstant();
|
|
|
+ Date date = Date.from(instant);
|
|
|
+ Long syncDate = date.getTime();
|
|
|
+ int colleges = Integer.parseInt(String.valueOf(examSyncStudentTemps.stream().map(ExamSyncStudentTemp::getJgmc).filter(StringUtils::isNotBlank).distinct().count()));
|
|
|
+ int subjects = Integer.parseInt(String.valueOf(examSyncStudentTemps.stream().map(ExamSyncStudentTemp::getKch).filter(StringUtils::isNotBlank).distinct().count()));
|
|
|
+ int students = examSyncStudentTemps.size();
|
|
|
+ ExamSyncTotal examSyncTotal = new ExamSyncTotal(syncDate, schoolId, schoolName, semesterId, semesterName, examTypeId, examTypeName, colleges, subjects, students, txtFileMd5);
|
|
|
+ examSyncTotalService.save(examSyncTotal);
|
|
|
+ // 生成excel文件
|
|
|
+ File excelFile = createExcel(schoolId, examSyncStudents);
|
|
|
+
|
|
|
+ // 更新文件路径
|
|
|
+ examSyncTotal.setFileName(excelFile.getName());
|
|
|
+ examSyncTotal.setFilePath(excelFile.getPath());
|
|
|
+ examSyncTotalService.updateById(examSyncTotal);
|
|
|
+ }
|
|
|
+ // 删除临时表数据
|
|
|
+ examSyncStudentTempService.deleteByExamSyncTotalId(examSyncTotalId);
|
|
|
+
|
|
|
+ result = TaskResultEnum.SUCCESS;
|
|
|
+ } catch (ApiException | IOException e) {
|
|
|
+ result = TaskResultEnum.ERROR;
|
|
|
+ errorMessage = errorMessage + e.getMessage();
|
|
|
+ } finally {
|
|
|
+ tbSyncTaskService.updateStatusAndResultById(tbSyncTask.getId(), TaskStatusEnum.FINISH, result, errorMessage);
|
|
|
+
|
|
|
+ // 关闭fis流
|
|
|
+ if (fis != null) {
|
|
|
+ try {
|
|
|
+ fis.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除txt文件
|
|
|
+ if (txtFile != null) {
|
|
|
+ txtFile.delete();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查数据是否有变动,需要新增一条新同步记录
|
|
|
+ *
|
|
|
+ * @param schoolId 学校ID
|
|
|
+ * @param semesterId 学期ID
|
|
|
+ * @param examTypeId 考试类型ID
|
|
|
+ * @param count 考生数量
|
|
|
+ * @param txtFileMd5 txt文件md5
|
|
|
+ * @return true:可以新增 false:不能新增
|
|
|
+ */
|
|
|
+ private boolean canAddTotal(Long schoolId, Long semesterId, Long examTypeId, int count, String txtFileMd5) {
|
|
|
+ // txtFileMd5为空,无法校验,返回true
|
|
|
+ if (txtFileMd5 == null) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询上一次同步数据,先比较数量
|
|
|
+ QueryWrapper<ExamSyncTotal> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.lambda().eq(ExamSyncTotal::getSchoolId, schoolId)
|
|
|
+ .eq(ExamSyncTotal::getSemesterId, semesterId)
|
|
|
+ .eq(ExamSyncTotal::getExamTypeId, examTypeId)
|
|
|
+ .orderByDesc(ExamSyncTotal::getSyncDate)
|
|
|
+ .orderByDesc(ExamSyncTotal::getCreateTime);
|
|
|
+ List<ExamSyncTotal> examSyncTotals = examSyncTotalService.list(queryWrapper);
|
|
|
+ // 没有同步记录,返回true
|
|
|
+ if (examSyncTotals.isEmpty()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ ExamSyncTotal examSyncTotal = examSyncTotals.get(0);
|
|
|
+ // 上一次同步数据量与本次不一样,返回true
|
|
|
+ if (count != examSyncTotal.getStudents()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ // 数据内容有变动,返回 true
|
|
|
+ return !txtFileMd5.equals(examSyncTotal.getDataMd5());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成txt,比较md5
|
|
|
+ *
|
|
|
+ * @param examSyncStudentTemps list
|
|
|
+ */
|
|
|
+ private File createTxt(Long schoolId, List<ExamSyncStudentTemp> examSyncStudentTemps) {
|
|
|
+ // 按学号排序
|
|
|
+ examSyncStudentTemps.sort(Comparator.comparing(ExamSyncStudentTemp::getXh));
|
|
|
+
|
|
|
+ List<String> list = examSyncStudentTemps.stream().map(m -> {
|
|
|
+ StringJoiner stringJoiner = new StringJoiner("|");
|
|
|
+ stringJoiner.add(m.getXnm())
|
|
|
+ .add(m.getXqm())
|
|
|
+ .add(m.getJxbId())
|
|
|
+ .add(m.getJxbmc())
|
|
|
+ .add(m.getKch())
|
|
|
+ .add(m.getKcmc())
|
|
|
+ .add(m.getJgh())
|
|
|
+ .add(m.getXm())
|
|
|
+ .add(m.getKkbm())
|
|
|
+ .add(m.getXf())
|
|
|
+ .add(m.getXh())
|
|
|
+ .add(m.getXsxm())
|
|
|
+ .add(m.getJgmc())
|
|
|
+ .add(m.getZymc())
|
|
|
+ .add(m.getCxbj())
|
|
|
+ .add(m.getNjdmId())
|
|
|
+ .add(m.getZwh())
|
|
|
+ .add(m.getCdmc())
|
|
|
+ .add(m.getKsbz());
|
|
|
+ return stringJoiner.toString();
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+
|
|
|
+ File file = null;
|
|
|
+ try {
|
|
|
+ String fileName = "file-folder" + File.separator + schoolId + File.separator + System.currentTimeMillis() + ".txt";
|
|
|
+ file = FileUtil.writeTxt(fileName, list);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("数据txt文件生成失败");
|
|
|
+ }
|
|
|
+ return file;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成excel文件
|
|
|
+ *
|
|
|
+ * @param examSyncStudents 考务数据
|
|
|
+ */
|
|
|
+ private File createExcel(Long schoolId, List<ExamSyncStudent> examSyncStudents) throws IOException {
|
|
|
+ List<List<String>> head = new ArrayList<>();
|
|
|
+ List<String> headTitle0 = new ArrayList<>();
|
|
|
+ headTitle0.add("学年");
|
|
|
+ List<String> headTitle1 = new ArrayList<>();
|
|
|
+ headTitle1.add("学期");
|
|
|
+ List<String> headTitle2 = new ArrayList<>();
|
|
|
+ headTitle2.add("教学班ID");
|
|
|
+ List<String> headTitle3 = new ArrayList<>();
|
|
|
+ headTitle3.add("教学班名称");
|
|
|
+ List<String> headTitle4 = new ArrayList<>();
|
|
|
+ headTitle4.add("课程号");
|
|
|
+ List<String> headTitle5 = new ArrayList<>();
|
|
|
+ headTitle5.add("课程名称");
|
|
|
+ List<String> headTitle6 = new ArrayList<>();
|
|
|
+ headTitle6.add("工号");
|
|
|
+ List<String> headTitle7 = new ArrayList<>();
|
|
|
+ headTitle7.add("姓名");
|
|
|
+ List<String> headTitle8 = new ArrayList<>();
|
|
|
+ headTitle8.add("开课部门");
|
|
|
+ List<String> headTitle9 = new ArrayList<>();
|
|
|
+ headTitle9.add("学分");
|
|
|
+ List<String> headTitle10 = new ArrayList<>();
|
|
|
+ headTitle10.add("学号");
|
|
|
+ List<String> headTitle11 = new ArrayList<>();
|
|
|
+ headTitle11.add("学生姓名");
|
|
|
+ List<String> headTitle12 = new ArrayList<>();
|
|
|
+ headTitle12.add("学院");
|
|
|
+ List<String> headTitle13 = new ArrayList<>();
|
|
|
+ headTitle13.add("专业");
|
|
|
+ List<String> headTitle14 = new ArrayList<>();
|
|
|
+ headTitle14.add("重修标记");
|
|
|
+ List<String> headTitle15 = new ArrayList<>();
|
|
|
+ headTitle15.add("年级");
|
|
|
+ List<String> headTitle16 = new ArrayList<>();
|
|
|
+ headTitle16.add("座位号");
|
|
|
+ List<String> headTitle17 = new ArrayList<>();
|
|
|
+ headTitle17.add("场地名称");
|
|
|
+ List<String> headTitle18 = new ArrayList<>();
|
|
|
+ headTitle18.add("考试备注");
|
|
|
+
|
|
|
+
|
|
|
+ head.add(headTitle0);
|
|
|
+ head.add(headTitle1);
|
|
|
+ head.add(headTitle2);
|
|
|
+ head.add(headTitle3);
|
|
|
+ head.add(headTitle4);
|
|
|
+ head.add(headTitle5);
|
|
|
+ head.add(headTitle6);
|
|
|
+ head.add(headTitle7);
|
|
|
+ head.add(headTitle8);
|
|
|
+ head.add(headTitle9);
|
|
|
+ head.add(headTitle10);
|
|
|
+ head.add(headTitle11);
|
|
|
+ head.add(headTitle12);
|
|
|
+ head.add(headTitle13);
|
|
|
+ head.add(headTitle14);
|
|
|
+ head.add(headTitle15);
|
|
|
+ head.add(headTitle16);
|
|
|
+ head.add(headTitle17);
|
|
|
+ head.add(headTitle18);
|
|
|
+
|
|
|
+ String fileName = "file-folder" + File.separator + schoolId + File.separator + System.currentTimeMillis() + ".xlsx";
|
|
|
+ File file = new File(fileName);
|
|
|
+ if (!file.exists()) {
|
|
|
+ file.createNewFile();
|
|
|
+ }
|
|
|
+ ExcelWriter excelWriter = EasyExcel.write(file).build();
|
|
|
+ //动态表头
|
|
|
+ WriteSheet writeSheet1 = EasyExcel.writerSheet(0, "考务数据").head(head).build();
|
|
|
+ excelWriter.write(examSyncStudents, writeSheet1);
|
|
|
+ excelWriter.finish();
|
|
|
+
|
|
|
+ return file;
|
|
|
+ }
|
|
|
+}
|