refactor(缺陷管理): 缺陷导出功能开发
This commit is contained in:
parent
42b1bcc60d
commit
589415ac05
|
@ -129,6 +129,8 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT
|
|||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'BUG:READ+ADD');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'BUG:READ+UPDATE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'BUG:READ+DELETE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id)
|
||||
VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_BUG:READ+EXPORT');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_BASE_INFO:READ+UPDATE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_API_DEBUG:READ');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_API_DEBUG:READ+ADD');
|
||||
|
@ -200,6 +202,8 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT
|
|||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'BUG:READ+ADD');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'BUG:READ+UPDATE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'BUG:READ+DELETE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id)
|
||||
VALUES (UUID_SHORT(), 'project_member', 'PROJECT_BUG:READ+EXPORT');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_BASE_INFO:READ+UPDATE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_API_DEBUG:READ');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_API_DEBUG:READ+ADD');
|
||||
|
|
|
@ -243,8 +243,8 @@ public class PermissionConstants {
|
|||
public static final String BUG_ADD = "BUG:READ+ADD";
|
||||
public static final String BUG_UPDATE = "BUG:READ+UPDATE";
|
||||
public static final String BUG_DELETE = "BUG:READ+DELETE";
|
||||
public static final String BUG_EXPORT = "PROJECT_BUG:READ+EXPORT";
|
||||
/*------ end: BUG ------*/
|
||||
|
||||
/*------ start: API_MANAGEMENT ------*/
|
||||
public static final String PROJECT_API_DEFINITION_READ = "PROJECT_API_DEFINITION:READ";
|
||||
public static final String PROJECT_API_DEFINITION_ADD = "PROJECT_API_DEFINITION:READ+ADD";
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package io.metersphere.sdk.util;
|
||||
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -9,7 +8,6 @@ import java.util.List;
|
|||
import java.util.zip.*;
|
||||
|
||||
public class CompressUtils {
|
||||
private final static String ZIP_PATH = "/opt/metersphere/data/tmp/";
|
||||
|
||||
/***
|
||||
* Zip压缩
|
||||
|
@ -40,12 +38,12 @@ public class CompressUtils {
|
|||
}
|
||||
|
||||
|
||||
private static File getFile(String fileName) throws IOException {
|
||||
private static File getFile(String filePath) throws IOException {
|
||||
// 创建文件对象
|
||||
File file;
|
||||
file = new File(ZIP_PATH, fileName);
|
||||
file = new File(filePath);
|
||||
if (!file.exists() && !file.createNewFile()) {
|
||||
throw new MSException("创建文件失败");
|
||||
file.createNewFile();
|
||||
}
|
||||
// 返回文件
|
||||
return file;
|
||||
|
@ -93,20 +91,18 @@ public class CompressUtils {
|
|||
|
||||
/**
|
||||
* 将多个文件压缩
|
||||
*
|
||||
* @param fileList 待压缩的文件列表
|
||||
* @param zipFileName 压缩文件名
|
||||
* @return 返回压缩好的文件
|
||||
* @param zipFilePath 压缩文件所在路径
|
||||
* @param fileList 要压缩的文件
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static File zipFiles(String zipFileName, List<File> fileList) throws IOException {
|
||||
File zipFile = getFile(zipFileName);
|
||||
public static File zipFiles(String zipFilePath, List<File> fileList) throws IOException {
|
||||
File zipFile = getFile(zipFilePath);
|
||||
// 文件输出流
|
||||
FileOutputStream outputStream = getFileStream(zipFile);
|
||||
// 压缩流
|
||||
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
|
||||
|
||||
int size = fileList.size();
|
||||
// 压缩列表中的文件
|
||||
for (File file : fileList) {
|
||||
zipFile(file, zipOutputStream);
|
||||
|
|
|
@ -95,4 +95,16 @@ bug_comment.reply_user.not_blank=缺陷回复人不能为空
|
|||
bug_comment_not_exist=缺陷评论不存在
|
||||
bug_relate_case_not_found=未查询到关联的用例
|
||||
bug_relate_case_type_unknown=关联的用例类型未知, 无法查看
|
||||
bug_relate_case_permission_error=无权限查看, 请联系管理员
|
||||
bug_relate_case_permission_error=无权限查看, 请联系管理员
|
||||
# bug export
|
||||
bug.system_columns.not_empty=系统字段不能为空
|
||||
bug.export.system.columns.name=缺陷名称
|
||||
bug.export.system.columns.id=ID
|
||||
bug.export.system.columns.content=缺陷内容
|
||||
bug.export.system.columns.status=缺陷状态
|
||||
bug.export.system.columns.handle_user=处理人
|
||||
bug.export.system.other.columns.create_user=创建人
|
||||
bug.export.system.other.columns.create_time=创建时间
|
||||
bug.export.system.other.columns.case_count=用例数
|
||||
bug.export.system.other.columns.comment=评论
|
||||
bug.export.system.other.columns.platform=所属平台
|
|
@ -96,3 +96,15 @@ bug_comment_not_exist=Bug comment does not exist
|
|||
bug_relate_case_not_found=Bug related case not found
|
||||
bug_relate_case_type_unknown=Bug related case type unknown
|
||||
bug_relate_case_permission_error=No permission to show the case
|
||||
# bug export
|
||||
bug.system_columns.not_empty=System columns cannot be empty
|
||||
bug.export.system.columns.name=Name
|
||||
bug.export.system.columns.id=ID
|
||||
bug.export.system.columns.content=Content
|
||||
bug.export.system.columns.status=Status
|
||||
bug.export.system.columns.handle_user=HandleUser
|
||||
bug.export.system.other.columns.create_user=Create user
|
||||
bug.export.system.other.columns.create_time=Create time
|
||||
bug.export.system.other.columns.case_count=Case count
|
||||
bug.export.system.other.columns.comment=Comment
|
||||
bug.export.system.other.columns.platform=Platform
|
||||
|
|
|
@ -95,4 +95,16 @@ bug_comment.reply_user.not_blank=缺陷回复人不能为空
|
|||
bug_comment_not_exist=缺陷评论不存在
|
||||
bug_relate_case_not_found=未查询到关联的用例
|
||||
bug_relate_case_type_unknown=关联的用例类型未知, 无法查看
|
||||
bug_relate_case_permission_error=无用例查看权限, 请联系管理员
|
||||
bug_relate_case_permission_error=无用例查看权限, 请联系管理员
|
||||
# bug export
|
||||
bug.system_columns.not_empty=系统字段不能为空
|
||||
bug.export.system.columns.name=缺陷名称
|
||||
bug.export.system.columns.id=ID
|
||||
bug.export.system.columns.content=缺陷内容
|
||||
bug.export.system.columns.status=缺陷状态
|
||||
bug.export.system.columns.handle_user=处理人
|
||||
bug.export.system.other.columns.create_user=创建人
|
||||
bug.export.system.other.columns.create_time=创建时间
|
||||
bug.export.system.other.columns.case_count=用例数
|
||||
bug.export.system.other.columns.comment=评论
|
||||
bug.export.system.other.columns.platform=所属平台
|
|
@ -96,3 +96,15 @@ bug_comment_not_exist=缺陷評論不存在
|
|||
bug_relate_case_not_found=未查詢到關聯的用例
|
||||
bug_relate_case_type_unknown=關聯的用例類型未知, 無法查看
|
||||
bug_relate_case_permission_error=無權限查看, 請聯繫管理員
|
||||
# bug export
|
||||
bug.system_columns.not_empty=系統字段不能為空
|
||||
bug.export.system.columns.name=缺陷名稱
|
||||
bug.export.system.columns.id=ID
|
||||
bug.export.system.columns.content=缺陷內容
|
||||
bug.export.system.columns.status=缺陷狀態
|
||||
bug.export.system.columns.handle_user=處理人
|
||||
bug.export.system.other.columns.create_user=創建人
|
||||
bug.export.system.other.columns.create_time=創建時間
|
||||
bug.export.system.other.columns.case_count=用例數
|
||||
bug.export.system.other.columns.comment=評論
|
||||
bug.export.system.other.columns.platform=所屬平台
|
|
@ -0,0 +1,39 @@
|
|||
package io.metersphere.bug.constants;
|
||||
|
||||
import io.metersphere.bug.dto.BugCustomFieldDTO;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 缺陷导出字段配置
|
||||
*/
|
||||
@Data
|
||||
public class BugExportColumns {
|
||||
private LinkedHashMap<String, String> systemColumns = new LinkedHashMap<>();
|
||||
private LinkedHashMap<String, String> otherColumns = new LinkedHashMap<>();
|
||||
private LinkedHashMap<String, String> customColumns = new LinkedHashMap<>();
|
||||
|
||||
public BugExportColumns() {
|
||||
systemColumns.put("name", Translator.get("bug.export.system.columns.name"));
|
||||
systemColumns.put("id", Translator.get("bug.export.system.columns.id"));
|
||||
systemColumns.put("content", Translator.get("bug.export.system.columns.content"));
|
||||
systemColumns.put("status", Translator.get("bug.export.system.columns.status"));
|
||||
systemColumns.put("handle_user", Translator.get("bug.export.system.columns.handle_user"));
|
||||
|
||||
otherColumns.put("create_user", Translator.get("bug.export.system.other.columns.create_user"));
|
||||
otherColumns.put("create_time", Translator.get("bug.export.system.other.columns.create_time"));
|
||||
otherColumns.put("case_count", Translator.get("bug.export.system.other.columns.case_count"));
|
||||
otherColumns.put("comment", Translator.get("bug.export.system.other.columns.comment"));
|
||||
otherColumns.put("platform", Translator.get("bug.export.system.other.columns.platform"));
|
||||
|
||||
}
|
||||
|
||||
public void initCustomColumns(List<BugCustomFieldDTO> customFieldList) {
|
||||
customFieldList.forEach(item -> {
|
||||
customColumns.put(item.getId(), item.getName());
|
||||
});
|
||||
}
|
||||
}
|
|
@ -2,11 +2,9 @@ package io.metersphere.bug.controller;
|
|||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.bug.constants.BugExportColumns;
|
||||
import io.metersphere.bug.dto.BugDTO;
|
||||
import io.metersphere.bug.dto.request.BugBatchRequest;
|
||||
import io.metersphere.bug.dto.request.BugBatchUpdateRequest;
|
||||
import io.metersphere.bug.dto.request.BugEditRequest;
|
||||
import io.metersphere.bug.dto.request.BugPageRequest;
|
||||
import io.metersphere.bug.dto.request.*;
|
||||
import io.metersphere.bug.service.BugService;
|
||||
import io.metersphere.project.dto.ProjectTemplateOptionDTO;
|
||||
import io.metersphere.project.service.ProjectTemplateService;
|
||||
|
@ -23,6 +21,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
@ -116,4 +115,19 @@ public class BugController {
|
|||
public void unfollow(@PathVariable String id) {
|
||||
bugService.unfollow(id, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@GetMapping("/export/columns/{projectId}")
|
||||
@Operation(summary = "缺陷管理-获取导出字段配置")
|
||||
@RequiresPermissions(PermissionConstants.BUG_EXPORT)
|
||||
public BugExportColumns getExportColumns(@PathVariable String projectId) {
|
||||
return bugService.getExportColumns(projectId);
|
||||
}
|
||||
|
||||
@PostMapping("/export")
|
||||
@Operation(summary = "缺陷管理-批量导出缺陷")
|
||||
@RequiresPermissions(PermissionConstants.BUG_EXPORT)
|
||||
public ResponseEntity<byte[]> export(@Validated @RequestBody BugExportRequest request) throws Exception {
|
||||
return bugService.export(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package io.metersphere.bug.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 缺陷导出DTO
|
||||
*/
|
||||
@Data
|
||||
public class BugExportDTO {
|
||||
@Schema(description = "缺陷ID")
|
||||
private String id;
|
||||
@Schema(description = "缺陷名称")
|
||||
private String name;
|
||||
@Schema(description = "缺陷内容")
|
||||
private String content;
|
||||
@Schema(description = "缺陷状态")
|
||||
private String status;
|
||||
@Schema(description = "缺陷处理人")
|
||||
private List<String> handleUsers;
|
||||
@Schema(description = "自定义字段集合")
|
||||
private Map<String, String> customFields;
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package io.metersphere.bug.dto;
|
||||
|
||||
import io.metersphere.bug.domain.BugContent;
|
||||
import io.metersphere.bug.dto.request.BugExportColumn;
|
||||
import io.metersphere.sdk.util.DateUtils;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 缺陷导出数据结构模型
|
||||
*/
|
||||
@Data
|
||||
public class BugExportExcelModel {
|
||||
// <key,text>. 如果是自定义字段,则是 <id,字段显示>
|
||||
private LinkedHashMap<String, String> excelHeader;
|
||||
|
||||
// <key,value>. 如果是自定义字段,则是 <id,数据>
|
||||
private List<LinkedHashMap<String, String>> excelRows;
|
||||
|
||||
public BugExportExcelModel(List<BugExportColumn> exportColumns,
|
||||
List<BugDTO> bugList,
|
||||
Map<String, List<BugCommentDTO>> bugComment,
|
||||
Map<String, BugContent> bugContents,
|
||||
Map<String, Long> bugCountMap) {
|
||||
this.excelHeader = new LinkedHashMap<>();
|
||||
//注入表头
|
||||
for (BugExportColumn exportColumn : exportColumns) {
|
||||
this.excelHeader.put(exportColumn.getKey(), exportColumn.getText());
|
||||
}
|
||||
this.excelRows = new ArrayList<>();
|
||||
for (BugDTO bugDTO : bugList) {
|
||||
LinkedHashMap<String, String> excelRow = new LinkedHashMap<>();
|
||||
for (String key : excelHeader.keySet()) {
|
||||
switch (key) {
|
||||
case "name" -> excelRow.put(key, bugDTO.getTitle());
|
||||
case "id" -> excelRow.put(key, bugDTO.getId());
|
||||
case "content" -> excelRow.put(key, this.getBugContent(bugContents, bugDTO.getId()));
|
||||
case "status" -> excelRow.put(key, bugDTO.getStatus());
|
||||
case "handleUser" -> excelRow.put(key, bugDTO.getHandleUserName());
|
||||
case "createUser" -> excelRow.put(key, bugDTO.getCreateUserName());
|
||||
case "createTime" -> excelRow.put(key, DateUtils.getTimeString(bugDTO.getCreateTime()));
|
||||
case "caseCount" -> excelRow.put(key, this.getBugCaseCount(bugCountMap, bugDTO.getId()));
|
||||
case "comment" -> excelRow.put(key, this.getBugComment(bugComment.get(bugDTO.getId())));
|
||||
case "platform" -> excelRow.put(key, bugDTO.getPlatform());
|
||||
default -> excelRow.put(key, this.getCustomFieldValue(bugDTO.getCustomFields(), key));
|
||||
}
|
||||
}
|
||||
excelRows.add(excelRow);
|
||||
}
|
||||
}
|
||||
|
||||
private String getCustomFieldValue(List<BugCustomFieldDTO> customFields, String key) {
|
||||
if (CollectionUtils.isNotEmpty(customFields)) {
|
||||
for (BugCustomFieldDTO customField : customFields) {
|
||||
if (key.equals(customField.getId())) {
|
||||
return customField.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
private String getBugCaseCount(Map<String, Long> bugCountMap, String id) {
|
||||
long count = 0;
|
||||
if (bugCountMap.containsKey(id)) {
|
||||
count = bugCountMap.get(id);
|
||||
}
|
||||
return String.valueOf(count);
|
||||
}
|
||||
|
||||
private String getBugContent(Map<String, BugContent> bugContents, String id) {
|
||||
if (bugContents.containsKey(id)) {
|
||||
return bugContents.get(id).getDescription();
|
||||
} else {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
public String getBugComment(List<BugCommentDTO> bugCommentList) {
|
||||
if (CollectionUtils.isEmpty(bugCommentList)) {
|
||||
return StringUtils.EMPTY;
|
||||
} else {
|
||||
StringBuilder commentBuilder = new StringBuilder();
|
||||
for (BugCommentDTO bugCommentDTO : bugCommentList) {
|
||||
commentBuilder.append(bugCommentDTO.getCreateUser());
|
||||
commentBuilder.append(StringUtils.SPACE);
|
||||
commentBuilder.append(DateUtils.getTimeString(bugCommentDTO.getCreateTime()));
|
||||
commentBuilder.append(StringUtils.LF);
|
||||
commentBuilder.append(bugCommentDTO.getContent());
|
||||
commentBuilder.append(StringUtils.LF);
|
||||
}
|
||||
return commentBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getHeadTexts() {
|
||||
return new ArrayList<>(excelHeader.values());
|
||||
}
|
||||
|
||||
public List<String> getHeadKeys() {
|
||||
return new ArrayList<>(excelHeader.keySet());
|
||||
}
|
||||
|
||||
public List<List<String>> getData() {
|
||||
List<List<String>> returnList = new ArrayList<>();
|
||||
returnList.add(this.getHeadTexts());
|
||||
for (LinkedHashMap<String, String> excelRow : excelRows) {
|
||||
List<String> row = new ArrayList<>();
|
||||
for (String key : excelHeader.keySet()) {
|
||||
row.add(excelRow.get(key));
|
||||
}
|
||||
returnList.add(row);
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package io.metersphere.bug.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BugExportColumn {
|
||||
@Schema(description = "字段key", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank
|
||||
private String key;
|
||||
@Schema(description = "字段名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank
|
||||
private String text;
|
||||
@Schema(description = "字段类型: 系统字段-system, 自定义字段-custom, 其他字段-other")
|
||||
@NotBlank
|
||||
private String columnType;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package io.metersphere.bug.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class BugExportRequest extends BugBatchRequest {
|
||||
@Schema(description = "导出的字段", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "{bug.system_columns.not_empty}")
|
||||
private List<BugExportColumn> exportColumns;
|
||||
}
|
|
@ -2,6 +2,7 @@ package io.metersphere.bug.dto.request;
|
|||
|
||||
import io.metersphere.system.dto.sdk.BasePageRequest;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
|
@ -10,6 +11,7 @@ import lombok.EqualsAndHashCode;
|
|||
public class BugPageRequest extends BasePageRequest {
|
||||
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{bug.project_id.not_blank}")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "是否回收站")
|
||||
|
|
|
@ -18,6 +18,7 @@ public interface ExtBugMapper {
|
|||
*/
|
||||
List<BugDTO> list(@Param("request") BugPageRequest request);
|
||||
|
||||
List<BugDTO> listByIds(@Param("ids") List<String> ids);
|
||||
/**
|
||||
* 获取缺陷业务ID
|
||||
*
|
||||
|
|
|
@ -7,6 +7,28 @@
|
|||
<include refid="queryWhereCondition"/>
|
||||
</select>
|
||||
|
||||
<select id="listByIds" resultType="io.metersphere.bug.dto.BugDTO">
|
||||
select b.id,
|
||||
b.num,
|
||||
b.title,
|
||||
b.handle_user,
|
||||
b.create_user,
|
||||
b.create_time,
|
||||
b.update_time,
|
||||
b.delete_time,
|
||||
b.delete_user,
|
||||
b.project_id,
|
||||
b.template_id,
|
||||
b.platform,
|
||||
b.status,
|
||||
bc.description
|
||||
from bug b
|
||||
left join bug_content bc on b.id = bc.bug_id
|
||||
WHERE b.id IN
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
<select id="getMaxNum" resultType="java.lang.Long">
|
||||
select max(num) from bug where project_id = #{projectId}
|
||||
</select>
|
||||
|
|
|
@ -17,6 +17,7 @@ import io.metersphere.system.mapper.BaseUserMapper;
|
|||
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -47,6 +48,16 @@ public class BugCommentService {
|
|||
BugCommentExample example = new BugCommentExample();
|
||||
example.createCriteria().andBugIdEqualTo(bugId);
|
||||
List<BugComment> bugComments = bugCommentMapper.selectByExample(example);
|
||||
return this.generateCommentDTOs(bugComments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成缺陷评论DTO
|
||||
*
|
||||
* @param bugComments 缺陷评论集合
|
||||
* @return 缺陷评论DTO
|
||||
*/
|
||||
private List<BugCommentDTO> generateCommentDTOs(List<BugComment> bugComments) {
|
||||
if (CollectionUtils.isEmpty(bugComments)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
@ -75,6 +86,23 @@ public class BugCommentService {
|
|||
return parentComments;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量获取缺陷ID
|
||||
*/
|
||||
public Map<String, List<BugCommentDTO>> getComments(@NotEmpty List<String> bugIds) {
|
||||
BugCommentExample example = new BugCommentExample();
|
||||
example.createCriteria().andBugIdIn(bugIds);
|
||||
List<BugComment> bugComments = bugCommentMapper.selectByExample(example);
|
||||
Map<String, List<BugComment>> bugCommentByBugId = bugComments.stream().collect(Collectors.groupingBy(BugComment::getBugId));
|
||||
|
||||
Map<String, List<BugCommentDTO>> returnMap = new HashMap<>();
|
||||
for (Map.Entry<String, List<BugComment>> entry : bugCommentByBugId.entrySet()) {
|
||||
returnMap.put(entry.getKey(), generateCommentDTOs(entry.getValue()));
|
||||
}
|
||||
return returnMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加评论
|
||||
* @param request 评论请求参数
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
package io.metersphere.bug.service;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.support.ExcelTypeEnum;
|
||||
import io.metersphere.bug.domain.BugContent;
|
||||
import io.metersphere.bug.domain.BugContentExample;
|
||||
import io.metersphere.bug.dto.BugCommentDTO;
|
||||
import io.metersphere.bug.dto.BugDTO;
|
||||
import io.metersphere.bug.dto.BugExportExcelModel;
|
||||
import io.metersphere.bug.dto.request.BugExportColumn;
|
||||
import io.metersphere.bug.mapper.BugContentMapper;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class BugExportService {
|
||||
|
||||
private static final int BATCH_PROCESS_QUANTITY = 2000;
|
||||
private static final String EXPORT_TEMP_BASE_FOLDER = "/tmp/metersphere/export/bug/";
|
||||
|
||||
@Resource
|
||||
private BugContentMapper bugContentMapper;
|
||||
@Resource
|
||||
private BugCommentService bugCommentService;
|
||||
|
||||
/**
|
||||
* @param list 缺陷数据
|
||||
* @param exportColumns excel导出的列
|
||||
* @return excel所在的文件夹
|
||||
* @throws Exception
|
||||
*/
|
||||
public String generateExcelFiles(List<BugDTO> list, List<BugExportColumn> exportColumns) {
|
||||
String filesFolder = EXPORT_TEMP_BASE_FOLDER + IDGenerator.nextStr();
|
||||
try {
|
||||
FileUtils.forceMkdir(new File(filesFolder));
|
||||
int index = 1;
|
||||
while (list.size() > 2000) {
|
||||
List<BugDTO> excelBugList = list.subList(0, BATCH_PROCESS_QUANTITY);
|
||||
this.generateExcelFile(excelBugList, index, filesFolder, exportColumns);
|
||||
list.removeAll(excelBugList);
|
||||
index = 1;
|
||||
}
|
||||
this.generateExcelFile(list, index, filesFolder, exportColumns);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
return filesFolder;
|
||||
}
|
||||
|
||||
private void generateExcelFile(List<BugDTO> list, int fileIndex, String excelPath, List<BugExportColumn> exportColumns) throws Exception {
|
||||
if (CollectionUtils.isNotEmpty(list)) {
|
||||
boolean exportComment = this.exportComment(exportColumns);
|
||||
boolean exportContent = this.exportContent(exportColumns);
|
||||
|
||||
List<String> bugIdList = list.stream().map(BugDTO::getId).toList();
|
||||
Map<String, List<BugCommentDTO>> bugCommentMap = new HashMap<>();
|
||||
Map<String, BugContent> bugContentMap = new HashMap<>();
|
||||
//todo 等昌昌需求确定,再实现
|
||||
Map<String, Long> bugCountMap = new HashMap<>();
|
||||
if (exportContent) {
|
||||
BugContentExample example = new BugContentExample();
|
||||
example.createCriteria().andBugIdIn(bugIdList);
|
||||
bugContentMap = bugContentMapper.selectByExample(example).stream().collect(Collectors.toMap(BugContent::getBugId, bugContent -> bugContent));
|
||||
}
|
||||
if (exportComment) {
|
||||
bugCommentMap = bugCommentService.getComments(bugIdList);
|
||||
}
|
||||
|
||||
//生成excel对象
|
||||
BugExportExcelModel bugExportExcelModel = new BugExportExcelModel(exportColumns, list, bugCommentMap, bugContentMap, bugCountMap);
|
||||
|
||||
//生成excel文件
|
||||
List<List<String>> data = bugExportExcelModel.getData();
|
||||
File createFile = new File(excelPath + File.separatorChar + "bug_" + fileIndex + ".xlsx");
|
||||
createFile.createNewFile();
|
||||
|
||||
EasyExcel.write(createFile).excelType(ExcelTypeEnum.XLSX).sheet("sheet").doWrite(data);
|
||||
}
|
||||
}
|
||||
|
||||
//是否包含缺陷评论
|
||||
public boolean exportComment(List<BugExportColumn> exportColumns) {
|
||||
for (BugExportColumn exportColumn : exportColumns) {
|
||||
if ("comment".equals(exportColumn.getKey()) && "other".equals(exportColumn.getColumnType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//是否包含缺陷内容
|
||||
public boolean exportContent(List<BugExportColumn> exportColumns) {
|
||||
for (BugExportColumn exportColumn : exportColumns) {
|
||||
if ("content".equals(exportColumn.getKey()) && "system".equals(exportColumn.getColumnType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,22 +1,24 @@
|
|||
package io.metersphere.bug.service;
|
||||
|
||||
import io.metersphere.bug.constants.BugExportColumns;
|
||||
import io.metersphere.bug.domain.*;
|
||||
import io.metersphere.bug.dto.BugCustomFieldDTO;
|
||||
import io.metersphere.bug.dto.BugDTO;
|
||||
import io.metersphere.bug.dto.BugRelateCaseCountDTO;
|
||||
import io.metersphere.bug.dto.BugTagEditDTO;
|
||||
import io.metersphere.bug.dto.request.BugBatchRequest;
|
||||
import io.metersphere.bug.dto.request.BugBatchUpdateRequest;
|
||||
import io.metersphere.bug.dto.request.BugEditRequest;
|
||||
import io.metersphere.bug.dto.request.BugPageRequest;
|
||||
import io.metersphere.bug.dto.request.*;
|
||||
import io.metersphere.bug.enums.BugPlatform;
|
||||
import io.metersphere.bug.mapper.*;
|
||||
import io.metersphere.bug.utils.CustomFieldUtils;
|
||||
import io.metersphere.bug.utils.ExportUtils;
|
||||
import io.metersphere.project.dto.filemanagement.FileLogRecord;
|
||||
import io.metersphere.project.service.FileAssociationService;
|
||||
import io.metersphere.project.service.FileService;
|
||||
import io.metersphere.project.service.ProjectTemplateService;
|
||||
import io.metersphere.sdk.constants.*;
|
||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||
import io.metersphere.sdk.constants.StorageType;
|
||||
import io.metersphere.sdk.constants.TemplateScene;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.FileAssociationSourceUtil;
|
||||
|
@ -39,6 +41,9 @@ import org.apache.ibatis.session.ExecutorType;
|
|||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
@ -87,6 +92,8 @@ public class BugService {
|
|||
private BaseTemplateService baseTemplateService;
|
||||
@Resource
|
||||
private BugFollowerMapper bugFollowerMapper;
|
||||
@Resource
|
||||
private BugExportService bugExportService;
|
||||
|
||||
/**
|
||||
* 缺陷列表查询
|
||||
|
@ -214,41 +221,46 @@ public class BugService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除缺陷
|
||||
* @param request 请求参数
|
||||
*/
|
||||
public void batchDelete(BugBatchRequest request) {
|
||||
private List<BugDTO> selectByBatchRequest(BugBatchRequest request) {
|
||||
// 非Local直接删除, Local移入回收站
|
||||
if (request.isSelectAll()) {
|
||||
// 全选
|
||||
BugPageRequest bugPageRequest = new BugPageRequest();
|
||||
BeanUtils.copyBean(bugPageRequest, request);
|
||||
bugPageRequest.setUseTrash(false);
|
||||
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(bugPageRequest);
|
||||
List<BugDTO> bugs = extBugMapper.list(bugPageRequest);
|
||||
if (CollectionUtils.isNotEmpty(bugs)) {
|
||||
List<String> deleteIds = bugs.stream().filter(bug -> !StringUtils.equals(BugPlatform.LOCAL.getName(), bug.getPlatform())).map(BugDTO::getId).toList();
|
||||
if (CollectionUtils.isNotEmpty(deleteIds)) {
|
||||
BugExample bugExample = new BugExample();
|
||||
bugExample.createCriteria().andIdIn(deleteIds);
|
||||
bugMapper.deleteByExample(bugExample);
|
||||
}
|
||||
bugs.stream().filter(bug -> StringUtils.equals(bug.getPlatform(), BugPlatform.LOCAL.getName())).forEach(bug -> {
|
||||
Bug record = new Bug();
|
||||
record.setId(bug.getId());
|
||||
record.setDeleted(true);
|
||||
bugMapper.updateByPrimaryKeySelective(record);
|
||||
});
|
||||
}
|
||||
return extBugMapper.list(bugPageRequest);
|
||||
} else {
|
||||
// 勾选部分
|
||||
if (CollectionUtils.isEmpty(request.getIncludeBugIds())) {
|
||||
throw new MSException(Translator.get("no_bug_select"));
|
||||
}
|
||||
// 勾选操作数据较少, 可逐条删除
|
||||
request.getIncludeBugIds().forEach(this::delete);
|
||||
return extBugMapper.listByIds(request.getIncludeBugIds());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除缺陷
|
||||
* @param request 请求参数
|
||||
*/
|
||||
public void batchDelete(BugBatchRequest request) {
|
||||
List<BugDTO> bugs = this.selectByBatchRequest(request);
|
||||
// 勾选部分
|
||||
if (CollectionUtils.isEmpty(request.getIncludeBugIds())) {
|
||||
throw new MSException(Translator.get("no_bug_select"));
|
||||
}
|
||||
List<String> deleteIds = bugs.stream().filter(bug -> !StringUtils.equals(BugPlatform.LOCAL.getName(), bug.getPlatform())).map(BugDTO::getId).toList();
|
||||
if (CollectionUtils.isNotEmpty(deleteIds)) {
|
||||
BugExample bugExample = new BugExample();
|
||||
bugExample.createCriteria().andIdIn(deleteIds);
|
||||
bugMapper.deleteByExample(bugExample);
|
||||
}
|
||||
bugs.stream().filter(bug -> StringUtils.equals(bug.getPlatform(), BugPlatform.LOCAL.getName())).forEach(bug -> {
|
||||
Bug record = new Bug();
|
||||
record.setId(bug.getId());
|
||||
record.setDeleted(true);
|
||||
bugMapper.updateByPrimaryKeySelective(record);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -639,4 +651,24 @@ public class BugService {
|
|||
fileRequest.setStorage(StorageType.MINIO.name());
|
||||
return fileRequest;
|
||||
}
|
||||
|
||||
public ResponseEntity<byte[]> export(BugExportRequest request) throws Exception {
|
||||
List<BugDTO> bugs = this.selectByBatchRequest(request);
|
||||
if (CollectionUtils.isEmpty(bugs)) {
|
||||
throw new MSException(Translator.get("no_bug_select"));
|
||||
}
|
||||
ExportUtils exportUtils = new ExportUtils(bugs, request.getExportColumns());
|
||||
byte[] bytes = exportUtils.exportToZipFile(bugExportService::generateExcelFiles);
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType("application/octet-stream"))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"bug-export.zip\"")
|
||||
.body(bytes);
|
||||
}
|
||||
|
||||
|
||||
public BugExportColumns getExportColumns(String projectId) {
|
||||
BugExportColumns bugExportColumns = new BugExportColumns();
|
||||
//todo 等待Scc提供自定义字段的查询方法
|
||||
return bugExportColumns;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package io.metersphere.bug.utils;
|
||||
|
||||
import io.metersphere.bug.dto.BugDTO;
|
||||
import io.metersphere.bug.dto.request.BugExportColumn;
|
||||
import io.metersphere.sdk.util.CompressUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class ExportUtils {
|
||||
|
||||
private List<BugDTO> bugs;
|
||||
private List<BugExportColumn> exportColumns;
|
||||
|
||||
public ExportUtils(
|
||||
List<BugDTO> bugs,
|
||||
List<BugExportColumn> exportColumns) {
|
||||
this.bugs = bugs;
|
||||
this.exportColumns = exportColumns;
|
||||
}
|
||||
|
||||
/*
|
||||
1.生成包含excel文件目录
|
||||
2.压缩
|
||||
3.删除该目录
|
||||
*/
|
||||
public byte[] exportToZipFile(BiFunction<List, List, String> generateExcelFilesFunction) throws Exception {
|
||||
//生成包含excel文件目录
|
||||
String folderPath = generateExcelFilesFunction.apply(bugs, exportColumns);
|
||||
File excelFolder = new File(folderPath);
|
||||
//压缩文件
|
||||
File zipFile = CompressUtils.zipFiles(folderPath + File.separatorChar + "bug-export.zip", List.of(excelFolder.listFiles()));
|
||||
byte[] returnByte = FileUtils.readFileToByteArray(zipFile);
|
||||
//删除目录
|
||||
FileUtils.deleteDirectory(excelFolder);
|
||||
return returnByte;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,9 @@
|
|||
},
|
||||
{
|
||||
"id": "BUG:READ+DELETE"
|
||||
},
|
||||
{
|
||||
"id": "PROJECT_BUG:READ+EXPORT"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -2,16 +2,15 @@ package io.metersphere.bug.controller;
|
|||
|
||||
import io.metersphere.bug.dto.BugCustomFieldDTO;
|
||||
import io.metersphere.bug.dto.BugDTO;
|
||||
import io.metersphere.bug.dto.request.BugBatchRequest;
|
||||
import io.metersphere.bug.dto.request.BugBatchUpdateRequest;
|
||||
import io.metersphere.bug.dto.request.BugEditRequest;
|
||||
import io.metersphere.bug.dto.request.BugPageRequest;
|
||||
import io.metersphere.bug.dto.request.*;
|
||||
import io.metersphere.bug.utils.CustomFieldUtils;
|
||||
import io.metersphere.project.dto.ProjectTemplateOptionDTO;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
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.TemplateDTO;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import io.metersphere.system.utils.Pager;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.jupiter.api.*;
|
||||
|
@ -44,6 +43,8 @@ public class BugControllerTests extends BaseTest {
|
|||
public static final String BUG_BATCH_UPDATE = "/bug/batch-update";
|
||||
public static final String BUG_FOLLOW = "/bug/follow";
|
||||
public static final String BUG_UN_FOLLOW = "/bug/unfollow";
|
||||
public static final String BUG_EXPORT_COLUMNS = "/bug/export/columns/%s";
|
||||
public static final String BUG_EXPORT = "/bug/export";
|
||||
|
||||
@Test
|
||||
@Order(0)
|
||||
|
@ -94,6 +95,7 @@ public class BugControllerTests extends BaseTest {
|
|||
bugPageRequest.setCurrent(1);
|
||||
bugPageRequest.setPageSize(10);
|
||||
bugPageRequest.setKeyword("default-x");
|
||||
bugPageRequest.setProjectId("default-project-for-bug");
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(BUG_PAGE, bugPageRequest);
|
||||
// 获取返回值
|
||||
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
|
@ -340,6 +342,68 @@ public class BugControllerTests extends BaseTest {
|
|||
|
||||
@Test
|
||||
@Order(12)
|
||||
void testExportColumns() throws Exception {
|
||||
this.requestGetWithOkAndReturn(String.format(BUG_EXPORT_COLUMNS, "default-project-for-bug"));
|
||||
//校验权限
|
||||
this.requestGetPermissionTest(PermissionConstants.BUG_EXPORT, String.format(BUG_EXPORT_COLUMNS, DEFAULT_PROJECT_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(13)
|
||||
void testExportBugs() throws Exception {
|
||||
BugExportRequest request = new BugExportRequest();
|
||||
request.setProjectId("default-project-for-bug");
|
||||
request.setSelectAll(true);
|
||||
List<BugExportColumn> exportColumns = new ArrayList<>();
|
||||
exportColumns.add(new BugExportColumn("name", "名称", "system"));
|
||||
exportColumns.add(new BugExportColumn("id", "ID", "system"));
|
||||
exportColumns.add(new BugExportColumn("content", "缺内容", "system"));
|
||||
exportColumns.add(new BugExportColumn("status", "陷状态", "system"));
|
||||
exportColumns.add(new BugExportColumn("handleUser", "处理人儿", "system"));
|
||||
exportColumns.add(new BugExportColumn("createUser", "创建人儿", "other"));
|
||||
exportColumns.add(new BugExportColumn("createTime", "搞定时间", "other"));
|
||||
exportColumns.add(new BugExportColumn("caseCount", "用例量", "other"));
|
||||
exportColumns.add(new BugExportColumn("comment", "评论", "other"));
|
||||
exportColumns.add(new BugExportColumn("platform", "平台", "other"));
|
||||
request.setExportColumns(exportColumns);
|
||||
|
||||
MvcResult result = this.requestPostDownloadFile(BUG_EXPORT, null, request);
|
||||
byte[] bytes = result.getResponse().getContentAsByteArray();
|
||||
Assertions.assertTrue(bytes.length > 0);
|
||||
|
||||
// 非Local的缺陷导出
|
||||
request.setProjectId("default-project-for-bug-no-local");
|
||||
result = this.requestPostDownloadFile(BUG_EXPORT, null, request);
|
||||
bytes = result.getResponse().getContentAsByteArray();
|
||||
Assertions.assertTrue(bytes.length > 0);
|
||||
|
||||
// 勾选部分
|
||||
request.setSelectAll(false);
|
||||
request.setIncludeBugIds(List.of("default-bug-id-single"));
|
||||
result = this.requestPostDownloadFile(BUG_EXPORT, null, request);
|
||||
bytes = result.getResponse().getContentAsByteArray();
|
||||
Assertions.assertTrue(bytes.length > 0);
|
||||
|
||||
//不存在的ID
|
||||
request.setIncludeBugIds(List.of(IDGenerator.nextStr()));
|
||||
this.requestPost(BUG_EXPORT, request).andExpect(status().is5xxServerError());
|
||||
|
||||
//没有数据
|
||||
request = new BugExportRequest();
|
||||
request.setProjectId("default-project-for-bug");
|
||||
request.setSelectAll(false);
|
||||
request.setExportColumns(exportColumns);
|
||||
this.requestPost(BUG_EXPORT, request).andExpect(status().is5xxServerError());
|
||||
|
||||
//测试权限
|
||||
request = new BugExportRequest();
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setSelectAll(true);
|
||||
request.setExportColumns(exportColumns);
|
||||
this.requestPostPermissionTest(PermissionConstants.BUG_EXPORT, BUG_EXPORT, request);
|
||||
}
|
||||
@Test
|
||||
@Order(90)
|
||||
void testDeleteBugSuccess() throws Exception {
|
||||
this.requestGet(BUG_DELETE + "/default-bug-id", status().isOk());
|
||||
// 非Local缺陷
|
||||
|
@ -347,13 +411,13 @@ public class BugControllerTests extends BaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Order(13)
|
||||
@Order(91)
|
||||
void testDeleteBugError() throws Exception {
|
||||
this.requestGet(BUG_DELETE + "/default-bug-id-not-exist", status().is5xxServerError());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(14)
|
||||
@Order(92)
|
||||
void testBatchDeleteEmptyBugSuccess() throws Exception {
|
||||
BugBatchRequest request = new BugBatchRequest();
|
||||
request.setProjectId("default-project-for-bug");
|
||||
|
@ -367,7 +431,7 @@ public class BugControllerTests extends BaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Order(15)
|
||||
@Order(93)
|
||||
void testFollowBug() throws Exception {
|
||||
// 关注的缺陷存在
|
||||
this.requestGet(BUG_FOLLOW + "/default-bug-id-single", status().isOk());
|
||||
|
@ -376,7 +440,7 @@ public class BugControllerTests extends BaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Order(16)
|
||||
@Order(94)
|
||||
void testUnFollowBug() throws Exception {
|
||||
// 取消关注的缺陷存在
|
||||
this.requestGet(BUG_UN_FOLLOW + "/default-bug-id-single", status().isOk());
|
||||
|
@ -385,7 +449,7 @@ public class BugControllerTests extends BaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Order(20)
|
||||
@Order(95)
|
||||
void testBatchDeleteBugSuccess() throws Exception {
|
||||
BugBatchRequest request = new BugBatchRequest();
|
||||
request.setProjectId("default-project-for-bug");
|
||||
|
@ -402,7 +466,7 @@ public class BugControllerTests extends BaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Order(21)
|
||||
@Order(96)
|
||||
void coverUtilsTest() throws Exception {
|
||||
CustomFieldUtils.appendToMultipleCustomField(null, "test");
|
||||
}
|
||||
|
|
|
@ -692,7 +692,7 @@ public class FileManagementControllerTests extends BaseTest {
|
|||
this.fileReUploadTestSuccess();
|
||||
}
|
||||
for (String fileMetadataId : FILE_ID_PATH.keySet()) {
|
||||
MvcResult mvcResult = this.downloadFile(String.format(FileManagementRequestUtils.URL_FILE_DOWNLOAD, fileMetadataId));
|
||||
MvcResult mvcResult = this.requestGetDownloadFile(String.format(FileManagementRequestUtils.URL_FILE_DOWNLOAD, fileMetadataId), null);
|
||||
byte[] fileBytes = mvcResult.getResponse().getContentAsByteArray();
|
||||
|
||||
//通过MD5判断是否是同一个文件
|
||||
|
@ -844,7 +844,7 @@ public class FileManagementControllerTests extends BaseTest {
|
|||
batchProcessDTO.setSelectAll(false);
|
||||
batchProcessDTO.setProjectId(project.getId());
|
||||
batchProcessDTO.setSelectIds(new ArrayList<>(FILE_ID_PATH.keySet()));
|
||||
MvcResult mvcResult = this.batchDownloadFile(FileManagementRequestUtils.URL_FILE_BATCH_DOWNLOAD, batchProcessDTO);
|
||||
MvcResult mvcResult = this.requestPostDownloadFile(FileManagementRequestUtils.URL_FILE_BATCH_DOWNLOAD, null, batchProcessDTO);
|
||||
byte[] fileBytes = mvcResult.getResponse().getContentAsByteArray();
|
||||
Assertions.assertTrue(fileBytes.length > 0);
|
||||
|
||||
|
@ -852,7 +852,7 @@ public class FileManagementControllerTests extends BaseTest {
|
|||
batchProcessDTO = new FileBatchProcessRequest();
|
||||
batchProcessDTO.setSelectAll(true);
|
||||
batchProcessDTO.setProjectId(project.getId());
|
||||
mvcResult = this.batchDownloadFile(FileManagementRequestUtils.URL_FILE_BATCH_DOWNLOAD, batchProcessDTO);
|
||||
mvcResult = this.requestPostDownloadFile(FileManagementRequestUtils.URL_FILE_BATCH_DOWNLOAD, null, batchProcessDTO);
|
||||
fileBytes = mvcResult.getResponse().getContentAsByteArray();
|
||||
Assertions.assertTrue(fileBytes.length > 0);
|
||||
|
||||
|
@ -930,13 +930,13 @@ public class FileManagementControllerTests extends BaseTest {
|
|||
List<FileInformationResponse> fileList = JSON.parseArray(JSON.toJSONString(pageResult.getList()), FileInformationResponse.class);
|
||||
|
||||
for (FileInformationResponse fileDTO : fileList) {
|
||||
MvcResult originalResult = this.downloadFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_ORIGINAL, "admin", fileDTO.getId()));
|
||||
MvcResult originalResult = this.requestGetDownloadFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_ORIGINAL, "admin", fileDTO.getId()), null);
|
||||
Assertions.assertTrue(originalResult.getResponse().getContentAsByteArray().length > 0);
|
||||
MvcResult compressedResult;
|
||||
if (StringUtils.equalsIgnoreCase(fileDTO.getFileType(), "svg")) {
|
||||
compressedResult = this.downloadSvgFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_COMPRESSED, "admin", fileDTO.getId()));
|
||||
compressedResult = this.requestGetDownloadFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_COMPRESSED, "admin", fileDTO.getId()), MediaType.valueOf("image/svg+xml"));
|
||||
} else {
|
||||
compressedResult = this.downloadFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_COMPRESSED, "admin", fileDTO.getId()));
|
||||
compressedResult = this.requestGetDownloadFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_COMPRESSED, "admin", fileDTO.getId()), null);
|
||||
}
|
||||
|
||||
byte[] fileBytes = compressedResult.getResponse().getContentAsByteArray();
|
||||
|
@ -953,14 +953,14 @@ public class FileManagementControllerTests extends BaseTest {
|
|||
}
|
||||
//测试重复获取
|
||||
for (FileInformationResponse fileDTO : fileList) {
|
||||
MvcResult originalResult = this.downloadFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_ORIGINAL, "admin", fileDTO.getId()));
|
||||
MvcResult originalResult = this.requestGetDownloadFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_ORIGINAL, "admin", fileDTO.getId()), null);
|
||||
Assertions.assertTrue(originalResult.getResponse().getContentAsByteArray().length > 0);
|
||||
|
||||
MvcResult compressedResult;
|
||||
if (StringUtils.equalsIgnoreCase(fileDTO.getFileType(), "svg")) {
|
||||
compressedResult = this.downloadSvgFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_COMPRESSED, "admin", fileDTO.getId()));
|
||||
compressedResult = this.requestGetDownloadFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_COMPRESSED, "admin", fileDTO.getId()), MediaType.valueOf("image/svg+xml"));
|
||||
} else {
|
||||
compressedResult = this.downloadFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_COMPRESSED, "admin", fileDTO.getId()));
|
||||
compressedResult = this.requestGetDownloadFile(String.format(FileManagementRequestUtils.URL_FILE_PREVIEW_COMPRESSED, "admin", fileDTO.getId()), null);
|
||||
}
|
||||
byte[] fileBytes = compressedResult.getResponse().getContentAsByteArray();
|
||||
if (TempFileUtils.isImage(fileDTO.getFileType())) {
|
||||
|
@ -2180,24 +2180,6 @@ public class FileManagementControllerTests extends BaseTest {
|
|||
.andReturn();
|
||||
}
|
||||
|
||||
protected MvcResult downloadSvgFile(String url, Object... uriVariables) throws Exception {
|
||||
return mockMvc.perform(getRequestBuilder(url, uriVariables))
|
||||
.andExpect(content().contentType(MediaType.valueOf("image/svg+xml")))
|
||||
.andExpect(status().isOk()).andReturn();
|
||||
}
|
||||
|
||||
protected MvcResult downloadFile(String url, Object... uriVariables) throws Exception {
|
||||
return mockMvc.perform(getRequestBuilder(url, uriVariables))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE))
|
||||
.andExpect(status().isOk()).andReturn();
|
||||
}
|
||||
|
||||
protected MvcResult batchDownloadFile(String url, Object param) throws Exception {
|
||||
return mockMvc.perform(getPostRequestBuilder(url, param))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE))
|
||||
.andExpect(status().isOk()).andReturn();
|
||||
}
|
||||
|
||||
private List<BaseTreeNode> getFileModuleTreeNode() throws Exception {
|
||||
MvcResult result = this.requestGetWithOkAndReturn(String.format(FileManagementRequestUtils.URL_MODULE_TREE, project.getId()));
|
||||
String returnData = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
|
|
|
@ -146,6 +146,25 @@ public abstract class BaseTest {
|
|||
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
|
||||
}
|
||||
|
||||
protected MvcResult requestGetDownloadFile(String url, MediaType contentType, Object... uriVariables) throws Exception {
|
||||
if (contentType == null) {
|
||||
contentType = MediaType.APPLICATION_OCTET_STREAM;
|
||||
}
|
||||
return mockMvc.perform(getRequestBuilder(url, uriVariables))
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(status().isOk()).andReturn();
|
||||
}
|
||||
|
||||
protected MvcResult requestPostDownloadFile(String url, MediaType contentType, Object param) throws Exception {
|
||||
if (contentType == null) {
|
||||
contentType = MediaType.APPLICATION_OCTET_STREAM;
|
||||
}
|
||||
return mockMvc.perform(getPostRequestBuilder(url, param))
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(status().isOk()).andReturn();
|
||||
}
|
||||
|
||||
|
||||
protected MvcResult requestPostAndReturn(String url, Object param, Object... uriVariables) throws Exception {
|
||||
return this.requestPost(url, param, uriVariables).andReturn();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue