Browse Source

add: 接口-excel批量生成项目

xuexiaobo 6 years ago
parent
commit
f723b2f151

+ 33 - 0
core/src/main/java/com/mooctest/crowd/domain/exception/Excel2ProjectException.java

@@ -0,0 +1,33 @@
+package com.mooctest.crowd.domain.exception;
+
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author: Diors.Po
+ * @Email: 171256175@qq.com
+ * @date 2019-08-11 22:46
+ */
+@NoArgsConstructor
+public class Excel2ProjectException extends BaseException {
+    private List<String> errorLog;
+
+    public Excel2ProjectException(List<String> errorLog){
+        this.errorLog = errorLog;
+    }
+
+    public Excel2ProjectException(List<String> errorLog, String msg){
+        super(msg);
+        this.errorLog = errorLog;
+    }
+
+    public String getErrorLogs() {
+        String logs = "";
+        for (String s : errorLog){
+            logs += (s+"\n");
+        }
+        return logs;
+    }
+}

+ 22 - 4
core/src/main/java/com/mooctest/crowd/domain/factory/CrowdTestProjectFactory.java

@@ -1,11 +1,11 @@
 package com.mooctest.crowd.domain.factory;
 
-import com.mooctest.crowd.domain.domainobject.CrowdTestProject;
-import com.mooctest.crowd.domain.domainobject.CrowdTestReport;
-import com.mooctest.crowd.domain.domainobject.CrowdTestTask;
-import com.mooctest.crowd.domain.domainobject.CrowdTestTaskStatus;
+import com.mooctest.crowd.domain.domainobject.*;
 import org.springframework.stereotype.Component;
 
+import java.sql.Date;
+import java.sql.Timestamp;
+
 /**
  * @author guochao
  * @date 2019/7/6 21:43
@@ -17,6 +17,24 @@ public class CrowdTestProjectFactory {
         return new CrowdTestProject();
     }
 
+    public static CrowdTestProject defaulstCrowdTestProject() {
+        CrowdTestProject project = new CrowdTestProject();
+        project.setStatus(CrowdTestProjectStatus.HAS_FINISHED);
+        project.setIsDeleted(0);
+        project.setProjectDistributionTypeId(1L);
+        project.setDistributionProvince("江苏");
+        project.setDistributionCity("南京");
+        project.setRegionalManagerId(1L);
+        project.setUserId(1L);
+        project.setProjectFile("");
+        project.setRequirementFile("");
+        project.setFixedPrice(30000.00);
+        project.setQuotedPrice(30000.00);
+        project.setDeadTime(new Timestamp(new Date(System.currentTimeMillis()).getTime()));
+        project.setEndTime(new Timestamp(new Date(System.currentTimeMillis()).getTime()));
+        return project;
+    }
+
     public static CrowdTestTask defaultFinishedCrowdTask() {
         CrowdTestTask task = new CrowdTestTask();
         task.setStatus(CrowdTestTaskStatus.HAS_FINISHED);

+ 10 - 0
site/src/main/java/com/mooctest/crowd/site/constants/CommonConstant.java

@@ -0,0 +1,10 @@
+package com.mooctest.crowd.site.constants;
+
+/**
+ * @author: Diors.Po
+ * @Email: 171256175@qq.com
+ * @date 2019-08-12 00:30
+ */
+public class CommonConstant {
+    public static final Long DEFAULT_REGIONAL_MANAGERID = 1L;
+}

+ 1 - 0
site/src/main/java/com/mooctest/crowd/site/controller/CrowdProjectController.java

@@ -1,5 +1,6 @@
 package com.mooctest.crowd.site.controller;
 
+import com.mooctest.crowd.domain.domainobject.CrowdTestProject;
 import com.mooctest.crowd.domain.exception.BadRequestException;
 import com.mooctest.crowd.domain.exception.BaseException;
 import com.mooctest.crowd.site.command.CrowdTestProjectCommand;

+ 8 - 1
site/src/main/java/com/mooctest/crowd/site/controller/TestController.java

@@ -1,6 +1,7 @@
 package com.mooctest.crowd.site.controller;
 
 import com.mooctest.crowd.site.annotation.LoginRequired;
