feat(项目管理): 项目设置同步需求
This commit is contained in:
parent
c707a65f22
commit
0b80fab0a6
|
@ -37,6 +37,8 @@ public class ProjectApplicationType {
|
||||||
public enum CASE_RELATED_CONFIG {
|
public enum CASE_RELATED_CONFIG {
|
||||||
CASE_RELATED,
|
CASE_RELATED,
|
||||||
CASE_ENABLE,
|
CASE_ENABLE,
|
||||||
|
CRON_EXPRESSION,
|
||||||
|
SYNC_ENABLE,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum PLATFORM_DEMAND_CONFIG {
|
public enum PLATFORM_DEMAND_CONFIG {
|
||||||
|
|
|
@ -5,6 +5,6 @@ public enum ScheduleResourceType {
|
||||||
API_SCENARIO,
|
API_SCENARIO,
|
||||||
TEST_PLAN,
|
TEST_PLAN,
|
||||||
CLEAN_REPORT,
|
CLEAN_REPORT,
|
||||||
|
DEMAND_SYNC,
|
||||||
BUG_SYNC
|
BUG_SYNC
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package io.metersphere.functional.job;
|
||||||
|
|
||||||
|
import io.metersphere.functional.service.DemandSyncService;
|
||||||
|
import io.metersphere.project.service.ProjectApplicationService;
|
||||||
|
import io.metersphere.sdk.util.CommonBeanFactory;
|
||||||
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
|
import io.metersphere.system.domain.ServiceIntegration;
|
||||||
|
import io.metersphere.system.schedule.BaseScheduleJob;
|
||||||
|
import org.quartz.JobDataMap;
|
||||||
|
import org.quartz.JobExecutionContext;
|
||||||
|
import org.quartz.JobKey;
|
||||||
|
import org.quartz.TriggerKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需求同步定时任务
|
||||||
|
*/
|
||||||
|
public class DemandSyncJob extends BaseScheduleJob {
|
||||||
|
|
||||||
|
private final DemandSyncService demandSyncService;
|
||||||
|
private final ProjectApplicationService projectApplicationService;
|
||||||
|
|
||||||
|
public DemandSyncJob() {
|
||||||
|
demandSyncService = CommonBeanFactory.getBean(DemandSyncService.class);
|
||||||
|
projectApplicationService = CommonBeanFactory.getBean(ProjectApplicationService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JobKey getJobKey(String resourceId) {
|
||||||
|
return new JobKey(resourceId, DemandSyncJob.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TriggerKey getTriggerKey(String resourceId) {
|
||||||
|
return new TriggerKey(resourceId, DemandSyncJob.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void businessExecute(JobExecutionContext context) {
|
||||||
|
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
|
||||||
|
String resourceId = jobDataMap.getString("resourceId");
|
||||||
|
String userId = jobDataMap.getString("userId");
|
||||||
|
if (!checkBeforeSync(resourceId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LogUtils.info("Start synchronizing demands");
|
||||||
|
try{
|
||||||
|
demandSyncService.syncPlatformDemandBySchedule(resourceId, userId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步前检验, 同步配置的平台是否开启插件集成
|
||||||
|
* @return 是否放行
|
||||||
|
*/
|
||||||
|
private boolean checkBeforeSync(String projectId) {
|
||||||
|
ServiceIntegration serviceIntegration = projectApplicationService.getPlatformServiceIntegrationWithSyncOrDemand(projectId, true);
|
||||||
|
return serviceIntegration != null && serviceIntegration.getEnable();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.functional.mapper;
|
package io.metersphere.functional.mapper;
|
||||||
|
|
||||||
|
import io.metersphere.functional.domain.FunctionalCaseDemand;
|
||||||
import io.metersphere.functional.dto.FunctionalDemandDTO;
|
import io.metersphere.functional.dto.FunctionalDemandDTO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
@ -12,4 +13,6 @@ public interface ExtFunctionalCaseDemandMapper {
|
||||||
|
|
||||||
List<FunctionalDemandDTO> selectParentDemandByKeyword(@Param("keyword") String keyword, @Param("caseId") String caseId);
|
List<FunctionalDemandDTO> selectParentDemandByKeyword(@Param("keyword") String keyword, @Param("caseId") String caseId);
|
||||||
|
|
||||||
|
List<FunctionalCaseDemand> selectDemandByProjectId(@Param("projectId") String projectId, @Param("platform") String platform);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,11 @@
|
||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectDemandByProjectId" resultType="io.metersphere.functional.domain.FunctionalCaseDemand">
|
||||||
|
select functional_case_demand.id, functional_case_demand.demand_id, functional_case_demand.case_id
|
||||||
|
from functional_case_demand
|
||||||
|
left join functional_case on functional_case.id = functional_case_demand.case_id
|
||||||
|
where functional_case.project_id = #{caseId} and functional_case_demand.demand_platform=#{platform}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -0,0 +1,70 @@
|
||||||
|
package io.metersphere.functional.service;
|
||||||
|
|
||||||
|
import io.metersphere.functional.job.DemandSyncJob;
|
||||||
|
import io.metersphere.project.domain.ProjectApplication;
|
||||||
|
import io.metersphere.sdk.constants.ProjectApplicationType;
|
||||||
|
import io.metersphere.sdk.constants.ScheduleResourceType;
|
||||||
|
import io.metersphere.sdk.constants.ScheduleType;
|
||||||
|
import io.metersphere.system.domain.Schedule;
|
||||||
|
import io.metersphere.system.schedule.ScheduleService;
|
||||||
|
import io.metersphere.system.service.BaseDemandScheduleService;
|
||||||
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class DemandScheduleServiceImpl implements BaseDemandScheduleService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ScheduleService scheduleService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateDemandSyncScheduleConfig(List<ProjectApplication> bugSyncConfigs, String projectId, String currentUser) {
|
||||||
|
List<ProjectApplication> syncCron = bugSyncConfigs.stream().filter(config -> config.getType().equals(ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "_" + ProjectApplicationType.CASE_RELATED_CONFIG.CRON_EXPRESSION.name())).toList();
|
||||||
|
List<ProjectApplication> caseEnable = bugSyncConfigs.stream().filter(config -> config.getType().equals(ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "_" + ProjectApplicationType.CASE_RELATED_CONFIG.CASE_ENABLE.name())).toList();
|
||||||
|
List<ProjectApplication> syncEnable = bugSyncConfigs.stream().filter(config -> config.getType().equals(ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "_" + ProjectApplicationType.CASE_RELATED_CONFIG.SYNC_ENABLE.name())).toList();
|
||||||
|
if (CollectionUtils.isNotEmpty(syncCron)) {
|
||||||
|
Boolean enableCase = Boolean.valueOf(caseEnable.getFirst().getTypeValue());
|
||||||
|
Boolean enableSync = Boolean.valueOf(syncEnable.getFirst().getTypeValue());
|
||||||
|
Boolean enable = enableCase && enableSync;
|
||||||
|
String typeValue = syncCron.getFirst().getTypeValue();
|
||||||
|
Schedule schedule = scheduleService.getScheduleByResource(projectId, DemandSyncJob.class.getName());
|
||||||
|
Optional<Schedule> optional = Optional.ofNullable(schedule);
|
||||||
|
optional.ifPresentOrElse(s -> {
|
||||||
|
s.setEnable(enable);
|
||||||
|
s.setValue(typeValue);
|
||||||
|
scheduleService.editSchedule(s);
|
||||||
|
scheduleService.addOrUpdateCronJob(s, DemandSyncJob.getJobKey(projectId), DemandSyncJob.getTriggerKey(projectId), DemandSyncJob.class);
|
||||||
|
}, () -> {
|
||||||
|
Schedule request = new Schedule();
|
||||||
|
request.setName("Demand Sync Job");
|
||||||
|
request.setResourceId(projectId);
|
||||||
|
request.setKey(IDGenerator.nextStr());
|
||||||
|
request.setProjectId(projectId);
|
||||||
|
request.setEnable(enable);
|
||||||
|
request.setCreateUser(currentUser);
|
||||||
|
request.setType(ScheduleType.CRON.name());
|
||||||
|
request.setValue(typeValue);
|
||||||
|
request.setJob(DemandSyncJob.class.getName());
|
||||||
|
request.setResourceType(ScheduleResourceType.DEMAND_SYNC.name());
|
||||||
|
scheduleService.addSchedule(request);
|
||||||
|
scheduleService.addOrUpdateCronJob(request, DemandSyncJob.getJobKey(projectId), DemandSyncJob.getTriggerKey(projectId), DemandSyncJob.class);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enableOrNotDemandSyncSchedule(String projectId, String currentUser, Boolean enable) {
|
||||||
|
Schedule schedule = scheduleService.getScheduleByResource(projectId, DemandSyncJob.class.getName());
|
||||||
|
if (schedule != null) {
|
||||||
|
schedule.setEnable(enable);
|
||||||
|
scheduleService.editSchedule(schedule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package io.metersphere.functional.service;
|
||||||
|
|
||||||
|
import com.github.pagehelper.Page;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import io.metersphere.functional.domain.FunctionalCaseDemand;
|
||||||
|
import io.metersphere.functional.mapper.ExtFunctionalCaseDemandMapper;
|
||||||
|
import io.metersphere.project.service.ProjectApplicationService;
|
||||||
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
|
import io.metersphere.system.utils.PageUtils;
|
||||||
|
import io.metersphere.system.utils.Pager;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author guoyuqi
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public class DemandSyncService {
|
||||||
|
@Resource
|
||||||
|
private ExtFunctionalCaseDemandMapper extFunctionalCaseDemandMapper;
|
||||||
|
@Resource
|
||||||
|
private ProjectApplicationService projectApplicationService;
|
||||||
|
|
||||||
|
public static int DEFAULT_BATCH_SIZE = 50;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时任务同步缺陷(存量-默认中文环境通知)
|
||||||
|
* @param projectId 项目ID
|
||||||
|
* @param scheduleUser 任务触发用户
|
||||||
|
*/
|
||||||
|
public void syncPlatformDemandBySchedule(String projectId, String scheduleUser) {
|
||||||
|
String platformName = projectApplicationService.getPlatformName(projectId);
|
||||||
|
// 创建一个 List 来保存合并后的结果
|
||||||
|
Map<String, List<FunctionalCaseDemand>> updateMap = new HashMap<>();
|
||||||
|
int pageNumber = 1;
|
||||||
|
boolean count = true;
|
||||||
|
Page<Object> page = PageHelper.startPage(pageNumber, DEFAULT_BATCH_SIZE, count);
|
||||||
|
Pager<List<FunctionalCaseDemand>> listPager = PageUtils.setPageInfo(page, extFunctionalCaseDemandMapper.selectDemandByProjectId(projectId,platformName));
|
||||||
|
long total = listPager.getTotal();
|
||||||
|
List<FunctionalCaseDemand> list = listPager.getList();
|
||||||
|
Map<String, List<FunctionalCaseDemand>> demandMap = list.stream().collect(Collectors.groupingBy(FunctionalCaseDemand::getDemandId));
|
||||||
|
Set<String> demandIds = demandMap.keySet();
|
||||||
|
//TODO: 调用三方接口获取最新需求, updateMap 缓存数据
|
||||||
|
count = false;
|
||||||
|
for (int i = 1; i < ((int)Math.ceil((double) total/DEFAULT_BATCH_SIZE)); i ++) {
|
||||||
|
Page<Object> pageCycle = PageHelper.startPage(i+1, DEFAULT_BATCH_SIZE, count);
|
||||||
|
Pager<List<FunctionalCaseDemand>> listPagerCycle = PageUtils.setPageInfo(pageCycle, extFunctionalCaseDemandMapper.selectDemandByProjectId(projectId,platformName));
|
||||||
|
List<FunctionalCaseDemand> pageResults = listPagerCycle.getList();
|
||||||
|
Map<String, List<FunctionalCaseDemand>> demandsMap = pageResults.stream().collect(Collectors.groupingBy(FunctionalCaseDemand::getDemandId));
|
||||||
|
Set<String> demandIdSet = demandsMap.keySet();
|
||||||
|
//TODO: 调用三方接口获取最新需求, updateMap 缓存数据
|
||||||
|
}
|
||||||
|
//TODO: 循环updateMap,更新需求
|
||||||
|
|
||||||
|
LogUtils.info("End synchronizing demands");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ import io.metersphere.project.dto.ModuleDTO;
|
||||||
import io.metersphere.project.request.ProjectApplicationRequest;
|
import io.metersphere.project.request.ProjectApplicationRequest;
|
||||||
import io.metersphere.project.service.ProjectApplicationService;
|
import io.metersphere.project.service.ProjectApplicationService;
|
||||||
import io.metersphere.project.service.ProjectService;
|
import io.metersphere.project.service.ProjectService;
|
||||||
import io.metersphere.sdk.constants.ApplicationScope;
|
|
||||||
import io.metersphere.sdk.constants.PermissionConstants;
|
import io.metersphere.sdk.constants.PermissionConstants;
|
||||||
import io.metersphere.sdk.constants.ProjectApplicationType;
|
import io.metersphere.sdk.constants.ProjectApplicationType;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
|
@ -25,7 +24,6 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -153,7 +151,7 @@ public class ProjectApplicationController {
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_CASE_UPDATE)
|
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_CASE_UPDATE)
|
||||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateRelatedRequirementsLog(#projectId, #configs)", msClass = ProjectApplicationService.class)
|
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateRelatedRequirementsLog(#projectId, #configs)", msClass = ProjectApplicationService.class)
|
||||||
public void updateRelated(@PathVariable("projectId") String projectId, @RequestBody Map<String, String> configs) {
|
public void updateRelated(@PathVariable("projectId") String projectId, @RequestBody Map<String, String> configs) {
|
||||||
projectApplicationService.updateRelated(projectId, configs);
|
projectApplicationService.updateRelated(projectId, configs, SessionUtils.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/case/related/info/{projectId}")
|
@GetMapping("/case/related/info/{projectId}")
|
||||||
|
|
|
@ -26,10 +26,7 @@ import io.metersphere.system.log.constants.OperationLogType;
|
||||||
import io.metersphere.system.log.dto.LogDTO;
|
import io.metersphere.system.log.dto.LogDTO;
|
||||||
import io.metersphere.system.mapper.PluginMapper;
|
import io.metersphere.system.mapper.PluginMapper;
|
||||||
import io.metersphere.system.mapper.TestResourcePoolMapper;
|
import io.metersphere.system.mapper.TestResourcePoolMapper;
|
||||||
import io.metersphere.system.service.BaseBugScheduleService;
|
import io.metersphere.system.service.*;
|
||||||
import io.metersphere.system.service.PlatformPluginService;
|
|
||||||
import io.metersphere.system.service.PluginLoadService;
|
|
||||||
import io.metersphere.system.service.ServiceIntegrationService;
|
|
||||||
import io.metersphere.system.utils.ServiceUtils;
|
import io.metersphere.system.utils.ServiceUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
@ -52,9 +49,6 @@ public class ProjectApplicationService {
|
||||||
@Resource
|
@Resource
|
||||||
private ExtProjectUserRoleMapper extProjectUserRoleMapper;
|
private ExtProjectUserRoleMapper extProjectUserRoleMapper;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ProjectTestResourcePoolMapper projectTestResourcePoolMapper;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PluginMapper pluginMapper;
|
private PluginMapper pluginMapper;
|
||||||
|
|
||||||
|
@ -110,6 +104,12 @@ public class ProjectApplicationService {
|
||||||
// 缺陷同步配置开启或关闭
|
// 缺陷同步配置开启或关闭
|
||||||
baseBugScheduleService.enableOrNotBugSyncSchedule(application.getProjectId(), currentUser, Boolean.valueOf(application.getTypeValue()));
|
baseBugScheduleService.enableOrNotBugSyncSchedule(application.getProjectId(), currentUser, Boolean.valueOf(application.getTypeValue()));
|
||||||
}
|
}
|
||||||
|
BaseDemandScheduleService baseDemandScheduleService = CommonBeanFactory.getBean(BaseDemandScheduleService.class);
|
||||||
|
if (StringUtils.equals(ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "_" + ProjectApplicationType.CASE_RELATED_CONFIG.CASE_ENABLE.name(),
|
||||||
|
application.getType()) && baseDemandScheduleService != null && !Boolean.parseBoolean(application.getTypeValue())) {
|
||||||
|
// 需求同步配置关闭
|
||||||
|
baseDemandScheduleService.enableOrNotDemandSyncSchedule(application.getProjectId(), currentUser, Boolean.valueOf(application.getTypeValue()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -440,10 +440,10 @@ public class ProjectApplicationService {
|
||||||
/**
|
/**
|
||||||
* 用例关联需求配置
|
* 用例关联需求配置
|
||||||
*
|
*
|
||||||
* @param projectId
|
* @param projectId 项目ID
|
||||||
* @param configs
|
* @param configs 关联需求配置信息
|
||||||
*/
|
*/
|
||||||
public void updateRelated(String projectId, Map<String, String> configs) {
|
public void updateRelated(String projectId, Map<String, String> configs, String currentUser) {
|
||||||
List<ProjectApplication> relatedConfigs = configs.entrySet().stream().map(config -> new ProjectApplication(projectId, ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "_" + config.getKey().toUpperCase(), config.getValue())).collect(Collectors.toList());
|
List<ProjectApplication> relatedConfigs = configs.entrySet().stream().map(config -> new ProjectApplication(projectId, ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "_" + config.getKey().toUpperCase(), config.getValue())).collect(Collectors.toList());
|
||||||
ProjectApplicationExample example = new ProjectApplicationExample();
|
ProjectApplicationExample example = new ProjectApplicationExample();
|
||||||
example.createCriteria().andProjectIdEqualTo(projectId).andTypeLike(ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "%");
|
example.createCriteria().andProjectIdEqualTo(projectId).andTypeLike(ProjectApplicationType.CASE_RELATED_CONFIG.CASE_RELATED.name() + "%");
|
||||||
|
@ -455,6 +455,11 @@ public class ProjectApplicationService {
|
||||||
} else {
|
} else {
|
||||||
projectApplicationMapper.batchInsert(relatedConfigs);
|
projectApplicationMapper.batchInsert(relatedConfigs);
|
||||||
}
|
}
|
||||||
|
// 更新需求定时任务配置
|
||||||
|
BaseDemandScheduleService baseDemandScheduleService = CommonBeanFactory.getBean(BaseDemandScheduleService.class);
|
||||||
|
if (baseDemandScheduleService != null) {
|
||||||
|
baseDemandScheduleService.updateDemandSyncScheduleConfig(relatedConfigs, projectId, currentUser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package io.metersphere.system.service;
|
||||||
|
|
||||||
|
import io.metersphere.project.domain.ProjectApplication;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface BaseDemandScheduleService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新项目的需求同步定时任务
|
||||||
|
* @param demandSyncConfigs 配置
|
||||||
|
* @param projectId 项目ID
|
||||||
|
* @param currentUser 当前用户
|
||||||
|
*/
|
||||||
|
void updateDemandSyncScheduleConfig(List<ProjectApplication> demandSyncConfigs, String projectId, String currentUser);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用或禁用需求同步定时任务
|
||||||
|
* @param projectId 项目ID
|
||||||
|
* @param currentUser 当前用户
|
||||||
|
* @param enable 开启或禁用
|
||||||
|
*/
|
||||||
|
void enableOrNotDemandSyncSchedule(String projectId, String currentUser, Boolean enable);
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ public class SubSearchListUtil {
|
||||||
|
|
||||||
public static int DEFAULT_BATCH_SIZE = 50;
|
public static int DEFAULT_BATCH_SIZE = 50;
|
||||||
|
|
||||||
public <T> List<T> doForSearchList(Function<Object, List<T>> selectListFunc){
|
public static <T> List<T> doForSearchList(Function<Object, List<T>> selectListFunc){
|
||||||
// 创建一个 List 来保存合并后的结果
|
// 创建一个 List 来保存合并后的结果
|
||||||
List<T> allResults = new ArrayList<>();
|
List<T> allResults = new ArrayList<>();
|
||||||
int pageNumber = 1;
|
int pageNumber = 1;
|
||||||
|
@ -31,7 +31,7 @@ public class SubSearchListUtil {
|
||||||
return allResults;
|
return allResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T, V> List<T> doForSearchByCountList(List<V> totalList, Function<Object, List<T>> selectInListFunc){
|
public static <T, V> List<T> doForSearchByCountList(List<V> totalList, Function<Object, List<T>> selectInListFunc){
|
||||||
if (CollectionUtils.isEmpty(totalList)) {
|
if (CollectionUtils.isEmpty(totalList)) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,13 @@ export function getBugSyncInfo(projectId: string) {
|
||||||
|
|
||||||
// 用例管理-获取关联需求信息
|
// 用例管理-获取关联需求信息
|
||||||
export function getCaseRelatedInfo(projectId: string) {
|
export function getCaseRelatedInfo(projectId: string) {
|
||||||
return MSR.get<{ demand_platform_config: string; platform_key: string; case_enable: string }>({
|
return MSR.get<{
|
||||||
|
demand_platform_config: string;
|
||||||
|
platform_key: string;
|
||||||
|
case_enable: string;
|
||||||
|
sync_enable: string;
|
||||||
|
cron_expression: string;
|
||||||
|
}>({
|
||||||
url: `${Url.getCaseRelatedInfoUrl}${projectId}`,
|
url: `${Url.getCaseRelatedInfoUrl}${projectId}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,39 @@
|
||||||
:form-rule="platformRules"
|
:form-rule="platformRules"
|
||||||
@mounted="handleMounted"
|
@mounted="handleMounted"
|
||||||
/>
|
/>
|
||||||
|
<a-form-item>
|
||||||
|
<a-tooltip v-if="okDisabled" :content="t('project.menu.defect.enableAfterConfig')">
|
||||||
|
<a-switch size="small" type="line" disabled />
|
||||||
|
</a-tooltip>
|
||||||
|
<a-switch
|
||||||
|
v-else
|
||||||
|
v-model="form.SYNC_ENABLE"
|
||||||
|
checked-value="true"
|
||||||
|
unchecked-value="false"
|
||||||
|
size="small"
|
||||||
|
type="line"
|
||||||
|
/>
|
||||||
|
<span class="ml-[8px] text-[var(--color-text-1)]">
|
||||||
|
{{ t('project.menu.updateSync') }}
|
||||||
|
</span>
|
||||||
|
<a-tooltip position="tl" :content-style="{ maxWidth: '500px' }">
|
||||||
|
<template #content>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div>{{ t('project.menu.updateSyncTip') }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<MsIcon
|
||||||
|
class="ml-[8px] text-[var(--color-text-4)] hover:text-[rgb(var(--primary-5))]"
|
||||||
|
type="icon-icon-maybe_outlined"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 同步频率 -->
|
||||||
|
<a-form-item field="CRON_EXPRESSION" :label="t('project.menu.CRON_EXPRESSION')">
|
||||||
|
<MsCronSelect v-model:model-value="form.CRON_EXPRESSION" />
|
||||||
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
<template v-if="platformOption.length" #footerLeft>
|
<template v-if="platformOption.length" #footerLeft>
|
||||||
<div class="flex flex-row items-center gap-[4px]">
|
<div class="flex flex-row items-center gap-[4px]">
|
||||||
|
@ -74,6 +107,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { FormInstance, Message } from '@arco-design/web-vue';
|
import { FormInstance, Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
import MsCronSelect from '@/components/pure/ms-cron-select/index.vue';
|
||||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue';
|
import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue';
|
||||||
import type { FormItem, FormRuleItem } from '@/components/pure/ms-form-create/types';
|
import type { FormItem, FormRuleItem } from '@/components/pure/ms-form-create/types';
|
||||||
|
@ -110,7 +144,9 @@
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
PLATFORM_KEY: '',
|
PLATFORM_KEY: '',
|
||||||
CASE_ENABLE: 'false', // 同步开关
|
CASE_ENABLE: 'false', // 关联需求开关
|
||||||
|
SYNC_ENABLE: 'false', // 同步开关
|
||||||
|
CRON_EXPRESSION: '0 0 0 * * ?', // 同步频率
|
||||||
});
|
});
|
||||||
|
|
||||||
const formCreateValue = ref<Record<string, any>>({});
|
const formCreateValue = ref<Record<string, any>>({});
|
||||||
|
@ -199,6 +235,8 @@
|
||||||
if (res && res.platform_key) {
|
if (res && res.platform_key) {
|
||||||
form.CASE_ENABLE = res.case_enable;
|
form.CASE_ENABLE = res.case_enable;
|
||||||
form.PLATFORM_KEY = res.platform_key;
|
form.PLATFORM_KEY = res.platform_key;
|
||||||
|
form.SYNC_ENABLE = res.sync_enable;
|
||||||
|
form.CRON_EXPRESSION = res.cron_expression;
|
||||||
formCreateValue.value = JSON.parse(res.demand_platform_config);
|
formCreateValue.value = JSON.parse(res.demand_platform_config);
|
||||||
// 如果平台key存在调用平台change拉取插件字段
|
// 如果平台key存在调用平台change拉取插件字段
|
||||||
await handlePlatformChange(res.platform_key);
|
await handlePlatformChange(res.platform_key);
|
||||||
|
|
|
@ -48,6 +48,9 @@ export default {
|
||||||
'project.menu.notConfig': 'Third-party information not configured, click',
|
'project.menu.notConfig': 'Third-party information not configured, click',
|
||||||
'project.menu.configure': 'to configure',
|
'project.menu.configure': 'to configure',
|
||||||
'project.menu.status': 'Status',
|
'project.menu.status': 'Status',
|
||||||
|
'project.menu.updateSync': 'Update mechanism',
|
||||||
|
'project.menu.updateSyncTip':
|
||||||
|
'When turned on, the associated requirements will be updated according to the set frequency.',
|
||||||
'project.menu.incrementalSync': 'Incremental Synchronization',
|
'project.menu.incrementalSync': 'Incremental Synchronization',
|
||||||
'project.menu.incrementalSyncTip': 'Only make content changes to existing third-party defects in MS',
|
'project.menu.incrementalSyncTip': 'Only make content changes to existing third-party defects in MS',
|
||||||
'project.menu.fullSync': 'Full Synchronization',
|
'project.menu.fullSync': 'Full Synchronization',
|
||||||
|
|
|
@ -44,6 +44,8 @@ export default {
|
||||||
'project.menu.notConfig': '未配置第三方信息,点击',
|
'project.menu.notConfig': '未配置第三方信息,点击',
|
||||||
'project.menu.configure': '进行配置',
|
'project.menu.configure': '进行配置',
|
||||||
'project.menu.status': '状态',
|
'project.menu.status': '状态',
|
||||||
|
'project.menu.updateSync': '更新机制',
|
||||||
|
'project.menu.updateSyncTip': '开启后,会根据设置的频率,更新已关联的需求',
|
||||||
'project.menu.incrementalSync': '增量同步',
|
'project.menu.incrementalSync': '增量同步',
|
||||||
'project.menu.incrementalSyncTip': '仅对 MS 中存在的三方缺陷做内容变更',
|
'project.menu.incrementalSyncTip': '仅对 MS 中存在的三方缺陷做内容变更',
|
||||||
'project.menu.fullSync': '全量同步',
|
'project.menu.fullSync': '全量同步',
|
||||||
|
|
Loading…
Reference in New Issue