feat(项目管理): 新增消息通知异步自定义资源池设置以及修改部分功能用例批量通知操作的问题

--bug=1039332 --user=郭雨琦 https://www.tapd.cn/55049933/bugtrace/bugs/view/1155049933001039332
--bug=1039160 --user=郭雨琦 https://www.tapd.cn/55049933/bugtrace/bugs/view/1155049933001039160
This commit is contained in:
guoyuqi 2024-04-15 14:36:16 +08:00 committed by 刘瑞斌
parent 33351bfee8
commit ded906fc5e
16 changed files with 213 additions and 62 deletions

View File

@ -366,6 +366,7 @@ message.domain.delete_user=Delete user
message.domain.create_time=Create time
message.domain.update_time=Update time
message.domain.delete_time=Delete time
message.domain.triggerMode=Trigger mode
#接口定义和case
message.domain.protocol=Interface Protocol
message.domain.method=Http protocol type

View File

@ -365,6 +365,7 @@ message.domain.deleteUser=删除人
message.domain.createTime=创建时间
message.domain.updateTime=更新时间
message.domain.deleteTime=删除时间
message.domain.triggerMode=触发方式
#接口定义和用例
message.domain.protocol=接口协议
message.domain.method=http协议类型

View File

@ -366,6 +366,7 @@ message.domain.deleteUser=刪除人
message.domain.createTime=創建時間
message.domain.updateTime=更新時間
message.domain.deleteTime=刪除時間
message.domain.triggerMode=觸發方式
#接口定義和用例
message.domain.protocol=介面協定
message.domain.method=http協定類型

View File

