Merge pull request '社区版项目管理' (#960) from wanjia9506/microservices:dev_issues_transform into master

This commit is contained in:
wanjia9506 2025-07-28 14:22:51 +08:00
commit a1fdb1ed31
16 changed files with 617 additions and 4 deletions

View File

@ -0,0 +1,24 @@
package com.microservices.pms.enums;
public enum PmsIssueTransformationCommentType {
REQUIREMENT("requirement", "需求阶段"),
DEVELOPMENT("development", "开发阶段"),
TESTING("testing", "测试阶段");
private final String key;
private final String name;
PmsIssueTransformationCommentType(String key, String name) {
this.key = key;
this.name = name;
}
public String getKey() {
return key;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,95 @@
package com.microservices.pms.project.controller;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.pms.project.service.PmsForgeApiForwardService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import static com.microservices.common.core.web.domain.AjaxResult.success;
@RestController
@RequestMapping("/{enterpriseIdentifier}/forge")
@Api(tags = "项目管理-直接转发forge相关接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "enterpriseIdentifier", value = "企业标识", paramType = "path", dataType = "String")
})
public class PmsForgeApiForwardController {
@Autowired
private PmsForgeApiForwardService pmsForgeApiForwardService;
@GetMapping("/projects")
@ApiOperation("代码库列表")
@ApiParam(name = "projectSearchInputVo",
value = "【字段说明】:更多入参参考forge接口文档\n" +
"page:页码默认为1;\n" +
"limit:每页记录数默认为15;\n" +
"sort_by:排序字段如updated_on;\n" +
"sort_direction:排序方向asc升序或desc降序;\n" +
"is_public:是否公开项目true或false;\n" +
"keyword:代码库名称关键字")
public AjaxResult listProjects(@PathVariable String enterpriseIdentifier, JSONObject projectSearchInputVo)
{
JSONObject result = pmsForgeApiForwardService.selectForgeRepositoryList(enterpriseIdentifier, projectSearchInputVo);
return success(result);
}
@GetMapping("{owner}/{repo}/project")
@ApiOperation("代码库详情")
public AjaxResult getProject(@ApiParam(name = "repo", value = "仓库标识") @PathVariable String repo,
@ApiParam(name = "owner", value = "仓库拥有者") @PathVariable String owner) {
JSONObject result = pmsForgeApiForwardService.selectForgeProject(repo, owner);
return success(result);
}
@GetMapping("{owner}/{repo}/issues")
@ApiOperation("疑修列表")
@ApiParam(name = "issueSearch",
value = "【字段说明】:更多入参参考forge接口文档\n" +
"page:页码默认为1;\n" +
"limit:每页记录数默认为15;\n" +
"sort_by:排序字段如updated_on;\n" +
"sort_direction:排序方向asc升序或desc降序;\n" +
"participant_category:参与类型all 全部 aboutme 关于我的 authoredme 我创建的 assignedme 我负责的 atme @我的;\n" +
"category:疑修类型all 全部 opened 开启中 closed 已关闭;"
)
public AjaxResult listIssues(@ApiParam(name = "repo", value = "仓库标识") @PathVariable String repo,
@ApiParam(name = "owner", value = "仓库拥有者") @PathVariable String owner,
JSONObject issueSearch) {
JSONObject result = pmsForgeApiForwardService.selectForgeIssueList(issueSearch);
return success(result);
}
@GetMapping("{owner}/{repo}/issues/{issue_id}")
@ApiOperation("疑修详情")
public AjaxResult getIssue(@ApiParam(name = "repo", value = "仓库标识") @PathVariable String repo,
@ApiParam(name = "owner", value = "仓库拥有者") @PathVariable String owner,
@ApiParam(name = "issue_id", value = "疑修id") @PathVariable String issue_id) {
JSONObject result = pmsForgeApiForwardService.selectForgeIssue(repo, owner, issue_id);
return success(result);
}
@PatchMapping("{owner}/{repo}/issues/{issue_id}")
@ApiOperation("更新疑修")
public AjaxResult updateIssue(@ApiParam(name = "repo", value = "仓库标识") @PathVariable String repo,
@ApiParam(name = "owner", value = "仓库拥有者") @PathVariable String owner,
@ApiParam(name = "issue_id", value = "疑修id") @PathVariable String issue_id,
@Validated @RequestBody JSONObject issue) {
JSONObject result = pmsForgeApiForwardService.updateForgeIssue(repo, owner, issue_id, issue);
return success(result);
}
@GetMapping("{owner}/{repo}/{issue_url}")
@ApiOperation("疑修相关枚举")
public AjaxResult getIssueEnum(@ApiParam(name = "repo", value = "仓库标识") @PathVariable String repo,
@ApiParam(name = "owner", value = "仓库拥有者") @PathVariable String owner,
@ApiParam(name = "issue_url", value = "疑修url") @PathVariable String issue_url,
@ApiParam(name = "only_name", value = "是否只返回名称") Boolean only_name) {
JSONObject result = pmsForgeApiForwardService.getIssueRelatedEnum(repo, owner, issue_url, only_name);
return success(result);
}
}

View File

@ -396,4 +396,16 @@ public class PmsProjectIssuesController extends BaseController {
boolean result = pmsProjectIssuesService.updateIssueEnterpriseIdentifier();
return success(result);
}
/**
* 添加社区疑修与项目工作项关联
*/
@RequiresPermissions(value = {"pms:pmsProjectIssues:edit", "pms:pmsProjectIssues:add"}, logical = Logical.OR)
@PostMapping("/repoLink")
@ApiOperation(value = "添加社区疑修与项目工作项关联")
public AjaxResult addRepoIssueLinks(@RequestBody PmsRepoIssueLinkProjectIssuesVo pmsRepoIssueLinkProjectIssuesVo) {
JSONObject result = pmsProjectIssuesService.addRepoIssueLink(pmsRepoIssueLinkProjectIssuesVo);
return success(result);
}
}

View File

@ -0,0 +1,14 @@
package com.microservices.pms.project.domain;
import lombok.Data;
@Data
public class PmsIssueTransformationCommentRecord {
private Long id;
private Long gitlinkIssueId;
private String commentType;
private Boolean hasComment;
}

View File

@ -0,0 +1,13 @@
package com.microservices.pms.project.domain;
import lombok.Data;
@Data
public class PmsIssuesLinkedCount {
private Integer linkedRequirementsCount;
private Integer linkedTasksCount;
private Integer linkedBugsCount;
}

View File

@ -0,0 +1,22 @@
package com.microservices.pms.project.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("社区疑修关联项目管理工作项对象")
public class PmsRepoIssueLinkProjectIssuesVo {
@ApiModelProperty("社区仓库Id")
private Long projectRepositoryId;
@ApiModelProperty("社区工作项id")
private Long issueId;
@ApiModelProperty("被关联的工作ids")
private Long[] linkIssueIds;
@ApiModelProperty("项目id")
private Long pmProjectId;
}

View File

@ -2,9 +2,12 @@ package com.microservices.pms.project.mapper;
import com.microservices.common.datasource.annotation.Slave;
import com.microservices.pms.project.domain.ForgeIssues;
import com.microservices.pms.project.domain.PmsIssuesLinkedCount;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Set;
/**
* 用户表 数据层
@ -18,4 +21,15 @@ public interface ForgeIssuesMapper {
List<ForgeIssues> getBriefIssues();
int updateForIssues(ForgeIssues forgeIssues);
// 查询指定linkableId直接关联的所有工作项
List<Long> selectDirectLinkedIssues(@Param("linkableId") Long linkableId,
@Param("linkableType") String linkableType,
@Param("beLinkableType") String beLinkableType);
// 批量查询多个linkableId关联的所有工作项
List<Long> selectLinkedIssuesByLinkableIds(@Param("linkableIds") List<Long> linkableIds,
@Param("beLinkableType") String beLinkableType);
PmsIssuesLinkedCount getIssuesLinkedCount(@Param("linkIssueIdSet") Set<Long> linkIssueIdSet);
}

View File

@ -0,0 +1,16 @@
package com.microservices.pms.project.mapper;
import com.microservices.pms.project.domain.PmsIssueTransformationCommentRecord;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface PmsIssueTransformationCommentRecordMapper {
boolean insertSelective(PmsIssueTransformationCommentRecord record);
boolean deleteByGitlinkIssueIdAndCommentType(PmsIssueTransformationCommentRecord record);
List<PmsIssueTransformationCommentRecord> selectByGitlinkIssueId(@Param("gitlinkIssueId") Long gitlinkIssueId);
}

View File

@ -0,0 +1,9 @@
package com.microservices.pms.project.service;
import com.microservices.pms.project.domain.PmsIssueTransformationCommentRecord;
public interface IPmsIssueTransformationCommentRecordService {
boolean updateByGitlinkIssueId(PmsIssueTransformationCommentRecord record);
}

View File

@ -0,0 +1,50 @@
package com.microservices.pms.project.service;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.pms.utils.PmsGitLinkRequestUrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.net.URISyntaxException;
@Service
public class PmsForgeApiForwardService {
@Autowired
private GitLinkRequestHelper gitLinkRequestHelper;
public JSONObject selectForgeRepositoryList(String enterpriseIdentifier, JSONObject projectSearchInputVo) {
try {
return gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_ORGANIZATION_PUBLIC_REPO_LIST(enterpriseIdentifier, projectSearchInputVo));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
public JSONObject selectForgeIssueList(JSONObject issueSearch) {
try {
return gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_ISSUE_LIST(issueSearch));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
public JSONObject selectForgeIssue(String repo, String owner, String issueId) {
return gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_ISSUE_DETAILS(repo, owner, issueId));
}
public JSONObject updateForgeIssue(String repo, String owner, String issueId, JSONObject issue) {
return gitLinkRequestHelper.doPatch(PmsGitLinkRequestUrl.UPDATE_ISSUE(repo, owner, issueId), issue);
}
public JSONObject selectForgeProject(String repo, String owner) {
return gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_PROJECT_DETAILS(repo, owner));
}
public JSONObject getIssueRelatedEnum(String repo, String owner, String issueUrl, Boolean only_name) {
return gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_ISSUE_RELATED_ENUM(repo, owner, issueUrl, only_name));
}
}

View File

@ -0,0 +1,178 @@
package com.microservices.pms.project.service;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.pms.enums.PmsIssueTransformationCommentType;
import com.microservices.pms.project.domain.PmsIssueTransformationCommentRecord;
import com.microservices.pms.project.domain.PmsIssuesLinkedCount;
import com.microservices.pms.project.domain.SimpleRepository;
import com.microservices.pms.project.domain.vo.PmsRepoIssueLinkProjectIssuesVo;
import com.microservices.pms.project.mapper.ForgeIssuesMapper;
import com.microservices.pms.project.mapper.PmsIssueTransformationCommentRecordMapper;
import com.microservices.pms.utils.PmsGitLinkRequestUrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
public class PmsLinkIssuesAsyncCommentService {
@Autowired
private PmsIssueTransformationCommentRecordMapper pmsIssueTransformationCommentRecordMapper;
@Autowired
private ForgeIssuesMapper forgeIssuesMapper;
@Lazy
@Autowired
private PmsProjectIssuesService pmsProjectIssuesService;
@Autowired
private GitLinkRequestHelper gitLinkRequestHelper;
@Autowired
private IPmsIssueTransformationCommentRecordService pmsIssueTransformationCommentRecordService;
@Async
public void asyncIssueComment(PmsRepoIssueLinkProjectIssuesVo pmsRepoIssueLinkProjectIssuesVo, Long issueId, Long[] linkIssueIds) {
List<PmsIssueTransformationCommentRecord> records = pmsIssueTransformationCommentRecordMapper.selectByGitlinkIssueId(issueId);
boolean requirementCommented = false;
boolean developmentCommented = false;
boolean testingCommented = false;
// 检查已存在的评论记录
for (PmsIssueTransformationCommentRecord record : records) {
if (PmsIssueTransformationCommentType.REQUIREMENT.getKey().equals(record.getCommentType()) && record.getHasComment()) {
requirementCommented = true;
}
if (PmsIssueTransformationCommentType.DEVELOPMENT.getKey().equals(record.getCommentType()) && record.getHasComment()) {
developmentCommented = true;
}
if (PmsIssueTransformationCommentType.TESTING.getKey().equals(record.getCommentType()) && record.getHasComment()) {
testingCommented = true;
}
}
// 获取关联项数量
Set<Long> linkIssueIdSet = this.getAllLinkedIssueIds(issueId, "Issue", "Issue");
if (linkIssueIdSet.isEmpty()) {
return;
}
PmsIssuesLinkedCount linkedCounts = forgeIssuesMapper.getIssuesLinkedCount(linkIssueIdSet);
boolean requirementCreated = linkedCounts.getLinkedRequirementsCount() > 0;
boolean developmentCreated = linkedCounts.getLinkedTasksCount() > 0;
boolean testingCreated = linkedCounts.getLinkedBugsCount() > 0;
// 获取仓库信息
SimpleRepository simpleRepository = pmsProjectIssuesService.getSimpleRepository(pmsRepoIssueLinkProjectIssuesVo.getProjectRepositoryId());
// 处理需求阶段评论
handleCommentIfNeeded(!requirementCommented, requirementCreated, "本疑修已纳入需求", issueId, simpleRepository);
// 处理开发阶段评论
handleCommentIfNeeded(!developmentCommented, developmentCreated, "本疑修正在开发中", issueId, simpleRepository);
// 处理测试阶段评论
handleCommentIfNeeded(!testingCommented, testingCreated, "本疑修正在测试中", issueId, simpleRepository);
// 更新评论状态记录
updateCommentRecordIfNecessary(requirementCommented, issueId, PmsIssueTransformationCommentType.REQUIREMENT);
updateCommentRecordIfNecessary(developmentCommented, issueId, PmsIssueTransformationCommentType.DEVELOPMENT);
updateCommentRecordIfNecessary(testingCommented, issueId, PmsIssueTransformationCommentType.TESTING);
}
/**
* 如果需要则添加评论
*/
private void handleCommentIfNeeded(boolean shouldComment, boolean isCreated, String note, Long issueId, SimpleRepository simpleRepository) {
if (shouldComment && isCreated) {
JSONObject journalsJson = new JSONObject();
journalsJson.put("notes", note);
gitLinkRequestHelper.doPost(
PmsGitLinkRequestUrl.ADD_REPO_ISSUE_JOURNAL(issueId,
simpleRepository.getRepoOwner(),
simpleRepository.getRepoIdentifier()),
journalsJson
);
}
}
/**
* 如有必要更新评论记录状态
*/
private void updateCommentRecordIfNecessary(boolean commented, Long issueId, PmsIssueTransformationCommentType type) {
if (!commented) {
PmsIssueTransformationCommentRecord update = new PmsIssueTransformationCommentRecord();
update.setGitlinkIssueId(issueId);
update.setCommentType(type.getKey());
update.setHasComment(true);
pmsIssueTransformationCommentRecordService.updateByGitlinkIssueId(update);
}
}
/**
* 递归查询所有关联的工作项ID
* @param linkableId 起始工作项ID
* @param linkableType 起始工作项类型
* @param beLinkableType 关联工作项类型
* @return 所有关联的工作项ID列表去重
*/
public Set<Long> getAllLinkedIssueIds(Long linkableId, String linkableType, String beLinkableType) {
Set<Long> allLinkedIssueIds = new HashSet<>();
// 递归查询所有关联的工作项
findLinkedIssuesRecursively(Arrays.asList(linkableId), linkableType, beLinkableType, allLinkedIssueIds, 0, 10);
// 移除起始工作项自身如果在结果中
allLinkedIssueIds.remove(linkableId);
return allLinkedIssueIds;
}
/**
* 递归查询关联的工作项
* @param linkableIds 当前层级的工作项ID列表
* @param linkableType 工作项类型
* @param beLinkableType 关联工作项类型
* @param result 结果集合
* @param currentDepth 当前递归深度
* @param maxDepth 最大递归深度
*/
private void findLinkedIssuesRecursively(List<Long> linkableIds,
String linkableType,
String beLinkableType,
Set<Long> result,
int currentDepth,
int maxDepth) {
// 防止无限递归
if (currentDepth >= maxDepth || linkableIds == null || linkableIds.isEmpty()) {
return;
}
// 查询当前层级关联的工作项
List<Long> linkedIssueIds;
// 后续层级查询多个工作项关联的工作项
linkedIssueIds = forgeIssuesMapper.selectLinkedIssuesByLinkableIds(linkableIds, beLinkableType);
// 如果没有更多关联的工作项结束递归
if (linkedIssueIds == null || linkedIssueIds.isEmpty() || linkedIssueIds.size() == result.size()) {
return;
}
// 将新发现的关联工作项添加到结果中
for (Long issueId : linkedIssueIds) {
if (!result.contains(issueId)) {
result.add(issueId);
}
}
// 递归查询下一层级
findLinkedIssuesRecursively(linkedIssueIds, linkableType, beLinkableType, result, currentDepth + 1, maxDepth);
}
}

