xiatian 3 weeks ago
parent
commit
19939f9520

+ 32 - 28
examcloud-core-questions-api-provider/src/main/java/cn/com/qmth/examcloud/core/questions/api/controller/CoursePropertyController.java

@@ -64,7 +64,7 @@ public class CoursePropertyController extends ControllerSupport {
         User user = getAccessUser();
         UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
 
-        List<CourseProperty> courseProperties = coursePropertyService.findAllByOrgId(user.getRootOrgId(),ud);
+        List<CourseProperty> courseProperties = coursePropertyService.findAllByOrgId(user.getRootOrgId(), ud);
         return new ResponseEntity<>(courseProperties, HttpStatus.OK);
     }
 
@@ -72,14 +72,15 @@ public class CoursePropertyController extends ControllerSupport {
     @ApiOperation(value = "根据orgId查询所有课程属性(分页)")
     @GetMapping(value = "/courseProperty/all/{curPage}/{pageSize}")
     public ResponseEntity<Object> findAllByOrgId(@ModelAttribute CoursePropertyDto coursePropertyDto,
-                                                 @PathVariable Integer curPage, @PathVariable Integer pageSize) {
+            @PathVariable Integer curPage, @PathVariable Integer pageSize) {
         User user = getAccessUser();
         UserDataRule userDataRule = super.getUserDataRule(DataRuleType.COURSE);
 
         coursePropertyDto.setOrgId(user.getRootOrgId());
 
         PageRequest pageable = PageRequest.of(curPage - 1, pageSize);
-        Page<CourseProperty> coursePropertiesPage = coursePropertyService.findList(coursePropertyDto, pageable, userDataRule);
+        Page<CourseProperty> coursePropertiesPage = coursePropertyService.findList(coursePropertyDto, pageable,
+                userDataRule);
 
         return new ResponseEntity<>(coursePropertiesPage, HttpStatus.OK);
     }
@@ -170,7 +171,8 @@ public class CoursePropertyController extends ControllerSupport {
             throw new StatusException(Constants.SYS_CODE_500, "请先登录!");
         }
 
-        List<CourseProperty> courseProperties = coursePropertyService.findAllByCourseCode(courseCode);
+        List<CourseProperty> courseProperties = coursePropertyService.findAllByCourseCode(courseCode,
+                user.getRootOrgId());
         return new ResponseEntity<>(courseProperties, HttpStatus.OK);
     }
 
@@ -184,37 +186,39 @@ public class CoursePropertyController extends ControllerSupport {
             throw new StatusException(Constants.SYS_CODE_500, "请先登录!");
         }
 
-        List<CourseProperty> courseProperties = coursePropertyService.findByEnable(courseCode, true,user,ud);
+        List<CourseProperty> courseProperties = coursePropertyService.findByEnable(courseCode, true, user, ud);
         return new ResponseEntity<>(courseProperties, HttpStatus.OK);
     }
-    
+
     @ApiOperation(value = "下载导入模板", notes = "下载导入模板")
-	@GetMapping("/courseProperty/importTemplate")
-	public void getImportTemplate(HttpServletResponse response) {
-		String resoucePath = PathUtil.getResoucePath("templates/coursePropertyImportTemplate.xlsx");
-		exportFile("课程属性导入模板.xlsx", new File(resoucePath));
-	}
-
-	@DataRule(type = DataRuleType.COURSE)
-	@ApiOperation(value = "导入课程属性", notes = "导入")
-	@PostMapping("/courseProperty/import")
-	public Map<String, Object> importCourseProperty(@RequestPart @NotNull(message = "上传文件不能为空!") MultipartFile file) {
-		User user = getAccessUser();
-		UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
-		List<Map<String, Object>> failRecords = coursePropertyService.importCourseProperty(ud, user, getRootOrgId(), file);
-		Map<String, Object> map = Maps.newHashMap();
-		map.put("hasError", CollectionUtils.isNotEmpty(failRecords));
-		map.put("failRecords", failRecords);
-		return map;
-	}
-	
-	@DataRule(type = DataRuleType.COURSE)
+    @GetMapping("/courseProperty/importTemplate")
+    public void getImportTemplate(HttpServletResponse response) {
+        String resoucePath = PathUtil.getResoucePath("templates/coursePropertyImportTemplate.xlsx");
+        exportFile("课程属性导入模板.xlsx", new File(resoucePath));
+    }
+
+    @DataRule(type = DataRuleType.COURSE)
+    @ApiOperation(value = "导入课程属性", notes = "导入")
+    @PostMapping("/courseProperty/import")
+    public Map<String, Object> importCourseProperty(@RequestPart @NotNull(message = "上传文件不能为空!") MultipartFile file) {
+        User user = getAccessUser();
+        UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
+        List<Map<String, Object>> failRecords = coursePropertyService.importCourseProperty(ud, user, getRootOrgId(),
+                file);
+        Map<String, Object> map = Maps.newHashMap();
+        map.put("hasError", CollectionUtils.isNotEmpty(failRecords));
+        map.put("failRecords", failRecords);
+        return map;
+    }
+
+    @DataRule(type = DataRuleType.COURSE)
     @ApiOperation(value = "导出课程属性")
     @RequestMapping(value = "/courseProperty/export", method = RequestMethod.GET)