@ -68,8 +68,7 @@ public class FunctionalCaseController {
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ)
@CheckOwner(resourceId = "#projectId", resourceType = "project")
public TemplateDTO getDefaultTemplateField(@PathVariable String projectId) {
TemplateDTO defaultTemplateDTO = projectTemplateService.getDefaultTemplateDTO(projectId, TemplateScene.FUNCTIONAL.name());
return defaultTemplateDTO;
return projectTemplateService.getDefaultTemplateDTO(projectId, TemplateScene.FUNCTIONAL.name());
}
@ -99,7 +98,7 @@ public class FunctionalCaseController {
@Operation(summary = "用例管理-功能用例-更新用例")
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateFunctionalCaseLog(#request, #files)", msClass = FunctionalCaseLogService.class)
@SendNotice(taskType = NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, event = NoticeConstants.Event.UPDATE, target = "#targetClass.getMainFunctionalCaseDTO(#request.name, #request.caseEditType, #request.projectId, #request.customFields)", targetClass = FunctionalCaseNoticeService.class)
@SendNotice(taskType = NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, event = NoticeConstants.Event.UPDATE, target = "#targetClass.getMainFunctionalCaseDTO(#request, #request.customFields)", targetClass = FunctionalCaseNoticeService.class)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public FunctionalCase updateFunctionalCase(@Validated @RequestPart("request") FunctionalCaseEditRequest request, @RequestPart(value = "files", required = false) List<MultipartFile> files) {
String userId = SessionUtils.getUserId();
@ -159,7 +158,6 @@ public class FunctionalCaseController {
@Operation(summary = "用例管理-功能用例-批量删除用例")
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_DELETE)
@Log(type = OperationLogType.DELETE, expression = "#msClass.batchDeleteFunctionalCaseLog(#request)", msClass = FunctionalCaseLogService.class)
@SendNotice(taskType = NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.getBatchDeleteFunctionalCaseDTO(#request)", targetClass = FunctionalCaseNoticeService.class)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public void batchDeleteFunctionalCaseToGc(@Validated @RequestBody FunctionalCaseBatchRequest request) {
String userId = SessionUtils.getUserId();
@ -199,7 +197,6 @@ public class FunctionalCaseController {
@Operation(summary = "用例管理-功能用例-批量编辑用例")
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.batchEditFunctionalCaseLog(#request)", msClass = FunctionalCaseLogService.class)
@SendNotice(taskType = NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, event = NoticeConstants.Event.UPDATE, target = "#targetClass.getBatchEditFunctionalCaseDTO(#request)", targetClass = FunctionalCaseNoticeService.class)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public void batchEditFunctionalCase(@Validated @RequestBody FunctionalCaseBatchEditRequest request) {
String userId = SessionUtils.getUserId();

View File

@ -1,17 +1,15 @@
package io.metersphere.functional.service;
import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.domain.FunctionalCaseCustomField;
import io.metersphere.functional.domain.FunctionalCaseCustomFieldExample;
import io.metersphere.functional.domain.*;
import io.metersphere.functional.dto.CaseCustomFieldDTO;
import io.metersphere.functional.dto.FunctionalCaseDTO;
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseMapper;
import io.metersphere.functional.mapper.CaseReviewMapper;
import io.metersphere.functional.mapper.FunctionalCaseCustomFieldMapper;
import io.metersphere.functional.mapper.FunctionalCaseMapper;
import io.metersphere.functional.request.FunctionalCaseBatchEditRequest;
import io.metersphere.functional.request.FunctionalCaseBatchRequest;
import io.metersphere.functional.request.FunctionalCaseCommentRequest;
import io.metersphere.functional.request.FunctionalCaseEditRequest;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.CustomField;
import io.metersphere.system.domain.CustomFieldExample;
import io.metersphere.system.dto.sdk.OptionDTO;
@ -41,25 +39,26 @@ public class FunctionalCaseNoticeService {
@Resource
private CustomFieldMapper customFieldMapper;
@Resource
private FunctionalCaseService functionalCaseService;
@Resource
private FunctionalCaseCustomFieldService functionalCaseCustomFieldService;
@Resource
private ExtOrganizationCustomFieldMapper extOrganizationCustomFieldMapper;
@Resource
private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper;
@Resource
private CaseReviewMapper caseReviewMapper;
public FunctionalCaseDTO getFunctionalCaseDTO(FunctionalCaseCommentRequest functionalCaseCommentRequest) {
FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(functionalCaseCommentRequest.getCaseId());
FunctionalCaseDTO functionalCaseDTO = new FunctionalCaseDTO();
functionalCaseDTO.setTriggerMode(Translator.get("log.test_plan.functional_case"));
functionalCaseDTO.setTriggerMode(NoticeConstants.TriggerMode.MANUAL_EXECUTION);
BeanUtils.copyBean(functionalCaseDTO, functionalCase);
setNotifier(functionalCaseCommentRequest, functionalCaseDTO);
List<OptionDTO> customFields = getCustomFields(functionalCaseCommentRequest.getCaseId());
functionalCaseDTO.setFields(customFields);
//TODO:设置测试计划名称
//TODO设置用例评审名称
setReviewName(functionalCaseCommentRequest.getCaseId(), functionalCaseDTO);
return functionalCaseDTO;
}
@ -129,12 +128,17 @@ public class FunctionalCaseNoticeService {
return optionDTOList;
}
public FunctionalCaseDTO getMainFunctionalCaseDTO(String name, String caseEditType, String projectId, List<CaseCustomFieldDTO> customFields) {
public FunctionalCaseDTO getMainFunctionalCaseDTO(FunctionalCaseEditRequest request, List<CaseCustomFieldDTO> customFields) {
FunctionalCaseDTO functionalCaseDTO = new FunctionalCaseDTO();
functionalCaseDTO.setName(name);
functionalCaseDTO.setProjectId(projectId);
functionalCaseDTO.setCaseEditType(caseEditType);
if (StringUtils.isNotBlank(request.getId())) {
FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(request.getId());
BeanUtils.copyBean(functionalCaseDTO, functionalCase);
setReviewName(request.getId(), functionalCaseDTO);
} else {
BeanUtils.copyBean(functionalCaseDTO, request);
functionalCaseDTO.setCreateUser(null);
}
functionalCaseDTO.setTriggerMode(NoticeConstants.TriggerMode.MANUAL_EXECUTION);
List<OptionDTO> fields = new ArrayList<>();
if (CollectionUtils.isNotEmpty(customFields)) {
for (CaseCustomFieldDTO customFieldDTO : customFields) {
@ -150,10 +154,24 @@ public class FunctionalCaseNoticeService {
}
functionalCaseDTO.setFields(fields);
//TODO:设置测试计划名称
//TODO设置用例评审名称
return functionalCaseDTO;
}
private void setReviewName(String caseId, FunctionalCaseDTO functionalCaseDTO) {
CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample();
caseReviewFunctionalCaseExample.createCriteria().andCaseIdEqualTo(caseId);
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample);
List<String> reviewIds = caseReviewFunctionalCases.stream().map(CaseReviewFunctionalCase::getReviewId).distinct().toList();
if (CollectionUtils.isNotEmpty(reviewIds)) {
CaseReviewExample caseReviewExample = new CaseReviewExample();
caseReviewExample.createCriteria().andIdIn(reviewIds);
List<CaseReview> caseReviews = caseReviewMapper.selectByExample(caseReviewExample);
List<String> reviewName = caseReviews.stream().map(CaseReview::getName).toList();
String string = reviewName.toString();
functionalCaseDTO.setReviewName(string);
}
}
public FunctionalCaseDTO getDeleteFunctionalCaseDTO(String id) {
FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(id);
@ -165,27 +183,41 @@ public class FunctionalCaseNoticeService {
});
//TODO:设置测试计划名称
//TODO设置用例评审名称
setReviewName(id, functionalCaseDTO);
return functionalCaseDTO;
}
public List<FunctionalCaseDTO> getBatchDeleteFunctionalCaseDTO(FunctionalCaseBatchRequest request) {
List<String> ids = functionalCaseService.doSelectIds(request, request.getProjectId());
return handleBatchNotice(request.getProjectId(), ids);
public Map<String, FunctionalCase> copyBaseCaseInfo(String projectId, List<String> ids) {
FunctionalCaseExample example = new FunctionalCaseExample();
example.createCriteria().andProjectIdEqualTo(projectId).andDeletedEqualTo(false).andIdIn(ids);
List<FunctionalCase> functionalCaseLists = functionalCaseMapper.selectByExample(example);
return functionalCaseLists.stream().collect(Collectors.toMap(FunctionalCase::getId, functionalCase -> functionalCase));
}
private List<FunctionalCaseDTO> handleBatchNotice(String projectId, List<String> ids) {
public List<FunctionalCaseDTO> handleBatchNotice(String projectId, List<String> ids) {
List<FunctionalCaseDTO> dtoList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(ids)) {
Map<String, FunctionalCase> functionalCaseMap = functionalCaseService.copyBaseInfo(projectId, ids);
Map<String, FunctionalCase> functionalCaseMap = copyBaseCaseInfo(projectId, ids);
Map<String, List<FunctionalCaseCustomField>> customFieldMap = functionalCaseCustomFieldService.getCustomFieldMapByCaseIds(ids);
AtomicReference<List<OptionDTO>> optionDTOS = new AtomicReference<>(new ArrayList<>());
CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample();
caseReviewFunctionalCaseExample.createCriteria().andCaseIdIn(ids);
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample);
List<String> reviewIds = caseReviewFunctionalCases.stream().map(CaseReviewFunctionalCase::getReviewId).distinct().toList();
Map<String, String> reviewMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(reviewIds)) {
CaseReviewExample caseReviewExample = new CaseReviewExample();
caseReviewExample.createCriteria().andIdIn(reviewIds);
List<CaseReview> caseReviews = caseReviewMapper.selectByExample(caseReviewExample);
reviewMap = caseReviews.stream().collect(Collectors.toMap(CaseReview::getId, CaseReview::getName));
}
Map<String, List<CaseReviewFunctionalCase>> caseReviewMap = caseReviewFunctionalCases.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCase::getCaseId));
Map<String, String> finalReviewMap = reviewMap;
ids.forEach(id -> {
FunctionalCase functionalCase = functionalCaseMap.get(id);
if (functionalCase != null) {
List<FunctionalCaseCustomField> customFields = customFieldMap.get(id);
if (CollectionUtils.isNotEmpty(customFields)) {
List<String> fields = customFields.stream().map(functionalCaseCustomField -> functionalCaseCustomField.getFieldId()).toList();
List<String> fields = customFields.stream().map(FunctionalCaseCustomField::getFieldId).toList();
optionDTOS.set(extOrganizationCustomFieldMapper.getCustomFieldOptions(fields));
}
FunctionalCaseDTO functionalCaseDTO = new FunctionalCaseDTO();
@ -194,17 +226,22 @@ public class FunctionalCaseNoticeService {
functionalCaseDTO.setCaseEditType(functionalCase.getCaseEditType());
functionalCaseDTO.setCreateUser(null);
functionalCaseDTO.setFields(optionDTOS.get());
List<CaseReviewFunctionalCase> caseReviewFunctionalCases1 = caseReviewMap.get(id);
List<String>reviewName = new ArrayList<>();
if (CollectionUtils.isNotEmpty(caseReviewFunctionalCases1)) {
for (CaseReviewFunctionalCase caseReviewFunctionalCase : caseReviewFunctionalCases1) {
String s = finalReviewMap.get(caseReviewFunctionalCase.getReviewId());
reviewName.add(s);
}
}
List<String> list = reviewName.stream().distinct().toList();
functionalCaseDTO.setReviewName(list.toString());
dtoList.add(functionalCaseDTO);
}
});
//TODO:设置测试计划名称
//TODO设置用例评审名称
}
return dtoList;
}
public List<FunctionalCaseDTO> getBatchEditFunctionalCaseDTO(FunctionalCaseBatchEditRequest request) {
List<String> ids = functionalCaseService.doSelectIds(request, request.getProjectId());
return handleBatchNotice(request.getProjectId(), ids);
}
}

View File

@ -168,6 +168,9 @@ public class FunctionalCaseService {
private FunctionalCaseCommentMapper functionalCaseCommentMapper;
@Resource
private ProjectService projectService;
@Resource
private FunctionalCaseNoticeService functionalCaseNoticeService;
private static final int MAX_TAG_SIZE = 10;
@ -608,10 +611,10 @@ public class FunctionalCaseService {
* @param userId userId
*/
public void deleteFunctionalCase(FunctionalCaseDeleteRequest request, String userId) {
handDeleteFunctionalCase(Collections.singletonList(request.getId()), request.getDeleteAll(), userId);
handDeleteFunctionalCase(Collections.singletonList(request.getId()), request.getDeleteAll(), userId, request.getProjectId());
}
private void handDeleteFunctionalCase(List<String> ids, Boolean deleteAll, String userId) {
private void handDeleteFunctionalCase(List<String> ids, Boolean deleteAll, String userId, String projectId) {
Map<String, Object> param = new HashMap<>();
if (deleteAll) {
//全部删除 进入回收站
@ -626,6 +629,8 @@ public class FunctionalCaseService {
param.put(CaseEvent.Param.CASE_IDS, CollectionUtils.isNotEmpty(ids) ? ids : new ArrayList<>());
doDelete(ids, userId);
}
User user = userMapper.selectByPrimaryKey(userId);
batchSendNotice(projectId, ids, user, NoticeConstants.Event.DELETE);
param.put(CaseEvent.Param.USER_ID, userId);
param.put(CaseEvent.Param.EVENT_NAME, CaseEvent.Event.DELETE_FUNCTIONAL_CASE);
provider.updateCaseReview(param);
@ -718,7 +723,7 @@ public class FunctionalCaseService {
public void batchDeleteFunctionalCaseToGc(FunctionalCaseBatchRequest request, String userId) {
List<String> ids = doSelectIds(request, request.getProjectId());
if (CollectionUtils.isNotEmpty(ids)) {
handDeleteFunctionalCase(ids, request.getDeleteAll(), userId);
handDeleteFunctionalCase(ids, request.getDeleteAll(), userId, request.getProjectId());
}
}
@ -744,10 +749,31 @@ public class FunctionalCaseService {
* @param userId userId
*/
public void batchMoveFunctionalCase(FunctionalCaseBatchMoveRequest request, String userId) {
User user = userMapper.selectByPrimaryKey(userId);
List<String> ids = doSelectIds(request, request.getProjectId());
if (CollectionUtils.isNotEmpty(ids)) {
List<String> refId = extFunctionalCaseMapper.getRefIds(ids, false);
extFunctionalCaseMapper.batchMoveModule(request, refId, userId);
batchSendNotice(request.getProjectId(), ids, user, NoticeConstants.Event.UPDATE);
}
}
private void batchSendNotice(String projectId, List<String> ids, User user, String event) {
int amount = 100;//每次读取的条数
long roundTimes = Double.valueOf(Math.ceil((double) ids.size() / amount)).longValue();//循环的次数
for (int i = 0; i < (int)roundTimes; i++) {
int fromIndex = (i*amount);
int toIndex = ((i+1)*amount);
if (i == roundTimes-1){//最后一次遍历
toIndex = ids.size();
} else if (toIndex > ids.size()){
toIndex = ids.size();
}
List<String> subList = ids.subList(fromIndex, toIndex);
List<FunctionalCaseDTO> functionalCaseDTOS = functionalCaseNoticeService.handleBatchNotice(projectId, subList);
List<Map> resources = new ArrayList<>();
resources.addAll(JSON.parseArray(JSON.toJSONString(functionalCaseDTOS), Map.class));
commonNoticeSendService.sendNotice(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, event, resources, user, projectId);
}
}
@ -833,6 +859,10 @@ public class FunctionalCaseService {
historyLogDTO.setFileAssociationList(fileAssociationList);
saveAddDataLog(functionalCase, new FunctionalCaseHistoryLogDTO(), historyLogDTO, userId, organizationId, OperationLogType.ADD.name(), OperationLogModule.FUNCTIONAL_CASE);
}
User user = userMapper.selectByPrimaryKey(userId);
batchSendNotice(request.getProjectId(), ids, user, NoticeConstants.Event.CREATE);
}
}
@ -875,6 +905,7 @@ public class FunctionalCaseService {
public void batchEditFunctionalCase(FunctionalCaseBatchEditRequest request, String userId) {
List<String> ids = doSelectIds(request, request.getProjectId());
if (CollectionUtils.isNotEmpty(ids)) {
User user = userMapper.selectByPrimaryKey(userId);
//标签处理
handleTags(request, userId, ids);
//自定义字段处理
@ -885,6 +916,7 @@ public class FunctionalCaseService {
functionalCase.setUpdateTime(System.currentTimeMillis());
functionalCase.setUpdateUser(userId);
extFunctionalCaseMapper.batchUpdate(functionalCase, ids);
batchSendNotice(request.getProjectId(), ids, user, NoticeConstants.Event.UPDATE);
}
}
@ -1057,7 +1089,7 @@ public class FunctionalCaseService {
/**
* 组装通知数据
*
* @param noticeList
* @param noticeList xiao
* @param functionalCaseExcelData
* @param request
* @param userId

View File

@ -1,10 +1,40 @@
package io.metersphere.system.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@EnableAsync(proxyTargetClass = true)
@Configuration
public class AsyncConfig {
/**
* 核心线程数
*/
private static final int CORE_POOL_SIZE = 10;
/**
* 最大线程数
*/
private static final int MAX_POOL_SIZE = 10;
/**
* ThreadPoolTaskExecutor不会自动创建ThreadPoolExecutor需要手动调initialize才会创建
* 如果@Bean就不需手动会自动InitializingBean的afterPropertiesSet来调initialize
*
*/
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置线程池最大线程数
executor.setMaxPoolSize(MAX_POOL_SIZE);
// 线程池活跃的线程数
executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setThreadNamePrefix("notice-task-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}

View File

@ -12,6 +12,7 @@ import io.metersphere.system.dto.request.OrganizationRequest;
import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.security.CheckOwner;
import io.metersphere.system.service.OrganizationService;
import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager;
@ -43,6 +44,7 @@ public class OrganizationController {
@PostMapping("/member/list")
@Operation(summary = "系统设置-组织-成员-获取组织成员列表")
@RequiresPermissions(PermissionConstants.ORGANIZATION_MEMBER_READ)
@CheckOwner(resourceId = "#organizationId", resourceType = "organization")
public Pager<List<OrgUserExtend>> getMemberList(@Validated @RequestBody OrganizationRequest organizationRequest) {
Page<Object> page = PageHelper.startPage(organizationRequest.getCurrent(), organizationRequest.getPageSize());
return PageUtils.setPageInfo(page, organizationService.getMemberListByOrg(organizationRequest));

View File

@ -17,4 +17,7 @@ public class BugSyncNoticeDTO {
@Schema(description ="message.domain.bug_sync_total_count")
private Integer total;
@Schema(description ="message.domain.triggerMode")
private String triggerMode;
}

View File

@ -11,9 +11,9 @@ public class FunctionalCaseMessageDTO {
@Schema(description ="message.domain.name")
private String name;
@Schema(description = "message.domain.testPlanName")
/* @Schema(description = "message.domain.testPlanName")
private String testPlanName;
*/
@Schema(description = "message.domain.reviewName")
private String reviewName;
@ -23,8 +23,8 @@ public class FunctionalCaseMessageDTO {
@Schema(description = "message.domain.caseModel")
private String caseEditType;
@Schema(description = "message.domain.lastExecuteResult")
private String lastExecuteResult;
/* @Schema(description = "message.domain.lastExecuteResult")
private String lastExecuteResult;*/
@Schema(description = "message.domain.createUser")
private String createUser;
@ -44,4 +44,7 @@ public class FunctionalCaseMessageDTO {
@Schema(description = "message.domain.deleteTime")
private Long deleteTime;
@Schema(description = "message.domain.deleteTime")
private String triggerMode;
}

View File

@ -213,7 +213,7 @@
<select id="getProjectMemberByUserId" resultType="io.metersphere.system.domain.User">
select distinct u.* from user_role_relation urr join `user` u on urr.user_id = u.id
where
u.deleted = 0 and u.enable = 1
u.deleted = 0
<if test="projectId != null and projectId != ''">
and urr.source_id = #{projectId}
</if>

View File

@ -231,7 +231,7 @@ public class MessageTemplateUtils {
if (CollectionUtils.isNotEmpty(customFields)) {
Map <String,String>customFielddNameMap = new HashMap<>();
for (CustomField customField : customFields) {
customFielddNameMap.put(customField.getName(), StringUtils.isBlank(customField.getName()) ? "-" : customField.getName());
customFielddNameMap.put(customField.getName(), StringUtils.isBlank(customField.getName()) ? "-" : "<"+customField.getName()+">");
}
map.putAll(customFielddNameMap);
}

View File

@ -62,7 +62,7 @@ public class NoticeSendService {
/**
* 在线操作发送通知
*/
@Async
@Async("threadPoolTaskExecutor")
public void send(String taskType, NoticeModel noticeModel) {
setLanguage(noticeModel);
try {
@ -96,7 +96,7 @@ public class NoticeSendService {
/**
* jenkins 和定时任务触发的发送
*/
@Async
@Async("threadPoolTaskExecutor")
public void sendJenkins(String triggerMode, NoticeModel noticeModel) {
// api和定时任务调用不排除自己
noticeModel.setExcludeSelf(false);
@ -127,7 +127,7 @@ public class NoticeSendService {
/**
* 后台触发的发送没有session
*/
@Async
@Async("threadPoolTaskExecutor")
public void send(Project project, String taskType, NoticeModel noticeModel) {
setLanguage(noticeModel);
try {

View File

@ -47,7 +47,7 @@ public class NotificationService {
record.setStatus(NotificationConstants.Status.READ.name());
NotificationExample example = new NotificationExample();
if (StringUtils.isNotBlank(resourceType)) {
example.createCriteria().andResourceTypeEqualTo(resourceType);
example.createCriteria().andResourceTypeEqualTo("%" + resourceType + "%");
}
example.createCriteria().andReceiverEqualTo(userId);
return notificationMapper.updateByExampleSelective(record, example);

View File

@ -246,7 +246,7 @@ public class TestResourcePoolService {
pool.getCreateUser(),
OperationLogType.UPDATE.name(),
OperationLogModule.SETTING_SYSTEM_RESOURCE_POOL,
"更新资源池配置");
pool.getName());
dto.setPath("/update");
dto.setMethod(HttpMethodConstants.POST.name());

View File

@ -2,23 +2,33 @@ package io.metersphere.system.controller;
import io.metersphere.project.domain.Notification;
import io.metersphere.project.domain.NotificationExample;
import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.NotificationMapper;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.dto.sdk.request.NotificationRequest;
import io.metersphere.system.log.dto.NotificationDTO;
import io.metersphere.system.notice.NoticeModel;
import io.metersphere.system.notice.constants.NoticeConstants;
import io.metersphere.system.notice.constants.NotificationConstants;
import io.metersphere.system.service.NoticeSendService;
import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource;
import org.apache.commons.beanutils.BeanMap;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.test.web.servlet.MvcResult;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@ -32,6 +42,10 @@ public class NotificationControllerTests extends BaseTest {
@Resource
protected NotificationMapper notificationMapper;
@Resource
protected NoticeSendService noticeSendService;
@Resource
protected ProjectMapper projectMapper;
void saveNotice() {
Notification notification = new Notification();
@ -113,4 +127,34 @@ public class NotificationControllerTests extends BaseTest {
}
@Autowired
ThreadPoolTaskExecutor threadPoolTaskExecutor; //会去匹配 @Bean("poolExecutor") 这个线程池
@Test
void contextLoads() throws InterruptedException {
for (int i = 0; i < 6; i++) {
Project project = projectMapper.selectByPrimaryKey("10000100001");
BeanMap beanMap = new BeanMap(project);
Map paramMap = new HashMap<>(beanMap);
paramMap.put(NoticeConstants.RelatedUser.OPERATOR, "admin");
paramMap.put("projectId", "10000100001");
NoticeModel noticeModel = NoticeModel.builder()
.operator("admin")
.context("nihao")
.paramMap(paramMap)
.subject("hahah")
.event("UPDATE")
.excludeSelf(true)
.build();
//一定要休眠 不然主线程关闭了子线程还没有启动
noticeSendService.send("FUNCTIONAL_CASE_TASK",noticeModel);
}
Thread.sleep(10000);
}
}