View File

@ -12,15 +12,14 @@ import com.microservices.pms.dashboard.domain.vo.MyProjectIssuesSearchVo;
import com.microservices.pms.dashboard.domain.vo.MyTodoProjectIssuesSearchVo;
import com.microservices.pms.enterprise.domain.PmsEnterprise;
import com.microservices.pms.enterprise.service.IPmsEnterpriseService;
import com.microservices.pms.enums.PmsIssueTransformationCommentType;
import com.microservices.pms.enums.ProjectIssueStatus;
import com.microservices.pms.product.domain.enums.ProductReqStatus;
import com.microservices.pms.product.service.IPmsProductRequirementService;
import com.microservices.pms.project.domain.ForgeIssues;
import com.microservices.pms.project.domain.PmsIssueCompletion;
import com.microservices.pms.project.domain.PmsProject;
import com.microservices.pms.project.domain.SimpleRepository;
import com.microservices.pms.project.domain.*;
import com.microservices.pms.project.domain.vo.*;
import com.microservices.pms.project.mapper.*;
import com.microservices.pms.specialArea.service.SoftwareFactStatisticsServiceImpl;
import com.microservices.pms.utils.PmsConstants;
import com.microservices.pms.utils.PmsGitLinkRequestUrl;
import com.microservices.pms.utils.PmsUtils;
@ -87,6 +86,8 @@ public class PmsProjectIssuesService {
private ForgeIssuesMapper forgeIssuesMapper;
@Autowired
private PmsIssueCompletionMapper pmsIssueCompletionMapper;
@Autowired
private PmsLinkIssuesAsyncCommentService pmsLinkIssuesAsyncCommentService;
public JSONObject selectPmsProjectIssuesList(PmsProjectIssuesSearchVo pmsProjectIssuesSearchVo) {
@ -800,4 +801,15 @@ public class PmsProjectIssuesService {
}
return true;
}
public JSONObject addRepoIssueLink(PmsRepoIssueLinkProjectIssuesVo pmsRepoIssueLinkProjectIssuesVo) {
JSONObject params = new JSONObject();
Long[] linkIssueIds = pmsRepoIssueLinkProjectIssuesVo.getLinkIssueIds();
Long pmProjectId = pmsRepoIssueLinkProjectIssuesVo.getPmProjectId();
Long issueId = pmsRepoIssueLinkProjectIssuesVo.getIssueId();
params.put("link_ids", linkIssueIds);
JSONObject result = gitLinkRequestHelper.doPost(PmsGitLinkRequestUrl.ADD_ISSUE_LINK(issueId, pmProjectId), params);
pmsLinkIssuesAsyncCommentService.asyncIssueComment(pmsRepoIssueLinkProjectIssuesVo, issueId, linkIssueIds);
return result;
}
}