-    public void exportCourseProperty(@RequestParam(required = false) String name,@RequestParam(required = false) Long courseId, HttpServletResponse response) {
+    public void exportCourseProperty(@RequestParam(required = false) String name,
+            @RequestParam(required = false) Long courseId, HttpServletResponse response) {
         User user = getAccessUser();
         UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
-        List<CoursePropertyImportInfo> dtos = coursePropertyService.exportCourseProperty(ud, user, name,courseId);
+        List<CoursePropertyImportInfo> dtos = coursePropertyService.exportCourseProperty(ud, user, name, courseId);
         ExportUtils.exportEXCEL("课程属性", CoursePropertyImportInfo.class, dtos, response);
     }
 

+ 18 - 16
examcloud-core-questions-dao/src/main/java/cn/com/qmth/examcloud/core/questions/dao/CoursePropertyRepo.java

@@ -12,38 +12,40 @@ import java.util.Set;
  * @describle 课程属性repo
  * @date 2017.11.2
  */
-public interface CoursePropertyRepo extends MongoRepository<CourseProperty, String>, QueryByExampleExecutor<CourseProperty> {
+public interface CoursePropertyRepo
+        extends MongoRepository<CourseProperty, String>, QueryByExampleExecutor<CourseProperty> {
 
-    //根据属性名查询
+    // 根据属性名查询
     CourseProperty findByOrgIdAndName(Long orgId, String name);
 
-    //根据课程id查询
+    // 根据课程id查询
     List<CourseProperty> findByCourseId(Long courseId);
 
-    List<CourseProperty> findByCourseCode(String courseCode);
+    List<CourseProperty> findByCourseCodeAndOrgId(String courseCode, Long rootOrgId);
 
-    //根据课程代码查询已开启的课程属性
+    // 根据课程代码查询已开启的课程属性
     List<CourseProperty> findByCourseCodeAndEnable(String courseCode, Boolean enable);
-    List<CourseProperty> findByOrgIdAndCourseCodeAndEnable(Long orgId,String courseCode, Boolean enable);
 
-    //根据课程id查询已经开启的课程属性
+    List<CourseProperty> findByOrgIdAndCourseCodeAndEnable(Long orgId, String courseCode, Boolean enable);
+
+    // 根据课程id查询已经开启的课程属性
     List<CourseProperty> findByCourseIdAndEnable(Long courseId, Boolean enable);
 
-    //根据id集合查询
+    // 根据id集合查询
     List<CourseProperty> findByIdIn(List<String> ids);
 
-	CourseProperty findByOrgIdAndCourseIdAndName(Long rootOrgId, Long courseId, String propertyName);
+    CourseProperty findByOrgIdAndCourseIdAndName(Long rootOrgId, Long courseId, String propertyName);
+
+    List<CourseProperty> findByOrgIdAndCourseIdIn(Long orgId, Set<Long> refIds);
 
-	List<CourseProperty> findByOrgIdAndCourseIdIn(Long orgId, Set<Long> refIds);
+    List<CourseProperty> findByOrgId(Long orgId);
 
-	List<CourseProperty> findByOrgId(Long orgId);
+    void deleteByOrgIdAndBatch(Long rootOrgId, String batch);
 
-	void deleteByOrgIdAndBatch(Long rootOrgId, String batch);
-	
-	CourseProperty findByOrgIdAndCourseIdAndBatch(Long rootOrgId,Long courseId, String batch);
+    CourseProperty findByOrgIdAndCourseIdAndBatch(Long rootOrgId, Long courseId, String batch);
 
-	List<CourseProperty> findByOrgIdAndCourseIdAndSourceId(Long rootOrgId, Long courseId, String sourceId);
+    List<CourseProperty> findByOrgIdAndCourseIdAndSourceId(Long rootOrgId, Long courseId, String sourceId);
 
-	List<CourseProperty> findAllByOrgIdAndCourseCode(Long rootOrgId, String courseCode);
+    List<CourseProperty> findAllByOrgIdAndCourseCode(Long rootOrgId, String courseCode);
 
 }

+ 8 - 7
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/CoursePropertyService.java

@@ -22,7 +22,8 @@ public interface CoursePropertyService {
 
     /**
      * 查询所有课程属性
-     * @param ud 
+     * 
+     * @param ud
      */
     List<CourseProperty> findAllByOrgId(Long orgId, UserDataRule ud);
 
@@ -44,12 +45,12 @@ public interface CoursePropertyService {
     /**
      * 根据课程code查询所有课程属性
      */
-    List<CourseProperty> findAllByCourseCode(String courseCode);
+    List<CourseProperty> findAllByCourseCode(String courseCode, Long rootOrgId);
 
     /**
      * 根据课程code查询所有开启的课程属性
      */
-    List<CourseProperty> findByEnable(String courseCode, Boolean enable,User user,UserDataRule ud);
+    List<CourseProperty> findByEnable(String courseCode, Boolean enable, User user, UserDataRule ud);
 
     /**
      * 批量启用/批量禁用
@@ -61,12 +62,12 @@ public interface CoursePropertyService {
      */
     void updateCoursePropertyStatus(String coursePropertyId, Boolean enable);
 
-	List<Map<String, Object>> importCourseProperty(UserDataRule ud, User user, Long rootOrgId, MultipartFile dataFile);
+    List<Map<String, Object>> importCourseProperty(UserDataRule ud, User user, Long rootOrgId, MultipartFile dataFile);
 
-	List<CoursePropertyImportInfo> exportCourseProperty(UserDataRule ud, User user, String name, Long courseId);
+    List<CoursePropertyImportInfo> exportCourseProperty(UserDataRule ud, User user, String name, Long courseId);
 
-	List<CourseProperty> findByOrgIdAndCourseIdAndSourceId(Long toRootOrgId, Long courseId, String id);
+    List<CourseProperty> findByOrgIdAndCourseIdAndSourceId(Long toRootOrgId, Long courseId, String id);
 
-	List<CourseProperty> findAllByOrgIdCourseCode(Long fromRootOrgId, String courseCode);
+    List<CourseProperty> findAllByOrgIdCourseCode(Long fromRootOrgId, String courseCode);
 
 }

+ 357 - 350
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/CoursePropertyServiceImpl.java

@@ -61,36 +61,36 @@ import cn.com.qmth.examcloud.web.config.SystemProperties;
 @Service("coursePropertyService")
 public class CoursePropertyServiceImpl implements CoursePropertyService {
 
-	private static final Logger log = LoggerFactory.getLogger(CoursePropertyServiceImpl.class);
-	
-	private static final String[] EXCEL_HEADER = new String[] { "课程代码", "课程名称", "属性名称", "一级属性编号", "一级属性内容", "二级属性编号",
-	"二级属性内容" };
+    private static final Logger log = LoggerFactory.getLogger(CoursePropertyServiceImpl.class);
+
+    private static final String[] EXCEL_HEADER = new String[] { "课程代码", "课程名称", "属性名称", "一级属性编号", "一级属性内容", "二级属性编号",
+            "二级属性内容" };
 
     @Autowired
     private CoursePropertyRepo coursePropertyRepo;
-    
-	@Autowired
-	private PropertyRepo propertyRepo;
-    
+
+    @Autowired
+    private PropertyRepo propertyRepo;
+
     @Autowired
     private CourseCloudService courseCloudService;
 
     @Autowired
     private MongoTemplate mongoTemplate;
-    
+
     @Autowired
     private SystemProperties systemProperties;
 
     @Override
-    public List<CourseProperty> findAllByOrgId(Long orgId,UserDataRule ud) {
-    	if (ud.assertEmptyQueryResult()) {
+    public List<CourseProperty> findAllByOrgId(Long orgId, UserDataRule ud) {
+        if (ud.assertEmptyQueryResult()) {
             return Lists.newArrayList();
         }
-    	if (ud.assertNeedQueryRefIds()) {
-    		return coursePropertyRepo.findByOrgIdAndCourseIdIn(orgId,ud.getRefIds());
-    	}else {
-    		return coursePropertyRepo.findByOrgId(orgId);
-    	}
+        if (ud.assertNeedQueryRefIds()) {
+            return coursePropertyRepo.findByOrgIdAndCourseIdIn(orgId, ud.getRefIds());
+        } else {
+            return coursePropertyRepo.findByOrgId(orgId);
+        }
     }
 
     @Override
@@ -113,7 +113,7 @@ public class CoursePropertyServiceImpl implements CoursePropertyService {
         }
 
         if (StringUtils.isBlank(dto.getId())) {
-            dto.setId(null);//剔除空字符串ID(导致异常数据)
+            dto.setId(null);// 剔除空字符串ID(导致异常数据)
         }
 
         courseProperty = new CourseProperty();
@@ -141,7 +141,7 @@ public class CoursePropertyServiceImpl implements CoursePropertyService {
         }
 
         if (dto.getCourseId() != null) {
-            if (userDataRule.assertNeedQueryRefIds()&&!userDataRule.getRefIds().contains(dto.getCourseId())) {
+            if (userDataRule.assertNeedQueryRefIds() && !userDataRule.getRefIds().contains(dto.getCourseId())) {
                 return Page.empty();
             }
             query.addCriteria(Criteria.where("courseId").is(dto.getCourseId()));
@@ -188,26 +188,26 @@ public class CoursePropertyServiceImpl implements CoursePropertyService {
     }
 
     @Override
-    public List<CourseProperty> findAllByCourseCode(String courseCode) {
-        return coursePropertyRepo.findByCourseCode(courseCode);
+    public List<CourseProperty> findAllByCourseCode(String courseCode, Long rootOrgId) {
+        return coursePropertyRepo.findByCourseCodeAndOrgId(courseCode, rootOrgId);
     }
 
     @Override
-    public List<CourseProperty> findByEnable(String courseCode, Boolean enable,User user,UserDataRule ud) {
-        
+    public List<CourseProperty> findByEnable(String courseCode, Boolean enable, User user, UserDataRule ud) {
+
         if (ud.assertEmptyQueryResult()) {
-			return new ArrayList<>();
-		}
-		Query query = new Query();
-		if (ud.assertNeedQueryRefIds()) {
-			query.addCriteria(Criteria.where("courseId").in(ud.getRefIds()));
-		}
-		query.addCriteria(Criteria.where("orgId").is(user.getRootOrgId()));
-		query.addCriteria(Criteria.where("courseCode").is(courseCode));
-		
-		query.addCriteria(Criteria.where("enable").is(true));
-		List<CourseProperty> paperList = this.mongoTemplate.find(query, CourseProperty.class);
-		return paperList;
+            return new ArrayList<>();
+        }
+        Query query = new Query();
+        if (ud.assertNeedQueryRefIds()) {
+            query.addCriteria(Criteria.where("courseId").in(ud.getRefIds()));
+        }
+        query.addCriteria(Criteria.where("orgId").is(user.getRootOrgId()));
+        query.addCriteria(Criteria.where("courseCode").is(courseCode));
+
+        query.addCriteria(Criteria.where("enable").is(true));
+        List<CourseProperty> paperList = this.mongoTemplate.find(query, CourseProperty.class);
+        return paperList;
     }
 
     @Override
@@ -240,11 +240,12 @@ public class CoursePropertyServiceImpl implements CoursePropertyService {
         courseProperty.setUpdateTime(new Date());
         coursePropertyRepo.save(courseProperty);
     }
-    
+
     @Transactional
-	@Override
-	public List<Map<String, Object>> importCourseProperty(UserDataRule ud, User user, Long rootOrgId, MultipartFile dataFile) {
-    	File file = new File(systemProperties.getTempDataDir() + File.separator + UUID.randomUUID() + ".xlsx");
+    @Override
+    public List<Map<String, Object>> importCourseProperty(UserDataRule ud, User user, Long rootOrgId,
+            MultipartFile dataFile) {
+        File file = new File(systemProperties.getTempDataDir() + File.separator + UUID.randomUUID() + ".xlsx");
         try {
             file.createNewFile();
             dataFile.transferTo(file);
@@ -255,261 +256,268 @@ public class CoursePropertyServiceImpl implements CoursePropertyService {
             FileUtil.deleteFile(file.getAbsolutePath());
         }
     }
-    
-	private List<Map<String, Object>> disposeImportCourseProperty(UserDataRule ud, User user, Long rootOrgId, File file) {
-		List<String[]> lineList = null;
-		try {
-			lineList = ExcelReader.readSheetBySax(PathUtil.getCanonicalPath(file), 1, 7);
-		} catch (Exception e) {
-			throw new StatusException("100110", "Excel 解析失败",e );
-		}
-
-		if (CollectionUtils.isEmpty(lineList)) {
-			throw new StatusException("100111", "Excel无内容");
-		}
-
-		if (10001 < lineList.size()) {
-			throw new StatusException("100112", "数据行数不能超过10000");
-		}
-
-		List<Map<String, Object>> failRecords = Collections.synchronizedList(new ArrayList<Map<String, Object>>());
-
-		List<CoursePropertyImportInfo> courseList = Lists.newArrayList();
-		Map<String, Course> cousreMap = new HashMap<>();
-		for (int i = 0; i < lineList.size(); i++) {
-			String[] line = lineList.get(i);
-			if (0 == i) {
-				if (headerError(line)) {
-					throw new StatusException("100111", "Excel表头错误");
-				}
-				continue;
-			}
-
-			boolean hasError = false;
-			StringBuilder msg = new StringBuilder();
-
-			CoursePropertyImportInfo courseInfo = new CoursePropertyImportInfo();
-
-			String courseCode = trimAndNullIfBlank(line[0]);
-			if (StringUtils.isBlank(courseCode)) {
-				msg.append("  课程代码不能为空");
-				hasError = true;
-			} else if (!checkCourseExist(cousreMap, courseCode, rootOrgId)) {
-				msg.append("  课程代码不存在");
-				hasError = true;
-			} else if ("false".equals(cousreMap.get(courseCode).getEnable())) {
-				msg.append("  课程已禁用");
-				hasError = true;
-			}
-			
-			courseInfo.setCourseCode(courseCode);
-			
-			if(cousreMap.get(courseCode)!=null) {
-				courseInfo.setCourseId(Long.valueOf(cousreMap.get(courseCode).getId()));
-			}
-
-			String propertyName = trimAndNullIfBlank(line[2]);
-			if (StringUtils.isBlank(propertyName)) {
-				msg.append("  属性名称不能为空");
-				hasError = true;
-			} else if (propertyName.length() > 100) {
-				msg.append("  属性名称不能超过100个字符");
-				hasError = true;
-			}
-			courseInfo.setPropertyName(propertyName);
-
-			String firstCode = trimAndNullIfBlank(line[3]);
-			if (StringUtils.isBlank(firstCode)) {
-				msg.append("  一级属性编号不能为空");
-				hasError = true;
-			} else if (firstCode.length() > 100) {
-				msg.append("  一级属性编号不能超过100个字符");
-				hasError = true;
-			}
-			courseInfo.setFirstPropertyCode(firstCode);
-
-			String firstName = trimAndNullIfBlank(line[4]);
-			if (StringUtils.isNotBlank(firstName) && firstName.length() > 100) {
-				msg.append("  一级属性内容不能超过100个字符");
-				hasError = true;
-			}
-			courseInfo.setFirstPropertyName(firstName);
-
-			String secCode = trimAndNullIfBlank(line[5]);
-			if (StringUtils.isNotBlank(secCode) && secCode.length() > 100) {
-				msg.append("  二级属性编号不能超过100个字符");
-				hasError = true;
-			}
-			courseInfo.setSecondPropertyCode(secCode);
-
-			String secName = trimAndNullIfBlank(line[6]);
-			if (StringUtils.isNotBlank(secName) && secName.length() > 100) {
-				msg.append("  二级属性内容不能超过100个字符");
-				hasError = true;
-			}
-			courseInfo.setSecondPropertyName(secName);
-
-			if (hasError) {
-				failRecords.add(newError(i + 1, msg.toString()));
-			} else {
-				courseList.add(courseInfo);
-			}
-
-		}
-
-		if (CollectionUtils.isNotEmpty(failRecords)) {
-			return failRecords;
-		}
-
-		for (int i = 0; i < courseList.size(); i++) {
-			CoursePropertyImportInfo cur = courseList.get(i);
-			try {
-				saveCoursePropertyInfo(user, ud, cur);
-			} catch (StatusException e) {
-				failRecords.add(newError(i + 2, e.getDesc()));
-			} catch (Exception e) {
-				failRecords.add(newError(i + 2, "系统异常"));
-				log.error("课程属性导入系统异常", e);
-			}
-		}
-		if (CollectionUtils.isNotEmpty(failRecords)) {
-			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
-		}
-
-		return failRecords;
-	}
-
-	private void saveCoursePropertyInfo(User user, UserDataRule ud, CoursePropertyImportInfo cur) {
-		if(ud.assertEmptyQueryResult()) {
-			throw new StatusException(" 课程不在该账号负责的课程中");
-		}
-		if (ud.assertNeedQueryRefIds() && !ud.getRefIds().contains(cur.getCourseId())) {
-			throw new StatusException(" 课程不在该账号负责的课程中");
-		}
-		CourseProperty c = coursePropertyRepo.findByOrgIdAndCourseIdAndName(user.getRootOrgId(),cur.getCourseId(), cur.getPropertyName());
-		if(c==null) {
-			c=new CourseProperty();
-			c.setCourseId(cur.getCourseId());
-			c.setCourseCode(cur.getCourseCode());
-			c.setName(cur.getPropertyName());
-			c.setOrgId(user.getRootOrgId());
-			c.setEnable(true);
-		}
-		c.setUpdateTime(new Date());
-		coursePropertyRepo.save(c);
-		
-		Property first=propertyRepo.findByOrgIdAndCoursePropertyIdAndParentIdAndCode(user.getRootOrgId(), c.getId(), Property.ROOT_PARENT_ID, cur.getFirstPropertyCode());
-		if(first!=null) {
-			first.setName(cur.getFirstPropertyName());
-		}else {
-			if(StringUtils.isBlank(cur.getFirstPropertyName())) {
-				throw new StatusException(" 一级属性内容不能为空");
-			}
-			first=new Property();
-			first.setParentId(Property.ROOT_PARENT_ID);
-			first.setOrgId(user.getRootOrgId());
-			first.setCoursePropertyId(c.getId());
-			first.setCode(cur.getFirstPropertyCode());
-			first.setName(cur.getFirstPropertyName());
-			Integer number = 0;
-            List<Property> parentProperties = propertyRepo.findByOrgIdAndCoursePropertyIdAndParentIdOrderByNumber(first.getOrgId(), first.getCoursePropertyId(), first.getParentId());
+
+    private List<Map<String, Object>> disposeImportCourseProperty(UserDataRule ud, User user, Long rootOrgId,
+            File file) {
+        List<String[]> lineList = null;
+        try {
+            lineList = ExcelReader.readSheetBySax(PathUtil.getCanonicalPath(file), 1, 7);
+        } catch (Exception e) {
+            throw new StatusException("100110", "Excel 解析失败", e);
+        }
+
+        if (CollectionUtils.isEmpty(lineList)) {
+            throw new StatusException("100111", "Excel无内容");
+        }
+
+        if (10001 < lineList.size()) {
+            throw new StatusException("100112", "数据行数不能超过10000");
+        }
+
+        List<Map<String, Object>> failRecords = Collections.synchronizedList(new ArrayList<Map<String, Object>>());
+
+        List<CoursePropertyImportInfo> courseList = Lists.newArrayList();
+        Map<String, Course> cousreMap = new HashMap<>();
+        for (int i = 0; i < lineList.size(); i++) {
+            String[] line = lineList.get(i);
+            if (0 == i) {
+                if (headerError(line)) {
+                    throw new StatusException("100111", "Excel表头错误");
+                }
+                continue;
+            }
+
+            boolean hasError = false;
+            StringBuilder msg = new StringBuilder();
+
+            CoursePropertyImportInfo courseInfo = new CoursePropertyImportInfo();
+
+            String courseCode = trimAndNullIfBlank(line[0]);
+            if (StringUtils.isBlank(courseCode)) {
+                msg.append("  课程代码不能为空");
+                hasError = true;
+            } else if (!checkCourseExist(cousreMap, courseCode, rootOrgId)) {
+                msg.append("  课程代码不存在");
+                hasError = true;
+            } else if ("false".equals(cousreMap.get(courseCode).getEnable())) {
+                msg.append("  课程已禁用");
+                hasError = true;
+            }
+
+            courseInfo.setCourseCode(courseCode);
+
+            if (cousreMap.get(courseCode) != null) {
+                courseInfo.setCourseId(Long.valueOf(cousreMap.get(courseCode).getId()));
+            }
+
+            String propertyName = trimAndNullIfBlank(line[2]);
+            if (StringUtils.isBlank(propertyName)) {
+                msg.append("  属性名称不能为空");
+                hasError = true;
+            } else if (propertyName.length() > 100) {
+                msg.append("  属性名称不能超过100个字符");
+                hasError = true;
+            }
+            courseInfo.setPropertyName(propertyName);
+
+            String firstCode = trimAndNullIfBlank(line[3]);
+            if (StringUtils.isBlank(firstCode)) {
+                msg.append("  一级属性编号不能为空");
+                hasError = true;
+            } else if (firstCode.length() > 100) {
+                msg.append("  一级属性编号不能超过100个字符");
+                hasError = true;
+            }
+            courseInfo.setFirstPropertyCode(firstCode);
+
+            String firstName = trimAndNullIfBlank(line[4]);
+            if (StringUtils.isNotBlank(firstName) && firstName.length() > 100) {
+                msg.append("  一级属性内容不能超过100个字符");
+                hasError = true;
+            }
+            courseInfo.setFirstPropertyName(firstName);
+
+            String secCode = trimAndNullIfBlank(line[5]);
+            if (StringUtils.isNotBlank(secCode) && secCode.length() > 100) {
+                msg.append("  二级属性编号不能超过100个字符");
+                hasError = true;
+            }
+            courseInfo.setSecondPropertyCode(secCode);
+
+            String secName = trimAndNullIfBlank(line[6]);
+            if (StringUtils.isNotBlank(secName) && secName.length() > 100) {
+                msg.append("  二级属性内容不能超过100个字符");
+                hasError = true;
+            }
+            courseInfo.setSecondPropertyName(secName);
+
+            if (hasError) {
+                failRecords.add(newError(i + 1, msg.toString()));
+            } else {
+                courseList.add(courseInfo);
+            }
+
+        }
+
+        if (CollectionUtils.isNotEmpty(failRecords)) {
+            return failRecords;
+        }
+
+        for (int i = 0; i < courseList.size(); i++) {
+            CoursePropertyImportInfo cur = courseList.get(i);
+            try {
+                saveCoursePropertyInfo(user, ud, cur);
+            } catch (StatusException e) {
+                failRecords.add(newError(i + 2, e.getDesc()));
+            } catch (Exception e) {
+                failRecords.add(newError(i + 2, "系统异常"));
+                log.error("课程属性导入系统异常", e);
+            }
+        }
+        if (CollectionUtils.isNotEmpty(failRecords)) {
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+        }
+
+        return failRecords;
+    }
+
+    private void saveCoursePropertyInfo(User user, UserDataRule ud, CoursePropertyImportInfo cur) {
+        if (ud.assertEmptyQueryResult()) {
+            throw new StatusException(" 课程不在该账号负责的课程中");
+        }
+        if (ud.assertNeedQueryRefIds() && !ud.getRefIds().contains(cur.getCourseId())) {
+            throw new StatusException(" 课程不在该账号负责的课程中");
+        }
+        CourseProperty c = coursePropertyRepo.findByOrgIdAndCourseIdAndName(user.getRootOrgId(), cur.getCourseId(),
+                cur.getPropertyName());
+        if (c == null) {
+            c = new CourseProperty();
+            c.setCourseId(cur.getCourseId());
+            c.setCourseCode(cur.getCourseCode());
+            c.setName(cur.getPropertyName());
+            c.setOrgId(user.getRootOrgId());
+            c.setEnable(true);
+        }
+        c.setUpdateTime(new Date());
+        coursePropertyRepo.save(c);
+
+        Property first = propertyRepo.findByOrgIdAndCoursePropertyIdAndParentIdAndCode(user.getRootOrgId(), c.getId(),
+                Property.ROOT_PARENT_ID, cur.getFirstPropertyCode());
+        if (first != null) {
+            first.setName(cur.getFirstPropertyName());
+        } else {
+            if (StringUtils.isBlank(cur.getFirstPropertyName())) {
+                throw new StatusException(" 一级属性内容不能为空");
+            }
+            first = new Property();
+            first.setParentId(Property.ROOT_PARENT_ID);
+            first.setOrgId(user.getRootOrgId());
+            first.setCoursePropertyId(c.getId());
+            first.setCode(cur.getFirstPropertyCode());
+            first.setName(cur.getFirstPropertyName());
+            Integer number = 0;
+            List<Property> parentProperties = propertyRepo.findByOrgIdAndCoursePropertyIdAndParentIdOrderByNumber(
+                    first.getOrgId(), first.getCoursePropertyId(), first.getParentId());
             if (parentProperties != null && parentProperties.size() > 0) {
                 number = parentProperties.get(parentProperties.size() - 1).getNumber();
             }
 
             first.setNumber(number + 1);
-		}
-		propertyRepo.save(first);
-		
-		if(StringUtils.isNotBlank(cur.getSecondPropertyCode())&&StringUtils.isBlank(cur.getSecondPropertyName())) {
-			throw new StatusException(" 二级属性内容不能为空");
-		}
-		if(StringUtils.isNotBlank(cur.getSecondPropertyCode())){
-			Property sec=propertyRepo.findByOrgIdAndCoursePropertyIdAndParentIdAndCode(user.getRootOrgId(), c.getId(), first.getId(), cur.getSecondPropertyCode());
-			if(sec!=null) {
-				sec.setName(cur.getSecondPropertyName());
-			}else {
-				sec=new Property();
-				sec.setParentId(first.getId());
-				sec.setOrgId(user.getRootOrgId());
-				sec.setCoursePropertyId(c.getId());
-				sec.setCode(cur.getSecondPropertyCode());
-				sec.setName(cur.getSecondPropertyName());
-				Integer number = 0;
-	            List<Property> parentProperties = propertyRepo.findByOrgIdAndCoursePropertyIdAndParentIdOrderByNumber(sec.getOrgId(), sec.getCoursePropertyId(), sec.getParentId());
-	            if (parentProperties != null && parentProperties.size() > 0) {
-	                number = parentProperties.get(parentProperties.size() - 1).getNumber();
-	            }
-
-	            sec.setNumber(number + 1);
-			}
-			propertyRepo.save(sec);
-		}
-		
-	}
-
-	private boolean checkCourseExist(Map<String, Course> cousre, String courseCode, Long rootOrgId) {
-		if (cousre.get(courseCode) != null) {
-			return true;
-		}
-		GetCourseReq req=new GetCourseReq();
-		req.setRootOrgId(rootOrgId);
-		req.setCode(courseCode);
-		GetCourseResp res=courseCloudService.getCourse(req);
-		if (res.getCourseBean() == null) {
-			return false;
-		} else {
-			cousre.put(courseCode, of(res.getCourseBean()));
-			return true;
-		}
-	}
-	
-	private Course of(CourseBean b) {
-		Course c=new Course();
-		c.setCode(b.getCode());
-		c.setEnable(b.getEnable()!=null?null:b.getEnable().toString());
-		c.setId(b.getId()+"");
-		c.setLevel(b.getLevel());
-		c.setName(b.getName());
-		c.setOrgId(b.getRootOrgId()+"");
-		return c;
-	}
-
-	private Map<String, Object> newError(int lineNum, String msg) {
-		Map<String, Object> map = Maps.newHashMap();
-		map.put("lineNum", lineNum);
-		map.put("msg", msg);
-		return map;
-	}
-
-	private String trimAndNullIfBlank(String s) {
-		if (StringUtils.isBlank(s)) {
-			return null;
-		}
-		return s.trim();
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @param header
-	 * @author WANGWEI
-	 */
-	private boolean headerError(String[] header) {
-		for (int i = 0; i < EXCEL_HEADER.length; i++) {
-			if (null == header[i]) {
-				return true;
-			}
-			if (!EXCEL_HEADER[i].equals(header[i].trim())) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	@Override
-	public List<CoursePropertyImportInfo> exportCourseProperty(UserDataRule userDataRule, User user, String name, Long courseId) {
-		if (userDataRule.assertEmptyQueryResult()) {
+        }
+        propertyRepo.save(first);
+
+        if (StringUtils.isNotBlank(cur.getSecondPropertyCode()) && StringUtils.isBlank(cur.getSecondPropertyName())) {
+            throw new StatusException(" 二级属性内容不能为空");
+        }
+        if (StringUtils.isNotBlank(cur.getSecondPropertyCode())) {
+            Property sec = propertyRepo.findByOrgIdAndCoursePropertyIdAndParentIdAndCode(user.getRootOrgId(), c.getId(),
+                    first.getId(), cur.getSecondPropertyCode());
+            if (sec != null) {
+                sec.setName(cur.getSecondPropertyName());
+            } else {
+                sec = new Property();
+                sec.setParentId(first.getId());
+                sec.setOrgId(user.getRootOrgId());
+                sec.setCoursePropertyId(c.getId());
+                sec.setCode(cur.getSecondPropertyCode());
+                sec.setName(cur.getSecondPropertyName());
+                Integer number = 0;
+                List<Property> parentProperties = propertyRepo.findByOrgIdAndCoursePropertyIdAndParentIdOrderByNumber(
+                        sec.getOrgId(), sec.getCoursePropertyId(), sec.getParentId());
+                if (parentProperties != null && parentProperties.size() > 0) {
+                    number = parentProperties.get(parentProperties.size() - 1).getNumber();
+                }
+
+                sec.setNumber(number + 1);
+            }
+            propertyRepo.save(sec);
+        }
+
+    }
+
+    private boolean checkCourseExist(Map<String, Course> cousre, String courseCode, Long rootOrgId) {
+        if (cousre.get(courseCode) != null) {
+            return true;
+        }
+        GetCourseReq req = new GetCourseReq();
+        req.setRootOrgId(rootOrgId);
+        req.setCode(courseCode);
+        GetCourseResp res = courseCloudService.getCourse(req);
+        if (res.getCourseBean() == null) {
+            return false;
+        } else {
+            cousre.put(courseCode, of(res.getCourseBean()));
+            return true;
+        }
+    }
+
+    private Course of(CourseBean b) {
+        Course c = new Course();
+        c.setCode(b.getCode());
+        c.setEnable(b.getEnable() != null ? null : b.getEnable().toString());
+        c.setId(b.getId() + "");
+        c.setLevel(b.getLevel());
+        c.setName(b.getName());
+        c.setOrgId(b.getRootOrgId() + "");
+        return c;
+    }
+
+    private Map<String, Object> newError(int lineNum, String msg) {
+        Map<String, Object> map = Maps.newHashMap();
+        map.put("lineNum", lineNum);
+        map.put("msg", msg);
+        return map;
+    }
+
+    private String trimAndNullIfBlank(String s) {
+        if (StringUtils.isBlank(s)) {
+            return null;
+        }
+        return s.trim();
+    }
+
+    /**
+     * 方法注释
+     *
+     * @param header
+     * @author WANGWEI
+     */
+    private boolean headerError(String[] header) {
+        for (int i = 0; i < EXCEL_HEADER.length; i++) {
+            if (null == header[i]) {
+                return true;
+            }
+            if (!EXCEL_HEADER[i].equals(header[i].trim())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public List<CoursePropertyImportInfo> exportCourseProperty(UserDataRule userDataRule, User user, String name,
+            Long courseId) {
+        if (userDataRule.assertEmptyQueryResult()) {
             return Lists.newArrayList();
         }
 
@@ -532,70 +540,69 @@ public class CoursePropertyServiceImpl implements CoursePropertyService {
             query.addCriteria(Criteria.where("name").regex(name.trim()));
         }
 
-
         query.with(Sort.by(new Sort.Order(Sort.Direction.DESC, "updateTime")));
         List<CourseProperty> coursePros = mongoTemplate.find(query, CourseProperty.class);
 
-		List<CoursePropertyImportInfo> ret=new ArrayList<>();
-		if(!CollectionUtils.isEmpty(coursePros)) {
-			for(CourseProperty cp:coursePros) {
-				fillProperty(ret, cp);
-			}
-		}
-		return ret;
-	}
-	
-	private void fillProperty(List<CoursePropertyImportInfo> ret,CourseProperty cp) {
-		List<Property> ps=propertyRepo.findByCoursePropertyIdOrderByNumber(cp.getId());
-		if(!CollectionUtils.isEmpty(ps)) {
-			Map<String,List<Property>> secPs=new HashMap<>();
-			for(Property p:ps) {
-				if(!Property.ROOT_PARENT_ID.equals(p.getParentId())) {
-					List<Property> list=secPs.get(p.getParentId());
-					if(list==null) {
-						list=new ArrayList<>();
-						secPs.put(p.getParentId(), list);
-					}
-					list.add(p);
-				}
-			}
-			
-			for(Property p:ps) {
-				if(Property.ROOT_PARENT_ID.equals(p.getParentId())) {
-					CoursePropertyImportInfo info=new CoursePropertyImportInfo();
-					info.setCourseCode(cp.getCourseCode());
-					info.setCourseName(CacheHelper.getCourse(cp.getCourseId()).getName());
-					info.setPropertyName(cp.getName());
-					info.setFirstPropertyCode(p.getCode());
-					info.setFirstPropertyName(p.getName());
-					ret.add(info);
-					List<Property> secPsList=secPs.get(p.getId());
-					if(!CollectionUtils.isEmpty(secPsList)) {
-						for(Property sec:secPsList) {
-							CoursePropertyImportInfo secinfo=new CoursePropertyImportInfo();
-							secinfo.setCourseCode(cp.getCourseCode());
-							secinfo.setCourseName(CacheHelper.getCourse(cp.getCourseId()).getName());
-							secinfo.setPropertyName(cp.getName());
-							secinfo.setFirstPropertyCode(p.getCode());
-							secinfo.setFirstPropertyName(p.getName());
-							secinfo.setSecondPropertyCode(sec.getCode());
-							secinfo.setSecondPropertyName(sec.getName());
-							ret.add(secinfo);
-						}
-					}
-				}
-			}
-		}
-	}
-
-	@Override
-	public List<CourseProperty> findByOrgIdAndCourseIdAndSourceId(Long rootOrgId, Long courseId, String sourceId) {
-		return coursePropertyRepo.findByOrgIdAndCourseIdAndSourceId( rootOrgId, courseId, sourceId);
-	}
-
-	@Override
-	public List<CourseProperty> findAllByOrgIdCourseCode(Long rootOrgId, String courseCode) {
-		return coursePropertyRepo.findAllByOrgIdAndCourseCode( rootOrgId, courseCode);
-	}
+        List<CoursePropertyImportInfo> ret = new ArrayList<>();
+        if (!CollectionUtils.isEmpty(coursePros)) {
+            for (CourseProperty cp : coursePros) {
+                fillProperty(ret, cp);
+            }
+        }
+        return ret;
+    }
+
+    private void fillProperty(List<CoursePropertyImportInfo> ret, CourseProperty cp) {
+        List<Property> ps = propertyRepo.findByCoursePropertyIdOrderByNumber(cp.getId());
+        if (!CollectionUtils.isEmpty(ps)) {
+            Map<String, List<Property>> secPs = new HashMap<>();
+            for (Property p : ps) {
+                if (!Property.ROOT_PARENT_ID.equals(p.getParentId())) {
+                    List<Property> list = secPs.get(p.getParentId());
+                    if (list == null) {
+                        list = new ArrayList<>();
+                        secPs.put(p.getParentId(), list);
+                    }
+                    list.add(p);
+                }
+            }
+
+            for (Property p : ps) {
+                if (Property.ROOT_PARENT_ID.equals(p.getParentId())) {
+                    CoursePropertyImportInfo info = new CoursePropertyImportInfo();
+                    info.setCourseCode(cp.getCourseCode());
+                    info.setCourseName(CacheHelper.getCourse(cp.getCourseId()).getName());
+                    info.setPropertyName(cp.getName());
+                    info.setFirstPropertyCode(p.getCode());
+                    info.setFirstPropertyName(p.getName());
+                    ret.add(info);
+                    List<Property> secPsList = secPs.get(p.getId());
+                    if (!CollectionUtils.isEmpty(secPsList)) {
+                        for (Property sec : secPsList) {
+                            CoursePropertyImportInfo secinfo = new CoursePropertyImportInfo();
+                            secinfo.setCourseCode(cp.getCourseCode());
+                            secinfo.setCourseName(CacheHelper.getCourse(cp.getCourseId()).getName());
+                            secinfo.setPropertyName(cp.getName());
+                            secinfo.setFirstPropertyCode(p.getCode());
+                            secinfo.setFirstPropertyName(p.getName());
+                            secinfo.setSecondPropertyCode(sec.getCode());
+                            secinfo.setSecondPropertyName(sec.getName());
+                            ret.add(secinfo);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public List<CourseProperty> findByOrgIdAndCourseIdAndSourceId(Long rootOrgId, Long courseId, String sourceId) {
+        return coursePropertyRepo.findByOrgIdAndCourseIdAndSourceId(rootOrgId, courseId, sourceId);
+    }
+
+    @Override
+    public List<CourseProperty> findAllByOrgIdCourseCode(Long rootOrgId, String courseCode) {
+        return coursePropertyRepo.findAllByOrgIdAndCourseCode(rootOrgId, courseCode);
+    }
 
 }