+import com.mooctest.crowd.site.service.CrowdProjectService;
 import com.mooctest.crowd.site.service.UploadService;
 import com.mooctest.crowd.site.util.FileUtil;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -20,13 +21,18 @@ import java.io.IOException;
 public class TestController {
 
     @Autowired
-    private UploadService uploadService;
+    private CrowdProjectService projectService;
 
     @RequestMapping(value = "/test", method = RequestMethod.POST)
     public Object exceptionTest(MultipartFile file) throws IOException {
         return FileUtil.checkFile(file.getInputStream());
     }
 
+    @RequestMapping(value = "/test/excel", method = RequestMethod.POST)
+    public Object excelTest(MultipartFile file) throws IOException {
+        return projectService.importMultiProjectsByExcel(file);
+    }
+
     @RequestMapping(value = "/session/put", method = RequestMethod.GET)
     public Object sessionTest(HttpServletRequest request) {
         request.getSession().setAttribute("test", 456);
@@ -42,4 +48,5 @@ public class TestController {
     }
 
 
+
 }

+ 8 - 4
site/src/main/java/com/mooctest/crowd/site/controller/advice/ExceptionAdvice.java

@@ -6,10 +6,7 @@ import com.mooctest.crowd.domain.exception.*;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.HttpRequestMethodNotSupportedException;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.bind.annotation.*;
 
 /**
  * @author: Diors.Po
@@ -61,4 +58,11 @@ public class ExceptionAdvice {
         log.error("System Error: "+e.getMessage(), e);
         return "There is a system error: "+e.getMessage();
     }
+
+    @ExceptionHandler(Excel2ProjectException.class)
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public String handleExcel2ProjectException(Excel2ProjectException e){
+        log.error("Excel表中存在错误:"+e.getErrorLogs());
+        return e.getErrorLogs();
+    }
 }

+ 197 - 6
site/src/main/java/com/mooctest/crowd/site/service/impl/CrowdProjectServiceImpl.java

@@ -1,10 +1,13 @@
 package com.mooctest.crowd.site.service.impl;
 
+import com.alibaba.fastjson.JSONArray;
 import com.mooctest.crowd.domain.domainobject.CrowdTestProject;
 import com.mooctest.crowd.domain.domainobject.CrowdTestProjectStatus;
 import com.mooctest.crowd.domain.domainobject.CrowdTestReport;
 import com.mooctest.crowd.domain.domainobject.CrowdTestTask;
+import com.mooctest.crowd.domain.exception.BadRequestException;
 import com.mooctest.crowd.domain.exception.BaseException;
+import com.mooctest.crowd.domain.exception.Excel2ProjectException;
 import com.mooctest.crowd.domain.factory.CrowdTestProjectFactory;
 import com.mooctest.crowd.domain.repository.CrowdTestProjectRepo;
 import com.mooctest.crowd.site.command.CrowdTestProjectCommand;
@@ -15,16 +18,21 @@ import com.mooctest.crowd.site.data.vo.CrowdProjectVO;
 import com.mooctest.crowd.site.mediator.OperationMediator;
 import com.mooctest.crowd.site.mediator.ViewMediator;
 import com.mooctest.crowd.site.service.CrowdProjectService;
-import com.mooctest.crowd.site.util.FileUtil;
 import com.mooctest.crowd.site.util.GenerateFlowCodeUtil;
-import com.sun.deploy.util.GeneralUtil;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
 
 /**
  * @author: Diors.Po
@@ -114,8 +122,191 @@ public class CrowdProjectServiceImpl implements CrowdProjectService {
 
     @Override
     public List<ProjectDetailsDTO> importMultiProjectsByExcel(MultipartFile file) {
-        List<CrowdTestProject> projects = FileUtil.importExcel(file, 0, 1, CrowdTestProject.class);
-        return null;
+        List<ProjectDetailsDTO> dtos = new ArrayList<>();
+        List<CrowdTestProject> projects = transferExcel2Projects(file);
+        projects.forEach(project -> {
+            project.setCode(GenerateFlowCodeUtil.generateProjCode());
+            List<CrowdTestTask> tasks = new ArrayList<>();
+            CrowdTestTask task = CrowdTestProjectFactory.defaultFinishedCrowdTask();
+            task.setType(((List<Integer>) JSONArray.parse(project.getType())).get(0));
+            task.setCode(GenerateFlowCodeUtil.generateTaskCode(ProjectType.getCode(task.getType())));
+            task.setCrowdTestProjectCode(project.getCode());
+            task.setEndTime(project.getEndTime());
+            task.setDeadTime(project.getDeadTime());
+            task.setRequirementFile(project.getRequirementFile());
+            task.setName(project.getName()+"-"+ProjectType.getName(task.getType()));
+            task.setQuotedPrice(project.getQuotedPrice());
+            task.setFixedPrice(project.getFixedPrice());
+            tasks.add(task);
+            project.setCrowdTestTaskList(tasks);
+            projectRepo.saveCrowdTestProject(project);
+            dtos.add(getProjectDetails(project.getCode()));
+        });
+        return dtos;
+    }
+
+    private List<CrowdTestProject> transferExcel2Projects(MultipartFile file){
+        List<String> logList = new ArrayList<>();
+        List<CrowdTestProject> projects = new ArrayList<>();
+        Workbook workbook = null;
+        try {
+            if (file.getOriginalFilename().endsWith("xlsx"))
+                workbook = new XSSFWorkbook(file.getInputStream());
+            else if (file.getOriginalFilename().endsWith("xls"))
+                workbook = new HSSFWorkbook(file.getInputStream());
+            else
+                throw new BadRequestException("不是合法的Excel文件");
+        } catch (IOException e) {
+            throw new BaseException("Excel读取出错,无法生成workbook");
+        }
+        Sheet sheet = workbook.getSheetAt(0);
+        if (sheet == null)
+            throw new BadRequestException("找不到标签页");
+        if (sheet.getPhysicalNumberOfRows() < 2)
+            throw new BadRequestException("数据内容为空,请重新编辑");
+
+        Row keyRow = sheet.getRow(0);
+        int cellCount = keyRow.getPhysicalNumberOfCells();
+        log.info("CellCount: "+cellCount);
+        log.info("Rows: " + sheet.getPhysicalNumberOfRows());
+        for (int i = 1; i < sheet.getPhysicalNumberOfRows(); i++ ){
+            CrowdTestProject project = CrowdTestProjectFactory.defaulstCrowdTestProject();
+            Row row = sheet.getRow(i);
+            if (row == null){
+                logList.add("表中存在错误的单元格,请把与内容无关的单元格置空");
+                break;
+            }
+            for (int j = 0; j < cellCount; j++){
+                Cell cell = row.getCell(j);
+                if (cell == null ) {
+                    logList.add("错误 - 行: " + (i + 1) + "; 列: " + (j + 1) + "; 原因: " + "单元格为空");
+                    log.error("错误 - 行: " + (i + 1) + "; 列: " + (j + 1) + "; 原因: " + "单元格为空");
+                    continue;
+                }
+                cell.setCellType(CellType.STRING);
+                log.info("ROW: "+i+", COL: "+j +", DATA: "+ cell.getStringCellValue());
+                if (cell.getStringCellValue().trim().equals("")){
+                    logList.add("错误 - 行: " + (i + 1) + "; 列: " + (j + 1) + "; 原因: " + "单元格为空");
+                    continue;
+                }
+                switch (j){
+                    case 0:
+                        project.setName(cell.getStringCellValue().trim());
+                        break;
+                    case 1:
+                        if(!isPlatform(cell.getStringCellValue())){
+                            logList.add("错误 - 行: " + (i + 1) + "; 列: " + (j + 1) + "; 原因: " + "测试平台数据不合法:"+cell.getStringCellValue());
+                            break;
+                        }
+                        project.setPlatform("["+cell.getStringCellValue().trim()+"]");
+                        break;
+                    case 2:
+                        project.setLinkMan(cell.getStringCellValue().trim());
+                        break;
+                    case 3:
+                        if (!isRightPhone(cell.getStringCellValue().trim())){
+                            logList.add("错误 - 行: " + (i + 1) + "; 列: " + (j + 1) + "; 原因: " + "不合法的手机号码:"+cell.getStringCellValue());
+                            break;
+                        }
+                        project.setLinkManMobile(cell.getStringCellValue().trim());
+                        break;
+                    case 4:
+                        if (!isType(cell.getStringCellValue().trim())){
+                            logList.add("错误 - 行: " + (i + 1) + "; 列: " + (j + 1) + "; 原因: " + "错误的测试服务类型:"+cell.getStringCellValue());
+                            break;
+                        }
+                        project.setType("["+cell.getStringCellValue().trim()+"]");
+                        break;
+                    case 5:
+                        project.setDescription(cell.getStringCellValue().trim());
+                        break;
+                    case 6:
+                        project.setFixedPrice(Double.parseDouble(cell.getStringCellValue().trim()));
+                        break;
+                }
+            }
+            project.setQuotedPrice(project.getFixedPrice());
+            projects.add(project);
+        }
+        projects.forEach(project -> {
+            log.info(project.toString());
+        });
+        if (logList.size()>0)
+            throw new Excel2ProjectException(logList);
+        return projects;
+    }
+
+    /**
+     * 匹配平台类型 0,1,2 任意  ^[0-2](([,][0-2])?([,][0-2])?)$
+     */
+    private boolean isPlatform(String str)throws PatternSyntaxException {
+        String regExp = "^[0-2](([,][0-2])?([,][0-2])?)$";
+        Pattern p = Pattern.compile(regExp);
+        Matcher m = p.matcher(str);
+        return m.matches();
+    }
+
+    /**
+     * 匹配项目类型 0,1,2,3,4,5,6 任意  ^[0-6](([,][0-6])?([,][0-6])?([,][0-6])?([,][0-6])?([,][0-6])?([,][0-6])?)$
+     */
+    private boolean isType(String str)throws PatternSyntaxException {
+        String regExp = "^[0-6](([,][0-6])?([,][0-6])?([,][0-6])?([,][0-6])?([,][0-6])?([,][0-6])?)$";
+        Pattern p = Pattern.compile(regExp);
+        Matcher m = p.matcher(str);
+        return m.matches();
+    }
+
+    /**
+     * 判断手机号或者座机是正确
+     * @param phone
+     * @return
+     */
+    private boolean isRightPhone(String phone){
+        if(phone.startsWith("0")){
+            if(!isTel(phone)){
+                return false;
+            }
+        }else{
+            if(!(isChinaPhoneLegal(phone) || isHKPhoneLegal(phone))){
+                return false;
+            }
+        }
+        return true;
+    }
+    /**
+     * 大陆手机号码11位数,匹配格式:前三位固定格式+后8位任意数
+     * 此方法中前三位格式有:
+     * 13+任意数
+     * 15+除4的任意数
+     * 18+除1和4的任意数
+     * 17+除9的任意数
+     * 147
+     */
+    private boolean isChinaPhoneLegal(String str) throws PatternSyntaxException {
+        String regExp = "^((13[0-9])|(15[^4])|(18[0,2,3,5-9])|(17[0-8])|(147))\\d{8}$";
+        Pattern p = Pattern.compile(regExp);
+        Matcher m = p.matcher(str);
+        return m.matches();
+    }
+
+    /**
+     * 香港手机号码8位数,5|6|8|9开头+7位任意数
+     */
+    private boolean isHKPhoneLegal(String str)throws PatternSyntaxException {
+        String regExp = "^(5|6|8|9)\\d{7}$";
+        Pattern p = Pattern.compile(regExp);
+        Matcher m = p.matcher(str);
+        return m.matches();
+    }
+
+    /**
+     * 座机号
+     */
+    private boolean isTel(String str)throws PatternSyntaxException {
+        String regExp = "^0[1-9](\\d{1,2}\\-?)\\d{7,8}";
+        Pattern p = Pattern.compile(regExp);
+        Matcher m = p.matcher(str);
+        return m.matches();
     }