wangwei 6 vuotta sitten
vanhempi
commit
2cf5f5f534

+ 86 - 37
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/SpecialtyController.java

@@ -1,17 +1,20 @@
 package cn.com.qmth.examcloud.core.basic.api.controller;
 
-import java.io.IOException;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
 import javax.persistence.criteria.Subquery;
-import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.fileupload.disk.DiskFileItem;
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
@@ -22,7 +25,6 @@ import org.springframework.data.jpa.domain.Specification;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
@@ -33,11 +35,14 @@ import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.commons.CommonsMultipartFile;
 
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 import cn.com.qmth.examcloud.commons.base.exception.StatusException;
-import cn.com.qmth.examcloud.commons.base.util.excel.ExcelError;
+import cn.com.qmth.examcloud.commons.base.helpers.poi.ExcelWriter;
+import cn.com.qmth.examcloud.commons.base.util.PathUtil;
 import cn.com.qmth.examcloud.commons.web.security.bean.User;
 import cn.com.qmth.examcloud.commons.web.support.ControllerSupport;
+import cn.com.qmth.examcloud.commons.web.support.SystemConfig;
 import cn.com.qmth.examcloud.core.basic.api.controller.bean.SpecialtyDomain;
 import cn.com.qmth.examcloud.core.basic.dao.CourseRepo;
 import cn.com.qmth.examcloud.core.basic.dao.CourseSpeciatlyRelationRepo;
