diff --git a/test-track/backend/src/main/java/io/metersphere/controller/IssuesController.java b/test-track/backend/src/main/java/io/metersphere/controller/IssuesController.java index 2e56185b4f..6ce3901cd7 100644 --- a/test-track/backend/src/main/java/io/metersphere/controller/IssuesController.java +++ b/test-track/backend/src/main/java/io/metersphere/controller/IssuesController.java @@ -153,9 +153,9 @@ public class IssuesController { return issuesService.getZentaoBuilds(request); } - @PostMapping("/sync") - public boolean getPlatformIssue(@RequestBody IssueSyncRequest request) { - return issuesService.syncThirdPartyIssues(request); + @GetMapping("/sync/{projectId}") + public boolean getPlatformIssue(@PathVariable String projectId) { + return issuesService.syncThirdPartyIssues(projectId); } @GetMapping("/sync/check/{projectId}") diff --git a/test-track/backend/src/main/java/io/metersphere/service/IssuesService.java b/test-track/backend/src/main/java/io/metersphere/service/IssuesService.java index 3314d1dbbc..6d75720813 100644 --- a/test-track/backend/src/main/java/io/metersphere/service/IssuesService.java +++ b/test-track/backend/src/main/java/io/metersphere/service/IssuesService.java @@ -886,9 +886,7 @@ public class IssuesService { List projectIds = trackProjectService.getThirdPartProjectIds(); projectIds.forEach(id -> { try { - IssueSyncRequest request = new IssueSyncRequest(); - request.setProjectId(id); - syncThirdPartyIssues(request); + syncThirdPartyIssues(id); } catch (Exception e) { LogUtil.error(e.getMessage(), e); } @@ -931,38 +929,35 @@ public class IssuesService { stringRedisTemplate.delete(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId); } - public boolean syncThirdPartyIssues(IssueSyncRequest syncRequest) { - if (StringUtils.isNotBlank(syncRequest.getProjectId())) { - String syncValue = getSyncKey(syncRequest.getProjectId()); + public boolean syncThirdPartyIssues(String projectId) { + if (StringUtils.isNotBlank(projectId)) { + String syncValue = getSyncKey(projectId); if (StringUtils.isNotEmpty(syncValue)) { return false; } - setSyncKey(syncRequest.getProjectId()); + setSyncKey(projectId); - Project project = baseProjectService.getProjectById(syncRequest.getProjectId()); - List issues = extIssuesMapper.getIssueForSync(syncRequest.getProjectId(), project.getPlatform()); - if (syncRequest.getCreateTime() != null) { - issues = filterSyncIssuesByCreated(issues, syncRequest); - } + Project project = baseProjectService.getProjectById(projectId); + List issues = extIssuesMapper.getIssueForSync(projectId, project.getPlatform()); if (CollectionUtils.isEmpty(issues)) { return true; } IssuesRequest issuesRequest = new IssuesRequest(); - issuesRequest.setProjectId(syncRequest.getProjectId()); + issuesRequest.setProjectId(projectId); issuesRequest.setWorkspaceId(project.getWorkspaceId()); try { if (!trackProjectService.isThirdPartTemplate(project)) { - String defaultCustomFields = getDefaultCustomFields(syncRequest.getProjectId()); + String defaultCustomFields = getDefaultCustomFields(projectId); issuesRequest.setDefaultCustomFields(defaultCustomFields); } if (PlatformPluginService.isPluginPlatform(project.getPlatform())) { // 分批处理 SubListUtil.dealForSubList(issues, 500, (subIssue) -> - syncPluginThirdPartyIssues(subIssue, project)); + syncPluginThirdPartyIssues(subIssue, project, issuesRequest.getDefaultCustomFields())); } else { IssuesPlatform platform = IssueFactory.createPlatform(project.getPlatform(), issuesRequest); syncThirdPartyIssues(platform::syncIssues, project, issues); @@ -970,13 +965,13 @@ public class IssuesService { } catch (Exception e) { throw e; } finally { - deleteSyncKey(syncRequest.getProjectId()); + deleteSyncKey(projectId); } } return true; } - public void syncPluginThirdPartyIssues(List issues, Project project) { + public void syncPluginThirdPartyIssues(List issues, Project project, String defaultCustomFields) { List platformIssues = JSON.parseArray(JSON.toJSONString(issues), PlatformIssuesDTO.class); platformIssues.stream().forEach(item -> { // 给缺陷添加自定义字段 @@ -991,6 +986,7 @@ public class IssuesService { }); SyncIssuesRequest request = new SyncIssuesRequest(); request.setIssues(platformIssues); + request.setDefaultCustomFields(defaultCustomFields); request.setProjectConfig(PlatformPluginService.getCompatibleProjectConfig(project)); Platform platform = platformPluginService.getPlatform(project.getPlatform()); @@ -999,38 +995,39 @@ public class IssuesService { List updateIssues = syncIssuesResult.getUpdateIssues(); SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); - IssuesMapper issueBatchMapper = sqlSession.getMapper(IssuesMapper.class); - AttachmentModuleRelationMapper batchAttachmentModuleRelationMapper = sqlSession.getMapper(AttachmentModuleRelationMapper.class); - - // 批量更新 - updateIssues.stream() - .map(item -> { - IssuesWithBLOBs issuesWithBLOBs = new IssuesWithBLOBs(); - BeanUtils.copyBean(issuesWithBLOBs, item); - return issuesWithBLOBs; - }) - .forEach(issueBatchMapper::updateByPrimaryKeySelective); - - // 批量删除 - syncIssuesResult.getDeleteIssuesIds() - .stream() - .forEach(issueBatchMapper::deleteByPrimaryKey); - try { - // 同步附件 - syncPluginIssueAttachment(platform, syncIssuesResult, batchAttachmentModuleRelationMapper); + IssuesMapper issueBatchMapper = sqlSession.getMapper(IssuesMapper.class); + AttachmentModuleRelationMapper batchAttachmentModuleRelationMapper = sqlSession.getMapper(AttachmentModuleRelationMapper.class); + + // 批量更新 + updateIssues.forEach(issueBatchMapper::updateByPrimaryKeySelective); + + // 批量删除 + syncIssuesResult.getDeleteIssuesIds() + .stream() + .forEach(issueBatchMapper::deleteByPrimaryKey); + + try { + // 同步附件 + syncPluginIssueAttachment(platform, syncIssuesResult, batchAttachmentModuleRelationMapper); + } catch (Exception e) { + LogUtil.error(e); + } + + HashMap> customFieldMap = new HashMap<>(); + updateIssues.forEach(item -> { + List customFieldResource = baseCustomFieldService.getCustomFieldResourceDTO(item.getCustomFields()); + customFieldMap.put(item.getId(), customFieldResource); + }); + + // 修改自定义字段 + customFieldIssuesService.batchEditFields(customFieldMap); + + sqlSession.commit(); } catch (Exception e) { - LogUtil.error(e); + sqlSession.close(); + MSException.throwException(e); } - - HashMap> customFieldMap = new HashMap<>(); - updateIssues.forEach(item -> { - List customFieldResource = baseCustomFieldService.getCustomFieldResourceDTO(item.getCustomFields()); - customFieldMap.put(item.getId(), customFieldResource); - }); - - // 修改自定义字段 - customFieldIssuesService.batchEditFields(customFieldMap); } private void syncPluginIssueAttachment(Platform platform, SyncIssuesResult syncIssuesResult, AttachmentModuleRelationMapper batchAttachmentModuleRelationMapper) { @@ -1049,8 +1046,8 @@ public class IssuesService { List syncAttachments = attachmentMap.get(issueId); for (PlatformAttachment syncAttachment : syncAttachments) { - jiraAttachmentSet.add(syncAttachment.getFileName()); if (!attachmentsNameSet.contains(syncAttachment.getFileName())) { + jiraAttachmentSet.add(syncAttachment.getFileName()); try { byte[] content = platform.getAttachmentContent(syncAttachment.getFileKey()); if (content == null) { diff --git a/test-track/backend/src/main/java/io/metersphere/service/wapper/IssueProxyResourceService.java b/test-track/backend/src/main/java/io/metersphere/service/wapper/IssueProxyResourceService.java index 6590022e1c..91a7913235 100644 --- a/test-track/backend/src/main/java/io/metersphere/service/wapper/IssueProxyResourceService.java +++ b/test-track/backend/src/main/java/io/metersphere/service/wapper/IssueProxyResourceService.java @@ -3,7 +3,6 @@ package io.metersphere.service.wapper; import io.metersphere.commons.exception.MSException; import io.metersphere.i18n.Translator; import io.metersphere.service.PlatformPluginService; -import io.metersphere.xpack.track.dto.request.IssuesRequest; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; @@ -35,10 +34,7 @@ public class IssueProxyResourceService { MSException.throwException(Translator.get("invalid_parameter")); } if (StringUtils.isNotBlank(platform)) { - IssuesRequest issuesRequest = new IssuesRequest(); - issuesRequest.setProjectId(projectId); - issuesRequest.setWorkspaceId(workspaceId); - return platformPluginService.getPlatform(platform) + return platformPluginService.getPlatform(platform, workspaceId) .proxyForGet(url, byte[].class); } diff --git a/test-track/frontend/src/api/issue.js b/test-track/frontend/src/api/issue.js index 22cb17e5ad..56cbc02cb3 100644 --- a/test-track/frontend/src/api/issue.js +++ b/test-track/frontend/src/api/issue.js @@ -146,16 +146,18 @@ export function getRelateIssues(page) { }); } -export function syncIssues(param) { - let url = 'issues/sync'; - if (hasLicense()) { - url = 'xpack/issue/sync'; - } +export function syncAllIssues(param) { // 浏览器默认策略,请求同一个url,可能导致 stalled 时间过长,加个uuid防止请求阻塞 - url = url + "?stamp=" + getUUID(); + let url = 'xpack/issue/sync' + "?stamp=" + getUUID(); return post(url, param); } +export function syncIssues() { + // 浏览器默认策略,请求同一个url,可能导致 stalled 时间过长,加个uuid防止请求阻塞 + let url = 'issues/sync/' + getCurrentProjectID() + "?stamp=" + getUUID(); + return get(url); +} + // 轮询同步状态 export function checkSyncIssues(loading, isNotFirst) { let url = 'issues/sync/check/' + getCurrentProjectID() + "?stamp=" + getUUID(); diff --git a/test-track/frontend/src/business/issue/IssueList.vue b/test-track/frontend/src/business/issue/IssueList.vue index b088bc4f23..880c1f0222 100644 --- a/test-track/frontend/src/business/issue/IssueList.vue +++ b/test-track/frontend/src/business/issue/IssueList.vue @@ -7,7 +7,21 @@ :create-tip="$t('test_track.issue.create_issue')" :tip="$t('commons.search_by_name_or_id')"> @@ -195,7 +209,7 @@ import { getIssues, syncIssues, deleteIssue, - getIssuesById, batchDeleteIssue, getPlatformOption + getIssuesById, batchDeleteIssue, getPlatformOption, syncAllIssues } from "@/api/issue"; import { getCustomFieldValue, @@ -214,6 +228,7 @@ import { getAdvSearchCustomField } from "metersphere-frontend/src/components/search/custom-component"; import MsMarkDownText from "metersphere-frontend/src/components/MsMarkDownText"; +import {hasLicense} from "metersphere-frontend/src/utils/permission"; export default { name: "IssueList", @@ -269,7 +284,8 @@ export default { creatorFilters: [], loading: false, dataSelectRange: "", - platformOptions: [] + platformOptions: [], + hasLicense: false }; }, watch: { @@ -303,6 +319,8 @@ export default { .then((r) => { this.platformOptions = r.data; }); + + this.hasLicense = hasLicense(); }, computed: { platformFilters() { @@ -467,7 +485,7 @@ export default { } return false; }, - syncIssues() { + syncAllIssues() { this.$refs.issueSyncSelect.open(); }, handleImport() { @@ -500,7 +518,20 @@ export default { "createTime": data.createTime.getTime(), "pre": data.preValue } - syncIssues(param) + syncAllIssues(param) + .then((response) => { + if (response.data === false) { + checkSyncIssues(this.loading); + } else { + this.$success(this.$t('test_track.issue.sync_complete')); + this.loading = false; + this.getIssues(); + } + }); + }, + syncIssues() { + this.loading = true; + syncIssues() .then((response) => { if (response.data === false) { checkSyncIssues(this.loading);