From c9e6f781fae7585b9c42d52c080c6be01a500c77 Mon Sep 17 00:00:00 2001 From: guoqibing Date: Mon, 3 Nov 2025 11:42:38 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E6=88=B7=E9=9C=80=E6=B1=82=E7=9C=8B?= =?UTF-8?q?=E6=9D=BF=EF=BC=8C=E5=85=A8=E5=B1=80=E6=90=9C=E7=B4=A2=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sa/zentao/conf/AfterRunner.java | 150 +++++- .../com/sa/zentao/conf/Base64ImageSaver.java | 75 +++ .../zentao/controller/CommonsController.java | 6 + .../zentao/controller/ZtStoryController.java | 8 + .../controller/ZtStoryUserController.java | 12 +- .../java/com/sa/zentao/dao/SearchDTO.java | 35 ++ .../java/com/sa/zentao/dao/UploadDTO.java | 3 +- .../com/sa/zentao/dao/ZtAllBusinessDTO.java | 2 +- .../com/sa/zentao/dao/ZtStoryUserTaskDTO.java | 4 + .../com/sa/zentao/entity/ZtStoryUserTask.java | 4 + .../com/sa/zentao/mapper/ZtStoryMapper.java | 22 + src/main/java/com/sa/zentao/qo/SearchQo.java | 18 + .../sa/zentao/service/IZtStoryService.java | 5 + .../zentao/service/IZtStoryUserService.java | 3 + .../zentao/service/impl/IZtCountService.java | 41 +- .../service/impl/ZtProductServiceImpl.java | 18 +- .../service/impl/ZtStoryServiceImpl.java | 465 +++++++++++------- .../service/impl/ZtStoryUserServiceImpl.java | 30 ++ .../impl/ZtStoryUserTaskServiceImpl.java | 19 +- .../service/impl/ZtTaskServiceImpl.java | 22 - src/main/resources/application-dev.yml | 3 +- src/main/resources/application-local.yml | 1 + src/main/resources/application.yml | 6 +- src/main/resources/mapper/ZtStoryMapper.xml | 64 +++ .../resources/templates/scope/测试工程师.xlsx | Bin 11892 -> 11911 bytes 25 files changed, 767 insertions(+), 249 deletions(-) create mode 100644 src/main/java/com/sa/zentao/conf/Base64ImageSaver.java create mode 100644 src/main/java/com/sa/zentao/dao/SearchDTO.java create mode 100644 src/main/java/com/sa/zentao/qo/SearchQo.java diff --git a/src/main/java/com/sa/zentao/conf/AfterRunner.java b/src/main/java/com/sa/zentao/conf/AfterRunner.java index 1598661..ba8c0b7 100644 --- a/src/main/java/com/sa/zentao/conf/AfterRunner.java +++ b/src/main/java/com/sa/zentao/conf/AfterRunner.java @@ -2,21 +2,29 @@ package com.sa.zentao.conf; //import com.dritec.FastDFSClient; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.sa.zentao.dao.BusinessException; import com.sa.zentao.dao.ZtProjectDTO; import com.sa.zentao.entity.*; import com.sa.zentao.service.*; import com.sa.zentao.task.SpringTaskJob; +import com.sa.zentao.utils.DateUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.List; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Component @Order(value = 1) @@ -33,19 +41,149 @@ public class AfterRunner implements ApplicationRunner { @Autowired private IZtYwTaskService ywTaskService; + @Autowired + private IZtStoryService ztStoryService; + @Autowired + private IZtStoryUserService ztStoryUserService; + @Autowired + private IZtStoryspecService ztStoryspecService; + @Autowired + private IZtStoryFeedbackService ztStoryFeedbackService; + @Autowired + private IZtTaskService ztTaskService; + @Autowired + private IZtBugService ztBugService; + @Autowired + private IZtStoryUserspecService ztStoryUserSpecService; + @Value("${file.baseUrl}") + String baseUrl; + @Autowired + private Base64ImageSaver base64ImageSaver; @Override public void run(ApplicationArguments args) throws Exception { + //初始化假期 festivalConfigService.initfestivalAndHoliday(); springTaskJob.dkEveryDay(); new Thread(new DevopsRunner()).start(); - -// ywTaskService.remindMail();; - - +// handStory(); +// handUserStory(); +// handStoryFeedback(); +// handTask(); +// handBug(); } + private void handStory(){ +// ZtStory byId = this.ztStoryService.getById(6493); +// LambdaQueryWrapper lambda = new QueryWrapper().lambda(); +// lambda.eq(ZtStoryspec::getStory,6493); + List list = ztStoryspecService.list(); + for (ZtStoryspec ztStoryspec : list) { + if(!StringUtils.isEmpty(ztStoryspec.getSpec())){ + System.out.println(ztStoryspec); + System.out.println(ztStoryspec); +// 正则表达式匹配Base64图片 + String pattern = ""; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(ztStoryspec.getSpec()); + String s = base64ImageSaver.saveBase64Images(ztStoryspec.getSpec()); + ztStoryspec.setSpec(s); + LambdaUpdateWrapper lambda1 = new UpdateWrapper().lambda(); + lambda1.set(ZtStoryspec::getSpec,s); + lambda1.eq(ZtStoryspec::getStory,ztStoryspec.getStory()); + ztStoryspecService.update(lambda1); + System.out.println("" + s + ""); + } + } + } + + private void handUserStory(){ +// ZtStory byId = this.ztStoryService.getById(6493); +// LambdaQueryWrapper lambda = new QueryWrapper().lambda(); +// lambda.eq(ZtStoryspec::getStory,6493); + List list = ztStoryUserSpecService.list(); + for (ZtStoryUserspec ztStoryspec : list) { + if(!StringUtils.isEmpty(ztStoryspec.getSpec())){ + System.out.println(ztStoryspec); + System.out.println(ztStoryspec); +// 正则表达式匹配Base64图片 + String pattern = ""; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(ztStoryspec.getSpec()); + String s = base64ImageSaver.saveBase64Images(ztStoryspec.getSpec()); + ztStoryspec.setSpec(s); + LambdaUpdateWrapper lambda1 = new UpdateWrapper().lambda(); + lambda1.set(ZtStoryUserspec::getSpec,s); + lambda1.eq(ZtStoryUserspec::getStory,ztStoryspec.getStory()); + ztStoryUserSpecService.update(lambda1); + System.out.println("" + s + ""); + } + } + } + + private void handStoryFeedback(){ +// ZtStory byId = this.ztStoryService.getById(6493); +// LambdaQueryWrapper lambda = new QueryWrapper().lambda(); +// lambda.eq(ZtStoryspec::getStory,6493); + List list = ztStoryFeedbackService.list(); + for (ZtStoryFeedback ztStoryspec : list) { + if(!StringUtils.isEmpty(ztStoryspec.getRemark())){ + System.out.println(ztStoryspec); + System.out.println(ztStoryspec); +// 正则表达式匹配Base64图片 + String pattern = ""; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(ztStoryspec.getRemark()); + String s = base64ImageSaver.saveBase64Images(ztStoryspec.getRemark()); + ztStoryspec.setRemark(s); + ztStoryFeedbackService.updateById(ztStoryspec); + System.out.println("" + s + ""); + } + } + } + + public void handTask(){ + // ZtStory byId = this.ztStoryService.getById(6493); +// LambdaQueryWrapper lambda = new QueryWrapper().lambda(); +// lambda.eq(ZtStoryspec::getStory,6493); + List list = ztTaskService.list(); + for (ZtTask ztStoryspec : list) { + if(!StringUtils.isEmpty(ztStoryspec.getDesc())){ + System.out.println(ztStoryspec); + System.out.println(ztStoryspec); +// 正则表达式匹配Base64图片 + String pattern = ""; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(ztStoryspec.getDesc()); + String s = base64ImageSaver.saveBase64Images(ztStoryspec.getDesc()); + ztStoryspec.setDesc(s); + ztTaskService.updateById(ztStoryspec); + System.out.println("" + s + ""); + } + } + } + + public void handBug(){ + // ZtStory byId = this.ztStoryService.getById(6493); +// LambdaQueryWrapper lambda = new QueryWrapper().lambda(); +// lambda.eq(ZtStoryspec::getStory,6493); + List list = Arrays.asList(ztBugService.getById(287)); + for (ZtBug ztStoryspec : list) { + if(!StringUtils.isEmpty(ztStoryspec.getSteps())){ + System.out.println(ztStoryspec); + System.out.println(ztStoryspec); +// 正则表达式匹配Base64图片 + String pattern = ""; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(ztStoryspec.getSteps()); + String s = base64ImageSaver.saveBase64Images(ztStoryspec.getSteps()); + ztStoryspec.setSteps(s); + ztBugService.updateById(ztStoryspec); + System.out.println("" + s + ""); + } + } + } } \ No newline at end of file diff --git a/src/main/java/com/sa/zentao/conf/Base64ImageSaver.java b/src/main/java/com/sa/zentao/conf/Base64ImageSaver.java new file mode 100644 index 0000000..1761b9b --- /dev/null +++ b/src/main/java/com/sa/zentao/conf/Base64ImageSaver.java @@ -0,0 +1,75 @@ +package com.sa.zentao.conf; + +import com.sa.zentao.utils.DateUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.util.Base64; +import java.util.Date; +import java.util.UUID; +import java.util.regex.*; + +@Component +public class Base64ImageSaver { + @Value("${file.path.windows}") + private String windowsFilePath; + @Value("${file.path.linux}") + private String linuxFilePath; + @Value("${file.baseUrl}") + private String baseUrl; + // 正则表达式匹配Base64图片 + private static final String IMG_PATTERN = ""; + + /** + * 从HTML内容中提取并保存Base64图片 + * @param htmlContent 包含Base64图片的HTML文本 + * @param outputDir 输出目录路径 + * @return 保存成功的图片数量 + */ + public String saveBase64Images(String htmlContent) { + Pattern pattern = Pattern.compile(IMG_PATTERN); + Matcher m = pattern.matcher(htmlContent); + int counter = 0; + + StringBuffer sb = new StringBuffer(); + while (m.find()) { + String imageType = m.group(1); // 图片类型(png/jpeg等) + String base64Data = m.group(2); // Base64数据 + + try { + // 解码Base64数据 + byte[] imageBytes = Base64.getDecoder().decode(base64Data); + String fName= DateUtils.formatDate(new Date(),"yyyyMMddHHmmss")+ UUID.randomUUID().toString().replaceAll("-","")+ "." + imageType; + + // 生成输出文件名 + String os = System.getProperty("os.name"); + if (os.toLowerCase().startsWith("win")) { //如果是Windows系统 + os=windowsFilePath +"\\"; + }else{ //linux和mac系统 + os=linuxFilePath+"/"; + } + + // 写入文件 + try (FileOutputStream fos = new FileOutputStream(os+fName)) { + fos.write(imageBytes); + } + + + // 替换为网络URL路径 + String replacement = ""; + m.appendReplacement(sb, replacement); + counter++; + + + System.out.println("图片保存成功: " + os+fName); + } catch (IOException e) { + System.err.println("保存图片失败: " + e.getMessage()); + } + } + m.appendTail(sb); + System.out.println(": " + sb.toString()); + return sb.toString(); + } + +} diff --git a/src/main/java/com/sa/zentao/controller/CommonsController.java b/src/main/java/com/sa/zentao/controller/CommonsController.java index 832a624..bc5c80c 100644 --- a/src/main/java/com/sa/zentao/controller/CommonsController.java +++ b/src/main/java/com/sa/zentao/controller/CommonsController.java @@ -33,6 +33,11 @@ import java.util.stream.Collectors; @RequestMapping("/common") public class CommonsController { + @PostMapping("/test") + public Result test( UploadDTO file){ + System.out.println(file); + return Result.success(); + } // @PostMapping("/upload") // public Result upload(@RequestParam("file") MultipartFile file){ @@ -67,6 +72,7 @@ public class CommonsController { if (file.getFile().isEmpty()) { return Result.fail(Code.FAIL); } + try { // 获取文件名 String fName = file.getFile().getOriginalFilename(); diff --git a/src/main/java/com/sa/zentao/controller/ZtStoryController.java b/src/main/java/com/sa/zentao/controller/ZtStoryController.java index a1ecf43..0a77009 100644 --- a/src/main/java/com/sa/zentao/controller/ZtStoryController.java +++ b/src/main/java/com/sa/zentao/controller/ZtStoryController.java @@ -6,6 +6,7 @@ import com.github.pagehelper.PageInfo; import com.sa.zentao.dao.*; import com.sa.zentao.entity.ZtProject; import com.sa.zentao.entity.ZtProjectproduct; +import com.sa.zentao.qo.SearchQo; import com.sa.zentao.qo.ZtProjectQo; import com.sa.zentao.service.IZtProjectproductService; import com.sa.zentao.service.IZtStoryService; @@ -185,6 +186,13 @@ public class ZtStoryController { return Result.success(list); } + //全局搜索 bug 需求 任务 问题反馈等 + @RequestMapping(value = "/searchByName", method = RequestMethod.POST, produces = "application/json; charset=UTF-8") + public Result searchByName(@RequestBody SearchQo qo){ + PageInfo searchDTOPageInfo = ztStoryService.searchByName(qo); + return Result.success(searchDTOPageInfo); + } + //迭代列表根据项目id diff --git a/src/main/java/com/sa/zentao/controller/ZtStoryUserController.java b/src/main/java/com/sa/zentao/controller/ZtStoryUserController.java index c0c058a..6eb4840 100644 --- a/src/main/java/com/sa/zentao/controller/ZtStoryUserController.java +++ b/src/main/java/com/sa/zentao/controller/ZtStoryUserController.java @@ -17,11 +17,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; - -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.Arrays; import java.util.List; @@ -63,6 +59,10 @@ public class ZtStoryUserController { storyUserService.addStory(dto); return Result.success(); } + @RequestMapping(value = "/getKanban", method = RequestMethod.POST, produces = "application/json; charset=UTF-8") + public Result getKanban(@RequestParam(name = "productId",required = true) Integer productId){ + return Result.success(storyUserService.getKanban(productId)); + } @RequestMapping(value = "/editStory", method = RequestMethod.POST, produces = "application/json; charset=UTF-8") public Result editStory(@RequestBody ZtStoryUserDTO dto){ @@ -88,7 +88,7 @@ public class ZtStoryUserController { if(CollectionUtils.isEmpty( qo.getStatusList())){ eq.notIn(ZtStoryUser::getStatus,UserStoryEnums.CLOSED.getCode()); }else { - eq.in(ZtStoryUser::getStatus, UserStoryEnums.CFM.getCode(),UserStoryEnums.KFZ.getCode()); + eq.in(ZtStoryUser::getStatus, UserStoryEnums.JH.getCode(),UserStoryEnums.CFM.getCode(),UserStoryEnums.KFZ.getCode()); } eq.select(ZtStoryUser::getId,ZtStoryUser::getTitle,ZtStoryUser::getProduct, ZtStoryUser::getOpenedby,ZtStoryUser::getAssignedto,ZtStoryUser::getYsUser diff --git a/src/main/java/com/sa/zentao/dao/SearchDTO.java b/src/main/java/com/sa/zentao/dao/SearchDTO.java new file mode 100644 index 0000000..4b8f09d --- /dev/null +++ b/src/main/java/com/sa/zentao/dao/SearchDTO.java @@ -0,0 +1,35 @@ +package com.sa.zentao.dao; + + +import lombok.Data; + +import java.util.Date; + +@Data +public class SearchDTO { + + /** + * id + */ + private Integer id; + /** + * 1 用户需求 2研发需求 3 任务 4 问题反馈 5 bug + */ + private Integer type; + /** + * 标题 + */ + private String name; + /** + * 描述 + */ + private String spec; + /** + * 验收标准 + */ + private String verify; + /** + * 创建日期 + */ + private Date openedDate; +} diff --git a/src/main/java/com/sa/zentao/dao/UploadDTO.java b/src/main/java/com/sa/zentao/dao/UploadDTO.java index 41a33b3..4cf659b 100644 --- a/src/main/java/com/sa/zentao/dao/UploadDTO.java +++ b/src/main/java/com/sa/zentao/dao/UploadDTO.java @@ -6,6 +6,7 @@ import lombok.EqualsAndHashCode; import org.springframework.web.multipart.MultipartFile; import java.io.Serializable; +import java.util.List; @Data @EqualsAndHashCode(callSuper = false) @@ -25,6 +26,6 @@ public class UploadDTO implements Serializable { private Integer objectId; - + private List testIds; } diff --git a/src/main/java/com/sa/zentao/dao/ZtAllBusinessDTO.java b/src/main/java/com/sa/zentao/dao/ZtAllBusinessDTO.java index 8d816a4..69f394e 100644 --- a/src/main/java/com/sa/zentao/dao/ZtAllBusinessDTO.java +++ b/src/main/java/com/sa/zentao/dao/ZtAllBusinessDTO.java @@ -29,7 +29,7 @@ public class ZtAllBusinessDTO implements Serializable { private Integer bugId; - // story task bug userStory + // story task bug userStory feedback private String searchType; private String searchId; } diff --git a/src/main/java/com/sa/zentao/dao/ZtStoryUserTaskDTO.java b/src/main/java/com/sa/zentao/dao/ZtStoryUserTaskDTO.java index c5672aa..9246380 100644 --- a/src/main/java/com/sa/zentao/dao/ZtStoryUserTaskDTO.java +++ b/src/main/java/com/sa/zentao/dao/ZtStoryUserTaskDTO.java @@ -120,4 +120,8 @@ public class ZtStoryUserTaskDTO implements Serializable { private String status; private String desc; + /** + * 交付物 + */ + private String deliverContent; } diff --git a/src/main/java/com/sa/zentao/entity/ZtStoryUserTask.java b/src/main/java/com/sa/zentao/entity/ZtStoryUserTask.java index 5abf992..fee2332 100644 --- a/src/main/java/com/sa/zentao/entity/ZtStoryUserTask.java +++ b/src/main/java/com/sa/zentao/entity/ZtStoryUserTask.java @@ -114,4 +114,8 @@ public class ZtStoryUserTask implements Serializable { //wait 未开始 doing 进行中 finished 完成 cancel取消 closed @TableField("`status`") private String status; + /** + * 交付物 + */ + private String deliverContent; } diff --git a/src/main/java/com/sa/zentao/mapper/ZtStoryMapper.java b/src/main/java/com/sa/zentao/mapper/ZtStoryMapper.java index 1b15264..8b0ab39 100644 --- a/src/main/java/com/sa/zentao/mapper/ZtStoryMapper.java +++ b/src/main/java/com/sa/zentao/mapper/ZtStoryMapper.java @@ -1,6 +1,7 @@ package com.sa.zentao.mapper; import com.baomidou.dynamic.datasource.annotation.DS; +import com.sa.zentao.dao.SearchDTO; import com.sa.zentao.dao.ZtStoryDTO; import com.sa.zentao.entity.ZtStory; import com.baomidou.mybatisplus.core.mapper.BaseMapper; @@ -37,4 +38,25 @@ public interface ZtStoryMapper extends BaseMapper { //pids 产品id List getStoryListByDatePidsProject(@Param("ids")List pids, @Param("project")Integer project , @Param("start")Date firstDayOfMonth, @Param("end")Date lastDayOfMonth); + + List searchBug(@Param("keyword") String keyword); + + List searchTask(@Param("keyword") String keyword); + + List searchStory(@Param("keyword") String keyword); + + List searchFeedback(@Param("keyword") String keyword); + + /** + * + * @param keyword 搜索内容 + * @return + */ + List searchUserStory(@Param("keyword") String keyword); + /** + * + * @param keyword 搜索内容 + * @return + */ + List searchAll(@Param("keyword") String keyword,@Param("pIds")List pIds); } diff --git a/src/main/java/com/sa/zentao/qo/SearchQo.java b/src/main/java/com/sa/zentao/qo/SearchQo.java new file mode 100644 index 0000000..78f398a --- /dev/null +++ b/src/main/java/com/sa/zentao/qo/SearchQo.java @@ -0,0 +1,18 @@ +package com.sa.zentao.qo; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = false) +public class SearchQo extends BaseQo { + /** + * 搜索项 + */ + private String keyword; + + /** + * 搜索类型 1 用户需求 2研发需求 3 任务 4 问题反馈 5 bug + */ + private String searchType; +} diff --git a/src/main/java/com/sa/zentao/service/IZtStoryService.java b/src/main/java/com/sa/zentao/service/IZtStoryService.java index 86a7393..010a171 100644 --- a/src/main/java/com/sa/zentao/service/IZtStoryService.java +++ b/src/main/java/com/sa/zentao/service/IZtStoryService.java @@ -1,6 +1,7 @@ package com.sa.zentao.service; import com.github.pagehelper.PageInfo; +import com.sa.zentao.dao.SearchDTO; import com.sa.zentao.dao.ZtStoryCaseDTO; import com.sa.zentao.dao.ZtStoryDTO; import com.sa.zentao.dao.ZtStoryUserDTO; @@ -9,6 +10,7 @@ import com.sa.zentao.entity.ZtStory; import com.baomidou.mybatisplus.extension.service.IService; import com.sa.zentao.entity.ZtStoryCase; import com.sa.zentao.enums.TaskType; +import com.sa.zentao.qo.SearchQo; import com.sa.zentao.qo.ZtProjectQo; import org.apache.ibatis.annotations.Param; @@ -50,6 +52,7 @@ public interface IZtStoryService extends IService { PageInfo projectStoryPageList(ZtProjectQo qo); List storyNoSyncProject(ZtProjectQo qo); + //未开始 void waitStory(Integer story); void startStory(Integer story); @@ -100,4 +103,6 @@ public interface IZtStoryService extends IService { public Map getStoryCaseMap(List list); List getStoryListByDatePidsProject(List pids, Integer id, Date firstDayOfMonth, Date lastDayOfMonth); + + PageInfo searchByName(SearchQo qo); } diff --git a/src/main/java/com/sa/zentao/service/IZtStoryUserService.java b/src/main/java/com/sa/zentao/service/IZtStoryUserService.java index d871962..8974572 100644 --- a/src/main/java/com/sa/zentao/service/IZtStoryUserService.java +++ b/src/main/java/com/sa/zentao/service/IZtStoryUserService.java @@ -11,6 +11,7 @@ import com.sa.zentao.qo.StoryQo; import com.sa.zentao.qo.ZtProjectQo; import java.util.List; +import java.util.Map; /** *

