用户需求看板,全局搜索等

This commit is contained in:
2025-11-03 11:42:38 +08:00
parent 253ea7035e
commit c9e6f781fa
25 changed files with 767 additions and 249 deletions

View File

@ -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<ZtStoryspec> lambda = new QueryWrapper<ZtStoryspec>().lambda();
// lambda.eq(ZtStoryspec::getStory,6493);
List<ZtStoryspec> list = ztStoryspecService.list();
for (ZtStoryspec ztStoryspec : list) {
if(!StringUtils.isEmpty(ztStoryspec.getSpec())){
System.out.println(ztStoryspec);
System.out.println(ztStoryspec);
// 正则表达式匹配Base64图片
String pattern = "<img\\s+src=\"data:image/[^;]+;base64,[^\"]+\"\\s*/?>";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(ztStoryspec.getSpec());
String s = base64ImageSaver.saveBase64Images(ztStoryspec.getSpec());
ztStoryspec.setSpec(s);
LambdaUpdateWrapper<ZtStoryspec> lambda1 = new UpdateWrapper<ZtStoryspec>().lambda();
lambda1.set(ZtStoryspec::getSpec,s);
lambda1.eq(ZtStoryspec::getStory,ztStoryspec.getStory());
ztStoryspecService.update(lambda1);
System.out.println("<UNK>" + s + "<UNK>");
}
}
}
private void handUserStory(){
// ZtStory byId = this.ztStoryService.getById(6493);
// LambdaQueryWrapper<ZtStoryspec> lambda = new QueryWrapper<ZtStoryspec>().lambda();
// lambda.eq(ZtStoryspec::getStory,6493);
List<ZtStoryUserspec> list = ztStoryUserSpecService.list();
for (ZtStoryUserspec ztStoryspec : list) {
if(!StringUtils.isEmpty(ztStoryspec.getSpec())){
System.out.println(ztStoryspec);
System.out.println(ztStoryspec);
// 正则表达式匹配Base64图片
String pattern = "<img\\s+src=\"data:image/[^;]+;base64,[^\"]+\"\\s*/?>";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(ztStoryspec.getSpec());
String s = base64ImageSaver.saveBase64Images(ztStoryspec.getSpec());
ztStoryspec.setSpec(s);
LambdaUpdateWrapper<ZtStoryUserspec> lambda1 = new UpdateWrapper<ZtStoryUserspec>().lambda();
lambda1.set(ZtStoryUserspec::getSpec,s);
lambda1.eq(ZtStoryUserspec::getStory,ztStoryspec.getStory());
ztStoryUserSpecService.update(lambda1);
System.out.println("<UNK>" + s + "<UNK>");
}
}
}
private void handStoryFeedback(){
// ZtStory byId = this.ztStoryService.getById(6493);
// LambdaQueryWrapper<ZtStoryspec> lambda = new QueryWrapper<ZtStoryspec>().lambda();
// lambda.eq(ZtStoryspec::getStory,6493);
List<ZtStoryFeedback> list = ztStoryFeedbackService.list();
for (ZtStoryFeedback ztStoryspec : list) {
if(!StringUtils.isEmpty(ztStoryspec.getRemark())){
System.out.println(ztStoryspec);
System.out.println(ztStoryspec);
// 正则表达式匹配Base64图片
String pattern = "<img\\s+src=\"data:image/[^;]+;base64,[^\"]+\"\\s*/?>";
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("<UNK>" + s + "<UNK>");
}
}
}
public void handTask(){
// ZtStory byId = this.ztStoryService.getById(6493);
// LambdaQueryWrapper<ZtStoryspec> lambda = new QueryWrapper<ZtStoryspec>().lambda();
// lambda.eq(ZtStoryspec::getStory,6493);
List<ZtTask> list = ztTaskService.list();
for (ZtTask ztStoryspec : list) {
if(!StringUtils.isEmpty(ztStoryspec.getDesc())){
System.out.println(ztStoryspec);
System.out.println(ztStoryspec);
// 正则表达式匹配Base64图片
String pattern = "<img\\s+src=\"data:image/[^;]+;base64,[^\"]+\"\\s*/?>";
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("<UNK>" + s + "<UNK>");
}
}
}
public void handBug(){
// ZtStory byId = this.ztStoryService.getById(6493);
// LambdaQueryWrapper<ZtStoryspec> lambda = new QueryWrapper<ZtStoryspec>().lambda();
// lambda.eq(ZtStoryspec::getStory,6493);
List<ZtBug> 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 = "<img\\s+src=\"data:image/[^;]+;base64,[^\"]+\"\\s*/?>";
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("<UNK>" + s + "<UNK>");
}
}
}
}

