fix(缺陷管理): 修复缺陷操作相关的通知问题

--bug=1036449 --user=宋昌昌 【项目管理】消息通知-批量编辑缺陷-未发送通知 https://www.tapd.cn/55049933/s/1467801
This commit is contained in:
song-cc-rock 2024-03-01 16:01:56 +08:00 committed by 刘瑞斌
parent 8265d5f21b
commit ceafebe073
5 changed files with 94 additions and 117 deletions

View File

@ -125,8 +125,8 @@ public class BugController {
@GetMapping("/delete/{id}")
@Operation(summary = "缺陷管理-列表-删除缺陷")
@RequiresPermissions(PermissionConstants.PROJECT_BUG_DELETE)
@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)
@Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#id)", msClass = BugLogService.class)
public void delete(@PathVariable String id) {
bugService.delete(id, SessionUtils.getUserId());
}
@ -176,6 +176,7 @@ public class BugController {
@Operation(summary = "缺陷管理-列表-批量删除缺陷")
@RequiresPermissions(PermissionConstants.PROJECT_BUG_DELETE)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
@SendNotice(taskType = NoticeConstants.TaskType.BUG_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.getBatchNoticeByRequest(#request)", targetClass = BugNoticeService.class)
public void batchDelete(@Validated @RequestBody BugBatchRequest request) {
request.setUseTrash(false);
bugService.batchDelete(request, SessionUtils.getUserId());
@ -185,6 +186,7 @@ public class BugController {
@Operation(summary = "缺陷管理-列表-批量编辑缺陷")
@RequiresPermissions(PermissionConstants.PROJECT_BUG_UPDATE)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
@SendNotice(taskType = NoticeConstants.TaskType.BUG_TASK, event = NoticeConstants.Event.UPDATE, target = "#targetClass.getBatchNoticeByRequest(#request)", targetClass = BugNoticeService.class)
public void batchUpdate(@Validated @RequestBody BugBatchUpdateRequest request) {
request.setUseTrash(false);
bugService.batchUpdate(request, SessionUtils.getUserId());

View File

@ -106,7 +106,7 @@ public class BugLogService {
* @param id 缺陷ID
* @return 缺陷DTO
*/
private BugDTO getOriginalValue(String id) {
public BugDTO getOriginalValue(String id) {
// 缺陷基础信息
BugDTO originalBug = new BugDTO();
Bug bug = bugMapper.selectByPrimaryKey(id);

View File

@ -1,27 +1,19 @@
package io.metersphere.bug.service;
import io.metersphere.bug.domain.Bug;
import io.metersphere.bug.dto.request.BugBatchRequest;
import io.metersphere.bug.dto.request.BugEditRequest;
import io.metersphere.bug.dto.response.BugCustomFieldDTO;
import io.metersphere.bug.mapper.ExtBugCustomFieldMapper;
import io.metersphere.bug.dto.response.BugDTO;
import io.metersphere.plugin.platform.dto.SelectOption;
import io.metersphere.system.domain.User;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.dto.BugNoticeDTO;
import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.mapper.UserMapper;
import io.metersphere.system.notice.NoticeModel;
import io.metersphere.system.notice.constants.NoticeConstants;
import io.metersphere.system.notice.utils.MessageTemplateUtils;
import io.metersphere.system.service.NoticeSendService;
import jakarta.annotation.Resource;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ -35,15 +27,13 @@ public class BugNoticeService {
public static final String CUSTOM_HANDLE_USER = "处理人";
@Resource
private UserMapper userMapper;
private BugService bugService;
@Resource
private BugLogService bugLogService;
@Resource
private BugCommonService bugCommonService;
@Resource
private BugStatusService bugStatusService;
@Resource
private NoticeSendService noticeSendService;
@Resource
private ExtBugCustomFieldMapper extBugCustomFieldMapper;
/**
* 获取缺陷通知
@ -84,43 +74,46 @@ public class BugNoticeService {
}
/**
* 发送删除缺陷通知
* @param bug 缺陷
* @param currentUser 当前用户
* 获取缺陷通知
* @param id 缺陷ID
*/
public void sendDeleteNotice(Bug bug, String currentUser) {
Map<String, String> statusMap = getStatusMap(bug.getProjectId());
Map<String, String> handlerMap = getHandleMap(bug.getProjectId());
// 缺陷相关内容
public BugNoticeDTO getNoticeById(String id) {
// 缺陷基础信息
BugDTO bugDTO = bugLogService.getOriginalValue(id);
// 构建通知对象
BugNoticeDTO notice = new BugNoticeDTO();
notice.setTitle(bug.getTitle());
notice.setStatus(statusMap.get(bug.getStatus()));
notice.setHandleUser(handlerMap.get(bug.getHandleUser()));
List<BugCustomFieldDTO> customFields = extBugCustomFieldMapper.getBugAllCustomFields(List.of(bug.getId()), bug.getProjectId());
List<OptionDTO> fields = customFields.stream().map(field -> {
OptionDTO fieldDTO = new OptionDTO();
fieldDTO.setId(field.getName());
fieldDTO.setName(field.getValue());
return fieldDTO;
}).toList();
notice.setCustomFields(fields);
BeanMap beanMap = new BeanMap(notice);
User user = userMapper.selectByPrimaryKey(currentUser);
Map paramMap = new HashMap<>(beanMap);
paramMap.put(NoticeConstants.RelatedUser.OPERATOR, user.getName());
Map<String, String> defaultTemplateMap = MessageTemplateUtils.getDefaultTemplateMap();
String template = defaultTemplateMap.get(NoticeConstants.TemplateText.BUG_TASK_DELETE);
Map<String, String> defaultSubjectMap = MessageTemplateUtils.getDefaultTemplateSubjectMap();
String subject = defaultSubjectMap.get(NoticeConstants.TemplateText.BUG_TASK_DELETE);
NoticeModel noticeModel = NoticeModel.builder().operator(currentUser)
.context(template).subject(subject).paramMap(paramMap).event(NoticeConstants.Event.DELETE).build();
noticeSendService.send(NoticeConstants.TaskType.BUG_TASK, noticeModel);
BeanUtils.copyBean(notice, bugDTO);
// 自定义字段解析{name: value}
if (CollectionUtils.isNotEmpty(bugDTO.getCustomFields())) {
List<OptionDTO> fields = new ArrayList<>();
bugDTO.getCustomFields().forEach(field -> {
// 其他自定义字段
OptionDTO fieldDTO = new OptionDTO();
fieldDTO.setId(field.getName());
fieldDTO.setName(field.getValue());
fields.add(fieldDTO);
});
notice.setCustomFields(fields);
}
return notice;
}
/**
* 获取批量操作的缺陷通知
* @param request 批量请求参数
* @return 缺陷通知集合
*/
public List<BugNoticeDTO> getBatchNoticeByRequest(BugBatchRequest request) {
List<BugNoticeDTO> notices = new ArrayList<>();
List<String> batchIds = bugService.getBatchIdsByRequest(request);
batchIds.forEach(id -> notices.add(getNoticeById(id)));
return notices;
}
/**
* 获取状态集合
* @param projectId 项目ID
* @return
* @return 状态集合
*/
private Map<String, String> getStatusMap(String projectId) {
List<SelectOption> statusOption = bugStatusService.getHeaderStatusOption(projectId);

View File

@ -91,8 +91,6 @@ import static io.metersphere.bug.enums.result.BugResultCode.NOT_LOCAL_BUG_ERROR;
@Transactional(rollbackFor = Exception.class)
public class BugService {
private static int MAX_TAG_SIZE = 10;
@Resource
private BugMapper bugMapper;
@Resource
@ -118,8 +116,6 @@ public class BugService {
@Resource
private BaseTemplateCustomFieldService baseTemplateCustomFieldService;
@Resource
private BugNoticeService bugNoticeService;
@Resource
private BugCommonService bugCommonService;
@Resource
private BugCustomFieldMapper bugCustomFieldMapper;
@ -162,6 +158,8 @@ public class BugService {
public static final Long INTERVAL_POS = 5000L;
private static final int MAX_TAG_SIZE = 10;
/**
* 缺陷列表查询
*
@ -178,12 +176,6 @@ public class BugService {
return buildExtraInfo(bugList);
}
private void checkTagLength(List<String> tags) {
if (CollectionUtils.isNotEmpty(tags) && tags.size() > MAX_TAG_SIZE) {
throw new MSException(Translator.getWithArgs("bug_tags_size_large_than", String.valueOf(MAX_TAG_SIZE)));
}
}
/**
* 创建或编辑缺陷
*
@ -332,8 +324,6 @@ public class BugService {
clearAssociate(id, bug.getProjectId());
bugMapper.deleteByPrimaryKey(id);
}
// 发送通知
bugNoticeService.sendDeleteNotice(bug, currentUser);
}
/**
@ -1511,4 +1501,14 @@ public class BugService {
Set<Object> keySet = ConcurrentHashMap.newKeySet();
return t -> keySet.add(function.apply(t));
}
/**
* 校验TAG长度
* @param tags 标签集合
*/
private void checkTagLength(List<String> tags) {
if (CollectionUtils.isNotEmpty(tags) && tags.size() > MAX_TAG_SIZE) {
throw new MSException(Translator.getWithArgs("bug_tags_size_large_than", String.valueOf(MAX_TAG_SIZE)));
}
}
}

View File

@ -123,53 +123,48 @@
</template>
<script lang="ts" async setup>
import { useRoute } from 'vue-router';
import { useIntervalFn } from '@vueuse/core';
import { Message, TableData } from '@arco-design/web-vue';
import {useRoute} from 'vue-router';
import {useIntervalFn} from '@vueuse/core';
import {Message, TableData} from '@arco-design/web-vue';
import { MsAdvanceFilter, timeSelectOptions } from '@/components/pure/ms-advance-filter';
import { BackEndEnum, FilterFormItem, FilterResult, FilterType } from '@/components/pure/ms-advance-filter/type';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsCard from '@/components/pure/ms-card/index.vue';
import MsExportDrawer from '@/components/pure/ms-export-drawer/index.vue';
import { MsExportDrawerMap, MsExportDrawerOption } from '@/components/pure/ms-export-drawer/types';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import BatchEditModal from './components/batchEditModal.vue';
import BugDetailDrawer from './components/bug-detail-drawer.vue';
import DeleteModal from './components/deleteModal.vue';
import {MsAdvanceFilter, timeSelectOptions} from '@/components/pure/ms-advance-filter';
import {BackEndEnum, FilterFormItem, FilterResult, FilterType} from '@/components/pure/ms-advance-filter/type';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsCard from '@/components/pure/ms-card/index.vue';
import MsExportDrawer from '@/components/pure/ms-export-drawer/index.vue';
import {MsExportDrawerMap, MsExportDrawerOption} from '@/components/pure/ms-export-drawer/types';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import {BatchActionParams, BatchActionQueryParams, MsTableColumn} from '@/components/pure/ms-table/type';
import useTable from '@/components/pure/ms-table/useTable';
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
import {ActionsItem} from '@/components/pure/ms-table-more-action/types';
import BatchEditModal from './components/batchEditModal.vue';
import BugDetailDrawer from './components/bug-detail-drawer.vue';
import DeleteModal from './components/deleteModal.vue';
import {
deleteBatchBug,
deleteSingleBug,
exportBug,
getBugList,
getCustomFieldHeader,
getExportConfig,
getSyncStatus,
syncBugEnterprise,
syncBugOpenSource,
} from '@/api/modules/bug-management';
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import router from '@/router';
import { useAppStore, useTableStore } from '@/store';
import useLicenseStore from '@/store/modules/setting/license';
import {
customFieldDataToTableData,
customFieldToColumns,
downloadByteFile,
tableParamsToRequestParams,
} from '@/utils';
import {
deleteBatchBug,
deleteSingleBug,
exportBug,
getBugList,
getCustomFieldHeader,
getExportConfig,
getSyncStatus,
syncBugEnterprise,
syncBugOpenSource,
} from '@/api/modules/bug-management';
import {useI18n} from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import router from '@/router';
import {useAppStore, useTableStore} from '@/store';
import useLicenseStore from '@/store/modules/setting/license';
import {customFieldDataToTableData, customFieldToColumns, downloadByteFile, tableParamsToRequestParams,} from '@/utils';
import { BugEditCustomField, BugListItem } from '@/models/bug-management';
import { RouteEnum } from '@/enums/routeEnum';
import { TableKeyEnum } from '@/enums/tableEnum';
import {BugEditCustomField, BugListItem} from '@/models/bug-management';
import {RouteEnum} from '@/enums/routeEnum';
import {TableKeyEnum} from '@/enums/tableEnum';
const { t } = useI18n();
const { t } = useI18n();
const tableStore = useTableStore();
const appStore = useAppStore();
@ -291,19 +286,7 @@
},
{
title: 'bugManagement.creator',
slotName: 'createUserName',
dataIndex: 'createUserName',
width: 112,
showTooltip: true,
showDrag: true,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
},
{
title: 'bugManagement.updateUser',
dataIndex: 'updateUserName',
dataIndex: 'createUser',
width: 112,
showTooltip: true,
showDrag: true,
@ -324,7 +307,6 @@
},
{
title: 'bugManagement.updateUser',
slotName: 'updateUserName',
dataIndex: 'updateUser',
width: 112,
showTooltip: true,