|  | @@ -1,10 +1,17 @@
 | 
	
		
			
				|  |  |  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;
 | 
	
		
			
				|  |  | +import com.mooctest.crowd.site.command.GenerateProjectCommand;
 | 
	
		
			
				|  |  |  import com.mooctest.crowd.site.data.dto.ProjectDetailsDTO;
 | 
	
		
			
				|  |  |  import com.mooctest.crowd.site.data.enums.ProjectType;
 | 
	
		
			
				|  |  |  import com.mooctest.crowd.site.data.vo.CrowdProjectVO;
 | 
	
	
		
			
				|  | @@ -13,8 +20,19 @@ import com.mooctest.crowd.site.mediator.ViewMediator;
 | 
	
		
			
				|  |  |  import com.mooctest.crowd.site.service.CrowdProjectService;
 | 
	
		
			
				|  |  |  import com.mooctest.crowd.site.util.GenerateFlowCodeUtil;
 | 
	
		
			
				|  |  |  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.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
 | 
	
	
		
			
				|  | @@ -34,8 +52,6 @@ public class CrowdProjectServiceImpl implements CrowdProjectService {
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private OperationMediator operationMediator;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    @Autowired
 | 
	
		
			
				|  |  | -    private GenerateFlowCodeUtil codeUtil;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      public ProjectDetailsDTO getProjectDetails(String projectCode) {
 | 
	
	
		
			
				|  | @@ -47,7 +63,7 @@ public class CrowdProjectServiceImpl implements CrowdProjectService {
 | 
	
		
			
				|  |  |          CrowdTestProject project = command.toCrowdProject();
 | 
	
		
			
				|  |  |          project.setStatus(CrowdTestProjectStatus.HAS_CREATED);
 | 
	
		
			
				|  |  |          log.info("\n"+project.toString()+"\n");
 | 
	
		
			
				|  |  | -        String projectCode = codeUtil.generateFlowCode("PROJ-");
 | 
	
		
			
				|  |  | +        String projectCode = GenerateFlowCodeUtil.generateFlowCode("PROJ");
 | 
	
		
			
				|  |  |          project.setCode(projectCode);
 | 
	
		
			
				|  |  |          ProjectDetailsDTO projectDetailsDTO = new ProjectDetailsDTO();
 | 
	
		
			
				|  |  |          projectRepo.saveCrowdTestProject(project);
 | 
	
	
		
			
				|  | @@ -74,4 +90,224 @@ public class CrowdProjectServiceImpl implements CrowdProjectService {
 | 
	
		
			
				|  |  |              throw new BaseException("没有权限");
 | 
	
		
			
				|  |  |          projectRepo.deleteByProjectId(projectId);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public ProjectDetailsDTO generateProjectWithData(GenerateProjectCommand command) {
 | 
	
		
			
				|  |  | +        CrowdTestProject project = command.toCrowdProject();
 | 
	
		
			
				|  |  | +        project.setCode(GenerateFlowCodeUtil.generateProjCode());
 | 
	
		
			
				|  |  | +        List<CrowdTestTask> tasks = new ArrayList<>();
 | 
	
		
			
				|  |  | +        command.getType().forEach(integer -> {
 | 
	
		
			
				|  |  | +            CrowdTestTask task = CrowdTestProjectFactory.defaultFinishedCrowdTask();
 | 
	
		
			
				|  |  | +            task.setType(integer);
 | 
	
		
			
				|  |  | +            task.setCode(GenerateFlowCodeUtil.generateTaskCode(ProjectType.getCode(integer)));
 | 
	
		
			
				|  |  | +            task.setCrowdTestProjectCode(project.getCode());
 | 
	
		
			
				|  |  | +            task.setEndTime(command.getDatetime());
 | 
	
		
			
				|  |  | +            task.setDeadTime(command.getDatetime());
 | 
	
		
			
				|  |  | +            task.setRequirementFile(command.getFile());
 | 
	
		
			
				|  |  | +            task.setName(command.getName()+"-"+ProjectType.getName(integer));
 | 
	
		
			
				|  |  | +            task.setQuotedPrice(command.getPrice()/command.getType().size());
 | 
	
		
			
				|  |  | +            task.setFixedPrice(command.getPrice()/command.getType().size());
 | 
	
		
			
				|  |  | +            tasks.add(task);
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        CrowdTestReport report = command.getReport();
 | 
	
		
			
				|  |  | +        report.setDependencyCode(project.getCode());
 | 
	
		
			
				|  |  | +        report.setCode(GenerateFlowCodeUtil.generateReportCode());
 | 
	
		
			
				|  |  | +        project.setCrowdTestReportForProject(report);
 | 
	
		
			
				|  |  | +        project.setCrowdTestTaskList(tasks);
 | 
	
		
			
				|  |  | +        projectRepo.saveCrowdTestProject(project);
 | 
	
		
			
				|  |  | +        log.info(project.toString());
 | 
	
		
			
				|  |  | +        return getProjectDetails(project.getCode());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public List<ProjectDetailsDTO> importMultiProjectsByExcel(MultipartFile file) {
 | 
	
		
			
				|  |  | +        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();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }
 |