View File

@ -0,0 +1,22 @@
package com.microservices.pms.project.service.impl;
import com.microservices.pms.project.domain.PmsIssueTransformationCommentRecord;
import com.microservices.pms.project.mapper.PmsIssueTransformationCommentRecordMapper;
import com.microservices.pms.project.service.IPmsIssueTransformationCommentRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class PmsIssueTransformationCommentRecordServiceImpl implements IPmsIssueTransformationCommentRecordService {
@Autowired
private PmsIssueTransformationCommentRecordMapper pmsIssueTransformationCommentRecordMapper;
@Override
@Transactional
public boolean updateByGitlinkIssueId(PmsIssueTransformationCommentRecord record) {
pmsIssueTransformationCommentRecordMapper.deleteByGitlinkIssueIdAndCommentType(record);
return pmsIssueTransformationCommentRecordMapper.insertSelective(record);
}
}

View File

@ -469,4 +469,34 @@ public class PmsGitLinkRequestUrl extends GitLinkRequestUrl {
return getGitLinkRequestUrl(
buildUri("/api/pm/weekly_issues/personal_issues.json", issueSearch));
}
public static GitLinkRequestUrl ADD_REPO_ISSUE_JOURNAL(Long issueId, String owner, String repo) {
String path = String.format("/api/v1/%s/%s/issues/%s/journals", owner, repo, issueId);
return getGitLinkRequestUrl(path);
}
public static GitLinkRequestUrl GET_ORGANIZATION_PUBLIC_REPO_LIST(String enterpriseIdentifier, JSONObject projectSearchInputVo) throws URISyntaxException {
String path = String.format("/api/v1/%s/projects.json", enterpriseIdentifier);
return getGitLinkRequestUrl(buildUri(path, projectSearchInputVo));
}
public static GitLinkRequestUrl GET_ISSUE_DETAILS(String repo, String owner, String issueId) {
return getGitLinkRequestUrl(String.format("/api/v1/%s/%s/issues/%s", owner, repo, issueId));
}
public static GitLinkRequestUrl UPDATE_ISSUE(String repo, String owner, String issueId) {
return getGitLinkRequestUrl(String.format("/api/v1/%s/%s/issues/%s", owner, repo, issueId));
}
public static GitLinkRequestUrl GET_PROJECT_DETAILS(String repo, String owner) {
return getGitLinkRequestUrl(String.format("/api/%s/%s/simple.json", owner, repo));
}
public static GitLinkRequestUrl GET_ISSUE_RELATED_ENUM(String repo, String owner, String issueUrl, Boolean onlyName) {
String path = String.format("/api/v1/%s/%s/%s", owner, repo, issueUrl);
if (onlyName != null) {
path = path + "?only_name=" + onlyName;
}
return getGitLinkRequestUrl(path);
}
}

