|
@@ -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();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
}
|