@@ -70,6 +75,8 @@ public class SpecialtyController extends ControllerSupport {
 	@Autowired
 	CourseSpeciatlyRelationRepo courseSpeciatlyRelationRepo;
 
+	private static final String[] EXCEL_HEADER = new String[]{"专业名称", "专业代码"};
+
 	/**
 	 * 方法注释
 	 *
@@ -134,14 +141,14 @@ public class SpecialtyController extends ControllerSupport {
 			@RequestParam(required = false) String code,
 			@RequestParam(required = false) Boolean enable,
 			@RequestParam(required = false) Long courseId) {
-		User accessUser = getAccessUser();
 
+		User accessUser = getAccessUser();
 		Long rootOrgId = accessUser.getRootOrgId();
 
 		Specification<SpecialtyEntity> specification = (root, query, cb) -> {
 			List<Predicate> predicates = new ArrayList<>();
 
-			predicates.add(cb.equal(root.get("rootOrgId"), accessUser.getRootOrgId()));
+			predicates.add(cb.equal(root.get("rootOrgId"), rootOrgId));
 
 			if (StringUtils.isNotBlank(name)) {
 				predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
@@ -287,43 +294,85 @@ public class SpecialtyController extends ControllerSupport {
 	}
 
 	@ApiOperation(value = "下载导入模板", notes = "下载导入模板")
-	@GetMapping("downloadTemplate")
+	@GetMapping("importTemplate")
 	public void getDownloadTemplate(HttpServletResponse response) {
-		// List<SpecialtyDto> list = new ArrayList<SpecialtyDto>();
-		// ExportService.exportEXCEL("专业导入模板", SpecialtyDto.class, list,
-		// response);
-
+		String resoucePath = PathUtil.getResoucePath("templates/courseImportTemplate.xlsx");
+		exportFile("课程导入模板.xlsx", new File(resoucePath));
 	}
 
 	@ApiOperation(value = "导入", notes = "导入")
-	@PostMapping("/import")
-	public List<ExcelError> importCourse(HttpServletRequest request,
-			@RequestParam CommonsMultipartFile file) throws IOException {
-		// cn.com.qmth.examcloud.commons.web.security.bean.User accessUser =
-		// getAccessUser();
-		// Long orgId = accessUser.getRootOrgId();
-		//
-		// List<ExcelError> errors = specialtyService.importSpecialty(orgId,
-		// file.getInputStream());
-		// return errors;
-		return null;
+	@PostMapping("import")
+	public Map<String, Object> importSpecialty(@RequestParam CommonsMultipartFile file) {
+		DiskFileItem item = (DiskFileItem) file.getFileItem();
+		File storeLocation = item.getStoreLocation();
+		List<Map<String, Object>> failRecords = specialtyService.importSpecialty(getRootOrgId(),
+				storeLocation);
+		Map<String, Object> map = Maps.newHashMap();
+		map.put("hasError", CollectionUtils.isNotEmpty(failRecords));
+		map.put("failRecords", failRecords);
+		return map;
 	}
 
-	/**
-	 * 导出专业
-	 * 
-	 * @param specialty
-	 * @param response
-	 */
-	@ApiOperation(value = "导出专业", notes = "导出专业")
+	@ApiOperation(value = "导出专业")
 	@GetMapping("export")
-	public void exportSpecialty(@ModelAttribute SpecialtyEntity specialty,
-			HttpServletResponse response) {
-		// List<SpecialtyDto> list = new ArrayList<SpecialtyDto>();
-		// specialtyService.findAll(specialty).forEach(c -> {
-		// list.add(new SpecialtyDto(c));
-		// });
-		// ExportService.exportEXCEL("专业列表", SpecialtyDto.class, list,
-		// response);
+	public void export(@RequestParam(required = false) String name,
+			@RequestParam(required = false) String code,
+			@RequestParam(required = false) Boolean enable,
+			@RequestParam(required = false) Long courseId) {
+		User accessUser = getAccessUser();
+
+		Specification<SpecialtyEntity> specification = (root, query, cb) -> {
+			List<Predicate> predicates = new ArrayList<>();
+
+			predicates.add(cb.equal(root.get("rootOrgId"), accessUser.getRootOrgId()));
+
+			if (StringUtils.isNotBlank(name)) {
+				predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
+			}
+			if (StringUtils.isNotBlank(code)) {
+				predicates.add(cb.like(root.get("code"), toSqlSearchPattern(code)));
+			}
+			if (null != enable) {
+				predicates.add(cb.equal(root.get("enable"), enable));
+			}
+
+			if (null != courseId) {
+				Subquery<CourseSpeciatlyRelationEntity> subquery = query
+						.subquery(CourseSpeciatlyRelationEntity.class);
+				Root<CourseSpeciatlyRelationEntity> subRoot = subquery
+						.from(CourseSpeciatlyRelationEntity.class);
+				subquery.select(subRoot.get("specialtyId"));
+				Predicate p1 = cb.equal(subRoot.get("courseId"), courseId);
+				Predicate p2 = cb.equal(subRoot.get("specialtyId"), root.get("id"));
+				subquery.where(cb.and(p1, p2));
+				predicates.add(cb.exists(subquery));
+			}
+
+			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+		};
+
+		long count = specialtyRepo.count(specification);
+		if (100000 < count) {
+			throw new StatusException("B-620200", "数据量过大,无法导出");
+		}
+
+		List<SpecialtyEntity> list = specialtyRepo.findAll(specification);
+
+		List<Object[]> datas = Lists.newArrayList();
+
+		for (SpecialtyEntity cur : list) {
+			datas.add(new Object[]{cur.getName(), cur.getCode()});
+		}
+
+		String filePath = SystemConfig.getTempDataDir() + File.separator
+				+ System.currentTimeMillis() + ".xlsx";
+		File file = new File(filePath);
+
+		ExcelWriter.write(EXCEL_HEADER, new Class[]{String.class, String.class}, datas,
+				new File(filePath));
+
+		exportFile("专业列表-" + getRootOrgId() + ".xlsx", file);
+
+		FileUtils.deleteQuietly(file);
 	}
 }

+ 14 - 0
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/SpecialtyService.java

@@ -1,5 +1,9 @@
 package cn.com.qmth.examcloud.core.basic.service;
 
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
 import cn.com.qmth.examcloud.core.basic.dao.entity.SpecialtyEntity;
 import cn.com.qmth.examcloud.core.basic.service.bean.SpecialtyInfo;
 
@@ -21,4 +25,14 @@ public interface SpecialtyService {
 	 */
 	SpecialtyEntity saveSpecialty(SpecialtyInfo info);
 
+	/**
+	 * 导入专业
+	 *
+	 * @author WANGWEI
+	 * @param rootOrgId
+	 * @param file
+	 * @return
+	 */
+	public List<Map<String, Object>> importSpecialty(Long rootOrgId, File file);
+
 }

+ 129 - 0
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/SpecialtyServiceImpl.java

@@ -1,10 +1,22 @@
 package cn.com.qmth.examcloud.core.basic.service.impl;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
 import cn.com.qmth.examcloud.commons.base.exception.StatusException;
+import cn.com.qmth.examcloud.commons.base.helpers.poi.ExcelReader;
+import cn.com.qmth.examcloud.commons.base.util.PathUtil;
 import cn.com.qmth.examcloud.core.basic.dao.SpecialtyRepo;
 import cn.com.qmth.examcloud.core.basic.dao.entity.SpecialtyEntity;
 import cn.com.qmth.examcloud.core.basic.service.SpecialtyService;
@@ -16,6 +28,8 @@ public class SpecialtyServiceImpl implements SpecialtyService {
 	@Autowired
 	SpecialtyRepo specialtyRepo;
 
+	private static final String[] EXCEL_HEADER = new String[]{"专业名称", "专业代码"};
+
 	@Override
 	public SpecialtyEntity saveSpecialty(SpecialtyInfo info) {
 		Long id = info.getId();
@@ -65,4 +79,119 @@ public class SpecialtyServiceImpl implements SpecialtyService {
 		return saved;
 	}
 
+	@Override
+	public List<Map<String, Object>> importSpecialty(Long rootOrgId, File file) {
+		List<String[]> lineList = null;
+		try {
+			lineList = ExcelReader.readSheetBySax(PathUtil.getCanonicalPath(file), 1, 3);
+		} catch (Exception e) {
+			throw new StatusException("B-100110", "Excel 解析失败");
+		}
+
+		if (CollectionUtils.isEmpty(lineList)) {
+			throw new StatusException("B-100111", "Excel无内容");
+		}
+
+		if (10001 < lineList.size()) {
+			throw new StatusException("B-100112", "数据行数不能超过10000");
+		}
+
+		List<Map<String, Object>> failRecords = Collections
+				.synchronizedList(new ArrayList<Map<String, Object>>());
+
+		List<SpecialtyEntity> courseList = Lists.newArrayList();
+
+		for (int i = 0; i < lineList.size(); i++) {
+			String[] line = lineList.get(i);
+			if (0 == i) {
+				if (headerError(line)) {
+					throw new StatusException("B-100111", "Excel表头错误");
+				}
+				continue;
+			}
+
+			boolean hasError = false;
+			StringBuilder msg = new StringBuilder();
+
+			SpecialtyEntity couse = new SpecialtyEntity();
+			couse.setRootOrgId(rootOrgId);
+			couse.setEnable(true);
+
+			String name = trimAndNullIfBlank(line[0]);
+			if (StringUtils.isBlank(name)) {
+				msg.append("  课程名称不能为空");
+				hasError = true;
+			} else if (name.length() > 30) {
+				msg.append("  课程名称不能超过30个字符");
+				hasError = true;
+			}
+			couse.setName(name);
+
+			String code = trimAndNullIfBlank(line[1]);
+			if (StringUtils.isBlank(code)) {
+				msg.append("  课程代码不能为空");
+				hasError = true;
+			} else if (code.length() > 30) {
+				msg.append("  课程代码不能超过30个字符");
+				hasError = true;
+			}
+
+			couse.setCode(code);
+
+			if (hasError) {
+				failRecords.add(newError(i + 1, msg.toString()));
+			} else {
+				courseList.add(couse);
+			}
+
+		}
+
+		if (CollectionUtils.isNotEmpty(failRecords)) {
+			return failRecords;
+		}
+
+		for (SpecialtyEntity cur : courseList) {
+			SpecialtyEntity query = specialtyRepo.findByRootOrgIdAndCode(cur.getRootOrgId(),
+					cur.getCode());
+
+			if (null != query) {
+				query.setName(cur.getName());
+				specialtyRepo.save(query);
+			} else {
+				specialtyRepo.save(cur);
+			}
+		}
+
+		return failRecords;
+	}
+
+	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();
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param header
+	 */
+	private boolean headerError(String[] header) {
+		for (int i = 0; i < EXCEL_HEADER.length; i++) {
+			if (!EXCEL_HEADER[i].equals(header[i].trim())) {
+				return true;
+			}
+		}
+		return false;
+	}
+
 }