fix(缺陷管理): 工作流被删除编辑时展示有误
--bug=1036430 --user=宋昌昌 【缺陷管理】已使用工作流-删除-编辑缺陷下拉应该显示其他状态 https://www.tapd.cn/55049933/s/1481941
This commit is contained in:
parent
17750d5636
commit
129e67b3f5
|
@ -5,6 +5,7 @@ import io.metersphere.bug.dto.request.BugFileSourceRequest;
|
|||
import io.metersphere.bug.dto.request.BugFileTransferRequest;
|
||||
import io.metersphere.bug.dto.request.BugUploadFileRequest;
|
||||
import io.metersphere.bug.dto.response.BugFileDTO;
|
||||
import io.metersphere.bug.service.BugAttachmentLogService;
|
||||
import io.metersphere.bug.service.BugAttachmentService;
|
||||
import io.metersphere.project.dto.filemanagement.request.FileMetadataTableRequest;
|
||||
import io.metersphere.project.dto.filemanagement.response.FileInformationResponse;
|
||||
|
@ -13,6 +14,8 @@ import io.metersphere.project.service.FileMetadataService;
|
|||
import io.metersphere.project.service.FileModuleService;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.metersphere.system.log.annotation.Log;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.security.CheckOwner;
|
||||
import io.metersphere.system.utils.Pager;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
|
@ -62,6 +65,7 @@ public class BugAttachmentController {
|
|||
@Operation(summary = "缺陷管理-附件-上传/关联文件")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.uploadLog(#request, #file)", msClass = BugAttachmentLogService.class)
|
||||
public void uploadFile(@Validated @RequestPart("request") BugUploadFileRequest request, @RequestPart(value = "file", required = false) MultipartFile file) {
|
||||
bugAttachmentService.uploadFile(request, file, SessionUtils.getUserId());
|
||||
}
|
||||
|
@ -70,6 +74,7 @@ public class BugAttachmentController {
|
|||
@Operation(summary = "缺陷管理-附件-删除/取消关联文件")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.deleteLog(#request)", msClass = BugAttachmentLogService.class)
|
||||
public void deleteFile(@RequestBody BugDeleteFileRequest request) {
|
||||
bugAttachmentService.deleteFile(request);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.springframework.web.bind.annotation.*;
|
|||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
|
@ -134,8 +135,8 @@ public class BugController {
|
|||
@GetMapping("/delete/{id}")
|
||||
@Operation(summary = "缺陷管理-列表-删除缺陷")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_DELETE)
|
||||
@SendNotice(taskType = NoticeConstants.TaskType.BUG_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.getNoticeById(#id)", targetClass = BugNoticeService.class)
|
||||
@Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#id)", msClass = BugLogService.class)
|
||||
@SendNotice(taskType = NoticeConstants.TaskType.BUG_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.getNoticeById(#id)", targetClass = BugNoticeService.class)
|
||||
public void delete(@PathVariable String id) {
|
||||
bugService.delete(id, SessionUtils.getUserId());
|
||||
}
|
||||
|
@ -145,7 +146,7 @@ public class BugController {
|
|||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
||||
public void sync(@PathVariable String projectId) {
|
||||
bugSyncService.syncBugs(projectId, SessionUtils.getUserId());
|
||||
bugSyncService.syncBugs(projectId, SessionUtils.getUserId(), Objects.requireNonNull(SessionUtils.getUser()).getLanguage());
|
||||
}
|
||||
|
||||
@PostMapping("/sync/all")
|
||||
|
@ -153,7 +154,7 @@ public class BugController {
|
|||
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
public void syncAll(@RequestBody BugSyncRequest request) {
|
||||
bugSyncService.syncAllBugs(request, SessionUtils.getUserId());
|
||||
bugSyncService.syncAllBugs(request, SessionUtils.getUserId(), Objects.requireNonNull(SessionUtils.getUser()).getLanguage());
|
||||
}
|
||||
|
||||
@GetMapping("/sync/check/{projectId}")
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
package io.metersphere.bug.service;
|
||||
|
||||
import io.metersphere.bug.domain.Bug;
|
||||
import io.metersphere.bug.dto.request.BugDeleteFileRequest;
|
||||
import io.metersphere.bug.dto.request.BugUploadFileRequest;
|
||||
import io.metersphere.bug.dto.response.BugFileDTO;
|
||||
import io.metersphere.bug.mapper.BugMapper;
|
||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.log.dto.LogDTO;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class BugAttachmentLogService {
|
||||
|
||||
@Resource
|
||||
private BugMapper bugMapper;
|
||||
@Resource
|
||||
private BugAttachmentService bugAttachmentService;
|
||||
|
||||
/**
|
||||
* 更新缺陷-上传附件日志
|
||||
*
|
||||
* @param request 请求参数
|
||||
* @param file 上传的文件
|
||||
* @return 日志
|
||||
*/
|
||||
public LogDTO uploadLog(BugUploadFileRequest request, MultipartFile file) {
|
||||
Bug bug = bugMapper.selectByPrimaryKey(request.getBugId());
|
||||
List<BugFileDTO> allBugFiles = bugAttachmentService.getAllBugFiles(request.getBugId());
|
||||
List<String> originalFileNames = allBugFiles.stream().map(BugFileDTO::getFileName).collect(Collectors.toList());
|
||||
LogDTO dto = buildUpdateLog(bug);
|
||||
dto.setModifiedValue(JSON.toJSONBytes(originalFileNames));
|
||||
originalFileNames.add(file.getOriginalFilename());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(originalFileNames));
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新缺陷-删除附件日志
|
||||
*
|
||||
* @param request 请求参数
|
||||
* @return 日志
|
||||
*/
|
||||
public LogDTO deleteLog(BugDeleteFileRequest request) {
|
||||
Bug bug = bugMapper.selectByPrimaryKey(request.getBugId());
|
||||
List<BugFileDTO> allBugFiles = bugAttachmentService.getAllBugFiles(request.getBugId());
|
||||
List<String> originalFileNames = allBugFiles.stream().map(BugFileDTO::getFileName).collect(Collectors.toList());
|
||||
BugFileDTO deleteFile;
|
||||
if (request.getAssociated()) {
|
||||
// 关联
|
||||
deleteFile = allBugFiles.stream().filter(file -> !file.getLocal() && StringUtils.equals(request.getRefId(), file.getRefId())).toList().get(0);
|
||||
} else {
|
||||
// 本地
|
||||
deleteFile = allBugFiles.stream().filter(file -> file.getLocal() && StringUtils.equals(request.getRefId(), file.getRefId())).toList().get(0);
|
||||
}
|
||||
LogDTO dto = buildUpdateLog(bug);
|
||||
dto.setModifiedValue(JSON.toJSONBytes(originalFileNames));
|
||||
originalFileNames.remove(deleteFile.getFileName());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(originalFileNames));
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建更新的缺陷日志对象
|
||||
* @param bug 缺陷内容
|
||||
* @return 日志对象
|
||||
*/
|
||||
private LogDTO buildUpdateLog(Bug bug) {
|
||||
LogDTO dto = new LogDTO(bug.getProjectId(), null, bug.getId(), null, OperationLogType.UPDATE.name(), OperationLogModule.BUG_MANAGEMENT_INDEX, bug.getTitle());
|
||||
dto.setHistory(true);
|
||||
dto.setPath("/bug/update");
|
||||
dto.setMethod(HttpMethodConstants.POST.name());
|
||||
return dto;
|
||||
}
|
||||
}
|
|
@ -520,11 +520,11 @@ public class BugService {
|
|||
* @param currentUser 当前用户
|
||||
*/
|
||||
@Async
|
||||
public void syncPlatformAllBugs(BugSyncRequest request, Project project, String currentUser) {
|
||||
public void syncPlatformAllBugs(BugSyncRequest request, Project project, String currentUser, String language) {
|
||||
try {
|
||||
XpackBugService bugService = CommonBeanFactory.getBean(XpackBugService.class);
|
||||
if (bugService != null) {
|
||||
bugService.syncPlatformBugs(project, request, currentUser);
|
||||
bugService.syncPlatformBugs(project, request, currentUser, language);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtils.error(e);
|
||||
|
@ -542,7 +542,7 @@ public class BugService {
|
|||
* @param project 项目
|
||||
*/
|
||||
@Async
|
||||
public void syncPlatformBugs(List<Bug> remainBugs, Project project, String currentUser) {
|
||||
public void syncPlatformBugs(List<Bug> remainBugs, Project project, String currentUser, String language) {
|
||||
try {
|
||||
// 分页同步
|
||||
SubListUtils.dealForSubList(remainBugs, 100, (subBugs) -> doSyncPlatformBugs(subBugs, project));
|
||||
|
@ -554,7 +554,7 @@ public class BugService {
|
|||
// 异常或正常结束都得删除当前项目执行同步的Key
|
||||
bugSyncExtraService.deleteSyncKey(project.getId());
|
||||
// 发送同步通知
|
||||
bugSyncNoticeService.sendNotice(remainBugs.size(), currentUser, project.getId());
|
||||
bugSyncNoticeService.sendNotice(remainBugs.size(), currentUser, language, project.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ public class BugSyncNoticeService {
|
|||
@Resource
|
||||
private NoticeSendService noticeSendService;
|
||||
|
||||
public void sendNotice(int total, String currentUser, String projectId) {
|
||||
public void sendNotice(int total, String currentUser, String language, String projectId) {
|
||||
User user = userMapper.selectByPrimaryKey(currentUser);
|
||||
Map<String, String> defaultTemplateMap = MessageTemplateUtils.getDefaultTemplateMap();
|
||||
String template = defaultTemplateMap.get(NoticeConstants.TemplateText.BUG_SYNC_TASK_EXECUTE_COMPLETED);
|
||||
|
@ -34,6 +34,7 @@ public class BugSyncNoticeService {
|
|||
paramMap.put(NoticeConstants.RelatedUser.OPERATOR, user.getName());
|
||||
paramMap.put("total", total);
|
||||
paramMap.put("projectId", projectId);
|
||||
paramMap.put("Language", language);
|
||||
NoticeModel noticeModel = NoticeModel.builder().operator(currentUser)
|
||||
.context(template).subject(subject).paramMap(paramMap).event(NoticeConstants.Event.EXECUTE_COMPLETED).build();
|
||||
noticeSendService.send(NoticeConstants.TaskType.BUG_SYNC_TASK, noticeModel);
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -52,7 +53,7 @@ public class BugSyncService {
|
|||
* @param request 同步全量参数
|
||||
* @param currentUser 当前用户
|
||||
*/
|
||||
public void syncAllBugs(BugSyncRequest request, String currentUser) {
|
||||
public void syncAllBugs(BugSyncRequest request, String currentUser, String language) {
|
||||
try {
|
||||
// 获取当前项目同步缺陷唯一Key
|
||||
String syncValue = bugSyncExtraService.getSyncKey(request.getProjectId());
|
||||
|
@ -60,7 +61,7 @@ public class BugSyncService {
|
|||
// 不存在, 设置保证唯一性, 并开始同步
|
||||
bugSyncExtraService.setSyncKey(request.getProjectId());
|
||||
Project project = getProjectById(request.getProjectId());
|
||||
bugService.syncPlatformAllBugs(request, project, currentUser);
|
||||
bugService.syncPlatformAllBugs(request, project, currentUser, language);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
bugSyncExtraService.deleteSyncKey(request.getProjectId());
|
||||
|
@ -72,7 +73,7 @@ public class BugSyncService {
|
|||
* 开源用户 (同步存量缺陷)
|
||||
* @param projectId 项目ID
|
||||
*/
|
||||
public void syncBugs(String projectId, String currentUser) {
|
||||
public void syncBugs(String projectId, String currentUser, String language) {
|
||||
try {
|
||||
String syncValue = bugSyncExtraService.getSyncKey(projectId);
|
||||
if (StringUtils.isEmpty(syncValue)) {
|
||||
|
@ -98,7 +99,7 @@ public class BugSyncService {
|
|||
Map<String, Template> templateMap = templates.stream().collect(Collectors.toMap(Template::getId, t -> t));
|
||||
// 非插件默认模板且模板不存在, 无需同步
|
||||
bugs.removeIf(bug -> !templateMap.containsKey(bug.getTemplateId()) && !StringUtils.equals(bug.getTemplateId(), pluginTemplate.getId()));
|
||||
bugService.syncPlatformBugs(bugs, project, currentUser);
|
||||
bugService.syncPlatformBugs(bugs, project, currentUser, language);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -130,10 +131,10 @@ public class BugSyncService {
|
|||
}
|
||||
|
||||
/**
|
||||
* 定时任务同步缺陷(存量)
|
||||
* 定时任务同步缺陷(存量-默认中文环境通知)
|
||||
*/
|
||||
public void syncPlatformBugBySchedule(String projectId, String scheduleUser) {
|
||||
syncBugs(projectId, scheduleUser);
|
||||
syncBugs(projectId, scheduleUser, Locale.SIMPLIFIED_CHINESE.getLanguage());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,7 +20,8 @@ public interface XpackBugService {
|
|||
* @param project 项目
|
||||
* @param request 同步请求参数
|
||||
* @param currentUser 当前用户
|
||||
* @param language 语言环境
|
||||
*/
|
||||
void syncPlatformBugs(Project project, BugSyncRequest request, String currentUser);
|
||||
void syncPlatformBugs(Project project, BugSyncRequest request, String currentUser, String language);
|
||||
|
||||
}
|
||||
|
|
|
@ -634,13 +634,13 @@ public class BugControllerTests extends BaseTest {
|
|||
List<Bug> remainBugs = bugMapper.selectByExample(example);
|
||||
Project defaultProject = projectMapper.selectByPrimaryKey("default-project-for-bug");
|
||||
// 同步第一次
|
||||
bugService.syncPlatformBugs(remainBugs, defaultProject, "admin");
|
||||
bugService.syncPlatformBugs(remainBugs, defaultProject, "admin", Locale.SIMPLIFIED_CHINESE.getLanguage());
|
||||
// 同步第二次
|
||||
renameLocalFile(updateRequest2.getId()); // 重命名后, 同步时会删除本地文件
|
||||
bugService.syncPlatformBugs(remainBugs, defaultProject, "admin");
|
||||
bugService.syncPlatformBugs(remainBugs, defaultProject, "admin", Locale.SIMPLIFIED_CHINESE.getLanguage());
|
||||
// 同步第三次
|
||||
deleteLocalFile(updateRequest2.getId()); // 手动删除关联的文件, 重新同步时会下载平台附件
|
||||
bugService.syncPlatformBugs(remainBugs, defaultProject, "admin");
|
||||
bugService.syncPlatformBugs(remainBugs, defaultProject, "admin", Locale.SIMPLIFIED_CHINESE.getLanguage());
|
||||
|
||||
// 全选删除所有Jira缺陷
|
||||
BugBatchRequest request = new BugBatchRequest();
|
||||
|
@ -719,9 +719,9 @@ public class BugControllerTests extends BaseTest {
|
|||
Project project = projectMapper.selectByPrimaryKey("default-project-for-bug");
|
||||
this.requestPostWithOk(BUG_SYNC_ALL, request);
|
||||
BugService mockBugService = Mockito.mock(BugService.class);
|
||||
Mockito.doThrow(new MSException("sync error!")).when(mockBugService).syncPlatformAllBugs(syncRequest, project, "admin");
|
||||
Mockito.doThrow(new MSException("sync error!")).when(mockBugService).syncPlatformAllBugs(syncRequest, project, "admin", Locale.SIMPLIFIED_CHINESE.getLanguage());
|
||||
ReflectionTestUtils.setField(bugSyncService, "bugService", mockBugService);
|
||||
MSException msException = assertThrows(MSException.class, () -> bugSyncService.syncAllBugs(syncRequest, "admin"));
|
||||
MSException msException = assertThrows(MSException.class, () -> bugSyncService.syncAllBugs(syncRequest, "admin", Locale.SIMPLIFIED_CHINESE.getLanguage()));
|
||||
assertEquals(msException.getMessage(), "sync error!");
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ public class XpackBugMockServiceImpl implements XpackBugService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void syncPlatformBugs(Project project, BugSyncRequest request, String currentUser) {
|
||||
public void syncPlatformBugs(Project project, BugSyncRequest request, String currentUser, String language) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import io.metersphere.system.dto.sdk.request.StatusDefinitionUpdateRequest;
|
|||
import io.metersphere.system.dto.sdk.request.StatusFlowUpdateRequest;
|
||||
import io.metersphere.system.dto.sdk.request.StatusItemAddRequest;
|
||||
import io.metersphere.system.mapper.StatusDefinitionMapper;
|
||||
import io.metersphere.system.mapper.StatusItemMapper;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
@ -41,6 +42,8 @@ import java.util.stream.Collectors;
|
|||
@Transactional(rollbackFor = Exception.class)
|
||||
public class BaseStatusFlowSettingService {
|
||||
|
||||
@Resource
|
||||
protected StatusItemMapper statusItemMapper;
|
||||
@Resource
|
||||
protected StatusDefinitionMapper statusDefinitionMapper;
|
||||
@Resource
|
||||
|
@ -280,8 +283,9 @@ public class BaseStatusFlowSettingService {
|
|||
* @return 状态选项集合
|
||||
*/
|
||||
public List<SelectOption> getStatusTransitions(String scopeId, String scene, String targetStatusId) {
|
||||
if (StringUtils.isBlank(targetStatusId)) {
|
||||
// 创建时, 获取开始状态的选项值即可
|
||||
StatusItem targetStatus = statusItemMapper.selectByPrimaryKey(targetStatusId);
|
||||
if (StringUtils.isBlank(targetStatusId) || targetStatus == null) {
|
||||
// 创建或该目标状态被删除时, 获取开始状态的选项值即可
|
||||
List<StatusItem> statusItems = baseStatusItemService.getByScopeIdAndScene(scopeId, scene);
|
||||
statusItems = baseStatusItemService.translateInternalStatusItem(statusItems);
|
||||
List<String> statusIds = statusItems.stream().map(StatusItem::getId).toList();
|
||||
|
|
|
@ -92,7 +92,9 @@
|
|||
<div v-for="element in couldSortColumn" :key="element.dataIndex" class="column-drag-item">
|
||||
<div class="flex w-[60%] items-center">
|
||||
<MsIcon type="icon-icon_drag" class="sort-handle cursor-move text-[16px] text-[var(--color-text-4)]" />
|
||||
<span class="ml-[8px]">{{ t((element.title || element.columnTitle) as string) }}</span>
|
||||
<span class="one-line-text ml-[8px] max-w-[85%]">{{
|
||||
t((element.title || element.columnTitle) as string)
|
||||
}}</span>
|
||||
</div>
|
||||
<a-switch v-model="element.showInTable" size="small" type="line" @change="handleSwitchChange" />
|
||||
</div>
|
||||
|
|
|
@ -34,7 +34,9 @@
|
|||
<div v-for="element in couldSortColumn" :key="element.dataIndex" class="column-drag-item">
|
||||
<div class="flex w-[90%] items-center">
|
||||
<MsIcon type="icon-icon_drag" class="sort-handle cursor-move text-[16px] text-[var(--color-text-4)]" />
|
||||
<span class="ml-[8px]">{{ t((element.title || element.columnTitle) as string) }}</span>
|
||||
<span class="one-line-text ml-[8px] max-w-[85%]">{{
|
||||
t((element.title || element.columnTitle) as string)
|
||||
}}</span>
|
||||
</div>
|
||||
<a-switch
|
||||
v-model="element.showInTable"
|
||||
|
|
Loading…
Reference in New Issue