@@ -26,6 +27,8 @@ public interface IZtStoryUserService extends IService { public void editStory(ZtStoryUserDTO dto); + public Map> getKanban(Integer productId); + PageInfo pageList(StoryQo dto); void changeStatus(ZtStoryUserDTO dto); diff --git a/src/main/java/com/sa/zentao/service/impl/IZtCountService.java b/src/main/java/com/sa/zentao/service/impl/IZtCountService.java index 5999952..33e261a 100644 --- a/src/main/java/com/sa/zentao/service/impl/IZtCountService.java +++ b/src/main/java/com/sa/zentao/service/impl/IZtCountService.java @@ -190,7 +190,7 @@ public class IZtCountService { return new ZtStoryCountDTO(); } String name = loginRiskUser.getName(); - if (userType == UserType.GSGC) { + if (userType == UserType.GSGC || userType == UserType.XMZL) { List list = null; List ztStory = null; @@ -208,19 +208,6 @@ public class IZtCountService { list = new ArrayList<>(); ztStory = new ArrayList<>(); } -// } else { -// list = this.storyUserService.list(new QueryWrapper().lambda().in(ZtStoryUser::getStatus, "active", "reviewing", "active", "unconfirmed", "waitcommunicate", "waitdesign", "designdoing", "designdone", "storyunconfirmed", "confirmed")); -// -// if (CollectionUtils.isEmpty(list)) { -// ztStory = new ArrayList<>(); -// } else { -// ztStory = storyService.list(new QueryWrapper() -// .lambda().eq(ZtStory::getDeleted, "0") -// .ne(ZtStory::getStatus, "closed") -// ); -// } -// } - List products = this.productService.list(new QueryWrapper().lambda().eq(ZtProduct::getStatus, "normal").in(ZtProduct::getId, pIds)); if (!CollectionUtils.isEmpty(products)) { @@ -405,11 +392,6 @@ public class IZtCountService { .lambda().eq(ZtStory::getDeleted, "0") .ne(ZtStory::getStatus, "closed"); - -// .in(ZtStory::getProduct,integers) -// .or() -// .in() - //所有的产品 eq.in(ZtStory::getProduct, pIds); List ztStory = this.storyService.list(eq); @@ -421,8 +403,12 @@ public class IZtCountService { Arrays.asList("active", "unconfirmed", "waitcommunicate", "waitdesign", "designdoing", "designdone", "storyunconfirmed", "confirmed").contains(o.getStatus())) .map(o -> o.getId() + "").collect(Collectors.joining(","))); - result.setPlanCount(ztStory.stream().filter(o -> "active".equals(o.getStatus())) - .filter(o -> o.getStage().equals("wait")).map(o -> o.getId() + "").collect(Collectors.joining(","))); +// result.setPlanCount(ztStory.stream().filter(o -> "active".equals(o.getStatus())) +// .filter(o -> o.getStage().equals("wait")).map(o -> o.getId() + "").collect(Collectors.joining(","))); + + //改为待确认 + result.setPlanCount(storyUsers.stream().filter(o -> "storyunconfirmed".equals(o.getStatus())) + .map(o -> o.getId() + "").collect(Collectors.joining(","))); result.setTestingCount(ztStory.stream().filter(o -> "active".equals(o.getStatus())) .filter(o -> Arrays.asList("testing", "tested").contains(o.getStage())).map(o -> o.getId() + "").collect(Collectors.joining(","))); @@ -733,7 +719,7 @@ public class IZtCountService { List releaseBugs = this.bugService.bugListByTestUser(null, firstDayOfMonth, lastDayOfMonth,csAccountIds, BugTypeEnums.RELEASE); //获取测试需求 List cswcStoryList = CollectionUtils.isEmpty(csAccountIds)?Collections.EMPTY_LIST:this.storyService.list(new QueryWrapper().lambda().in(ZtStory::getProduct, pids) - .in(ZtStory::getAssignedTo, csAccountIds).ge(ZtStory::getEndDate, firstDayOfMonth).le(ZtStory::getEndDate, lastDayOfMonth)); + .in(ZtStory::getAssignedTo, csAccountIds).ge(ZtStory::getReleaseddate, firstDayOfMonth).le(ZtStory::getReleaseddate, lastDayOfMonth)); for (ZtUser u : ztUsers) { @@ -812,7 +798,7 @@ public class IZtCountService { List releaseBugs = this.bugService.bugListByTestUser(null, firstDayOfMonth, lastDayOfMonth,csAccountIds , BugTypeEnums.RELEASE); //获取测试需求 List cswcStoryList = CollectionUtils.isEmpty(csAccountIds)?Collections.EMPTY_LIST:this.storyService.list(new QueryWrapper().lambda().in(ZtStory::getProduct, pids) - .in(ZtStory::getAssignedTo, csAccountIds).ge(ZtStory::getEndDate, firstDayOfMonth).le(ZtStory::getEndDate, lastDayOfMonth)); + .in(ZtStory::getAssignedTo, csAccountIds).ge(ZtStory::getReleaseddate, firstDayOfMonth).le(ZtStory::getReleaseddate, lastDayOfMonth)); for (ZtUser u : ztUsers) { @@ -2321,6 +2307,7 @@ public class IZtCountService { int i = bugRate.multiply(BigDecimal.valueOf(100)).intValue(); if (i <= 5) { result.setBugScore(BigDecimal.valueOf(20)); + return result; } //严重10 分 轻微3分一个 int bugScore = 0; @@ -2500,7 +2487,7 @@ public class IZtCountService { dataMap.put("name", name); dataMap.put("date", DateUtils.formatDate(d, "yyyy-MM")); dataMap.put("准时率得分", performanceDTO.getPunctualityScore()==null?"0": performanceDTO.getPunctualityScore().toString()); - dataMap.put("缺陷检出率", performanceDTO.getBugFindScore() ==null?"0":performanceDTO.getBugFindScore().toString()); + dataMap.put("缺陷检出率", performanceDTO.getBugFindRate() ==null?"0":performanceDTO.getBugFindRate().multiply(BigDecimal.valueOf(100)).toString()); dataMap.put("测试文档", performanceDTO.getDocumentQualityScore()==null?"0":performanceDTO.getDocumentQualityScore().toString()); dataMap.put("工作态度", performanceDTO.getWorkAttitude()==null?"0":performanceDTO.getWorkAttitude().toString()); @@ -2518,12 +2505,12 @@ public class IZtCountService { dataMap.put("测试普通bug", performanceDTO.getDevSlightBug()==null?"0": performanceDTO.getDevSlightBug().toString()); dataMap.put("测试重大bug", performanceDTO.getDevSeriousBug() ==null?"0": performanceDTO.getDevSeriousBug().toString()); - dataMap.put("缺陷检出分数", performanceDTO.getBugFindScore()==null?"0": performanceDTO.getBugFindScore().multiply(BigDecimal.valueOf(100)).toString()); + dataMap.put("缺陷检出分数", performanceDTO.getBugFindScore()==null?"0": performanceDTO.getBugFindScore().toString()); dataMap.put("线上普通bug", performanceDTO.getSlightBug() ==null?"0": performanceDTO.getSlightBug().toString()); dataMap.put("线上重大bug", performanceDTO.getSeriousBug()==null?"0": performanceDTO.getSeriousBug().toString()); dataMap.put("总分", devlopTotal(dataMap.get("准时率得分") - , dataMap.get("缺陷检出率"), + , dataMap.get("缺陷检出分数"), dataMap.get("测试文档"), dataMap.get("工作态度"), dataMap.get("质量贡献"), dataMap.get("线上Bug"), dataMap.get("创新贡献")) ); @@ -2599,7 +2586,7 @@ public class IZtCountService { List releaseBugs = this.bugService.bugListByTestUser(null, firstDayOfMonth, lastDayOfMonth, Arrays.asList(u.getAccount()), BugTypeEnums.RELEASE); //获取测试需求 List cswcStoryList = this.storyService.list(new QueryWrapper().lambda().in(ZtStory::getProduct, pids) - .in(ZtStory::getAssignedTo, Arrays.asList(u.getAccount())).ge(ZtStory::getEndDate, firstDayOfMonth).le(ZtStory::getEndDate, lastDayOfMonth)); + .in(ZtStory::getAssignedTo, Arrays.asList(u.getAccount())).ge(ZtStory::getReleaseddate, firstDayOfMonth).le(ZtStory::getReleaseddate, lastDayOfMonth)); if (name.equals("liyuyan")) { result = buildXMZLScore(u, approvalList, firstDayOfMonth, lastDayOfMonth, taskList, d); diff --git a/src/main/java/com/sa/zentao/service/impl/ZtProductServiceImpl.java b/src/main/java/com/sa/zentao/service/impl/ZtProductServiceImpl.java index def69ee..7697576 100644 --- a/src/main/java/com/sa/zentao/service/impl/ZtProductServiceImpl.java +++ b/src/main/java/com/sa/zentao/service/impl/ZtProductServiceImpl.java @@ -432,12 +432,16 @@ public class ZtProductServiceImpl extends ServiceImpl ztProjects = this.projectService.listByIds(projectproductlist.stream().map(o -> o.getProject()).collect(Collectors.toList())); result.put("project",ztProjects); List list = this.executionprojectService.list(new QueryWrapper().lambda().in(ZtExecutionproject::getProject, ztProjects.stream().map(o -> o.getId()).collect(Collectors.toList()))); - List execList = this.projectService - .list(new QueryWrapper().lambda() - .ne(ZtProject::getStatus,"closed") - .in(ZtProject::getId,list.stream().map(o -> o.getExecution()).collect(Collectors.toList())) - .orderByDesc(ZtProject::getId) - ); + List execList = new ArrayList<>(); + if(!CollectionUtils.isEmpty(list)){ + execList=this.projectService + .list(new QueryWrapper().lambda() + .ne(ZtProject::getStatus,"closed") + .in(ZtProject::getId,list.stream().map(o -> o.getExecution()).collect(Collectors.toList())) + .orderByDesc(ZtProject::getId) + ); + } + result.put("execution",execList); }else{ result.put("project",Arrays.asList()); @@ -603,6 +607,8 @@ public class ZtProductServiceImpl extends ServiceImpl impl } ZtProduct ztProduct = pMap.get(d.getProduct()); - if(ztProduct!=null){ + if (ztProduct != null) { d.setProductName(ztProduct.getName()); } ztUser = userMap.get(d.getOpenedby()); @@ -209,15 +213,15 @@ public class ZtStoryServiceImpl extends ServiceImpl impl if (dto.getFeedback() != null && dto.getFeedback() != 0) { ZtStoryFeedback storyFeedback = this.storyFeedbackService.getById(dto.getFeedback()); - if (!Arrays.asList("wait","doing").contains(storyFeedback.getStatus())) { + if (!Arrays.asList("wait", "doing").contains(storyFeedback.getStatus())) { throw new BusinessException("问题反馈已被处理"); } this.storyFeedbackService.feedbackStart(dto.getFeedback()); } if (dto.getUserStory() != null && dto.getUserStory() != 0) { ZtStoryUser storyUser = storyUserService.getById(dto.getUserStory()); - if(storyUser.getStatus().equals(UserStoryEnums.CFM.getCode())){ - storyUserService.storyFinishedChangeStatus(storyUser.getId(),UserStoryEnums.KFZ); + if (storyUser.getStatus().equals(UserStoryEnums.CFM.getCode())) { + storyUserService.storyFinishedChangeStatus(storyUser.getId(), UserStoryEnums.KFZ); } } @@ -258,9 +262,9 @@ public class ZtStoryServiceImpl extends ServiceImpl impl //查找需求管理的项目 需求只会被项目关联一次 List list = this.executionprojectService.list(new QueryWrapper().lambda().in(ZtExecutionproject::getExecution, executions)); - if(!CollectionUtils.isEmpty(list)){ + if (!CollectionUtils.isEmpty(list)) { Map> map = list.stream().collect(Collectors.groupingBy(ZtExecutionproject::getProject)); - if(map.keySet().size()>1){ + if (map.keySet().size() > 1) { throw new BusinessException("当前无法关联多个项目请检查"); } @@ -269,28 +273,30 @@ public class ZtStoryServiceImpl extends ServiceImpl impl this.executionBindStory(s, executions); } - storySendZpMessage(s.getId(),"",s.getAssignedTo()); + storySendZpMessage(s.getId(), "", s.getAssignedTo()); } - private void storySendZpMessage(Integer id, String oldUser,String newUser) { - if(ObjectUtils.notEqual(oldUser, newUser)&&!StringUtils.isEmpty(newUser)){ + private void storySendZpMessage(Integer id, String oldUser, String newUser) { + if (ObjectUtils.notEqual(oldUser, newUser) && !StringUtils.isEmpty(newUser)) { List storyExecutions = this.projectstoryService.projectListByStory(Arrays.asList(id), ProjectTypeEnums.execution); - if(!CollectionUtils.isEmpty(storyExecutions)){ - this.vxService.sendMessageToVx(newUser, VxMessageUtils.storyMessage.assignToMessage(id),new Date()); + if (!CollectionUtils.isEmpty(storyExecutions)) { + this.vxService.sendMessageToVx(newUser, VxMessageUtils.storyMessage.assignToMessage(id), new Date()); } } } + private void storyYsFalseSendMessage(Integer id, List newUsers) { - if(!CollectionUtils.isEmpty(newUsers)){ - for (String u:newUsers) { - if(!StringUtils.isEmpty(u)){ - this.vxService.sendMessageToVx(u, VxMessageUtils.storyMessage.ysFalseMessage(id),new Date()); + if (!CollectionUtils.isEmpty(newUsers)) { + for (String u : newUsers) { + if (!StringUtils.isEmpty(u)) { + this.vxService.sendMessageToVx(u, VxMessageUtils.storyMessage.ysFalseMessage(id), new Date()); } } } } + private ZtStoryspec buildSpec(ZtStoryDTO dto, ZtStory s) { ZtStoryspec spec = new ZtStoryspec(); @@ -305,16 +311,16 @@ public class ZtStoryServiceImpl extends ServiceImpl impl } private ZtStory buildStory(ZtStoryDTO dto) { - if(dto.getUserStory()!=null&&dto.getUserStory()!=0){ + if (dto.getUserStory() != null && dto.getUserStory() != 0) { ZtStoryUser ztStoryUser = this.storyUserService.getById(dto.getUserStory()); - if(ztStoryUser==null){ + if (ztStoryUser == null) { throw new BusinessException("未查询到用户需求"); } - if(!Arrays.asList(UserStoryEnums.CFM.getCode(),UserStoryEnums.KFZ.getCode(),UserStoryEnums.JH.getCode()).contains(ztStoryUser.getStatus())){ + if (!Arrays.asList(UserStoryEnums.CFM.getCode(), UserStoryEnums.KFZ.getCode(), UserStoryEnums.JH.getCode()).contains(ztStoryUser.getStatus())) { throw new BusinessException("用户需求无法关联请检查"); } - if(UserStoryEnums.JH.getCode().equals(ztStoryUser.getStatus())){ - this.storyUserService.changeStatus(ztStoryUser.getId(),UserStoryEnums.CFM); + if (UserStoryEnums.JH.getCode().equals(ztStoryUser.getStatus())) { + this.storyUserService.changeStatus(ztStoryUser.getId(), UserStoryEnums.CFM); } } ZtStory s = new ZtStory(); @@ -458,12 +464,12 @@ public class ZtStoryServiceImpl extends ServiceImpl impl @Override public List getNormalStory(List sList) { - List result=new ArrayList(); - for (ZtStory st:sList) { - if(!st.getStatus().equals("closed")){ + List result = new ArrayList(); + for (ZtStory st : sList) { + if (!st.getStatus().equals("closed")) { result.add(st); } - if(st.getStatus().equals("closed")&&st.getYsFlag()!=null&&st.getYsFlag()!=0){ + if (st.getStatus().equals("closed") && st.getYsFlag() != null && st.getYsFlag() != 0) { result.add(st); } @@ -493,9 +499,9 @@ public class ZtStoryServiceImpl extends ServiceImpl impl //查找需求管理的项目 需求只会被项目关联一次 List list = this.executionprojectService.list(new QueryWrapper().lambda().in(ZtExecutionproject::getExecution, executions)); - if(!CollectionUtils.isEmpty(list)){ + if (!CollectionUtils.isEmpty(list)) { Map> map = list.stream().collect(Collectors.groupingBy(ZtExecutionproject::getProject)); - if(map.keySet().size()>1){ + if (map.keySet().size() > 1) { throw new BusinessException("当前无法关联多个项目请检查"); } @@ -577,13 +583,13 @@ public class ZtStoryServiceImpl extends ServiceImpl impl } - - + ztStory.setLasteditedby(RiskUserThreadLocal.get().getName()); + ztStory.setLastediteddate(new Date()); this.baseMapper.updateById(ztStory); - if(dto.getReleaseId()!=null&&dto.getReleaseId()!=0){ - this.releaseService.changeRelease(dto.getReleaseId(),ztStory.getId(),"story"); - }else{ - ZtReleaseQo qo =new ZtReleaseQo(); + if (dto.getReleaseId() != null && dto.getReleaseId() != 0) { + this.releaseService.changeRelease(dto.getReleaseId(), ztStory.getId(), "story"); + } else { + ZtReleaseQo qo = new ZtReleaseQo(); qo.setStoryList(Arrays.asList(id)); this.releaseService.removeStory(qo); } @@ -594,12 +600,12 @@ public class ZtStoryServiceImpl extends ServiceImpl impl s.setStage(dto.getStage()); this.changeStatus(s); } - if(ObjectUtils.notEqual(userStory,newUserStory)){ - if(userStory!=null&&userStory!=0){ - this.storyUserService.storyFinishedChangeStatus(userStory,UserStoryEnums.YWC); + if (ObjectUtils.notEqual(userStory, newUserStory)) { + if (userStory != null && userStory != 0) { + this.storyUserService.storyFinishedChangeStatus(userStory, UserStoryEnums.YWC); } - if(newUserStory!=null&&newUserStory!=0){ - this.storyUserService.storyFinishedChangeStatus(newUserStory,UserStoryEnums.KFZ); + if (newUserStory != null && newUserStory != 0) { + this.storyUserService.storyFinishedChangeStatus(newUserStory, UserStoryEnums.KFZ); } } @@ -631,7 +637,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl RiskUserThreadLocal.get().getName(), dto.getRemark(), ""); } - storySendZpMessage(ztStory.getId(),oldAssignedTo,ztStory.getAssignedTo()); + storySendZpMessage(ztStory.getId(), oldAssignedTo, ztStory.getAssignedTo()); } @@ -659,7 +665,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl //一个需求如果绑定多个项目 不是当前的项目 List bindProject = this.projectstoryService.list(new QueryWrapper().lambda() .ne(ZtProjectstory::getProject, project) - .eq(ZtProjectstory::getType,"project") + .eq(ZtProjectstory::getType, "project") .eq(ZtProjectstory::getStory, storyId) ); @@ -669,7 +675,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl 切换的迭代不是当前需求已经绑定的迭代 this.projectstoryService.remove(new QueryWrapper().lambda().eq(ZtProjectstory::getProject, oldProject).eq(ZtProjectstory::getStory, storyId)); */ - if(!CollectionUtils.isEmpty(bindProject)) throw new BusinessException("需求被多个项目关联"); + if (!CollectionUtils.isEmpty(bindProject)) throw new BusinessException("需求被多个项目关联"); if (CollectionUtils.isEmpty(list)) { ZtProjectDTO d = new ZtProjectDTO(); @@ -719,18 +725,18 @@ public class ZtStoryServiceImpl extends ServiceImpl impl List pAuth = this.projectService.authProductList(); - if(CollectionUtils.isEmpty(pAuth)){ + if (CollectionUtils.isEmpty(pAuth)) { return Arrays.asList(); } List sList = this.baseMapper.selectList(new QueryWrapper().lambda() .ne(ZtStory::getStatus, "closed") - .in(ZtStory::getProduct,pAuth) - .and(o-> o.eq(ZtStory::getAssignedTo, RiskUserThreadLocal.get().getName()) + .in(ZtStory::getProduct, pAuth) + .and(o -> o.eq(ZtStory::getAssignedTo, RiskUserThreadLocal.get().getName()) .or().eq(ZtStory::getOpenedby, RiskUserThreadLocal.get().getName())) - .orderByDesc(ZtStory::getId) + .orderByDesc(ZtStory::getId) ); - List storyDTOList = BeanCopyUtil.copyListProperties(sList, ZtStoryDTO::new,new BeanCopyUtilCallBack() { + List storyDTOList = BeanCopyUtil.copyListProperties(sList, ZtStoryDTO::new, new BeanCopyUtilCallBack() { @Override public void callBack(ZtStory t, ZtStoryDTO s) { s.setOpeneddate(t.getOpenedDate()); @@ -750,7 +756,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl } if (userType == UserType.CP) { List uStory = this.storyUserService.list(new QueryWrapper().lambda().ne(ZtStoryUser::getStatus, "closed") - .in(ZtStoryUser::getProduct,pAuth) + .in(ZtStoryUser::getProduct, pAuth) .eq(ZtStoryUser::getOpenedby, RiskUserThreadLocal.get().getName()).orderByDesc(ZtStoryUser::getId) ); if (!CollectionUtils.isEmpty(uStory)) { @@ -785,9 +791,9 @@ public class ZtStoryServiceImpl extends ServiceImpl impl Map userMap = this.userService.userMapByIds(null); - Map> taskCountMap = getTaskCountMap(list); + Map> taskCountMap = getTaskCountMap(list); - Map caseMap = getStoryCaseMap(list); + Map caseMap = getStoryCaseMap(list); for (ZtStoryDTO d : list) { @@ -795,24 +801,24 @@ public class ZtStoryServiceImpl extends ServiceImpl impl d.setViews(rMap.get(d.getId())); List ztTasks = taskCountMap.get(d.getId()); ZtStoryCaseDTO ztStoryCaseDTO = caseMap.get(d.getId()); - if(ztStoryCaseDTO!=null){ + if (ztStoryCaseDTO != null) { ZtUser ztUser = userMap.get(ztStoryCaseDTO.getOpenedUser()); - if(ztUser!=null){ + if (ztUser != null) { ztStoryCaseDTO.setOpenedUserName(ztUser.getNickname()); } ztUser = userMap.get(ztStoryCaseDTO.getUpdateUser()); - if(ztUser!=null){ + if (ztUser != null) { ztStoryCaseDTO.setUpdateUserName(ztUser.getNickname()); } ztUser = userMap.get(ztStoryCaseDTO.getPsUser()); - if(ztUser!=null){ + if (ztUser != null) { ztStoryCaseDTO.setPsUserName(ztUser.getNickname()); } d.setCaseInfo(ztStoryCaseDTO); } - d.setTaskCount(ztTasks==null?0:ztTasks.size()); + d.setTaskCount(ztTasks == null ? 0 : ztTasks.size()); List ztProjectList = execMap.get(d.getId()); @@ -843,7 +849,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl public Map getStoryCaseMap(List list) { - if(CollectionUtils.isEmpty(list)){ + if (CollectionUtils.isEmpty(list)) { return new HashMap<>(); } List sIds = list.stream().map(o -> o.getId()).collect(Collectors.toList()); @@ -851,9 +857,9 @@ public class ZtStoryServiceImpl extends ServiceImpl impl List caseList = this.storyCaseService.list(new QueryWrapper().lambda() .select(SFunctionColums.caseColumes()) .in(ZtStoryCase::getStory, sIds)); - if(CollectionUtils.isEmpty(caseList)){ + if (CollectionUtils.isEmpty(caseList)) { return new HashMap<>(); - }else{ + } else { List ztStoryCaseDTOS = BeanCopyUtil.copyListProperties(caseList, ZtStoryCaseDTO::new); return ztStoryCaseDTOS.stream().collect(Collectors.toMap(ZtStoryCaseDTO::getStory, o -> o)); } @@ -861,7 +867,108 @@ public class ZtStoryServiceImpl extends ServiceImpl impl @Override public List getStoryListByDatePidsProject(List pids, Integer id, Date firstDayOfMonth, Date lastDayOfMonth) { - return this.baseMapper.getStoryListByDatePidsProject(pids,id,firstDayOfMonth,lastDayOfMonth); + return this.baseMapper.getStoryListByDatePidsProject(pids, id, firstDayOfMonth, lastDayOfMonth); + } + @Autowired + private SqlSession sqlSession; + @Override + public PageInfo searchByName(SearchQo qo) { + + + Page page = PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize()); +// 1 用户需求 2研发需求 3 任务 4 问题反馈 5 bug + List searchDTOS = new ArrayList<>(); + List pIds = this.projectService.authProductList(); + if(CollectionUtils.isEmpty(pIds)) { + throw new BusinessException("当前无权限"); + } + + if (qo.getSearchType().contains("100")) { + searchDTOS = searchAll(qo,pIds); + } else { + StringBuilder builder = new StringBuilder(); + String[] split = qo.getSearchType().split(","); + for (int i =0;io.toString()).collect(Collectors.joining(",")) + + ") and (spc.spec like concat('%', '"+qo.getKeyword()+"', '%') or spc.verify like concat('%', '"+qo.getKeyword()+"', '%') or st.title like concat('%', '"+qo.getKeyword()+"', '%') ) order by id desc"); + }else if(split[i].equals("2")){ + builder.append("SELECT id,st.title name, spc.spec spec,spc.verify verify,2 type,openedDate from zt_story st" + + " left join zt_storyspec spc on st.id=spc.story WHERE 1=1 " + + " and product in (" + pIds.stream().map(o->o.toString()).collect(Collectors.joining(",")) + + ") and (spc.spec like concat('%', '"+qo.getKeyword()+"', '%') or spc.verify like concat('%', '"+qo.getKeyword()+"', '%') or st.title like concat('%', '"+qo.getKeyword()+"', '%') ) order by id desc"); + }else if(split[i].equals("3")){ + builder.append("SELECT id,name name, `desc` spec,'' verify,3 type,openedDate from zt_task WHERE 1=1" + + " and product in (" + pIds.stream().map(o->o.toString()).collect(Collectors.joining(",")) + + ") and (name like concat('%', '"+qo.getKeyword()+"', '%') or `desc` like concat('%','"+qo.getKeyword()+"', '%') ) order by id desc"); + }else if(split[i].equals("4")){ + builder.append("SELECT id,remark name, spec spec,'' verify,4 type,opened_date openedDate from zt_story_feedback WHERE 1=1" + + " and product in (" + pIds.stream().map(o->o.toString()).collect(Collectors.joining(",")) + + ") and (remark like concat('%', '"+qo.getKeyword()+"', '%') or spec like concat('%', '"+qo.getKeyword()+"', '%') ) order by id desc "); + }else if(split[i].equals("5")){ + builder.append(" SELECT id,title name, steps spec,'' verify,5 type,openedDate from zt_bug WHERE 1=1 and product in ("+ + pIds.stream().map(o->o.toString()).collect(Collectors.joining(",")) + + ") and (title like concat('%','"+qo.getKeyword()+"', '%') or steps like concat('%', '"+qo.getKeyword()+"', '%') ) order by id desc "); + + } + builder.append(") "); + if(split.length>1&&i!=split.length-1){ + builder.append(" UNION "); + } + } + List> result = SqlRunner.db().selectList(builder.toString()); + for (Map map : result) { + if(map.get("spec")!=null&&map.get("spec") instanceof byte[]){ + map.put("spec", new String((byte[]) map.get("spec"))); + } + if(map.get("verify")!=null&&map.get("verify") instanceof byte[]){ + map.put("verify", new String((byte[]) map.get("verify"))); + } + searchDTOS.add(JSON.parseObject(JSON.toJSONString(map),SearchDTO.class) ); + } + } +// if (qo.getSearchType() == 1) { +// searchDTOS = searchUserStory(qo); +// } else if (qo.getSearchType() == 2) { +// searchDTOS = searchStory(qo); +// } else if (qo.getSearchType() == 3) { +// searchDTOS = searchTask(qo); +// } else if (qo.getSearchType() == 4) { +// searchDTOS = searchFeedback(qo); +// } else if (qo.getSearchType() == 5) { +// searchDTOS = searchBug(qo); +// } + long total = page.getTotal(); + PageInfo searchDTOPageInfo = new PageInfo<>(searchDTOS); + searchDTOPageInfo.setTotal(total); + return searchDTOPageInfo; + } + + private List searchBug(SearchQo qo) { + return this.baseMapper.searchBug(qo.getKeyword()); + } + + private List searchTask(SearchQo qo) { + return this.baseMapper.searchTask(qo.getKeyword()); + } + + private List searchStory(SearchQo qo) { + return this.baseMapper.searchStory(qo.getKeyword()); + } + + private List searchFeedback(SearchQo qo) { + return this.baseMapper.searchFeedback(qo.getKeyword()); + } + + private List searchUserStory(SearchQo qo) { + return this.baseMapper.searchUserStory(qo.getKeyword()); + } + + private List searchAll(SearchQo qo,List pIds) { + return this.baseMapper.searchAll(qo.getKeyword(),pIds); } private Map> getTaskCountMap(List list) { @@ -869,9 +976,9 @@ public class ZtStoryServiceImpl extends ServiceImpl impl List tList = this.taskService.list(new QueryWrapper().lambda() .select(SFunctionColums.taskColumes()) .in(ZtTask::getStory, list.stream().map(o -> o.getId()).collect(Collectors.toList()))); - if(CollectionUtils.isEmpty(tList)){ + if (CollectionUtils.isEmpty(tList)) { return new HashMap<>(); - }else{ + } else { return tList.stream().collect(Collectors.groupingBy(ZtTask::getStory)); } } @@ -988,7 +1095,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl @Override @Transactional - public void waitStory(Integer id){ + public void waitStory(Integer id) { if (id == null || id == 0) { return; } @@ -1020,7 +1127,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl if ("closed".equals(ztStory.getStatus())) { throw new BusinessException("需求当前已关闭"); } - if("developing".equals(ztStory.getStage())){ + if ("developing".equals(ztStory.getStage())) { return; } @@ -1050,7 +1157,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl if (ztStory == null) { throw new BusinessException("未查询到需求"); } - if(ztStory.getStatus().equals("developed")){ + if (ztStory.getStatus().equals("developed")) { return; } if (ztStory.getFeedback() != null && ztStory.getFeedback() != 0) { @@ -1165,7 +1272,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl ZtStory ztStory = this.baseMapper.selectById(story); if (ztStory.getFeedback() != null && ztStory.getFeedback() != 0) { - this.storyFeedbackService.feedbackFinished(ztStory.getFeedback(),null); + this.storyFeedbackService.feedbackFinished(ztStory.getFeedback(), null); } if (ztStory == null) { @@ -1208,7 +1315,6 @@ public class ZtStoryServiceImpl extends ServiceImpl impl String ysUser = ztStory.getYsUser(); - for (Integer execId : execIds) { if (execId != null) { this.kanbanlaneService.changeStatus(execId, ztStory.getId(), "story", "released"); @@ -1228,53 +1334,57 @@ public class ZtStoryServiceImpl extends ServiceImpl impl } if (ztStory.getFeedback() != null && ztStory.getFeedback() != 0) { - this.storyFeedbackService.feedbackFinished(ztStory.getFeedback(),null); + this.storyFeedbackService.feedbackFinished(ztStory.getFeedback(), null); } actionService.addAction(ActionType.XQ, ActionStatus.FBCG, ztStory.getId(), ztStory.getProduct() + "", ztStory.getProject(), execIds.get(0), RiskUserThreadLocal.get().getName(), null, ""); } + @Override - public void taskFinishChangeStatus(Integer story, String finishBy,TaskType type,Boolean cancelFlag) { + public void taskFinishChangeStatus(Integer story, String finishBy, TaskType type, Boolean cancelFlag) { ZtStory ztStory = this.getById(story); - if(ztStory!=null&&ztStory.getStatus().equals("closed")){ + if(ztStory == null) { return; } - if(type!=TaskType.test&&type!=TaskType.devel){ + if (ztStory != null && ztStory.getStatus().equals("closed")) { return; } - if(story==null||story==0){ + if (type != TaskType.test && type != TaskType.devel) { +// return; + } + if (story == null || story == 0) { return; } - if(cancelFlag&&type==TaskType.devel){ + if (cancelFlag && type == TaskType.devel) { List develList = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .in(ZtTask::getStatus, Arrays.asList( "wait", "doing", "pause")) + .in(ZtTask::getStatus, Arrays.asList("wait", "doing", "pause")) .eq(ZtTask::getType, type.getCode())); - if(!CollectionUtils.isEmpty(develList)){ + if (!CollectionUtils.isEmpty(develList)) { this.startStory(story); - }else{ + } else { List testList = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .in(ZtTask::getStatus, Arrays.asList( "wait", "doing", "pause")) + .in(ZtTask::getStatus, Arrays.asList("wait", "doing", "pause")) .eq(ZtTask::getType, TaskType.test.getCode())); - if(!CollectionUtils.isEmpty(testList)){ + if (!CollectionUtils.isEmpty(testList)) { testingStory(story); - }else{ + } else { List doneList = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .in(ZtTask::getStatus, Arrays.asList( "done"))); - if(CollectionUtils.isEmpty(doneList)){ + .in(ZtTask::getStatus, Arrays.asList("done"))); + if (CollectionUtils.isEmpty(doneList)) { this.waitStory(story); return; } List testedList = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .in(ZtTask::getStatus, Arrays.asList( "done")) + .in(ZtTask::getStatus, Arrays.asList("done")) .eq(ZtTask::getType, TaskType.test.getCode())); - if(!CollectionUtils.isEmpty(testedList)){ - testedStory(story,finishBy); - }else{ - this.finishStory(story,finishBy); + if (!CollectionUtils.isEmpty(testedList)) { + testedStory(story, finishBy); + } else { + this.finishStory(story, finishBy); } } @@ -1282,92 +1392,112 @@ public class ZtStoryServiceImpl extends ServiceImpl impl return; } //测试任务取消 - if(cancelFlag&&type==TaskType.test){ + if (cancelFlag && type == TaskType.test) { List develing = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .in(ZtTask::getStatus, Arrays.asList( "wait", "doing", "pause")) + .in(ZtTask::getStatus, Arrays.asList("wait", "doing", "pause")) .eq(ZtTask::getType, TaskType.devel.getCode())); - if(!CollectionUtils.isEmpty(develing)){ + if (!CollectionUtils.isEmpty(develing)) { startStory(story); return; } List testling = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .in(ZtTask::getStatus, Arrays.asList( "wait", "doing", "pause")) + .in(ZtTask::getStatus, Arrays.asList("wait", "doing", "pause")) .eq(ZtTask::getType, TaskType.test.getCode())); - if(!CollectionUtils.isEmpty(testling)){ + if (!CollectionUtils.isEmpty(testling)) { testingStory(story); return; } List doneList = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .in(ZtTask::getStatus, Arrays.asList( "done"))); - if(CollectionUtils.isEmpty(doneList)){ + .in(ZtTask::getStatus, Arrays.asList("done"))); + if (CollectionUtils.isEmpty(doneList)) { this.waitStory(story); return; } List testedList = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .eq(ZtTask::getType,TaskType.test.getCode()) - .in(ZtTask::getStatus, Arrays.asList( "done"))); - if(!CollectionUtils.isEmpty(testedList)){ - this.testedStory(story,finishBy); + .eq(ZtTask::getType, TaskType.test.getCode()) + .in(ZtTask::getStatus, Arrays.asList("done"))); + if (!CollectionUtils.isEmpty(testedList)) { + this.testedStory(story, finishBy); return; } List develedList = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .eq(ZtTask::getType,TaskType.devel.getCode()) - .in(ZtTask::getStatus, Arrays.asList( "done"))); - if(!CollectionUtils.isEmpty(develedList)){ - this.finishStory(story,finishBy); + .eq(ZtTask::getType, TaskType.devel.getCode()) + .in(ZtTask::getStatus, Arrays.asList("done"))); + if (!CollectionUtils.isEmpty(develedList)) { + this.finishStory(story, finishBy); return; } return; } - if(type==TaskType.test){ + if (type == TaskType.test) { // 测试 List testList = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .in(ZtTask::getStatus, Arrays.asList( "wait", "doing", "pause")) + .in(ZtTask::getStatus, Arrays.asList("wait", "doing", "pause")) .eq(ZtTask::getType, type.getCode())); List develList = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .in(ZtTask::getStatus, Arrays.asList( "wait", "doing", "pause")) + .in(ZtTask::getStatus, Arrays.asList("wait", "doing", "pause")) .eq(ZtTask::getType, TaskType.devel.getCode())); - - - if(CollectionUtils.isEmpty(develList)&&CollectionUtils.isEmpty(testList)){ + if (CollectionUtils.isEmpty(develList) && CollectionUtils.isEmpty(testList)) { long done = taskService.count(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .eq(ZtTask::getType,type.getCode()) + .eq(ZtTask::getType, type.getCode()) .in(ZtTask::getStatus, Arrays.asList("done"))); - if(done<1){ + if (done < 1) { return; } - this.testedStory(story,finishBy); - }else{ - if(CollectionUtils.isEmpty(develList)){ + this.testedStory(story, finishBy); + } else { + if (CollectionUtils.isEmpty(develList)) { this.testingStory(story); - }else if(!CollectionUtils.isEmpty(develList)){ + } else if (!CollectionUtils.isEmpty(develList)) { this.startStory(story); - }else if(!CollectionUtils.isEmpty(testList)){ + } else if (!CollectionUtils.isEmpty(testList)) { this.testingStory(story); } } - }else if(type==TaskType.devel){ + } else if (type == TaskType.devel) { // 开发 List taskList = taskService.list(new QueryWrapper().lambda().eq(ZtTask::getStory, story) - .in(ZtTask::getStatus, Arrays.asList( "wait", "doing", "pause")) + .in(ZtTask::getStatus, Arrays.asList("wait", "doing", "pause")) .eq(ZtTask::getType, type.getCode())); - if(!CollectionUtils.isEmpty(taskList)){ + if (!CollectionUtils.isEmpty(taskList)) { this.startStory(story); - }else{ + } else { long done = taskService.count(new QueryWrapper().lambda().eq(ZtTask::getStory, story) .in(ZtTask::getStatus, Arrays.asList("done"))); - if(done<1){ + if (done < 1) { - }else{ - this.finishStory(story,finishBy); + } else { + this.finishStory(story, finishBy); } } + } else { + //开发测试任务 + long kfTaskCount = taskService.count(new QueryWrapper().lambda().eq(ZtTask::getStory, story) + .in(ZtTask::getStatus, Arrays.asList("wait", "doing", "pause", "done", "reviewing")) + .in(ZtTask::getType, Arrays.asList("devel", "test"))); + if (kfTaskCount > 0) { + return; + } + //其他类型任务完成 + long otherWaitCount = taskService.count(new QueryWrapper().lambda().eq(ZtTask::getStory, story) + .in(ZtTask::getStatus, Arrays.asList("wait", "doing", "pause", "reviewing")) + .notIn(ZtTask::getType, Arrays.asList("devel", "test"))); + String srotyType=null; + if (otherWaitCount > 0) { + srotyType="backlog"; + }else{ + srotyType="ready"; + } + List executionId = this.getExecutionId(ztStory); + for (Integer execution : executionId) { + kanbanlaneService.changeStatus(execution, story, "story", srotyType); + } } } @@ -1382,7 +1512,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl if (ztStory == null) { throw new BusinessException("未查询到数据-需求"); } - if(ztStory.getStatus().equals("testing")){ + if (ztStory.getStatus().equals("testing")) { return; } if (ztStory.getFeedback() != null && ztStory.getFeedback() != 0) { @@ -1634,9 +1764,9 @@ public class ZtStoryServiceImpl extends ServiceImpl impl qo.setObjIds(ids); // list=this.baseMapper.storyPageListByIds(ids); } - if(productId!=null&&productId!=0){ + if (productId != null && productId != 0) { qo.setProductIds(Arrays.asList(productId)); - }else{ + } else { List pids = this.projectService.authProductList(); if (!CollectionUtils.isEmpty(pids)) { @@ -1650,13 +1780,12 @@ public class ZtStoryServiceImpl extends ServiceImpl impl page = PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize()); qo.setKfz(1); list = this.baseMapper.projectStoryPageList(qo); - }else{ + } else { page = PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize()); list = this.baseMapper.myStoryPageList(qo); } - if (!CollectionUtils.isEmpty(list)) { Map> rMap = getReviewMap(list); @@ -1759,17 +1888,17 @@ public class ZtStoryServiceImpl extends ServiceImpl impl ProductStoryStatus oldPStatus = getProductStatus(status); this.productService.productChangeStatus(ztStory.getProduct(), oldPStatus, ProductStoryStatus.GB); } - List execList = this.projectstoryService.projectListByStory(Arrays.asList(ztStory.getId()),ProjectTypeEnums.execution); - if(!CollectionUtils.isEmpty(execList)){ - for (ZtProjectstory s:execList ) { - this.kanbanlaneService.changeStatus(s.getProject(),ztStory.getId(),"story","closed"); + List execList = this.projectstoryService.projectListByStory(Arrays.asList(ztStory.getId()), ProjectTypeEnums.execution); + if (!CollectionUtils.isEmpty(execList)) { + for (ZtProjectstory s : execList) { + this.kanbanlaneService.changeStatus(s.getProject(), ztStory.getId(), "story", "closed"); } } this.closeTaskBug(ztStory.getId()); - if(ztStory.getUserStory()!=null&&ztStory.getUserStory()!=0){ + if (ztStory.getUserStory() != null && ztStory.getUserStory() != 0) { //研发需求关闭去验收用户需求 - storyUserService.storyFinishedChangeStatus(ztStory.getUserStory(),UserStoryEnums.YWC); + storyUserService.storyFinishedChangeStatus(ztStory.getUserStory(), UserStoryEnums.YWC); // storyUserService.storyFinishedChangeStatus(ztStory.getUserStory(),UserStoryEnums.CFM); } } @@ -1791,7 +1920,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl actionService.addAction(ActionType.XQ, ActionStatus.FP, ztStory.getId(), ztStory.getProduct() + "", null, null, RiskUserThreadLocal.get().getName(), dto.getDesc(), ztStory.getAssignedTo()); - storySendZpMessage(ztStory.getId(),oldAssignedTo,ztStory.getAssignedTo()); + storySendZpMessage(ztStory.getId(), oldAssignedTo, ztStory.getAssignedTo()); } @@ -1861,11 +1990,11 @@ public class ZtStoryServiceImpl extends ServiceImpl impl product.setReleases(product.getReleases() - 1); this.productService.updateById(product); List pStory = this.projectstoryService.projectListByStory(Arrays.asList(ztStory.getId()), ProjectTypeEnums.execution); - if(CollectionUtils.isEmpty(pStory)){ + if (CollectionUtils.isEmpty(pStory)) { throw new BusinessException("当前未配置迭代无法验收"); } - for (ZtProjectstory s:pStory ) { - this.kanbanlaneService.changeStatus(s.getProject(),s.getStory(),"story","verified"); + for (ZtProjectstory s : pStory) { + this.kanbanlaneService.changeStatus(s.getProject(), s.getStory(), "story", "verified"); } } @@ -1889,10 +2018,10 @@ public class ZtStoryServiceImpl extends ServiceImpl impl if (revieweResult == 1 && ztStory.getFeedback() != null && ztStory.getFeedback() != 0) { this.storyFeedbackService.ysFeedback(ztStory.getFeedback()); } - if(ztStory.getStatus().equals("finished")){ + if (ztStory.getStatus().equals("finished")) { //验收通过 - storyUserService.storyFinishedChangeStatus(ztStory.getUserStory(),UserStoryEnums.YWC); - }else{ + storyUserService.storyFinishedChangeStatus(ztStory.getUserStory(), UserStoryEnums.YWC); + } else { //验收不通过 发送微信通知 sendYsFalseToVx(ztStory); } @@ -1903,8 +2032,8 @@ public class ZtStoryServiceImpl extends ServiceImpl impl private void sendYsFalseToVx(ZtStory ztStory) { List teamList = this.teamService.list(new QueryWrapper().lambda().eq(ZtTeam::getRoot, ztStory.getProduct()).eq(ZtTeam::getType, "product")); - if(!CollectionUtils.isEmpty(teamList)){ - storyYsFalseSendMessage(ztStory.getId(),teamList.stream().map(o->o.getAccount()).collect(Collectors.toList())); + if (!CollectionUtils.isEmpty(teamList)) { + storyYsFalseSendMessage(ztStory.getId(), teamList.stream().map(o -> o.getAccount()).collect(Collectors.toList())); } } @@ -1920,7 +2049,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl BeanUtils.copyProperties(ztStory, d); ZtRelease release = releaseService.getReleaseByStory(ztStory.getId()); - if(release!=null){ + if (release != null) { d.setReleaseId(release.getId()); d.setReleaseName(release.getName()); } @@ -1946,9 +2075,9 @@ public class ZtStoryServiceImpl extends ServiceImpl impl } } Integer feedback = ztStory.getFeedback(); - if(feedback!=null&&feedback!=0){ + if (feedback != null && feedback != 0) { ZtStoryFeedback ztStoryFeedback = this.storyFeedbackService.getById(feedback); - if(ztStoryFeedback!=null){ + if (ztStoryFeedback != null) { d.setFeedbackSpec(ztStoryFeedback.getSpec()); } } @@ -1974,18 +2103,18 @@ public class ZtStoryServiceImpl extends ServiceImpl impl } d.setReviewedbyName(b.toString()); } - List execStory = this.projectstoryService.projectListByStory(Arrays.asList(d.getId()),ProjectTypeEnums.execution); + List execStory = this.projectstoryService.projectListByStory(Arrays.asList(d.getId()), ProjectTypeEnums.execution); - if(!CollectionUtils.isEmpty(execStory)){ + if (!CollectionUtils.isEmpty(execStory)) { List ztProjects = this.projectService.listByIds(execStory.stream().map(o -> o.getProject()).collect(Collectors.toList())); List execInfoList = BeanCopyUtil.copyListProperties(ztProjects, ZtProjectDTO::new); - for (ZtProjectDTO execInfo:execInfoList) { + for (ZtProjectDTO execInfo : execInfoList) { ZtUser ztUser = userMap.get(execInfo.getPm()); - if(ztUser!=null){ + if (ztUser != null) { execInfo.setPmName(ztUser.getNickname()); } ztUser = userMap.get(execInfo.getOpenedBy()); - if(ztUser!=null){ + if (ztUser != null) { execInfo.setOpenedByName(ztUser.getNickname()); } @@ -2059,22 +2188,22 @@ public class ZtStoryServiceImpl extends ServiceImpl impl } Integer parent = ztStoryUserDTO.getParent(); - if(parent!=null&&parent!=0){ + if (parent != null && parent != 0) { ZtStoryUser ztStoryUser = this.storyUserService.getById(parent); - if(ztStoryUser!=null){ + if (ztStoryUser != null) { ztStoryUserDTO.setParentName(ztStoryUser.getTitle()); } } Integer product = ztStoryUserDTO.getProduct(); - if(product!=null&&product!=0){ + if (product != null && product != 0) { ZtProduct ztProduct = this.productService.getById(product); ztStoryUserDTO.setProductName(ztProduct.getName()); } Integer module = ztStoryUserDTO.getModule(); - if(module!=null&&module!=0){ + if (module != null && module != 0) { ZtModule ztModule = this.moduleService.getById(module); @@ -2084,22 +2213,22 @@ public class ZtStoryServiceImpl extends ServiceImpl impl } List bugs = this.bugService.list(new QueryWrapper().lambda().eq(ZtBug::getTostory, d.getId())); - if(!CollectionUtils.isEmpty(bugs)){ + if (!CollectionUtils.isEmpty(bugs)) { List ztBugDTOS = BeanCopyUtil.copyListProperties(bugs, ZtBugDTO::new); - if(!CollectionUtils.isEmpty(ztBugDTOS)){ - for (ZtBugDTO bug:ztBugDTOS) { + if (!CollectionUtils.isEmpty(ztBugDTOS)) { + for (ZtBugDTO bug : ztBugDTOS) { ztUser = userMap.get(bug.getOpenedby()); - if(ztUser!=null){ + if (ztUser != null) { bug.setOpenedbyName(ztUser.getNickname()); } ztUser = userMap.get(bug.getAssignedTo()); - if(ztUser!=null){ + if (ztUser != null) { bug.setAssignedToName(ztUser.getNickname()); } ztUser = userMap.get(bug.getYsUser()); - if(ztUser!=null){ + if (ztUser != null) { bug.setYsUserName(ztUser.getNickname()); } } @@ -2107,7 +2236,7 @@ public class ZtStoryServiceImpl extends ServiceImpl impl d.setBugList(ztBugDTOS); } List specList = this.storyspecService.list(new QueryWrapper().lambda().eq(ZtStoryspec::getStory, d.getId())); - if(!CollectionUtils.isEmpty(specList)){ + if (!CollectionUtils.isEmpty(specList)) { ZtStoryspec ztStoryspec = specList.get(0); d.setSpec(ztStoryspec.getSpec()); d.setVerify(ztStoryspec.getVerify()); @@ -2115,19 +2244,19 @@ public class ZtStoryServiceImpl extends ServiceImpl impl ZtStoryCase ztStoryCase = this.storyCaseService.getOne(new QueryWrapper().lambda().eq(ZtStoryCase::getStory, d.getId())); - if(ztStoryCase!=null){ - ZtStoryCaseDTO ztStoryCaseDTO=new ZtStoryCaseDTO(); - BeanUtils.copyProperties(ztStoryCase,ztStoryCaseDTO); - ztUser = userMap.get(ztStoryCaseDTO.getOpenedUser()); - if(ztUser!=null){ + if (ztStoryCase != null) { + ZtStoryCaseDTO ztStoryCaseDTO = new ZtStoryCaseDTO(); + BeanUtils.copyProperties(ztStoryCase, ztStoryCaseDTO); + ztUser = userMap.get(ztStoryCaseDTO.getOpenedUser()); + if (ztUser != null) { ztStoryCaseDTO.setOpenedUserName(ztUser.getNickname()); } ztUser = userMap.get(ztStoryCaseDTO.getUpdateUser()); - if(ztUser!=null){ + if (ztUser != null) { ztStoryCaseDTO.setUpdateUserName(ztUser.getNickname()); } ztUser = userMap.get(ztStoryCaseDTO.getPsUser()); - if(ztUser!=null){ + if (ztUser != null) { ztStoryCaseDTO.setPsUserName(ztUser.getNickname()); } d.setCaseInfo(ztStoryCaseDTO); diff --git a/src/main/java/com/sa/zentao/service/impl/ZtStoryUserServiceImpl.java b/src/main/java/com/sa/zentao/service/impl/ZtStoryUserServiceImpl.java index 9168c5f..375f0da 100644 --- a/src/main/java/com/sa/zentao/service/impl/ZtStoryUserServiceImpl.java +++ b/src/main/java/com/sa/zentao/service/impl/ZtStoryUserServiceImpl.java @@ -21,6 +21,7 @@ import com.sa.zentao.qo.ZtProjectQo; import com.sa.zentao.service.*; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.sa.zentao.utils.BeanCopyUtil; +import com.sa.zentao.utils.BeanCopyUtilCallBack; import com.sa.zentao.utils.SendEmail; import com.sa.zentao.utils.VxMessageUtils; import lombok.extern.slf4j.Slf4j; @@ -244,6 +245,35 @@ public class ZtStoryUserServiceImpl extends ServiceImpl> getKanban(Integer productId) { + List ztStoryUsers = this.baseMapper.selectList(new QueryWrapper().lambda().eq(ZtStoryUser::getProduct, productId).orderByDesc(ZtStoryUser::getId)); + Map> map = new HashMap<>(); + Map stringZtUserMap = this.userService.userMapByIds(ztStoryUsers.stream().map(o -> o.getOpenedby()).collect(Collectors.toList())); + + List ztStoryUserDTOS = BeanCopyUtil.copyListProperties(ztStoryUsers, ZtStoryUserDTO::new, new BeanCopyUtilCallBack() { + @Override + public void callBack(ZtStoryUser t, ZtStoryUserDTO s) { + ZtUser ztUser = stringZtUserMap.get(t.getOpenedby()); + if(ztUser!=null){ + s.setOpenedbyName(ztUser.getNickname()); + } + } + }); + + + map.put("active",ztStoryUserDTOS.stream().filter(o->"active".equals(o.getStatus())).collect(Collectors.toList())); + map.put("unconfirmed",ztStoryUserDTOS.stream().filter(o->"unconfirmed".equals(o.getStatus())).collect(Collectors.toList())); + map.put("waitcommunicate",ztStoryUserDTOS.stream().filter(o->"waitcommunicate".equals(o.getStatus())).collect(Collectors.toList())); + map.put("waitdesign",ztStoryUserDTOS.stream().filter(o->"waitdesign".equals(o.getStatus())).collect(Collectors.toList())); + map.put("designdoing",ztStoryUserDTOS.stream().filter(o->"designdoing".equals(o.getStatus())).collect(Collectors.toList())); + + map.put("designdone",ztStoryUserDTOS.stream().filter(o->"designdone".equals(o.getStatus())).collect(Collectors.toList())); + map.put("storyunconfirmed",ztStoryUserDTOS.stream().filter(o->"storyunconfirmed".equals(o.getStatus())).collect(Collectors.toList())); + map.put("confirmed",ztStoryUserDTOS.stream().filter(o->"confirmed".equals(o.getStatus())).collect(Collectors.toList())); + return Map.of(); + } + @Override public PageInfo pageList(StoryQo qo) { diff --git a/src/main/java/com/sa/zentao/service/impl/ZtStoryUserTaskServiceImpl.java b/src/main/java/com/sa/zentao/service/impl/ZtStoryUserTaskServiceImpl.java index 623f681..a66684e 100644 --- a/src/main/java/com/sa/zentao/service/impl/ZtStoryUserTaskServiceImpl.java +++ b/src/main/java/com/sa/zentao/service/impl/ZtStoryUserTaskServiceImpl.java @@ -296,16 +296,9 @@ public class ZtStoryUserTaskServiceImpl extends ServiceImpl impleme project.setStatus("doing"); this.ztProjectService.updateById(project); } -// if (dto.getFinishedFlag() == 1) { -// String type = ztTask.getType(); -// if (ztTask.getStory() != null && ztTask.getStory() != 0) { -//// if ("test".equals(type)) { -//// this.storyService.taskFinishChangeStatus(ztTask.getStory(),null,TaskType.test); -//// } else if ("devel".equals(type)) { -//// //开发 -//// this.storyService.taskFinishChangeStatus(ztTask.getStory(),null,TaskType.test); -//// } -// this.storyService.taskFinishChangeStatus(ztTask.getStory(), null, TaskType.transferType(type), false); -// } -// }else{ -// -// } - this.storyService.taskFinishChangeStatus(ztTask.getStory(), null, TaskType.transferType(ztTask.getType()), false); - } @Override @@ -991,12 +975,6 @@ public class ZtTaskServiceImpl extends ServiceImpl impleme String type = ztTask.getType(); if (ztTask.getStory() != null && ztTask.getStory() != 0) { this.storyService.taskFinishChangeStatus(ztTask.getStory(), finishBy, TaskType.transferType(type), false); -// if ("test".equals(type)) { -// this.storyService.taskFinishChangeStatus(ztTask.getStory(),finishBy,TaskType.test); -// } else if ("devel".equals(type)) { -// //开发 -// this.storyService.taskFinishChangeStatus(ztTask.getStory(),finishBy,TaskType.devel); -// } } if (ztTask.getFeedback() != null && ztTask.getFeedback() != 0) { this.storyFeedbackService.feedbackFinished(ztTask.getFeedback(),ztTask.getFeedbackRemark()); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index bfeab03..fb9b54b 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -31,7 +31,8 @@ spring: file: - baseUrl: http://192.168.3.200:8013 +# baseUrl: http://192.168.3.200:8013 + baseUrl: https://itsm.sino-assist.com meeting: /data/buildzentao/meeting.docx #vx: diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 6542dd3..ab9efc4 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -40,6 +40,7 @@ spring: file: baseUrl: http://192.168.1.161:8085 +# baseUrl: http://127.0.0.1:8085 meeting: /data/buildzentao/meeting.docx #spring: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a88accf..3eb58b4 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -37,8 +37,10 @@ mybatis: typeEnumsPackage: com.sa.zentao.enums - file: path: windows: D:\files - linux: /files \ No newline at end of file + linux: /files +mybatis-plus: + global-config: + enable-sql-runner: true \ No newline at end of file diff --git a/src/main/resources/mapper/ZtStoryMapper.xml b/src/main/resources/mapper/ZtStoryMapper.xml index c54ee1e..04bb38f 100644 --- a/src/main/resources/mapper/ZtStoryMapper.xml +++ b/src/main/resources/mapper/ZtStoryMapper.xml @@ -1209,4 +1209,68 @@ + + + + + + + + + diff --git a/src/main/resources/templates/scope/测试工程师.xlsx b/src/main/resources/templates/scope/测试工程师.xlsx index 207824c2beeb1ca58f8cd6bf84a509c6adc6da6a..0e15668fa939e424d2851f94f5fa220dcd77378c 100644 GIT binary patch delta 4288 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