fix(缺陷管理): 修复缺陷更新刷新方式
--bug=1038739 --user=宋昌昌 【缺陷管理】优化更新缺陷刷新方式 https://www.tapd.cn/55049933/s/1491966 --bug=1038537 --user=宋昌昌 【项目管理】添加文件提示和逻辑优化 https://www.tapd.cn/55049933/s/1493052 --bug=1039006 --user=宋昌昌 【项目管理】项目与权限-应用设置-用例管理-关联需求输入错误的key提示优化 https://www.tapd.cn/55049933/s/1493115
This commit is contained in:
parent
0987e1fc82
commit
08826e6236
|
@ -432,6 +432,8 @@ message.domain.bug_updateTime=更新时间
|
||||||
message.domain.bug_deleteUser=删除人
|
message.domain.bug_deleteUser=删除人
|
||||||
message.domain.bug_deleteTime=删除时间
|
message.domain.bug_deleteTime=删除时间
|
||||||
message.domain.bug_handleUser=处理人
|
message.domain.bug_handleUser=处理人
|
||||||
|
message.domain.bug_sync_platform=同步平台
|
||||||
|
message.domain.bug_sync_total_count=同步数量
|
||||||
#UI
|
#UI
|
||||||
message.domain.ui_name=场景名称
|
message.domain.ui_name=场景名称
|
||||||
message.domain.ui_level=用例等级
|
message.domain.ui_level=用例等级
|
||||||
|
|
|
@ -468,6 +468,8 @@ message.domain.bug_updateTime=Update time
|
||||||
message.domain.bug_deleteUser=Delete user
|
message.domain.bug_deleteUser=Delete user
|
||||||
message.domain.bug_deleteTime=Delete time
|
message.domain.bug_deleteTime=Delete time
|
||||||
message.domain.bug_handleUser=Processor
|
message.domain.bug_handleUser=Processor
|
||||||
|
message.domain.bug_sync_platform=Platform
|
||||||
|
message.domain.bug_sync_total_count=Total
|
||||||
#UI
|
#UI
|
||||||
message.domain.ui_name=Scenario name
|
message.domain.ui_name=Scenario name
|
||||||
message.domain.ui_level=Case level
|
message.domain.ui_level=Case level
|
||||||
|
|
|
@ -467,6 +467,8 @@ message.domain.bug_updateTime=更新时间
|
||||||
message.domain.bug_deleteUser=删除人
|
message.domain.bug_deleteUser=删除人
|
||||||
message.domain.bug_deleteTime=删除时间
|
message.domain.bug_deleteTime=删除时间
|
||||||
message.domain.bug_handleUser=处理人
|
message.domain.bug_handleUser=处理人
|
||||||
|
message.domain.bug_sync_platform=同步平台
|
||||||
|
message.domain.bug_sync_total_count=同步数量
|
||||||
#UI
|
#UI
|
||||||
message.domain.ui_name=场景名称
|
message.domain.ui_name=场景名称
|
||||||
message.domain.ui_level=用例等级
|
message.domain.ui_level=用例等级
|
||||||
|
|
|
@ -468,6 +468,8 @@ message.domain.bug_updateTime=更新時間
|
||||||
message.domain.bug_deleteUser=刪除人
|
message.domain.bug_deleteUser=刪除人
|
||||||
message.domain.bug_deleteTime=刪除時間
|
message.domain.bug_deleteTime=刪除時間
|
||||||
message.domain.bug_handleUser=處理人
|
message.domain.bug_handleUser=處理人
|
||||||
|
message.domain.bug_sync_platform=同步平臺
|
||||||
|
message.domain.bug_sync_total_count=同步數量
|
||||||
#UI
|
#UI
|
||||||
message.domain.ui_name=場景名稱
|
message.domain.ui_name=場景名稱
|
||||||
message.domain.ui_level=用例等級
|
message.domain.ui_level=用例等級
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.bug.service;
|
package io.metersphere.bug.service;
|
||||||
|
|
||||||
|
import io.metersphere.project.service.ProjectApplicationService;
|
||||||
import io.metersphere.system.domain.User;
|
import io.metersphere.system.domain.User;
|
||||||
import io.metersphere.system.mapper.UserMapper;
|
import io.metersphere.system.mapper.UserMapper;
|
||||||
import io.metersphere.system.notice.NoticeModel;
|
import io.metersphere.system.notice.NoticeModel;
|
||||||
|
@ -23,19 +24,24 @@ public class BugSyncNoticeService {
|
||||||
@Resource
|
@Resource
|
||||||
private NoticeSendService noticeSendService;
|
private NoticeSendService noticeSendService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ProjectApplicationService projectApplicationService;
|
||||||
|
|
||||||
public void sendNotice(int total, String currentUser, String language, String projectId) {
|
public void sendNotice(int total, String currentUser, String language, String projectId) {
|
||||||
|
String platformName = projectApplicationService.getPlatformName(projectId);
|
||||||
User user = userMapper.selectByPrimaryKey(currentUser);
|
User user = userMapper.selectByPrimaryKey(currentUser);
|
||||||
Map<String, String> defaultTemplateMap = MessageTemplateUtils.getDefaultTemplateMap();
|
Map<String, String> defaultTemplateMap = MessageTemplateUtils.getDefaultTemplateMap();
|
||||||
String template = defaultTemplateMap.get(NoticeConstants.TemplateText.BUG_SYNC_TASK_EXECUTE_COMPLETED);
|
String template = defaultTemplateMap.get(NoticeConstants.TemplateText.BUG_SYNC_TASK_EXECUTE_COMPLETED);
|
||||||
Map<String, String> defaultSubjectMap = MessageTemplateUtils.getDefaultTemplateSubjectMap();
|
Map<String, String> defaultSubjectMap = MessageTemplateUtils.getDefaultTemplateSubjectMap();
|
||||||
String subject = defaultSubjectMap.get(NoticeConstants.TemplateText.BUG_SYNC_TASK_EXECUTE_COMPLETED);
|
String subject = defaultSubjectMap.get(NoticeConstants.TemplateText.BUG_SYNC_TASK_EXECUTE_COMPLETED);
|
||||||
// ${OPERATOR}同步了${total}条缺陷
|
// ${OPERATOR}同步了${total}条缺陷
|
||||||
Map<String, Object> paramMap = new HashMap<>(3);
|
Map<String, Object> paramMap = new HashMap<>(4);
|
||||||
paramMap.put(NoticeConstants.RelatedUser.OPERATOR, user.getName());
|
paramMap.put(NoticeConstants.RelatedUser.OPERATOR, user.getName());
|
||||||
paramMap.put("total", total);
|
paramMap.put("total", total);
|
||||||
paramMap.put("projectId", projectId);
|
paramMap.put("projectId", projectId);
|
||||||
paramMap.put("Language", language);
|
paramMap.put("Language", language);
|
||||||
NoticeModel noticeModel = NoticeModel.builder().operator(currentUser)
|
paramMap.put("platform", platformName);
|
||||||
|
NoticeModel noticeModel = NoticeModel.builder().operator(currentUser).excludeSelf(false)
|
||||||
.context(template).subject(subject).paramMap(paramMap).event(NoticeConstants.Event.EXECUTE_COMPLETED).build();
|
.context(template).subject(subject).paramMap(paramMap).event(NoticeConstants.Event.EXECUTE_COMPLETED).build();
|
||||||
noticeSendService.send(NoticeConstants.TaskType.BUG_SYNC_TASK, noticeModel);
|
noticeSendService.send(NoticeConstants.TaskType.BUG_SYNC_TASK, noticeModel);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,10 @@ import io.metersphere.sdk.util.Translator;
|
||||||
import io.metersphere.system.domain.CustomField;
|
import io.metersphere.system.domain.CustomField;
|
||||||
import io.metersphere.system.domain.CustomFieldExample;
|
import io.metersphere.system.domain.CustomFieldExample;
|
||||||
import io.metersphere.system.domain.Schedule;
|
import io.metersphere.system.domain.Schedule;
|
||||||
import io.metersphere.system.dto.BugNoticeDTO;
|
import io.metersphere.system.dto.BugMessageDTO;
|
||||||
|
import io.metersphere.system.dto.BugSyncNoticeDTO;
|
||||||
|
import io.metersphere.system.dto.request.DefaultBugCustomField;
|
||||||
|
import io.metersphere.system.dto.request.DefaultFunctionalCustomField;
|
||||||
import io.metersphere.system.dto.sdk.ApiDefinitionCaseDTO;
|
import io.metersphere.system.dto.sdk.ApiDefinitionCaseDTO;
|
||||||
import io.metersphere.system.dto.sdk.ApiScenarioMessageDTO;
|
import io.metersphere.system.dto.sdk.ApiScenarioMessageDTO;
|
||||||
import io.metersphere.system.dto.sdk.FunctionalCaseMessageDTO;
|
import io.metersphere.system.dto.sdk.FunctionalCaseMessageDTO;
|
||||||
|
@ -71,11 +74,16 @@ public class NoticeTemplateService {
|
||||||
//TODO:获取报告
|
//TODO:获取报告
|
||||||
}
|
}
|
||||||
case NoticeConstants.TaskType.BUG_TASK -> {
|
case NoticeConstants.TaskType.BUG_TASK -> {
|
||||||
Field[] allFields = FieldUtils.getAllFields(BugNoticeDTO.class);
|
Field[] allFields = FieldUtils.getAllFields(BugMessageDTO.class);
|
||||||
addOptionDto(messageTemplateFieldDTOList, allFields, null);
|
addOptionDto(messageTemplateFieldDTOList, allFields, null);
|
||||||
addCustomFiled(messageTemplateFieldDTOList, projectId, TemplateScene.BUG.toString());
|
addCustomFiled(messageTemplateFieldDTOList, projectId, TemplateScene.BUG.toString());
|
||||||
//TODO:获取报告
|
//TODO:获取报告
|
||||||
}
|
}
|
||||||
|
case NoticeConstants.TaskType.BUG_SYNC_TASK -> {
|
||||||
|
Field[] allFields = FieldUtils.getAllFields(BugSyncNoticeDTO.class);
|
||||||
|
addOptionDto(messageTemplateFieldDTOList, allFields, null);
|
||||||
|
//TODO:获取报告
|
||||||
|
}
|
||||||
case NoticeConstants.TaskType.UI_SCENARIO_TASK -> {
|
case NoticeConstants.TaskType.UI_SCENARIO_TASK -> {
|
||||||
Field[] allFields = FieldUtils.getAllFields(UiScenario.class);
|
Field[] allFields = FieldUtils.getAllFields(UiScenario.class);
|
||||||
addOptionDto(messageTemplateFieldDTOList, allFields, "ui_");
|
addOptionDto(messageTemplateFieldDTOList, allFields, "ui_");
|
||||||
|
@ -120,7 +128,13 @@ public class NoticeTemplateService {
|
||||||
for (CustomField customField : customFields) {
|
for (CustomField customField : customFields) {
|
||||||
MessageTemplateFieldDTO messageTemplateFieldDTO = new MessageTemplateFieldDTO();
|
MessageTemplateFieldDTO messageTemplateFieldDTO = new MessageTemplateFieldDTO();
|
||||||
messageTemplateFieldDTO.setId(customField.getName());
|
messageTemplateFieldDTO.setId(customField.getName());
|
||||||
messageTemplateFieldDTO.setName(StringUtils.isBlank(customField.getRemark()) ? "-" : customField.getRemark());
|
if (StringUtils.equalsAnyIgnoreCase(customField.getName(),
|
||||||
|
DefaultBugCustomField.DEGREE.getName(), DefaultFunctionalCustomField.PRIORITY.getName())) {
|
||||||
|
// 缺陷严重程度, 用例等级 作为系统内置的自定义字段需要国际化后在模板展示
|
||||||
|
messageTemplateFieldDTO.setName(Translator.get("custom_field." + customField.getName()));
|
||||||
|
} else {
|
||||||
|
messageTemplateFieldDTO.setName(customField.getName());
|
||||||
|
}
|
||||||
messageTemplateFieldDTO.setFieldSource(NoticeConstants.FieldSource.CUSTOM_FIELD);
|
messageTemplateFieldDTO.setFieldSource(NoticeConstants.FieldSource.CUSTOM_FIELD);
|
||||||
messageTemplateFieldDTOS.add(messageTemplateFieldDTO);
|
messageTemplateFieldDTOS.add(messageTemplateFieldDTO);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package io.metersphere.system.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class BugMessageDTO {
|
||||||
|
|
||||||
|
@Schema(description ="message.domain.bug_num")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description ="message.domain.bug_title")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Schema(description ="message.domain.bug_handleUser")
|
||||||
|
private String handleUser;
|
||||||
|
|
||||||
|
@Schema(description ="message.domain.bug_status")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_createUser")
|
||||||
|
private String createUser;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_updateUser")
|
||||||
|
private String updateUser;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_deleteUser")
|
||||||
|
private String deleteUser;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_createTime")
|
||||||
|
private Long createTime;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_updateTime")
|
||||||
|
private Long updateTime;
|
||||||
|
|
||||||
|
@Schema(description = "message.domain.bug_deleteTime")
|
||||||
|
private Long deleteTime;
|
||||||
|
}
|
|
@ -3,47 +3,15 @@ package io.metersphere.system.dto;
|
||||||
import io.metersphere.system.dto.sdk.OptionDTO;
|
import io.metersphere.system.dto.sdk.OptionDTO;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class BugNoticeDTO {
|
public class BugNoticeDTO extends BugMessageDTO{
|
||||||
|
|
||||||
@Schema(description ="message.domain.bug_num")
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
@Schema(description ="message.domain.bug_title")
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
@Schema(description ="message.domain.bug_handleUser")
|
|
||||||
private String handleUser;
|
|
||||||
|
|
||||||
@Schema(description ="message.domain.bug_status")
|
|
||||||
private String status;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_createUser")
|
|
||||||
private String createUser;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_updateUser")
|
|
||||||
private String updateUser;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_deleteUser")
|
|
||||||
private String deleteUser;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_createTime")
|
|
||||||
private Long createTime;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_updateTime")
|
|
||||||
private Long updateTime;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_deleteTime")
|
|
||||||
private Long deleteTime;
|
|
||||||
|
|
||||||
@Schema(description = "自定义字段内容")
|
@Schema(description = "自定义字段内容")
|
||||||
private List<OptionDTO> customFields;
|
private List<OptionDTO> customFields;
|
||||||
|
|
|
@ -1,47 +1,20 @@
|
||||||
package io.metersphere.system.dto;
|
package io.metersphere.system.dto;
|
||||||
|
|
||||||
import io.metersphere.system.dto.sdk.OptionDTO;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class BugSyncNoticeDTO {
|
public class BugSyncNoticeDTO {
|
||||||
|
|
||||||
@Schema(description ="message.domain.bug_title")
|
@Schema(description ="message.domain.bug_sync_platform")
|
||||||
private String title;
|
private String platform;
|
||||||
|
|
||||||
@Schema(description ="message.domain.bug_handleUser")
|
@Schema(description ="message.domain.bug_sync_total_count")
|
||||||
private String handleUser;
|
private Integer total;
|
||||||
|
|
||||||
@Schema(description ="message.domain.bug_status")
|
|
||||||
private String status;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_createUser")
|
|
||||||
private String createUser;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_updateUser")
|
|
||||||
private String updateUser;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_deleteUser")
|
|
||||||
private String deleteUser;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_createTime")
|
|
||||||
private Long createTime;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_updateTime")
|
|
||||||
private Long updateTime;
|
|
||||||
|
|
||||||
@Schema(description = "message.domain.bug_deleteTime")
|
|
||||||
private Long deleteTime;
|
|
||||||
|
|
||||||
@Schema(description = "自定义字段内容")
|
|
||||||
private List<OptionDTO> customFields;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import io.metersphere.load.domain.LoadTest;
|
||||||
import io.metersphere.plan.domain.TestPlan;
|
import io.metersphere.plan.domain.TestPlan;
|
||||||
import io.metersphere.sdk.util.Translator;
|
import io.metersphere.sdk.util.Translator;
|
||||||
import io.metersphere.system.domain.Schedule;
|
import io.metersphere.system.domain.Schedule;
|
||||||
import io.metersphere.system.dto.BugNoticeDTO;
|
import io.metersphere.system.dto.BugMessageDTO;
|
||||||
import io.metersphere.system.dto.sdk.ApiDefinitionCaseDTO;
|
import io.metersphere.system.dto.sdk.ApiDefinitionCaseDTO;
|
||||||
import io.metersphere.system.dto.sdk.FunctionalCaseMessageDTO;
|
import io.metersphere.system.dto.sdk.FunctionalCaseMessageDTO;
|
||||||
import io.metersphere.system.notice.constants.NoticeConstants;
|
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||||
|
@ -153,7 +153,7 @@ public class MessageTemplateUtils {
|
||||||
allFields = FieldUtils.getAllFields(FunctionalCaseMessageDTO.class);
|
allFields = FieldUtils.getAllFields(FunctionalCaseMessageDTO.class);
|
||||||
}
|
}
|
||||||
case NoticeConstants.TaskType.BUG_TASK -> {
|
case NoticeConstants.TaskType.BUG_TASK -> {
|
||||||
allFields = FieldUtils.getAllFields(BugNoticeDTO.class);
|
allFields = FieldUtils.getAllFields(BugMessageDTO.class);
|
||||||
}
|
}
|
||||||
case NoticeConstants.TaskType.UI_SCENARIO_TASK -> {
|
case NoticeConstants.TaskType.UI_SCENARIO_TASK -> {
|
||||||
allFields = FieldUtils.getAllFields(UiScenario.class);
|
allFields = FieldUtils.getAllFields(UiScenario.class);
|
||||||
|
|
|
@ -4,8 +4,8 @@ import io.metersphere.project.domain.*;
|
||||||
import io.metersphere.project.mapper.MessageTaskBlobMapper;
|
import io.metersphere.project.mapper.MessageTaskBlobMapper;
|
||||||
import io.metersphere.project.mapper.MessageTaskMapper;
|
import io.metersphere.project.mapper.MessageTaskMapper;
|
||||||
import io.metersphere.project.mapper.ProjectRobotMapper;
|
import io.metersphere.project.mapper.ProjectRobotMapper;
|
||||||
import io.metersphere.system.notice.MessageDetail;
|
|
||||||
import io.metersphere.sdk.util.LogUtils;
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
|
import io.metersphere.system.notice.MessageDetail;
|
||||||
import io.metersphere.system.notice.utils.MessageTemplateUtils;
|
import io.metersphere.system.notice.utils.MessageTemplateUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
@ -13,7 +13,10 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -62,5 +62,4 @@ declare global {
|
||||||
declare global {
|
declare global {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
|
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
|
||||||
import('vue')
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
:detail-id="props.detailId"
|
:detail-id="props.detailId"
|
||||||
:detail-index="props.detailIndex"
|
:detail-index="props.detailIndex"
|
||||||
:table-data="props.tableData"
|
:table-data="props.tableData"
|
||||||
|
@loading-detail="setDetailLoading"
|
||||||
@loaded="handleDetailLoaded"
|
@loaded="handleDetailLoaded"
|
||||||
/>
|
/>
|
||||||
<div class="ml-auto flex items-center">
|
<div class="ml-auto flex items-center">
|
||||||
|
@ -59,7 +60,7 @@
|
||||||
getDetailFunc: (id: string) => Promise<any>; // 获取详情的请求函数
|
getDetailFunc: (id: string) => Promise<any>; // 获取详情的请求函数
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits(['update:visible', 'loaded']);
|
const emit = defineEmits(['update:visible', 'loaded', 'loadingDetail']);
|
||||||
|
|
||||||
const prevNextButtonRef = ref<InstanceType<typeof MsPrevNextButton>>();
|
const prevNextButtonRef = ref<InstanceType<typeof MsPrevNextButton>>();
|
||||||
|
|
||||||
|
@ -99,6 +100,10 @@
|
||||||
emit('loaded', val);
|
emit('loaded', val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setDetailLoading() {
|
||||||
|
emit('loadingDetail');
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => innerVisible.value,
|
() => innerVisible.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
|
@ -128,4 +133,4 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
|
@ -52,7 +52,7 @@
|
||||||
getDetailFunc: (id: string) => Promise<any>; // 获取详情的请求函数
|
getDetailFunc: (id: string) => Promise<any>; // 获取详情的请求函数
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits(['update:loading', 'loaded']);
|
const emit = defineEmits(['update:loading', 'loaded', 'loadingDetail']);
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@
|
||||||
async function initDetail() {
|
async function initDetail() {
|
||||||
try {
|
try {
|
||||||
innerLoading.value = true;
|
innerLoading.value = true;
|
||||||
|
emit('loadingDetail');
|
||||||
const res = await props.getDetailFunc(activeDetailId.value);
|
const res = await props.getDetailFunc(activeDetailId.value);
|
||||||
emit('loaded', res);
|
emit('loaded', res);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -171,4 +172,4 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
|
@ -225,6 +225,18 @@
|
||||||
tooltip: item.tooltip,
|
tooltip: item.tooltip,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
if (ruleItem.type === 'input') {
|
||||||
|
// input 需要单独emit监听事件 emit:['change', 'blur'],
|
||||||
|
ruleItem.on = {
|
||||||
|
blur: () => {
|
||||||
|
// 失去焦点后value值改变
|
||||||
|
if (item.value !== fApi.value.getValue(item.name)) {
|
||||||
|
fApi.value.validateField(item.name);
|
||||||
|
emit('change', fApi.value.getValue(item.name), ruleItem, fApi.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
// 如果存在placeholder, 替换掉默认的placeholder
|
// 如果存在placeholder, 替换掉默认的placeholder
|
||||||
if (item.platformPlaceHolder) {
|
if (item.platformPlaceHolder) {
|
||||||
ruleItem.props.placeholder = item.platformPlaceHolder;
|
ruleItem.props.placeholder = item.platformPlaceHolder;
|
||||||
|
@ -256,6 +268,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeHandler(value: any, defaultValue: any, formRuleItem: FormRuleItem, api: any) {
|
||||||
|
if (formRuleItem.type === 'input') {
|
||||||
|
// 输入框失去焦点后再保存
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fApi.value.validateField(value);
|
||||||
|
emit('change', defaultValue, formRuleItem, api);
|
||||||
|
}
|
||||||
|
|
||||||
function getControlFormItems() {
|
function getControlFormItems() {
|
||||||
const convertedData = formItems.value.map((item: FormItem) => convertItem(item));
|
const convertedData = formItems.value.map((item: FormItem) => convertItem(item));
|
||||||
formRuleList.value = convertedData;
|
formRuleList.value = convertedData;
|
||||||
|
@ -270,7 +291,6 @@
|
||||||
}
|
}
|
||||||
function setValue() {
|
function setValue() {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
console.log(props.formRule);
|
|
||||||
const tempObj: Record<string, any> = {};
|
const tempObj: Record<string, any> = {};
|
||||||
props.formRule.forEach((item) => {
|
props.formRule.forEach((item) => {
|
||||||
tempObj[item.name] = item.value;
|
tempObj[item.name] = item.value;
|
||||||
|
@ -306,11 +326,6 @@
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function changeHandler(value: any, defaultValue: any, formRuleItem: FormRuleItem, api: any) {
|
|
||||||
fApi.value.validateField(value);
|
|
||||||
emit('change', defaultValue, formRuleItem, api);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleMounted() {
|
function handleMounted() {
|
||||||
// setValue();
|
// setValue();
|
||||||
emit('mounted');
|
emit('mounted');
|
||||||
|
@ -339,4 +354,4 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
|
@ -56,7 +56,7 @@
|
||||||
v-if="item.status === UploadStatus.init"
|
v-if="item.status === UploadStatus.init"
|
||||||
class="text-[12px] leading-[16px] text-[var(--color-text-4)]"
|
class="text-[12px] leading-[16px] text-[var(--color-text-4)]"
|
||||||
>
|
>
|
||||||
{{ t('ms.upload.waiting_save') }}
|
{{ initFileSaveTips ? initFileSaveTips : t('ms.upload.waiting') }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="item.status === UploadStatus.done"
|
v-else-if="item.status === UploadStatus.done"
|
||||||
|
@ -76,8 +76,8 @@
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<div v-if="showUploadSuccess(item)" class="flex items-center">
|
<div v-if="showUploadSuccess(item)" class="ml-4 flex items-center">
|
||||||
<MsIcon type="icon-icon_succeed_colorful" />
|
<MsIcon type="icon-icon_succeed_colorful" class="mr-2" />
|
||||||
{{ t('ms.upload.uploadSuccess') }}
|
{{ t('ms.upload.uploadSuccess') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -185,6 +185,7 @@
|
||||||
showDelete?: boolean; // 是否展示删除按钮
|
showDelete?: boolean; // 是否展示删除按钮
|
||||||
handleView?: (item: MsFileItem) => void; // 是否自定义预览
|
handleView?: (item: MsFileItem) => void; // 是否自定义预览
|
||||||
showUploadTypeDesc?: boolean; // 自定义上传类型关联于&上传于
|
showUploadTypeDesc?: boolean; // 自定义上传类型关联于&上传于
|
||||||
|
initFileSaveTips?: string; // 上传初始文件时的提示
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
mode: 'remote',
|
mode: 'remote',
|
||||||
|
@ -211,6 +212,7 @@
|
||||||
watch(
|
watch(
|
||||||
() => props.fileList,
|
() => props.fileList,
|
||||||
(val) => {
|
(val) => {
|
||||||
|
console.log(props.initFileSaveTips);
|
||||||
innerFileList.value = val.sort((a, b) => {
|
innerFileList.value = val.sort((a, b) => {
|
||||||
if (a.status === UploadStatus.init && b.status !== UploadStatus.init) {
|
if (a.status === UploadStatus.init && b.status !== UploadStatus.init) {
|
||||||
return -1; // "init" 排在前面
|
return -1; // "init" 排在前面
|
||||||
|
@ -381,4 +383,4 @@
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -15,6 +15,7 @@
|
||||||
show-full-screen
|
show-full-screen
|
||||||
unmount-on-close
|
unmount-on-close
|
||||||
:mask="false"
|
:mask="false"
|
||||||
|
@loading-detail="setDetailLoading"
|
||||||
@loaded="loadedBug"
|
@loaded="loadedBug"
|
||||||
>
|
>
|
||||||
<template #titleLeft>
|
<template #titleLeft>
|
||||||
|
@ -90,113 +91,115 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #default="{ loading }">
|
<template #default="{ loading }">
|
||||||
<div ref="wrapperRef" class="h-full bg-white">
|
<a-spin :loading="detailLoading" class="w-full">
|
||||||
<MsSplitBox
|
<div ref="wrapperRef" class="h-full bg-white">
|
||||||
ref="wrapperRef"
|
<MsSplitBox
|
||||||
expand-direction="right"
|
ref="wrapperRef"
|
||||||
:max="0.7"
|
expand-direction="right"
|
||||||
:min="0.7"
|
:max="0.7"
|
||||||
:size="900"
|
:min="0.7"
|
||||||
:class="{ 'left-bug-detail': activeTab === 'comment' }"
|
:size="900"
|
||||||
>
|
:class="{ 'left-bug-detail': activeTab === 'comment' }"
|
||||||
<template #first>
|
>
|
||||||
<div class="leftWrapper h-full">
|
<template #first>
|
||||||
<div class="header h-[50px]">
|
<div class="leftWrapper h-full">
|
||||||
<MsTab
|
<div class="header h-[50px]">
|
||||||
v-model:active-key="activeTab"
|
<MsTab
|
||||||
:content-tab-list="contentTabList"
|
v-model:active-key="activeTab"
|
||||||
:get-text-func="getTabBadge"
|
:content-tab-list="contentTabList"
|
||||||
class="no-content relative mb-[8px]"
|
:get-text-func="getTabBadge"
|
||||||
/>
|
class="no-content relative mb-[8px]"
|
||||||
<div class="tab-pane-container">
|
|
||||||
<BugDetailTab
|
|
||||||
v-if="activeTab === 'detail'"
|
|
||||||
ref="bugDetailTabRef"
|
|
||||||
:form-item="formItem"
|
|
||||||
:allow-edit="hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])"
|
|
||||||
:detail-info="detailInfo"
|
|
||||||
:is-platform-default-template="isPlatformDefaultTemplate"
|
|
||||||
:platform-system-fields="platformSystemFields"
|
|
||||||
:current-platform="props.currentPlatform"
|
|
||||||
@update-success="updateSuccess"
|
|
||||||
/>
|
/>
|
||||||
|
<div class="tab-pane-container">
|
||||||
|
<BugDetailTab
|
||||||
|
v-if="activeTab === 'detail'"
|
||||||
|
ref="bugDetailTabRef"
|
||||||
|
:form-item="formItem"
|
||||||
|
:allow-edit="hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])"
|
||||||
|
:detail-info="detailInfo"
|
||||||
|
:is-platform-default-template="isPlatformDefaultTemplate"
|
||||||
|
:platform-system-fields="platformSystemFields"
|
||||||
|
:current-platform="props.currentPlatform"
|
||||||
|
@update-success="updateSuccess"
|
||||||
|
/>
|
||||||
|
|
||||||
<BugCaseTab
|
<BugCaseTab
|
||||||
v-else-if="activeTab === 'case'"
|
v-else-if="activeTab === 'case'"
|
||||||
:bug-id="detailInfo.id"
|
:bug-id="detailInfo.id"
|
||||||
@update-case-success="updateSuccess"
|
@update-case-success="updateSuccess"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CommentTab v-else-if="activeTab === 'comment'" ref="commentRef" :bug-id="detailInfo.id" />
|
<CommentTab v-else-if="activeTab === 'comment'" ref="commentRef" :bug-id="detailInfo.id" />
|
||||||
|
|
||||||
<BugHistoryTab v-else-if="activeTab === 'history'" :bug-id="detailInfo.id" />
|
<BugHistoryTab v-else-if="activeTab === 'history'" :bug-id="detailInfo.id" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
<template #second>
|
||||||
<template #second>
|
<a-spin :loading="rightLoading" class="w-full">
|
||||||
<a-spin :loading="rightLoading" class="w-full">
|
<!-- 所属平台一致, 详情展示 -->
|
||||||
<!-- 所属平台一致, 详情展示 -->
|
<div v-if="props.currentPlatform === detailInfo.platform" class="rightWrapper p-[24px]">
|
||||||
<div v-if="props.currentPlatform === detailInfo.platform" class="rightWrapper p-[24px]">
|
<!-- 自定义字段开始 -->
|
||||||
<!-- 自定义字段开始 -->
|
<div class="inline-block w-full break-words">
|
||||||
<div class="inline-block w-full break-words">
|
<a-skeleton v-if="loading" class="w-full" :loading="loading" :animation="true">
|
||||||
<a-skeleton v-if="loading" class="w-full" :loading="loading" :animation="true">
|
<a-space direction="vertical" class="w-[100%]" size="large">
|
||||||
<a-space direction="vertical" class="w-[100%]" size="large">
|
<a-skeleton-line :rows="14" :line-height="30" :line-spacing="30" />
|
||||||
<a-skeleton-line :rows="14" :line-height="30" :line-spacing="30" />
|
</a-space>
|
||||||
</a-space>
|
</a-skeleton>
|
||||||
</a-skeleton>
|
<div v-if="!loading" class="mb-4 font-medium">
|
||||||
<div v-if="!loading" class="mb-4 font-medium">
|
<strong>
|
||||||
<strong>
|
{{ t('bugManagement.detail.basicInfo') }}
|
||||||
{{ t('bugManagement.detail.basicInfo') }}
|
</strong>
|
||||||
</strong>
|
</div>
|
||||||
</div>
|
<MsFormCreate
|
||||||
<MsFormCreate
|
v-if="!loading"
|
||||||
v-if="!loading"
|
ref="formCreateRef"
|
||||||
ref="formCreateRef"
|
v-model:form-item="formItem"
|
||||||
v-model:form-item="formItem"
|
v-model:api="fApi"
|
||||||
v-model:api="fApi"
|
:form-rule="formRules"
|
||||||
:form-rule="formRules"
|
class="w-full"
|
||||||
class="w-full"
|
:option="options"
|
||||||
:option="options"
|
@change="handelFormCreateChange"
|
||||||
@change="handelFormCreateChange"
|
/>
|
||||||
/>
|
<!-- 自定义字段结束 -->
|
||||||
<!-- 自定义字段结束 -->
|
<div
|
||||||
<div
|
v-if="!isPlatformDefaultTemplate && hasAnyPermission(['PROJECT_BUG:READ+UPDATE']) && !loading"
|
||||||
v-if="!isPlatformDefaultTemplate && hasAnyPermission(['PROJECT_BUG:READ+UPDATE']) && !loading"
|
class="baseItem"
|
||||||
class="baseItem"
|
|
||||||
>
|
|
||||||
<a-form
|
|
||||||
:model="{}"
|
|
||||||
:label-col-props="{
|
|
||||||
span: 9,
|
|
||||||
}"
|
|
||||||
:wrapper-col-props="{
|
|
||||||
span: 15,
|
|
||||||
}"
|
|
||||||
label-align="left"
|
|
||||||
content-class="tags-class"
|
|
||||||
>
|
>
|
||||||
<a-form-item field="tags" :label="t('system.orgTemplate.tags')">
|
<a-form
|
||||||
<MsTagsInput
|
:model="{}"
|
||||||
v-model:model-value="tags"
|
:label-col-props="{
|
||||||
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])"
|
span: 9,
|
||||||
@blur="changeTag"
|
}"
|
||||||
/>
|
:wrapper-col-props="{
|
||||||
</a-form-item>
|
span: 15,
|
||||||
</a-form>
|
}"
|
||||||
|
label-align="left"
|
||||||
|
content-class="tags-class"
|
||||||
|
>
|
||||||
|
<a-form-item field="tags" :label="t('system.orgTemplate.tags')">
|
||||||
|
<MsTagsInput
|
||||||
|
v-model:model-value="tags"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])"
|
||||||
|
@blur="changeTag"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 内置基础信息结束 -->
|
<!-- 内置基础信息结束 -->
|
||||||
</div>
|
</div>
|
||||||
<!-- 所属平台不一致, 详情不展示, 展示空面板 -->
|
<!-- 所属平台不一致, 详情不展示, 展示空面板 -->
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<a-empty> {{ $t('messageBox.noContent') }} </a-empty>
|
<a-empty> {{ $t('messageBox.noContent') }} </a-empty>
|
||||||
</div>
|
</div>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</template>
|
</template>
|
||||||
</MsSplitBox>
|
</MsSplitBox>
|
||||||
</div>
|
</div>
|
||||||
|
</a-spin>
|
||||||
<CommentInput
|
<CommentInput
|
||||||
v-if="activeTab === 'comment' && hasAnyPermission(['PROJECT_BUG:READ+COMMENT'])"
|
v-if="activeTab === 'comment' && hasAnyPermission(['PROJECT_BUG:READ+COMMENT'])"
|
||||||
:content="commentContent"
|
:content="commentContent"
|
||||||
|
@ -241,7 +244,7 @@
|
||||||
followBug,
|
followBug,
|
||||||
getBugDetail,
|
getBugDetail,
|
||||||
getTemplateById,
|
getTemplateById,
|
||||||
} from '@/api/modules/bug-management/index';
|
} from '@/api/modules/bug-management';
|
||||||
import { EditorPreviewFileUrl } from '@/api/requrls/bug-management';
|
import { EditorPreviewFileUrl } from '@/api/requrls/bug-management';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
|
@ -251,8 +254,7 @@
|
||||||
import { hasAnyPermission } from '@/utils/permission';
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
import type { CustomFieldItem } from '@/models/bug-management';
|
import type { CustomFieldItem } from '@/models/bug-management';
|
||||||
import { BugEditCustomField, BugEditFormObject, BugTemplateRequest } from '@/models/bug-management';
|
import { BugEditCustomField, BugEditFormObject } from '@/models/bug-management';
|
||||||
import { SelectValue } from '@/models/projectManagement/menuManagement';
|
|
||||||
import { RouteEnum } from '@/enums/routeEnum';
|
import { RouteEnum } from '@/enums/routeEnum';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -290,7 +292,7 @@
|
||||||
const bugDetailTabRef = ref();
|
const bugDetailTabRef = ref();
|
||||||
const isPlatformDefaultTemplate = ref(false);
|
const isPlatformDefaultTemplate = ref(false);
|
||||||
const rightLoading = ref(false);
|
const rightLoading = ref(false);
|
||||||
const rowLength = ref<number>(0);
|
const detailLoading = ref(false);
|
||||||
const activeTab = ref<string>('detail');
|
const activeTab = ref<string>('detail');
|
||||||
|
|
||||||
const detailInfo = ref<Record<string, any>>({ match: [] }); // 存储当前详情信息,通过loadBug 获取
|
const detailInfo = ref<Record<string, any>>({ match: [] }); // 存储当前详情信息,通过loadBug 获取
|
||||||
|
@ -332,53 +334,33 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentCustomFields = ref<CustomFieldItem[]>([]);
|
const currentCustomFields = ref<CustomFieldItem[]>([]);
|
||||||
|
|
||||||
const templateChange = async (v: SelectValue, valueObj: BugEditFormObject, request: BugTemplateRequest) => {
|
|
||||||
if (v) {
|
|
||||||
try {
|
|
||||||
const res = await getTemplateById({
|
|
||||||
projectId: appStore.currentProjectId,
|
|
||||||
id: v,
|
|
||||||
fromStatusId: request.fromStatusId,
|
|
||||||
platformBugKey: request.platformBugKey,
|
|
||||||
});
|
|
||||||
platformSystemFields.value = res.customFields.filter((field) => field.platformSystemField);
|
|
||||||
platformSystemFields.value.forEach((item) => {
|
|
||||||
item.defaultValue = valueObj[item.fieldId];
|
|
||||||
});
|
|
||||||
getFormRules(
|
|
||||||
res.customFields.filter((field) => !field.platformSystemField),
|
|
||||||
valueObj
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const getOptionFromTemplate = (field: CustomFieldItem | undefined) => {
|
const getOptionFromTemplate = (field: CustomFieldItem | undefined) => {
|
||||||
if (field) {
|
if (field) {
|
||||||
return field.options ? field.options : JSON.parse(field.platformOptionJson);
|
return field.options ? field.options : JSON.parse(field.platformOptionJson);
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
async function loadedBug(detail: BugEditFormObject) {
|
async function loadedBug(detail: BugEditFormObject) {
|
||||||
detailInfo.value = { ...detail };
|
|
||||||
const { templateId } = detailInfo.value;
|
|
||||||
// 是否平台默认模板
|
// 是否平台默认模板
|
||||||
isPlatformDefaultTemplate.value = detail.platformDefault;
|
isPlatformDefaultTemplate.value = detail.platformDefault;
|
||||||
// TAG 赋值
|
// 关闭loading
|
||||||
tags.value = detail.tags || [];
|
detailLoading.value = false;
|
||||||
caseCount.value = detailInfo.value.linkCaseCount;
|
|
||||||
const tmpObj = { status: detailInfo.value.status };
|
|
||||||
// 初始化自定义字段
|
|
||||||
const customFieldsRes = await getTemplateById({
|
const customFieldsRes = await getTemplateById({
|
||||||
projectId: appStore.currentProjectId,
|
projectId: appStore.currentProjectId,
|
||||||
id: templateId,
|
id: detail.templateId,
|
||||||
fromStatusId: detail.status,
|
fromStatusId: detail.status,
|
||||||
platformBugKey: detail.platformBugId,
|
platformBugKey: detail.platformBugId,
|
||||||
});
|
});
|
||||||
|
// 详情信息, TAG赋值
|
||||||
|
detailInfo.value = { ...detail };
|
||||||
|
tags.value = detail.tags || [];
|
||||||
|
caseCount.value = detailInfo.value.linkCaseCount;
|
||||||
|
const tmpObj = { status: detailInfo.value.status };
|
||||||
|
platformSystemFields.value = customFieldsRes.customFields.filter((field) => field.platformSystemField);
|
||||||
currentCustomFields.value = customFieldsRes.customFields || [];
|
currentCustomFields.value = customFieldsRes.customFields || [];
|
||||||
if (detailInfo.value.customFields && Array.isArray(detailInfo.value.customFields)) {
|
if (detailInfo.value.customFields && Array.isArray(detailInfo.value.customFields)) {
|
||||||
const MULTIPLE_TYPE = ['MULTIPLE_SELECT', 'MULTIPLE_INPUT', 'CHECKBOX', 'MULTIPLE_MEMBER'];
|
const MULTIPLE_TYPE = ['MULTIPLE_SELECT', 'MULTIPLE_INPUT', 'CHECKBOX', 'MULTIPLE_MEMBER'];
|
||||||
|
@ -392,8 +374,7 @@
|
||||||
const optionsIds = (multipleOptions || []).map((e: any) => e.value);
|
const optionsIds = (multipleOptions || []).map((e: any) => e.value);
|
||||||
if (item.value) {
|
if (item.value) {
|
||||||
if (item.type !== 'MULTIPLE_INPUT') {
|
if (item.type !== 'MULTIPLE_INPUT') {
|
||||||
const currentDefaultValue = optionsIds.filter((e: any) => JSON.parse(item.value).includes(e));
|
tmpObj[item.id] = optionsIds.filter((e: any) => JSON.parse(item.value).includes(e));
|
||||||
tmpObj[item.id] = currentDefaultValue;
|
|
||||||
} else {
|
} else {
|
||||||
tmpObj[item.id] = JSON.parse(item.value);
|
tmpObj[item.id] = JSON.parse(item.value);
|
||||||
}
|
}
|
||||||
|
@ -411,16 +392,29 @@
|
||||||
);
|
);
|
||||||
// 如果该值在选项中已经被删除掉
|
// 如果该值在选项中已经被删除掉
|
||||||
const optionsIds = (multipleOptions || []).map((e: any) => e.value);
|
const optionsIds = (multipleOptions || []).map((e: any) => e.value);
|
||||||
const currentDefaultValue = optionsIds.find((e: any) => item.value === e) || '';
|
tmpObj[item.id] = optionsIds.find((e: any) => item.value === e) || '';
|
||||||
tmpObj[item.id] = currentDefaultValue;
|
|
||||||
} else {
|
} else {
|
||||||
tmpObj[item.id] = item.value;
|
tmpObj[item.id] = item.value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 初始化自定义字段
|
// 初始化自定义字段
|
||||||
await templateChange(templateId, tmpObj, { platformBugKey: detail.platformBugId, fromStatusId: detail.status });
|
platformSystemFields.value.forEach((item) => {
|
||||||
|
item.defaultValue = tmpObj[item.fieldId];
|
||||||
|
});
|
||||||
|
getFormRules(
|
||||||
|
customFieldsRes.customFields.filter((field) => !field.platformSystemField),
|
||||||
|
tmpObj
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 详情加载中
|
||||||
|
*/
|
||||||
|
function setDetailLoading() {
|
||||||
|
detailLoading.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 tab 的参数数量徽标
|
* 获取 tab 的参数数量徽标
|
||||||
*/
|
*/
|
||||||
|
@ -443,7 +437,6 @@
|
||||||
|
|
||||||
function updateSuccess() {
|
function updateSuccess() {
|
||||||
rightLoading.value = false;
|
rightLoading.value = false;
|
||||||
detailDrawerRef.value?.initDetail();
|
|
||||||
emit('submit');
|
emit('submit');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,4 +767,4 @@
|
||||||
// width: 100%;
|
// width: 100%;
|
||||||
// word-wrap: break-word;
|
// word-wrap: break-word;
|
||||||
//}
|
//}
|
||||||
</style>
|
</style>
|
|
@ -84,6 +84,7 @@
|
||||||
:upload-func="uploadOrAssociationFile"
|
:upload-func="uploadOrAssociationFile"
|
||||||
:handle-delete="deleteFileHandler"
|
:handle-delete="deleteFileHandler"
|
||||||
:show-delete="props.allowEdit"
|
:show-delete="props.allowEdit"
|
||||||
|
:init-file-save-tips="t('ms.upload.waiting_save')"
|
||||||
@finish="uploadFileOver"
|
@finish="uploadFileOver"
|
||||||
>
|
>
|
||||||
<template #actions="{ item }">
|
<template #actions="{ item }">
|
||||||
|
@ -570,4 +571,4 @@
|
||||||
:deep(.arco-form-item-label) {
|
:deep(.arco-form-item-label) {
|
||||||
font-weight: bold !important;
|
font-weight: bold !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -76,7 +76,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<MsFileList ref="fileListRef" v-model:file-list="fileList" mode="static">
|
<MsFileList
|
||||||
|
ref="fileListRef"
|
||||||
|
v-model:file-list="fileList"
|
||||||
|
:init-file-save-tips="t('ms.upload.waiting_save')"
|
||||||
|
mode="static"
|
||||||
|
>
|
||||||
<template #actions="{ item }">
|
<template #actions="{ item }">
|
||||||
<!-- 本地文件 -->
|
<!-- 本地文件 -->
|
||||||
<div v-if="item.local || item.status === 'init'" class="flex flex-nowrap">
|
<div v-if="item.local || item.status === 'init'" class="flex flex-nowrap">
|
||||||
|
@ -826,4 +831,4 @@
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--color-text-4);
|
color: var(--color-text-4);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -35,6 +35,7 @@ export function convertToFileByBug(fileInfo: AssociatedList): MsFileItem {
|
||||||
isCopyFlag,
|
isCopyFlag,
|
||||||
associateId: refId,
|
associateId: refId,
|
||||||
createUserName,
|
createUserName,
|
||||||
|
createTime,
|
||||||
uploadedTime: createTime,
|
uploadedTime: createTime,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,13 @@
|
||||||
</a-form>
|
</a-form>
|
||||||
<!-- 文件列表开始 -->
|
<!-- 文件列表开始 -->
|
||||||
<div class="w-[90%]">
|
<div class="w-[90%]">
|
||||||
<MsFileList ref="fileListRef" v-model:file-list="fileList" mode="static" :show-upload-type-desc="true">
|
<MsFileList
|
||||||
|
ref="fileListRef"
|
||||||
|
v-model:file-list="fileList"
|
||||||
|
mode="static"
|
||||||
|
:init-file-save-tips="t('ms.upload.waiting_save')"
|
||||||
|
:show-upload-type-desc="true"
|
||||||
|
>
|
||||||
<template #actions="{ item }">
|
<template #actions="{ item }">
|
||||||
<!-- 本地文件 -->
|
<!-- 本地文件 -->
|
||||||
<div v-if="item.local || item.status === 'init'" class="flex flex-nowrap">
|
<div v-if="item.local || item.status === 'init'" class="flex flex-nowrap">
|
||||||
|
@ -283,8 +289,6 @@
|
||||||
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
||||||
import useUserStore from '@/store/modules/user';
|
import useUserStore from '@/store/modules/user';
|
||||||
import { downloadByteFile, getGenerateId } from '@/utils';
|
import { downloadByteFile, getGenerateId } from '@/utils';
|
||||||
import { scrollIntoView } from '@/utils/dom';
|
|
||||||
import { hasAnyPermission } from '@/utils/permission';
|
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
AssociatedList,
|
AssociatedList,
|
||||||
|
@ -842,4 +846,4 @@
|
||||||
color: var(--color-text-4);
|
color: var(--color-text-4);
|
||||||
background: var(--color-text-n8);
|
background: var(--color-text-n8);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -54,8 +54,8 @@
|
||||||
<a-tooltip position="tl" :content-style="{ maxWidth: '500px' }">
|
<a-tooltip position="tl" :content-style="{ maxWidth: '500px' }">
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div>{{ t('project.menu.defect.enableTip') }}</div>
|
<div>{{ t('project.menu.demand.enableTip') }}</div>
|
||||||
<div class="flex flex-nowrap">{{ t('project.menu.defect.closeTip') }}</div>
|
<div class="flex flex-nowrap">{{ t('project.menu.demand.closeTip') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div>
|
<div>
|
||||||
|
@ -216,4 +216,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
|
@ -74,5 +74,7 @@ export default {
|
||||||
'Turn on: The defects created by the platform are synced to the third-party project management platform',
|
'Turn on: The defects created by the platform are synced to the third-party project management platform',
|
||||||
'project.menu.defect.closeTip':
|
'project.menu.defect.closeTip':
|
||||||
'Turn off: The defects created by the platform cannot be synced to the third-party project management platform',
|
'Turn off: The defects created by the platform cannot be synced to the third-party project management platform',
|
||||||
|
'project.menu.demand.enableTip': 'On: functional cases can relate to third-party demands',
|
||||||
|
'project.menu.demand.closeTip': 'Off: functional cases cannot relate to third party demands',
|
||||||
'project.menu.defect.customLabel': 'Custom Frequency',
|
'project.menu.defect.customLabel': 'Custom Frequency',
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,6 +67,8 @@ export default {
|
||||||
// 同步缺陷
|
// 同步缺陷
|
||||||
'project.menu.defect.enableTip': '开启:平台创建的缺陷同步至第三方项目管理平台',
|
'project.menu.defect.enableTip': '开启:平台创建的缺陷同步至第三方项目管理平台',
|
||||||
'project.menu.defect.closeTip': '关闭:平台创建的缺陷则无法同步至第三方项目管理平台',
|
'project.menu.defect.closeTip': '关闭:平台创建的缺陷则无法同步至第三方项目管理平台',
|
||||||
|
'project.menu.demand.enableTip': '开启:平台创建的用例可关联第三方需求',
|
||||||
|
'project.menu.demand.closeTip': '关闭:平台创建的用例无法关联第三方的需求',
|
||||||
'project.menu.defect.customLabel': '自定义频率',
|
'project.menu.defect.customLabel': '自定义频率',
|
||||||
'project.menu.defect.enableAfterConfig': '配置第三方信息后可开启',
|
'project.menu.defect.enableAfterConfig': '配置第三方信息后可开启',
|
||||||
// 误报规则
|
// 误报规则
|
||||||
|
|
Loading…
Reference in New Issue