View File

@ -58,4 +58,53 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
issues
WHERE pm_project_id IS NOT NULL AND (enterprise_identifier IS NULL OR enterprise_identifier = '');
</select>
<!-- 查询指定linkableId直接关联的所有工作项 -->
<select id="selectDirectLinkedIssues" resultType="java.lang.Long">
SELECT be_linkable_id
FROM pm_links
WHERE linkable_id = #{linkableId}
AND linkable_type = #{linkableType}
AND be_linkable_type = #{beLinkableType}
</select>
<!-- 批量查询多个linkableId关联的所有工作项 -->
<select id="selectLinkedIssuesByLinkableIds" resultType="java.lang.Long">
SELECT DISTINCT be_linkable_id AS linkedIssueIds
FROM pm_links
WHERE be_linkable_type = #{beLinkableType}
AND (linkable_id IN
<foreach item="item" index="index" collection="linkableIds" open="(" separator="," close=")">
#{item}
</foreach>
OR be_linkable_id IN
<foreach item="item" index="index" collection="linkableIds" open="(" separator="," close=")">
#{item}
</foreach>)
UNION
SELECT DISTINCT linkable_id AS linkedIssueIds
FROM pm_links
WHERE be_linkable_type = #{beLinkableType}
AND (linkable_id IN
<foreach item="item" index="index" collection="linkableIds" open="(" separator="," close=")">
#{item}
</foreach>
OR be_linkable_id IN
<foreach item="item" index="index" collection="linkableIds" open="(" separator="," close=")">
#{item}
</foreach>)
</select>
<select id="getIssuesLinkedCount" resultType="com.microservices.pms.project.domain.PmsIssuesLinkedCount">
SELECT
COUNT(CASE WHEN pm_issue_type = 1 THEN 1 END) AS linkedRequirementsCount,
COUNT(CASE WHEN pm_issue_type = 2 THEN 1 END) AS linkedTasksCount,
COUNT(CASE WHEN pm_issue_type = 3 THEN 1 END) AS linkedBugsCount
FROM issues
WHERE id IN
<foreach item="item" index="index" collection="linkIssueIdSet" open="(" separator="," close=")">
#{item}
</foreach>
</select>
</mapper>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.microservices.pms.project.mapper.PmsIssueTransformationCommentRecordMapper">
<resultMap id="BaseResultMap" type="com.microservices.pms.project.domain.PmsIssueTransformationCommentRecord">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="gitlink_issue_id" property="gitlinkIssueId" jdbcType="INTEGER" />
<result column="comment_type" property="commentType" jdbcType="VARCHAR" />
<result column="has_comment" property="hasComment" jdbcType="BIT" />
</resultMap>
<delete id="deleteByGitlinkIssueIdAndCommentType">
DELETE FROM pms_issue_transformation_comment_record
WHERE comment_type = #{commentType} AND gitlink_issue_id = #{gitlinkIssueId}
</delete>
<insert id="insertSelective" parameterType="com.microservices.pms.project.domain.PmsIssueTransformationCommentRecord">
INSERT INTO pms_issue_transformation_comment_record
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="gitlinkIssueId != null">
gitlink_issue_id,
</if>
<if test="commentType != null">
comment_type,
</if>
<if test="hasComment != null">
has_comment,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="gitlinkIssueId != null">
#{gitlinkIssueId},
</if>
<if test="commentType != null">
#{commentType},
</if>
<if test="hasComment != null">
#{hasComment},
</if>
</trim>
</insert>
<select id="selectByGitlinkIssueId"
resultMap="BaseResultMap">
select id,
gitlink_issue_id,
comment_type,
has_comment
from pms_issue_transformation_comment_record
where gitlink_issue_id = #{gitlinkIssueId}
</select>
</mapper>