View File

@ -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 = "<img\\s+src=\"data:image/([^;]+);base64,([^\"]+)\"\\s*/?>";
/**
* 从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 = "<img src=\""+ baseUrl+"/zentao/img/"+fName+ "\">";
m.appendReplacement(sb, replacement);
counter++;
System.out.println("图片保存成功: " + os+fName);
} catch (IOException e) {
System.err.println("保存图片失败: " + e.getMessage());
}
}
m.appendTail(sb);
System.out.println("<UNK>: " + sb.toString());
return sb.toString();
}
}

View File

@ -33,6 +33,11 @@ import java.util.stream.Collectors;
@RequestMapping("/common")
public class CommonsController {
@PostMapping("/test")
public Result<String> test( UploadDTO file){
System.out.println(file);
return Result.success();
}
// @PostMapping("/upload")
// public Result<String> 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();

View File

@ -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<PageInfo> searchByName(@RequestBody SearchQo qo){
PageInfo<SearchDTO> searchDTOPageInfo = ztStoryService.searchByName(qo);
return Result.success(searchDTOPageInfo);
}
//迭代列表根据项目id

View File

@ -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

View File

@ -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;
}

View File

@ -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<Integer> testIds;
}

View File

@ -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;
}

View File

@ -120,4 +120,8 @@ public class ZtStoryUserTaskDTO implements Serializable {
private String status;
private String desc;
/**
* 交付物
*/
private String deliverContent;
}

View File

@ -114,4 +114,8 @@ public class ZtStoryUserTask implements Serializable {
//wait 未开始 doing 进行中 finished 完成 cancel取消 closed
@TableField("`status`")
private String status;
/**
* 交付物
*/
private String deliverContent;
}

View File

@ -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<ZtStory> {
//pids 产品id
List<ZtStory> getStoryListByDatePidsProject(@Param("ids")List<Integer> pids, @Param("project")Integer project
, @Param("start")Date firstDayOfMonth, @Param("end")Date lastDayOfMonth);
List<SearchDTO> searchBug(@Param("keyword") String keyword);
List<SearchDTO> searchTask(@Param("keyword") String keyword);
List<SearchDTO> searchStory(@Param("keyword") String keyword);
List<SearchDTO> searchFeedback(@Param("keyword") String keyword);
/**
*
* @param keyword 搜索内容
* @return
*/
List<SearchDTO> searchUserStory(@Param("keyword") String keyword);
/**
*
* @param keyword 搜索内容
* @return
*/
List<SearchDTO> searchAll(@Param("keyword") String keyword,@Param("pIds")List<Integer> pIds);
}

View File

@ -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;
}

View File

