소스 검색

跨学校复制题库数据

xiatian 1 년 전
부모
커밋
5fabae4b29

+ 126 - 35
examcloud-core-questions-api-provider/src/main/java/cn/com/qmth/examcloud/core/questions/api/controller/CopyDataController.java

@@ -1,14 +1,37 @@
 package cn.com.qmth.examcloud.core.questions.api.controller;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.NotNull;
 
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestPart;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
+import cn.com.qmth.examcloud.api.commons.security.bean.User;
+import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.core.basic.api.CourseCloudService;
+import cn.com.qmth.examcloud.core.basic.api.bean.CourseBean;
+import cn.com.qmth.examcloud.core.basic.api.request.GetCourseByOrgReq;
+import cn.com.qmth.examcloud.core.basic.api.response.GetCourseByOrgResp;
 import cn.com.qmth.examcloud.core.questions.service.CopyDataService;
+import cn.com.qmth.examcloud.core.questions.service.bean.CopyDataCourseInfo;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import cn.com.qmth.examcloud.web.support.ServletUtil;
@@ -17,52 +40,120 @@ import cn.com.qmth.examcloud.web.support.ServletUtil;
 @RequestMapping("${api_cqb}/copy")
 public class CopyDataController extends ControllerSupport {
 	private static int cacheLockTimeout = 60 * 10;
-	private static String withoutReduplicateLock = "$_COPY_QUESTION_DATA_NO_REDUPLICATE_LOCK";
+	private static String copyQuestionDataLock = "$_COPY_QUESTION_DATA_LOCK";
 	@Autowired
 	private CopyDataService copyDataService;
 	@Autowired
 	private RedisClient redisClient;
-//
-//	//西交大数据复制
-//	@GetMapping("data")
-//	public void copyData(HttpServletResponse response) {
-//		Long fromRootOrgId = 371L;
-//		Long toRootOrgId = 21595L;
-////		Long fromRootOrgId = 141L;
-////		Long toRootOrgId = 150L;
-//		User user = getAccessUser();
-//		if (!user.getRootOrgId().equals(toRootOrgId)) {
-//			ServletUtil.returnJson("请求失败,没有权限", response);
-//			return;
-//		}
-//		String cacheLock = "$_COPY_QUESTION_DATA_LOCK";
-//		Boolean lock = redisClient.setIfAbsent(cacheLock, cacheLock, cacheLockTimeout);
-//		if (!lock) {
-//			ServletUtil.returnJson("请求失败,正在处理数据", response);
-//			return;
-//		}
-//		copyDataService.copyData(getAccessUser(), fromRootOrgId, toRootOrgId);
-//	}
-	
-	
-	//试题去重后复制
-	@GetMapping("noreduplicate")
-	public void copyNoReduplicate(HttpServletResponse response,@RequestParam String batch) {
-		Boolean lock = redisClient.setIfAbsent(withoutReduplicateLock, withoutReduplicateLock, cacheLockTimeout);
+	@Autowired
+	private CourseCloudService courseCloudService;
+
+	@PostMapping(value = "data")
+	public void copyData(HttpServletResponse response,
+			@RequestPart @NotNull(message = "上传文件不能为空!") MultipartFile dataFile, @RequestParam Long fromRootOrgId,
+			@RequestParam Long toRootOrgId) {
+		User user = getAccessUser();
+		if (!user.getRootOrgId().equals(toRootOrgId)) {
+			ServletUtil.returnJson("请求失败,没有权限", response);
+			return;
+		}
+		Boolean lock = redisClient.setIfAbsent(copyQuestionDataLock, copyQuestionDataLock, cacheLockTimeout);
 		if (!lock) {
 			ServletUtil.returnJson("请求失败,正在处理数据", response);
 			return;
 		}
-		copyDataService.copyNoReduplicate(getAccessUser(), batch);
-		ServletUtil.returnJson("请求成功", response);
+		try {
+			LinkedHashSet<String> cs = readSubject(dataFile);
+			if (CollectionUtils.isEmpty(cs)) {
+				throw new StatusException("请填写要处理的课程");
+			}
+			Map<String, Long> coursesMap = new HashMap<>();
+			GetCourseByOrgReq courseReq = new GetCourseByOrgReq();
+			courseReq.setRootOrgId(toRootOrgId);
+			GetCourseByOrgResp res = courseCloudService.getCourseByOrg(courseReq);
+			if (CollectionUtils.isEmpty(res.getCourseList())) {
+				throw new StatusException("请先导入课程");
+			}
+
+			for (CourseBean c : res.getCourseList()) {
+				coursesMap.put(c.getCode(), c.getId());
+			}
+			List<CopyDataCourseInfo> courses = new ArrayList<>();
+			for (String c : cs) {
+				if (coursesMap.get(c) == null) {
+					throw new StatusException("未找到课程信息:" + c);
+				} else {
+					courses.add(new CopyDataCourseInfo(coursesMap.get(c), c));
+				}
+			}
+			copyDataService.copyData(user, fromRootOrgId, toRootOrgId, courses);
+			ServletUtil.returnJson("请求成功", response);
+		} catch (StatusException e) {
+			ServletUtil.returnJson("请求失败" + e.getDesc(), response);
+			redisClient.delete(copyQuestionDataLock);
+		} catch (Exception e) {
+			ServletUtil.returnJson("请求失败" + e.getMessage(), response);
+			redisClient.delete(copyQuestionDataLock);
+			throw e;
+		}
+
+	}
+
+	private LinkedHashSet<String> readSubject(MultipartFile dataFile) {
+		LinkedHashSet<String> list = new LinkedHashSet<>();
+		XSSFWorkbook wb = null;
+		InputStream in = null;
+		try {
+			in = dataFile.getInputStream();
+			wb = new XSSFWorkbook(in);
+			XSSFSheet sheet = wb.getSheetAt(0);
+			int rows = sheet.getLastRowNum();
+			for (int i = 1; i <= rows; i++) {
+				XSSFRow row = sheet.getRow(i);
+				String code;
+				try {
+					code = row.getCell(0).getStringCellValue().trim();
+				} catch (Exception e) {
+					code = (row.getCell(0).getNumericCellValue() + "").trim();
+				}
+				list.add(code);
+			}
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		} finally {
+			if (in != null) {
+				try {
+					in.close();
+				} catch (IOException e) {
+				}
+			}
+			if (wb != null) {
+				try {
+					wb.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+		return list;
 	}
-	
-	@GetMapping("noreduplicate/status")
+	// 试题去重后复制
+//	@GetMapping("noreduplicate")
+//	public void copyNoReduplicate(HttpServletResponse response,@RequestParam String batch) {
+//		Boolean lock = redisClient.setIfAbsent(withoutReduplicateLock, withoutReduplicateLock, cacheLockTimeout);
+//		if (!lock) {
+//			ServletUtil.returnJson("请求失败,正在处理数据", response);
+//			return;
+//		}
+//		copyDataService.copyNoReduplicate(getAccessUser(), batch);
+//		ServletUtil.returnJson("请求成功", response);
+//	}
+
+	@GetMapping("status")
 	public void copyNoReduplicateStatus(HttpServletResponse response) {
-		String lock = redisClient.get(withoutReduplicateLock,String.class);
-		if (lock!=null) {
+		String lock = redisClient.get(copyQuestionDataLock, String.class);
+		if (lock != null) {
 			ServletUtil.returnJson("正在处理数据", response);
-		}else {
+		} else {
 			ServletUtil.returnJson("处理数据结束", response);
 		}
 	}

+ 1 - 1
examcloud-core-questions-dao/src/main/java/cn/com/qmth/examcloud/core/questions/dao/QuesTypeNameRepo.java

@@ -20,5 +20,5 @@ public interface QuesTypeNameRepo extends MongoRepository<QuesTypeName, String>
 
 	void deleteByOrgId(String toRootOrgId);
 
-	List<QuesTypeName> findByOrgId(Long fromRootOrgId);
+	List<QuesTypeName> findByOrgId(String fromRootOrgId);
 }

+ 11 - 0
examcloud-core-questions-dao/src/main/java/cn/com/qmth/examcloud/core/questions/dao/entity/Paper.java

@@ -91,6 +91,9 @@ public class Paper extends MongoBaseEntity {
     private Integer inUse;
     
     private Boolean auditStatus;
+    
+    //试卷来源id
+    private String fromId;
 
     public String getName() {
         return name;
@@ -313,6 +316,14 @@ public class Paper extends MongoBaseEntity {
 		this.auditStatus = auditStatus;
 	}
 
+	public String getFromId() {
+		return fromId;
+	}
+
+	public void setFromId(String fromId) {
+		this.fromId = fromId;
+	}
+
 	
 	
 }

+ 5 - 2
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/CopyDataService.java

@@ -1,12 +1,15 @@
 package cn.com.qmth.examcloud.core.questions.service;
 
+import java.util.List;
+
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
+import cn.com.qmth.examcloud.core.questions.service.bean.CopyDataCourseInfo;
 
 public interface CopyDataService {
 
-	void copyData(User user, Long fromRootOrgId, Long toRootOrgId);
+	void copyData(User user, Long fromRootOrgId, Long toRootOrgId,List<CopyDataCourseInfo> courses);
 
-	void copyNoReduplicate(User user,String batch);
+//	void copyNoReduplicate(User user,String batch);
 
 }
 

+ 4 - 0
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/PaperService.java

@@ -320,4 +320,8 @@ public interface PaperService {
 
 	public void deletePapersPlus(List<String> paperList, User user);
 
+	List<Paper> getImportPapersByCourse(Long ordId, String courseCode);
+	
+	boolean existsImportPaperByFromId(Long ordId, String courseCode,String fromId);
+
 }

+ 29 - 0
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/bean/CopyDataCourseInfo.java

@@ -0,0 +1,29 @@
+package cn.com.qmth.examcloud.core.questions.service.bean;
+
+public class CopyDataCourseInfo {
+	private Long courseId;
+	private String courseCode;
+
+	public Long getCourseId() {
+		return courseId;
+	}
+
+	public void setCourseId(Long courseId) {
+		this.courseId = courseId;
+	}
+
+	public String getCourseCode() {
+		return courseCode;
+	}
+
+	public void setCourseCode(String courseCode) {
+		this.courseCode = courseCode;
+	}
+
+	public CopyDataCourseInfo(Long courseId, String courseCode) {
+		super();
+		this.courseId = courseId;
+		this.courseCode = courseCode;
+	}
+
+}

+ 24 - 22
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/bean/CopyDataDto.java

@@ -1,30 +1,13 @@
 package cn.com.qmth.examcloud.core.questions.service.bean;
 
-import java.util.Map;
-
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
 
 public class CopyDataDto {
-	private Map<String, Long> courses;
-	private String paperId;
+	private CopyDataCourseInfo course;
+	private Long fromRootOrgId;
 	private Long toRootOrgId;
 	private User user;
 
-	public Map<String, Long> getCourses() {
-		return courses;
-	}
-
-	public void setCourses(Map<String, Long> courses) {
-		this.courses = courses;
-	}
-
-	public String getPaperId() {
-		return paperId;
-	}
-
-	public void setPaperId(String paperId) {
-		this.paperId = paperId;
-	}
 
 	public Long getToRootOrgId() {
 		return toRootOrgId;
@@ -42,12 +25,31 @@ public class CopyDataDto {
 		this.user = user;
 	}
 
-	public CopyDataDto(Map<String, Long> courses, String paperId, Long toRootOrgId, User user) {
+
+	public Long getFromRootOrgId() {
+		return fromRootOrgId;
+	}
+
+	public void setFromRootOrgId(Long fromRootOrgId) {
+		this.fromRootOrgId = fromRootOrgId;
+	}
+
+	public CopyDataCourseInfo getCourse() {
+		return course;
+	}
+
+	public void setCourse(CopyDataCourseInfo course) {
+		this.course = course;
+	}
+
+	public CopyDataDto(CopyDataCourseInfo course, Long fromRootOrgId, Long toRootOrgId, User user) {
 		super();
-		this.courses = courses;
-		this.paperId = paperId;
+		this.course = course;
+		this.fromRootOrgId = fromRootOrgId;
 		this.toRootOrgId = toRootOrgId;
 		this.user = user;
 	}
 
+
+
 }

+ 40 - 25
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/consumer/CopyDataConsumer.java

@@ -9,6 +9,7 @@ import java.util.Map;
 import java.util.TreeMap;
 import java.util.UUID;
 
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Scope;
@@ -20,7 +21,6 @@ import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.core.questions.base.BeanCopierUtil;
 import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
 import cn.com.qmth.examcloud.core.questions.base.IoUtils;
-import cn.com.qmth.examcloud.core.questions.base.Model;
 import cn.com.qmth.examcloud.core.questions.base.multithread.Consumer;
 import cn.com.qmth.examcloud.core.questions.dao.PaperDetailRepo;
 import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitRepo;
@@ -32,6 +32,7 @@ import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetailUnit;
 import cn.com.qmth.examcloud.core.questions.dao.entity.QuesOption;
 import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
 import cn.com.qmth.examcloud.core.questions.dao.entity.QuestionAudio;
+import cn.com.qmth.examcloud.core.questions.service.PaperService;
 import cn.com.qmth.examcloud.core.questions.service.QuestionAudioService;
 import cn.com.qmth.examcloud.core.questions.service.UpYunService;
 import cn.com.qmth.examcloud.core.questions.service.bean.CopyDataDto;
@@ -39,11 +40,13 @@ import cn.com.qmth.examcloud.core.questions.service.config.SysProperty;
 import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
 import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
 import cn.com.qmth.examcloud.web.filestorage.YunPathInfo;
+import cn.com.qmth.examcloud.web.redis.RedisClient;
 
 @Scope("prototype")
 @Service
 public class CopyDataConsumer extends Consumer<CopyDataDto> {
-	
+	private static int cacheLockTimeout = 60 * 10;
+	private static String copyQuestionDataLock = "$_COPY_QUESTION_DATA_LOCK";
 	@Autowired
 	private PaperRepo paperRepo;
 	
@@ -58,23 +61,39 @@ public class CopyDataConsumer extends Consumer<CopyDataDto> {
 	
 	@Autowired
 	private QuestionAudioService questionAudioService;
-	
+
+	@Autowired
+	private PaperService paperService;
 	@Autowired
 	private QuesRepo quesRepo;
-
+	@Autowired
+	private RedisClient redisClient;
+	
+	
     @Transactional
     @Override
     public int consume(CopyDataDto dto) {
-    	clonePaper(dto);
+    	disposeCourse(dto);
         return 1;
     }
-
-    private void clonePaper(CopyDataDto dto){
-    	String paperId=dto.getPaperId();
+    private void disposeCourse(CopyDataDto dto){
+    	List<Paper> papers=paperService.getImportPapersByCourse(dto.getFromRootOrgId(), dto.getCourse().getCourseCode());
+    	
+    	redisClient.expire(copyQuestionDataLock, cacheLockTimeout);
+    	
+    	if(CollectionUtils.isEmpty(papers)) {
+    		return;
+    	}
+    	for(Paper paper:papers) {
+    		if(!paperService.existsImportPaperByFromId(dto.getToRootOrgId(), dto.getCourse().getCourseCode(), paper.getId())) {
+    			clonePaper(paper, dto);
+    		}
+    		redisClient.expire(copyQuestionDataLock, cacheLockTimeout);
+    	}
+    }
+    
+    private void clonePaper(Paper oldPaper,CopyDataDto dto){
     	User user=dto.getUser();
-        if (StringUtils.isBlank(paperId)) {
-            throw new StatusException("待复制的试卷ID不能为空!");
-        }
 
         if (user == null) {
             throw new StatusException("当前用户信息不能为空!");
@@ -84,11 +103,6 @@ public class CopyDataConsumer extends Consumer<CopyDataDto> {
             throw new StatusException("当前用户的顶级机构ID不能为空!");
         }
 
-        Paper oldPaper = Model.of(paperRepo.findById(paperId));
-        if (oldPaper == null) {
-            throw new StatusException("待复制的试卷不存在!");
-        }
-
         //复制原试卷的所有试题信息
         Map<PaperDetail, List<PaperDetailUnit>> detailMaps = this.copyPaperDetails(oldPaper, dto);
 
@@ -307,7 +321,7 @@ public class CopyDataConsumer extends Consumer<CopyDataDto> {
     private Question copyQuestion(Question oldQuestion,CopyDataDto dto) {
         Question question = BeanCopierUtil.copyProperties(oldQuestion, Question.class);
         question.setId(null);
-        question.getCourse().setId(getCourseId(dto.getCourses(), question.getCourse().getCode()).toString());
+        question.getCourse().setId(dto.getCourse().getCourseId().toString());
         question.getCourse().setOrgId(dto.getToRootOrgId().toString());
         question.setOrgId(dto.getToRootOrgId().toString());
         question.setQuesProperties(null);
@@ -383,7 +397,7 @@ public class CopyDataConsumer extends Consumer<CopyDataDto> {
      */
     private Paper copyPaper(Paper oldPaper, CopyDataDto dto) {
         Paper newPaper = BeanCopierUtil.copyProperties(oldPaper, Paper.class);
-        newPaper.getCourse().setId(getCourseId(dto.getCourses(), newPaper.getCourse().getCode()).toString());
+        newPaper.getCourse().setId(dto.getCourse().getCourseId().toString());
         newPaper.getCourse().setOrgId(dto.getToRootOrgId().toString());
         newPaper.setOrgId(String.valueOf(dto.getToRootOrgId()));
         newPaper.setCreateTime(CommonUtils.getCurDateTime());
@@ -392,16 +406,17 @@ public class CopyDataConsumer extends Consumer<CopyDataDto> {
         newPaper.setCreationBy(dto.getUser().getUserId());
         newPaper.setUpdateBy(dto.getUser().getUserId());
         newPaper.setId(null);
+        newPaper.setFromId(oldPaper.getId());
         return newPaper;
     }
     private String randomUUID() {
         return UUID.randomUUID().toString().replaceAll("-", "");
     }
-	private Long getCourseId(Map<String,Long> courses,String code) {
-		Long id=courses.get(code);
-		if(id==null) {
-			throw new StatusException("没有课程信息code="+code);
-		}
-		return id;
-	}
+//	private Long getCourseId(Map<String,Long> courses,String code) {
+//		Long id=courses.get(code);
+//		if(id==null) {
+//			throw new StatusException("没有课程信息code="+code);
+//		}
+//		return id;
+//	}
 }

+ 141 - 136
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/CopyDataServiceImpl.java

@@ -2,8 +2,10 @@ package cn.com.qmth.examcloud.core.questions.service.impl;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.collections4.CollectionUtils;
 import org.slf4j.Logger;
@@ -11,26 +13,13 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
-import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.core.basic.api.CourseCloudService;
-import cn.com.qmth.examcloud.core.basic.api.bean.CourseBean;
-import cn.com.qmth.examcloud.core.basic.api.request.GetCourseByOrgReq;
-import cn.com.qmth.examcloud.core.basic.api.response.GetCourseByOrgResp;
-import cn.com.qmth.examcloud.core.questions.dao.PaperDetailRepo;
-import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitRepo;
-import cn.com.qmth.examcloud.core.questions.dao.PaperRepo;
-import cn.com.qmth.examcloud.core.questions.dao.QuesRepo;
 import cn.com.qmth.examcloud.core.questions.dao.QuesTypeNameRepo;
-import cn.com.qmth.examcloud.core.questions.dao.QuestionAudioRepo;
 import cn.com.qmth.examcloud.core.questions.dao.entity.QuesTypeName;
 import cn.com.qmth.examcloud.core.questions.service.CopyDataService;
-import cn.com.qmth.examcloud.core.questions.service.PaperService;
+import cn.com.qmth.examcloud.core.questions.service.bean.CopyDataCourseInfo;
 import cn.com.qmth.examcloud.core.questions.service.bean.CopyDataDto;
-import cn.com.qmth.examcloud.core.questions.service.bean.CopyDataNoReduplicateDto;
-import cn.com.qmth.examcloud.core.questions.service.producer.CopyDataNoReduplicateProducer;
 import cn.com.qmth.examcloud.core.questions.service.producer.CopyDataProducer;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 
@@ -38,104 +27,101 @@ import cn.com.qmth.examcloud.web.redis.RedisClient;
 public class CopyDataServiceImpl implements CopyDataService {
 	private static final Logger log = LoggerFactory.getLogger(CopyDataService.class);
 	private static int cacheLockTimeout = 60 * 10;
-	private static String withoutReduplicateLock = "$_COPY_QUESTION_DATA_NO_REDUPLICATE_LOCK";
-	@Autowired
-	private CourseCloudService courseCloudService;
-
-	@Autowired
-	private PaperRepo paperRepo;
-
+	private static String copyQuestionDataLock = "$_COPY_QUESTION_DATA_LOCK";
 	@Autowired
 	private CopyDataProducer copyDataProducer;
-	
-	@Autowired
-	private CopyDataNoReduplicateProducer copyDataNoReduplicateProducer;
 
-	@Autowired
-	private PaperDetailRepo paperDetailRepo;
+//	@Autowired
+//	private CopyDataNoReduplicateProducer copyDataNoReduplicateProducer;
 
-	@Autowired
-	private PaperDetailUnitRepo paperDetailUnitRepo;
-
-	@Autowired
-	private PaperService paperService;
-
-	@Autowired
-	private QuesRepo quesRepo;
 	@Autowired
 	private QuesTypeNameRepo quesTypeNameRepo;
-	@Autowired
-	private QuestionAudioRepo questionAudioRepo;
-
 	@Autowired
 	private RedisClient redisClient;
 
+//	@Async
+//	@Override
+//	@Transactional
+//	public void copyNoReduplicate(User user, String batch) {
+//		Long rootOrgId = user.getRootOrgId();
+//		boolean sucss = true;
+//		long s1 = System.currentTimeMillis();
+//		try {
+//			log.warn("数据复制开始 | rootOrgId=" + rootOrgId);
+//			disposeCopyNoReduplicate(user, batch);
+//		} catch (Exception e) {
+//			sucss = false;
+//			throw e;
+//		} finally {
+//			long s2 = System.currentTimeMillis();
+//			if (sucss) {
+//				log.warn("数据复制结束 | 成功 |  " + ((s2 - s1) / 1000) + "秒 |  rootOrgId=" + rootOrgId);
+//			} else {
+//				log.warn("数据复制结束 | 失败 |  " + ((s2 - s1) / 1000) + "秒 |  rootOrgId=" + rootOrgId);
+//			}
+//			redisClient.delete(copyQuestionDataLock);
+//		}
+//	}
+//
+//	private void disposeCopyNoReduplicate(User user, String batch) {
+//		Long rootOrgId=user.getRootOrgId();
+//		redisClient.expire(copyQuestionDataLock, cacheLockTimeout);
+//		List<CourseBean> courses = new ArrayList<>();
+//		GetCourseByOrgReq courseReq = new GetCourseByOrgReq();
+//		courseReq.setRootOrgId(rootOrgId);
+//		GetCourseByOrgResp res = courseCloudService.getCourseByOrg(courseReq);
+//		if (CollectionUtils.isEmpty(res.getCourseList())) {
+//			log.warn("没有课程数据");
+//		}
+//		for (CourseBean c : res.getCourseList()) {
+//			if (c.getEnable()) {
+//				courses.add(c);
+//			}
+//		}
+//		if (courses.size() == 0) {
+//			log.warn("没有课程数据");
+//		}
+//		redisClient.expire(copyQuestionDataLock, cacheLockTimeout);
+//		List<CopyDataNoReduplicateDto> dtos = new ArrayList<>();
+//		for (CourseBean c : courses) {
+//			dtos.add(new CopyDataNoReduplicateDto(c, user,batch));
+//		}
+//		Map<String, Object> param = new HashMap<>();
+//		param.put("dtos", dtos);
+//		copyDataNoReduplicateProducer.startDispose(4, param, dtos.size());
+//		String countInfo = "成功科目数:" + copyDataNoReduplicateProducer.getProcess() + " 科目总数:" + copyDataNoReduplicateProducer.getTotal();
+//		log.warn(countInfo);
+//	}
+
 	@Async
 	@Override
-	@Transactional
-	public void copyNoReduplicate(User user, String batch) {
-		Long rootOrgId = user.getRootOrgId();
+	public void copyData(User user, Long fromRootOrgId, Long toRootOrgId, List<CopyDataCourseInfo> courses) {
 		boolean sucss = true;
 		long s1 = System.currentTimeMillis();
 		try {
-			log.warn("数据复制开始 | rootOrgId=" + rootOrgId);
-			disposeCopyNoReduplicate(user, batch);
-		} catch (Exception e) {
-			sucss = false;
-			throw e;
-		} finally {
-			long s2 = System.currentTimeMillis();
-			if (sucss) {
-				log.warn("数据复制结束 | 成功 |  " + ((s2 - s1) / 1000) + "秒 |  rootOrgId=" + rootOrgId);
+			log.warn("数据复制开始 | fromRootOrgId=" + fromRootOrgId + " | toRootOrgId=" + toRootOrgId);
+			redisClient.expire(copyQuestionDataLock, cacheLockTimeout);
+			if (CollectionUtils.isNotEmpty(courses)) {
+				List<CopyDataDto> dtos = new ArrayList<>();
+				for (CopyDataCourseInfo course : courses) {
+					dtos.add(new CopyDataDto(course, fromRootOrgId, toRootOrgId, user));
+					redisClient.expire(copyQuestionDataLock, cacheLockTimeout);
+				}
+				Map<String, Object> param = new HashMap<>();
+				param.put("dtos", dtos);
+				copyDataProducer.startDispose(8, param, dtos.size());
+				redisClient.expire(copyQuestionDataLock, cacheLockTimeout);
+				copyQuesTypeName(fromRootOrgId, toRootOrgId);
+				String countInfo = "成功数:" + copyDataProducer.getProcess() + " 总数:" + copyDataProducer.getTotal();
+				log.warn(countInfo);
 			} else {
-				log.warn("数据复制结束 | 失败 |  " + ((s2 - s1) / 1000) + "秒 |  rootOrgId=" + rootOrgId);
-			}
-			redisClient.delete(withoutReduplicateLock);
-		}
-	}
-
-	private void disposeCopyNoReduplicate(User user, String batch) {
-		Long rootOrgId=user.getRootOrgId();
-		redisClient.expire(withoutReduplicateLock, cacheLockTimeout);
-		List<CourseBean> courses = new ArrayList<>();
-		GetCourseByOrgReq courseReq = new GetCourseByOrgReq();
-		courseReq.setRootOrgId(rootOrgId);
-		GetCourseByOrgResp res = courseCloudService.getCourseByOrg(courseReq);
-		if (CollectionUtils.isEmpty(res.getCourseList())) {
-			log.warn("没有课程数据");
-		}
-		for (CourseBean c : res.getCourseList()) {
-			if (c.getEnable()) {
-				courses.add(c);
+				log.warn("没有试卷数据需要处理");
 			}
-		}
-		if (courses.size() == 0) {
-			log.warn("没有课程数据");
-		}
-		redisClient.expire(withoutReduplicateLock, cacheLockTimeout);
-		List<CopyDataNoReduplicateDto> dtos = new ArrayList<>();
-		for (CourseBean c : courses) {
-			dtos.add(new CopyDataNoReduplicateDto(c, user,batch));
-		}
-		Map<String, Object> param = new HashMap<>();
-		param.put("dtos", dtos);
-		copyDataNoReduplicateProducer.startDispose(4, param, dtos.size());
-		String countInfo = "成功科目数:" + copyDataNoReduplicateProducer.getProcess() + " 科目总数:" + copyDataNoReduplicateProducer.getTotal();
-		log.warn(countInfo);
-	}
-
-	@Override
-	@Transactional
-	public void copyData(User user, Long fromRootOrgId, Long toRootOrgId) {
-		boolean sucss = true;
-		long s1 = System.currentTimeMillis();
-		try {
-			log.warn("数据复制开始 | fromRootOrgId=" + fromRootOrgId + " | toRootOrgId=" + toRootOrgId);
-			dispose(user, fromRootOrgId, toRootOrgId);
-		} catch (Exception e) {
+		}catch (Exception e) {
 			sucss = false;
 			throw e;
 		} finally {
+			redisClient.delete(copyQuestionDataLock);
 			long s2 = System.currentTimeMillis();
 			if (sucss) {
 				log.warn("数据复制结束 | 成功 |  " + ((s2 - s1) / 1000) + "秒 |  fromRootOrgId=" + fromRootOrgId
@@ -144,59 +130,78 @@ public class CopyDataServiceImpl implements CopyDataService {
 				log.warn("数据复制结束 | 失败 |  " + ((s2 - s1) / 1000) + "秒 |  fromRootOrgId=" + fromRootOrgId
 						+ " | toRootOrgId=" + toRootOrgId);
 			}
-			String cacheLock = "$_COPY_QUESTION_DATA_LOCK";
-			redisClient.delete(cacheLock);
 		}
 	}
 
-	private void dispose(User user, Long fromRootOrgId, Long toRootOrgId) {
-		clearData(toRootOrgId);
-		redisClient.expire("$_COPY_QUESTION_DATA_LOCK", cacheLockTimeout);
-		Map<String, Long> courses = new HashMap<>();
-		GetCourseByOrgReq courseReq = new GetCourseByOrgReq();
-		courseReq.setRootOrgId(toRootOrgId);
-		GetCourseByOrgResp res = courseCloudService.getCourseByOrg(courseReq);
-		if (CollectionUtils.isEmpty(res.getCourseList())) {
-			throw new StatusException("请先导入课程");
+	private void copyQuesTypeName(Long fromRootOrgId, Long toRootOrgId) {
+		List<QuesTypeName> from = quesTypeNameRepo.findByOrgId(fromRootOrgId.toString());
+		if (CollectionUtils.isEmpty(from)) {
+			return;
 		}
-		for (CourseBean c : res.getCourseList()) {
-			courses.put(c.getCode(), c.getId());
-		}
-		copyQuesTypeName(courses, fromRootOrgId, toRootOrgId);
-		redisClient.expire("$_COPY_QUESTION_DATA_LOCK", cacheLockTimeout);
-		List<String> paperIds = paperService.findPaperId(fromRootOrgId);
-		if (CollectionUtils.isNotEmpty(paperIds)) {
-			List<CopyDataDto> dtos = new ArrayList<>();
-			for (String paperId : paperIds) {
-				dtos.add(new CopyDataDto(courses, paperId, toRootOrgId, user));
-			}
-			Map<String, Object> param = new HashMap<>();
-			param.put("dtos", dtos);
-			copyDataProducer.startDispose(8, param, dtos.size());
-			String countInfo = "成功数:" + copyDataProducer.getProcess() + " 总数:" + copyDataProducer.getTotal();
-			log.warn(countInfo);
-		} else {
-			log.warn("没有试卷数据需要处理");
-		}
-	}
+		List<QuesTypeName> to = quesTypeNameRepo.findByOrgId(toRootOrgId.toString());
 
-	private void copyQuesTypeName(Map<String, Long> courses, Long fromRootOrgId, Long toRootOrgId) {
-		List<QuesTypeName> cps = quesTypeNameRepo.findByOrgId(fromRootOrgId);
-		if (CollectionUtils.isNotEmpty(cps)) {
-			for (QuesTypeName cp : cps) {
+		if (CollectionUtils.isEmpty(to)) {
+			for (QuesTypeName cp : from) {
 				cp.setOrgId(toRootOrgId.toString());
 				cp.setId(null);
 			}
+			quesTypeNameRepo.saveAll(from);
+		} else {
+			Map<String, QuesTypeName> fromMap = new HashMap<>();
+			Map<String, QuesTypeName> toMap = new HashMap<>();
+			List<QuesTypeName> add = new ArrayList<>();
+			List<QuesTypeName> update = new ArrayList<>();
+			for (QuesTypeName cp : from) {
+				String key = cp.getCourseNo() + "-" + cp.getQuestionType().name();
+				fromMap.put(key, cp);
+			}
+			for (QuesTypeName cp : to) {
+				String key = cp.getCourseNo() + "-" + cp.getQuestionType().name();
+				toMap.put(key, cp);
+			}
+			for (QuesTypeName cp : from) {
+				String key = cp.getCourseNo() + "-" + cp.getQuestionType().name();
+				QuesTypeName temUp = toMap.get(key);
+				if (temUp != null) {
+					temUp.setQuesNames(merge(temUp.getQuesNames(), cp.getQuesNames()));
+					update.add(temUp);
+				} else {
+					cp.setOrgId(toRootOrgId.toString());
+					cp.setId(null);
+					add.add(cp);
+				}
+			}
+			if (CollectionUtils.isNotEmpty(add)) {
+				quesTypeNameRepo.saveAll(add);
+			}
+			if (CollectionUtils.isNotEmpty(update)) {
+				quesTypeNameRepo.saveAll(update);
+			}
 		}
-		quesTypeNameRepo.saveAll(cps);
 	}
 
-	private void clearData(Long toRootOrgId) {
-		quesTypeNameRepo.deleteByOrgId(toRootOrgId.toString());
-		paperRepo.deleteByOrgId(toRootOrgId.toString());
-		paperDetailRepo.deleteByOrgId(toRootOrgId);
-		paperDetailUnitRepo.deleteByOrgId(toRootOrgId);
-		quesRepo.deleteByOrgId(toRootOrgId.toString());
-		questionAudioRepo.deleteByOrgId(toRootOrgId);
+	private List<String> merge(List<String> list1, List<String> list2) {
+		if (list1 == null && list2 == null) {
+			return new ArrayList<>();
+		}
+		if (list1 == null) {
+			return list2;
+		}
+		if (list2 == null) {
+			return list1;
+		}
+		Set<String> set = new LinkedHashSet<>();
+		set.addAll(list1);
+		set.addAll(list2);
+		return new ArrayList<>(set);
 	}
+
+//	private void clearData(Long toRootOrgId) {
+//		quesTypeNameRepo.deleteByOrgId(toRootOrgId.toString());
+//		paperRepo.deleteByOrgId(toRootOrgId.toString());
+//		paperDetailRepo.deleteByOrgId(toRootOrgId);
+//		paperDetailUnitRepo.deleteByOrgId(toRootOrgId);
+//		quesRepo.deleteByOrgId(toRootOrgId.toString());
+//		questionAudioRepo.deleteByOrgId(toRootOrgId);
+//	}
 }

+ 21 - 1
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/PaperServiceImpl.java

@@ -329,7 +329,27 @@ public class PaperServiceImpl implements PaperService {
 		List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
 		return paperList;
 	}
-
+	
+	@Override
+	public List<Paper> getImportPapersByCourse(Long ordId,String courseCode) {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(ordId.toString()));
+		query.addCriteria(Criteria.where("paperType").is(PaperType.IMPORT.name()));
+		query.addCriteria(Criteria.where("course.code").is(courseCode));
+		List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
+		return paperList;
+	}
+	
+	@Override
+	public boolean existsImportPaperByFromId(Long ordId,String courseCode,String fromId) {
+		Query query = new Query();
+		query.addCriteria(Criteria.where("orgId").is(ordId.toString()));
+		query.addCriteria(Criteria.where("paperType").is(PaperType.IMPORT.name()));
+		query.addCriteria(Criteria.where("course.code").is(courseCode));
+		query.addCriteria(Criteria.where("fromId").is(fromId));
+		List<Paper> paperList = this.mongoTemplate.find(query, Paper.class);
+		return CollectionUtils.isNotEmpty(paperList);
+	}
 	/**
 	 * 根据条件查询
 	 *