@ -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<ZtStory> {
PageInfo<ZtStoryDTO> projectStoryPageList(ZtProjectQo qo);
List<ZtStoryDTO> storyNoSyncProject(ZtProjectQo qo);
//未开始
void waitStory(Integer story);
void startStory(Integer story);
@ -100,4 +103,6 @@ public interface IZtStoryService extends IService<ZtStory> {
public Map<Integer, ZtStoryCaseDTO> getStoryCaseMap(List<ZtStoryDTO> list);
List<ZtStory> getStoryListByDatePidsProject(List<Integer> pids, Integer id, Date firstDayOfMonth, Date lastDayOfMonth);
PageInfo<SearchDTO> searchByName(SearchQo qo);
}

View File

@ -11,6 +11,7 @@ import com.sa.zentao.qo.StoryQo;
import com.sa.zentao.qo.ZtProjectQo;
import java.util.List;
import java.util.Map;
/**
* <p>
@ -26,6 +27,8 @@ public interface IZtStoryUserService extends IService<ZtStoryUser> {
public void editStory(ZtStoryUserDTO dto);
public Map<String,List<ZtStoryUserDTO>> getKanban(Integer productId);
PageInfo<ZtStoryUserDTO> pageList(StoryQo dto);
void changeStatus(ZtStoryUserDTO dto);

View File

@ -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<ZtStoryUser> list = null;
List<ZtStory> ztStory = null;
@ -208,19 +208,6 @@ public class IZtCountService {
list = new ArrayList<>();
ztStory = new ArrayList<>();
}
// } else {
// list = this.storyUserService.list(new QueryWrapper<ZtStoryUser>().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<ZtStory>()
// .lambda().eq(ZtStory::getDeleted, "0")
// .ne(ZtStory::getStatus, "closed")
// );
// }
// }
List<ZtProduct> products = this.productService.list(new QueryWrapper<ZtProduct>().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> 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<ZtBug> releaseBugs = this.bugService.bugListByTestUser(null, firstDayOfMonth, lastDayOfMonth,csAccountIds, BugTypeEnums.RELEASE);
//获取测试需求
List<ZtStory> cswcStoryList = CollectionUtils.isEmpty(csAccountIds)?Collections.EMPTY_LIST:this.storyService.list(new QueryWrapper<ZtStory>().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<ZtBug> releaseBugs = this.bugService.bugListByTestUser(null, firstDayOfMonth, lastDayOfMonth,csAccountIds , BugTypeEnums.RELEASE);
//获取测试需求
List<ZtStory> cswcStoryList = CollectionUtils.isEmpty(csAccountIds)?Collections.EMPTY_LIST:this.storyService.list(new QueryWrapper<ZtStory>().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<ZtBug> releaseBugs = this.bugService.bugListByTestUser(null, firstDayOfMonth, lastDayOfMonth, Arrays.asList(u.getAccount()), BugTypeEnums.RELEASE);
//获取测试需求
List<ZtStory> cswcStoryList = this.storyService.list(new QueryWrapper<ZtStory>().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);

View File

@ -432,12 +432,16 @@ public class ZtProductServiceImpl extends ServiceImpl<ZtProductMapper, ZtProduct
List<ZtProject> ztProjects = this.projectService.listByIds(projectproductlist.stream().map(o -> o.getProject()).collect(Collectors.toList()));
result.put("project",ztProjects);
List<ZtExecutionproject> list = this.executionprojectService.list(new QueryWrapper<ZtExecutionproject>().lambda().in(ZtExecutionproject::getProject, ztProjects.stream().map(o -> o.getId()).collect(Collectors.toList())));
List<ZtProject> execList = this.projectService
List<ZtProject> execList = new ArrayList<>();
if(!CollectionUtils.isEmpty(list)){
execList=this.projectService
.list(new QueryWrapper<ZtProject>().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<ZtProductMapper, ZtProduct
result=this.storyUserService.getById(dto.getSearchId());
}else if("bug".equals(dto.getSearchType())){
result=this.bugService.getById(dto.getSearchId());
} if("feedback".equals(dto.getSearchType())){
result=this.storyFeedbackService.getById(dto.getSearchId());
}
return result;

View File

@ -1,10 +1,12 @@
package com.sa.zentao.service.impl;
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.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
@ -14,15 +16,14 @@ import com.sa.zentao.dao.*;
import com.sa.zentao.entity.*;
import com.sa.zentao.enums.*;
import com.sa.zentao.mapper.ZtStoryMapper;
import com.sa.zentao.qo.KanbanQo;
import com.sa.zentao.qo.ZtBugQo;
import com.sa.zentao.qo.ZtProjectQo;
import com.sa.zentao.qo.ZtReleaseQo;
import com.sa.zentao.qo.*;
import com.sa.zentao.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sa.zentao.utils.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -30,6 +31,9 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
/**
@ -282,6 +286,7 @@ public class ZtStoryServiceImpl extends ServiceImpl<ZtStoryMapper, ZtStory> impl
}
}
}
private void storyYsFalseSendMessage(Integer id, List<String> newUsers) {
if (!CollectionUtils.isEmpty(newUsers)) {
for (String u : newUsers) {
@ -291,6 +296,7 @@ public class ZtStoryServiceImpl extends ServiceImpl<ZtStoryMapper, ZtStory> impl
}
}
}
private ZtStoryspec buildSpec(ZtStoryDTO dto, ZtStory s) {
ZtStoryspec spec = new ZtStoryspec();
@ -577,8 +583,8 @@ public class ZtStoryServiceImpl extends ServiceImpl<ZtStoryMapper, ZtStory> 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");
@ -863,6 +869,107 @@ public class ZtStoryServiceImpl extends ServiceImpl<ZtStoryMapper, ZtStory> impl
public List<ZtStory> getStoryListByDatePidsProject(List<Integer> pids, Integer id, Date firstDayOfMonth, Date lastDayOfMonth) {
return this.baseMapper.getStoryListByDatePidsProject(pids, id, firstDayOfMonth, lastDayOfMonth);
}
@Autowired
private SqlSession sqlSession;
@Override
public PageInfo<SearchDTO> searchByName(SearchQo qo) {
Page<SearchDTO> page = PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize());
// 1 用户需求 2研发需求 3 任务 4 问题反馈 5 bug
List<SearchDTO> searchDTOS = new ArrayList<>();
List<Integer> 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;i<split.length;i++) {
builder.append(" (");
if(split[i].equals("1")){
builder.append("SELECT id,st.title name, spc.spec spec,spc.verify verify,1 type,openedDate from zt_story_user st " +
" LEFT JOIN zt_story_userspec 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("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<Map<String, Object>> result = SqlRunner.db().selectList(builder.toString());
for (Map<String, Object> 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<SearchDTO> searchDTOPageInfo = new PageInfo<>(searchDTOS);
searchDTOPageInfo.setTotal(total);
return searchDTOPageInfo;
}
private List<SearchDTO> searchBug(SearchQo qo) {
return this.baseMapper.searchBug(qo.getKeyword());
}
private List<SearchDTO> searchTask(SearchQo qo) {
return this.baseMapper.searchTask(qo.getKeyword());
}
private List<SearchDTO> searchStory(SearchQo qo) {
return this.baseMapper.searchStory(qo.getKeyword());
}
private List<SearchDTO> searchFeedback(SearchQo qo) {
return this.baseMapper.searchFeedback(qo.getKeyword());
}
private List<SearchDTO> searchUserStory(SearchQo qo) {
return this.baseMapper.searchUserStory(qo.getKeyword());
}
private List<SearchDTO> searchAll(SearchQo qo,List<Integer> pIds) {
return this.baseMapper.searchAll(qo.getKeyword(),pIds);
}
private Map<Integer, List<ZtTask>> getTaskCountMap(List<ZtStoryDTO> list) {
@ -1208,7 +1315,6 @@ public class ZtStoryServiceImpl extends ServiceImpl<ZtStoryMapper, ZtStory> impl
String ysUser = ztStory.getYsUser();
for (Integer execId : execIds) {
if (execId != null) {
this.kanbanlaneService.changeStatus(execId, ztStory.getId(), "story", "released");
@ -1235,14 +1341,18 @@ public class ZtStoryServiceImpl extends ServiceImpl<ZtStoryMapper, ZtStory> impl
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) {
ZtStory ztStory = this.getById(story);
if(ztStory == null) {
return;
}
if (ztStory != null && ztStory.getStatus().equals("closed")) {
return;
}
if (type != TaskType.test && type != TaskType.devel) {
return;
// return;
}
if (story == null || story == 0) {
return;
@ -1332,8 +1442,6 @@ public class ZtStoryServiceImpl extends ServiceImpl<ZtStoryMapper, ZtStory> impl
.eq(ZtTask::getType, TaskType.devel.getCode()));
if (CollectionUtils.isEmpty(develList) && CollectionUtils.isEmpty(testList)) {
long done = taskService.count(new QueryWrapper<ZtTask>().lambda().eq(ZtTask::getStory, story)
.eq(ZtTask::getType, type.getCode())
@ -1368,6 +1476,28 @@ public class ZtStoryServiceImpl extends ServiceImpl<ZtStoryMapper, ZtStory> impl
this.finishStory(story, finishBy);
}
}
} else {
//开发测试任务
long kfTaskCount = taskService.count(new QueryWrapper<ZtTask>().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<ZtTask>().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<Integer> executionId = this.getExecutionId(ztStory);
for (Integer execution : executionId) {
kanbanlaneService.changeStatus(execution, story, "story", srotyType);
}
}
}
@ -1656,7 +1786,6 @@ public class ZtStoryServiceImpl extends ServiceImpl<ZtStoryMapper, ZtStory> impl
}
if (!CollectionUtils.isEmpty(list)) {
Map<Integer, List<ZtStoryreviewDTO>> rMap = getReviewMap(list);

View File

@ -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<ZtStoryUserMapper, ZtSto
}
@Override
public Map<String, List<ZtStoryUserDTO>> getKanban(Integer productId) {
List<ZtStoryUser> ztStoryUsers = this.baseMapper.selectList(new QueryWrapper<ZtStoryUser>().lambda().eq(ZtStoryUser::getProduct, productId).orderByDesc(ZtStoryUser::getId));
Map<String, List<ZtStoryUserDTO>> map = new HashMap<>();
Map<String, ZtUser> stringZtUserMap = this.userService.userMapByIds(ztStoryUsers.stream().map(o -> o.getOpenedby()).collect(Collectors.toList()));
List<ZtStoryUserDTO> ztStoryUserDTOS = BeanCopyUtil.copyListProperties(ztStoryUsers, ZtStoryUserDTO::new, new BeanCopyUtilCallBack<ZtStoryUser, ZtStoryUserDTO>() {
@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<ZtStoryUserDTO> pageList(StoryQo qo) {

View File

@ -296,16 +296,9 @@ public class ZtStoryUserTaskServiceImpl extends ServiceImpl<ZtStoryUserTaskMapp
ztStoryUserTask.setLastEditedDate(new Date());
ztStoryUserTask.setFinishedby(RiskUserThreadLocal.get().getName());
ztStoryUserTask.setFinisheddate(new Date());
ztStoryUserTask.setDeliverContent(dto.getDeliverContent());
this.baseMapper.updateById(ztStoryUserTask);
// if("improve".equals(ztStoryUserTask.getType())){
// //需要会议
// if ((dto.getNeedMeeting()!=null&&dto.getNeedMeeting()==2)&&(dto.getNeedDesign()!=null&&dto.getNeedDesign()==1)){
// //用户状态待沟通 需要详细设计
// this.add(dto.getInfo());
// }
// }
ZtEffort e=new ZtEffort();
e.setObjectid(ztStoryUserTask.getId());
@ -316,10 +309,18 @@ public class ZtStoryUserTaskServiceImpl extends ServiceImpl<ZtStoryUserTaskMapp
e.setDate(new Date());
effortService.save(e);
if("improve".equals(ztStoryUserTask.getType())&&StringUtils.isNotBlank(dto.getDeliverContent())){
actionService.addAction(ActionType.STORYUSERTASK, ActionStatus.MQXU, ztStoryUserTask.getId()
, ztStoryUserTask.getProduct().toString(), null, null,
RiskUserThreadLocal.get().getName(),dto.getDeliverContent(), null);
actionService.addAction(ActionType.USERXQ, ActionStatus.MQXU, ztStoryUserTask.getUserStoryId()
, ztStoryUserTask.getProduct().toString(), null, null,
RiskUserThreadLocal.get().getName(),dto.getDeliverContent(), null);
}
actionService.addAction(ActionType.STORYUSERTASK, ActionStatus.WC, ztStoryUserTask.getId()
, ztStoryUserTask.getProduct().toString(), null, null,
RiskUserThreadLocal.get().getName(),dto.getDesc(), null);
}
@Override

View File

@ -912,23 +912,7 @@ public class ZtTaskServiceImpl extends ServiceImpl<ZtTaskMapper, ZtTask> 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<ZtTaskMapper, ZtTask> 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());

View File

@ -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:

View File

@ -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:

View File

@ -37,8 +37,10 @@ mybatis:
typeEnumsPackage: com.sa.zentao.enums
file:
path:
windows: D:\files
linux: /files
mybatis-plus:
global-config:
enable-sql-runner: true

View File

@ -1209,4 +1209,68 @@
</if>
</select>
<select id="searchBug" resultType="com.sa.zentao.dao.SearchDTO">
SELECT id,title name, steps spec,5 type,openedDate from zt_bug WHERE 1=1 and (title like concat('%', #{keyword}, '%') or steps like concat('%', #{keyword}, '%') ) order by id desc
</select>
<select id="searchTask" resultType="com.sa.zentao.dao.SearchDTO">
SELECT id,name name, `desc` spec,3 type,openedDate from zt_task WHERE 1=1 and (name like concat('%', #{keyword}, '%') or `desc` like concat('%', #{keyword}, '%') ) order by id desc
</select>
<select id="searchStory" resultType="com.sa.zentao.dao.SearchDTO">
SELECT id,st.title name, spc.spec spec,spc.verify verify,2 type,openedDate from zt_story st,zt_storyspec spc WHERE 1=1 and st.id=spc.story and (spc.spec like concat('%', #{keyword}, '%') or spc.verify like concat('%', #{keyword}, '%') ) order by id desc
</select>
<select id="searchFeedback" resultType="com.sa.zentao.dao.SearchDTO">
SELECT id,remark name, spec spec,4 type,opened_date from zt_story_feedback WHERE 1=1 and (remark like concat('%', #{keyword}, '%') or spec like concat('%', #{keyword}, '%') ) order by id desc
</select>
<select id="searchUserStory" resultType="com.sa.zentao.dao.SearchDTO">
SELECT id,st.title name, spc.spec spec,spc.verify verify,1 type,openedDate from zt_story_user st,zt_story_userspec spc WHERE 1=1 and st.id=spc.story and (spc.spec like concat('%', #{keyword}, '%') or spc.verify like concat('%', #{keyword}, '%') ) order by id desc
</select>
<select id="searchAll" resultType="com.sa.zentao.dao.SearchDTO">
(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 (spc.spec like concat('%', #{keyword}, '%') or spc.verify like concat('%', #{keyword}, '%') or st.title like concat('%', #{keyword}, '%') )
and st.product in
<foreach collection="pIds" item="id" index="index"
open="(" close=")" separator=",">
#{id}
</foreach>
order by id desc )
UNION
(SELECT id,title name, steps spec,'' verify,5 type,openedDate from zt_bug
WHERE 1=1 and (title like concat('%', #{keyword}, '%') or steps like concat('%', #{keyword}, '%') )
and product in
<foreach collection="pIds" item="id" index="index"
open="(" close=")" separator=",">
#{id}
</foreach>
order by id desc )
UNION
(SELECT id,remark name, spec spec,'' verify,4 type,opened_date from zt_story_feedback
WHERE 1=1 and (remark like concat('%', #{keyword}, '%') or spec like concat('%', #{keyword}, '%') )
and product in
<foreach collection="pIds" item="id" index="index"
open="(" close=")" separator=",">
#{id}
</foreach>
order by id desc )
UNION
(SELECT id,name name, `desc` spec,'' verify,3 type,openedDate from zt_task
WHERE 1=1 and (name like concat('%', #{keyword}, '%') or `desc` like concat('%', #{keyword}, '%') )
and product in
<foreach collection="pIds" item="id" index="index"
open="(" close=")" separator=",">
#{id}
</foreach>
order by id desc )
UNION
(SELECT id,st.title name, spc.spec spec,spc.verify verify,1 type,openedDate from zt_story_user st left join zt_story_userspec spc on st.id=spc.story
WHERE 1=1
and product in
<foreach collection="pIds" item="id" index="index"
open="(" close=")" separator=",">
#{id}
</foreach>
and (spc.spec like concat('%', #{keyword}, '%') or spc.verify like concat('%', #{keyword}, '%') or st.title like concat('%', #{keyword}, '%') ) order by id desc )
</select>
</mapper>