feat(测试用例): 导出任务校验

This commit is contained in:
WangXu10 2024-08-08 12:45:55 +08:00 committed by Craftsman
parent e98ad1d4c2
commit 99ee96da02
11 changed files with 271 additions and 110 deletions

View File

@ -5,11 +5,10 @@ import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import lombok.Data;
@Data
public class ExportTask implements Serializable {
@ -27,7 +26,7 @@ public class ExportTask implements Serializable {
private String type;
@Schema(description = "文件id")
private String fileid;
private String fileId;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{export_task.state.not_blank}", groups = {Created.class})
@ -51,19 +50,23 @@ public class ExportTask implements Serializable {
@Size(min = 1, max = 50, message = "{export_task.project_id.length_range}", groups = {Created.class, Updated.class})
private String projectId;
@Schema(description = "文件类型")
private String fileType;
private static final long serialVersionUID = 1L;
public enum Column {
id("id", "id", "VARCHAR", false),
name("name", "name", "VARCHAR", true),
type("type", "type", "VARCHAR", true),
fileid("fileId", "fileid", "VARCHAR", false),
fileId("file_id", "fileId", "VARCHAR", false),
state("state", "state", "VARCHAR", true),
createUser("create_user", "createUser", "VARCHAR", false),
createTime("create_time", "createTime", "BIGINT", false),
updateUser("update_user", "updateUser", "VARCHAR", false),
updateTime("update_time", "updateTime", "BIGINT", false),
projectId("project_id", "projectId", "VARCHAR", false);
projectId("project_id", "projectId", "VARCHAR", false),
fileType("file_type", "fileType", "VARCHAR", false);
private static final String BEGINNING_DELIMITER = "`";
@ -108,7 +111,7 @@ public class ExportTask implements Serializable {
return this.getEscapedColumnName() + " ASC";
}
public static Column[] excludes(Column... excludes) {
public static Column[] excludes(Column ... excludes) {
ArrayList<Column> columns = new ArrayList<>(Arrays.asList(Column.values()));
if (excludes != null && excludes.length > 0) {
columns.removeAll(new ArrayList<>(Arrays.asList(excludes)));

View File

@ -314,73 +314,73 @@ public class ExportTaskExample {
return (Criteria) this;
}
public Criteria andFileidIsNull() {
addCriterion("fileId is null");
public Criteria andFileIdIsNull() {
addCriterion("file_id is null");
return (Criteria) this;
}
public Criteria andFileidIsNotNull() {
addCriterion("fileId is not null");
public Criteria andFileIdIsNotNull() {
addCriterion("file_id is not null");
return (Criteria) this;
}
public Criteria andFileidEqualTo(String value) {
addCriterion("fileId =", value, "fileid");
public Criteria andFileIdEqualTo(String value) {
addCriterion("file_id =", value, "fileId");
return (Criteria) this;
}
public Criteria andFileidNotEqualTo(String value) {
addCriterion("fileId <>", value, "fileid");
public Criteria andFileIdNotEqualTo(String value) {
addCriterion("file_id <>", value, "fileId");
return (Criteria) this;
}
public Criteria andFileidGreaterThan(String value) {
addCriterion("fileId >", value, "fileid");
public Criteria andFileIdGreaterThan(String value) {
addCriterion("file_id >", value, "fileId");
return (Criteria) this;
}
public Criteria andFileidGreaterThanOrEqualTo(String value) {
addCriterion("fileId >=", value, "fileid");
public Criteria andFileIdGreaterThanOrEqualTo(String value) {
addCriterion("file_id >=", value, "fileId");
return (Criteria) this;
}
public Criteria andFileidLessThan(String value) {
addCriterion("fileId <", value, "fileid");
public Criteria andFileIdLessThan(String value) {
addCriterion("file_id <", value, "fileId");
return (Criteria) this;
}
public Criteria andFileidLessThanOrEqualTo(String value) {
addCriterion("fileId <=", value, "fileid");
public Criteria andFileIdLessThanOrEqualTo(String value) {
addCriterion("file_id <=", value, "fileId");
return (Criteria) this;
}
public Criteria andFileidLike(String value) {
addCriterion("fileId like", value, "fileid");
public Criteria andFileIdLike(String value) {
addCriterion("file_id like", value, "fileId");
return (Criteria) this;
}
public Criteria andFileidNotLike(String value) {
addCriterion("fileId not like", value, "fileid");
public Criteria andFileIdNotLike(String value) {
addCriterion("file_id not like", value, "fileId");
return (Criteria) this;
}
public Criteria andFileidIn(List<String> values) {
addCriterion("fileId in", values, "fileid");
public Criteria andFileIdIn(List<String> values) {
addCriterion("file_id in", values, "fileId");
return (Criteria) this;
}
public Criteria andFileidNotIn(List<String> values) {
addCriterion("fileId not in", values, "fileid");
public Criteria andFileIdNotIn(List<String> values) {
addCriterion("file_id not in", values, "fileId");
return (Criteria) this;
}
public Criteria andFileidBetween(String value1, String value2) {
addCriterion("fileId between", value1, value2, "fileid");
public Criteria andFileIdBetween(String value1, String value2) {
addCriterion("file_id between", value1, value2, "fileId");
return (Criteria) this;
}
public Criteria andFileidNotBetween(String value1, String value2) {
addCriterion("fileId not between", value1, value2, "fileid");
public Criteria andFileIdNotBetween(String value1, String value2) {
addCriterion("file_id not between", value1, value2, "fileId");
return (Criteria) this;
}
@ -783,6 +783,76 @@ public class ExportTaskExample {
addCriterion("project_id not between", value1, value2, "projectId");
return (Criteria) this;
}
public Criteria andFileTypeIsNull() {
addCriterion("file_type is null");
return (Criteria) this;
}
public Criteria andFileTypeIsNotNull() {
addCriterion("file_type is not null");
return (Criteria) this;
}
public Criteria andFileTypeEqualTo(String value) {
addCriterion("file_type =", value, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeNotEqualTo(String value) {
addCriterion("file_type <>", value, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeGreaterThan(String value) {
addCriterion("file_type >", value, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeGreaterThanOrEqualTo(String value) {
addCriterion("file_type >=", value, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeLessThan(String value) {
addCriterion("file_type <", value, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeLessThanOrEqualTo(String value) {
addCriterion("file_type <=", value, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeLike(String value) {
addCriterion("file_type like", value, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeNotLike(String value) {
addCriterion("file_type not like", value, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeIn(List<String> values) {
addCriterion("file_type in", values, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeNotIn(List<String> values) {
addCriterion("file_type not in", values, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeBetween(String value1, String value2) {
addCriterion("file_type between", value1, value2, "fileType");
return (Criteria) this;
}
public Criteria andFileTypeNotBetween(String value1, String value2) {
addCriterion("file_type not between", value1, value2, "fileType");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {

View File

@ -5,13 +5,14 @@
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="type" jdbcType="VARCHAR" property="type" />
<result column="fileId" jdbcType="VARCHAR" property="fileid" />
<result column="file_id" jdbcType="VARCHAR" property="fileId" />
<result column="state" jdbcType="VARCHAR" property="state" />
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_user" jdbcType="VARCHAR" property="updateUser" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="file_type" jdbcType="VARCHAR" property="fileType" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
@ -72,8 +73,8 @@
</where>
</sql>
<sql id="Base_Column_List">
id, `name`, `type`, fileId, `state`, create_user, create_time, update_user, update_time,
project_id
id, `name`, `type`, file_id, `state`, create_user, create_time, update_user, update_time,
project_id, file_type
</sql>
<select id="selectByExample" parameterType="io.metersphere.functional.domain.ExportTaskExample" resultMap="BaseResultMap">
select
@ -107,13 +108,13 @@
</delete>
<insert id="insert" parameterType="io.metersphere.functional.domain.ExportTask">
insert into export_task (id, `name`, `type`,
fileId, `state`, create_user,
file_id, `state`, create_user,
create_time, update_user, update_time,
project_id)
project_id, file_type)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR},
#{fileid,jdbcType=VARCHAR}, #{state,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR},
#{fileId,jdbcType=VARCHAR}, #{state,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{updateUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT},
#{projectId,jdbcType=VARCHAR})
#{projectId,jdbcType=VARCHAR}, #{fileType,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.functional.domain.ExportTask">
insert into export_task
@ -127,8 +128,8 @@
<if test="type != null">
`type`,
</if>
<if test="fileid != null">
fileId,
<if test="fileId != null">
file_id,
</if>
<if test="state != null">
`state`,
@ -148,6 +149,9 @@
<if test="projectId != null">
project_id,
</if>
<if test="fileType != null">
file_type,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
@ -159,8 +163,8 @@
<if test="type != null">
#{type,jdbcType=VARCHAR},
</if>
<if test="fileid != null">
#{fileid,jdbcType=VARCHAR},
<if test="fileId != null">
#{fileId,jdbcType=VARCHAR},
</if>
<if test="state != null">
#{state,jdbcType=VARCHAR},
@ -180,6 +184,9 @@
<if test="projectId != null">
#{projectId,jdbcType=VARCHAR},
</if>
<if test="fileType != null">
#{fileType,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.functional.domain.ExportTaskExample" resultType="java.lang.Long">
@ -200,8 +207,8 @@
<if test="record.type != null">
`type` = #{record.type,jdbcType=VARCHAR},
</if>
<if test="record.fileid != null">
fileId = #{record.fileid,jdbcType=VARCHAR},
<if test="record.fileId != null">
file_id = #{record.fileId,jdbcType=VARCHAR},
</if>
<if test="record.state != null">
`state` = #{record.state,jdbcType=VARCHAR},
@ -221,6 +228,9 @@
<if test="record.projectId != null">
project_id = #{record.projectId,jdbcType=VARCHAR},
</if>
<if test="record.fileType != null">
file_type = #{record.fileType,jdbcType=VARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -231,13 +241,14 @@
set id = #{record.id,jdbcType=VARCHAR},
`name` = #{record.name,jdbcType=VARCHAR},
`type` = #{record.type,jdbcType=VARCHAR},
fileId = #{record.fileid,jdbcType=VARCHAR},
file_id = #{record.fileId,jdbcType=VARCHAR},
`state` = #{record.state,jdbcType=VARCHAR},
create_user = #{record.createUser,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_user = #{record.updateUser,jdbcType=VARCHAR},
update_time = #{record.updateTime,jdbcType=BIGINT},
project_id = #{record.projectId,jdbcType=VARCHAR}
project_id = #{record.projectId,jdbcType=VARCHAR},
file_type = #{record.fileType,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -251,8 +262,8 @@
<if test="type != null">
`type` = #{type,jdbcType=VARCHAR},
</if>
<if test="fileid != null">
fileId = #{fileid,jdbcType=VARCHAR},
<if test="fileId != null">
file_id = #{fileId,jdbcType=VARCHAR},
</if>
<if test="state != null">
`state` = #{state,jdbcType=VARCHAR},
@ -272,6 +283,9 @@
<if test="projectId != null">
project_id = #{projectId,jdbcType=VARCHAR},
</if>
<if test="fileType != null">
file_type = #{fileType,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
@ -279,25 +293,26 @@
update export_task
set `name` = #{name,jdbcType=VARCHAR},
`type` = #{type,jdbcType=VARCHAR},
fileId = #{fileid,jdbcType=VARCHAR},
file_id = #{fileId,jdbcType=VARCHAR},
`state` = #{state,jdbcType=VARCHAR},
create_user = #{createUser,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_user = #{updateUser,jdbcType=VARCHAR},
update_time = #{updateTime,jdbcType=BIGINT},
project_id = #{projectId,jdbcType=VARCHAR}
project_id = #{projectId,jdbcType=VARCHAR},
file_type = #{fileType,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<insert id="batchInsert" parameterType="map">
insert into export_task
(id, `name`, `type`, fileId, `state`, create_user, create_time, update_user, update_time,
project_id)
(id, `name`, `type`, file_id, `state`, create_user, create_time, update_user, update_time,
project_id, file_type)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.type,jdbcType=VARCHAR},
#{item.fileid,jdbcType=VARCHAR}, #{item.state,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR},
#{item.fileId,jdbcType=VARCHAR}, #{item.state,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR},
#{item.createTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT},
#{item.projectId,jdbcType=VARCHAR})
#{item.projectId,jdbcType=VARCHAR}, #{item.fileType,jdbcType=VARCHAR})
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -319,8 +334,8 @@
<if test="'type'.toString() == column.value">
#{item.type,jdbcType=VARCHAR}
</if>
<if test="'fileId'.toString() == column.value">
#{item.fileid,jdbcType=VARCHAR}
<if test="'file_id'.toString() == column.value">
#{item.fileId,jdbcType=VARCHAR}
</if>
<if test="'state'.toString() == column.value">
#{item.state,jdbcType=VARCHAR}
@ -340,6 +355,9 @@
<if test="'project_id'.toString() == column.value">
#{item.projectId,jdbcType=VARCHAR}
</if>
<if test="'file_type'.toString() == column.value">
#{item.fileType,jdbcType=VARCHAR}
</if>
</foreach>
)
</foreach>

View File

@ -11,7 +11,8 @@ CREATE TABLE export_task(
`id` VARCHAR(50) NOT NULL COMMENT '任务唯一ID' ,
`name` VARCHAR(255) COMMENT '名称' ,
`type` VARCHAR(50) NOT NULL COMMENT '资源类型' ,
`fileId` VARCHAR(255) COMMENT '文件id' ,
`file_id` VARCHAR(255) COMMENT '文件id' ,
`file_type` VARCHAR(64) COMMENT '文件类型' ,
`project_id` VARCHAR(255) NOT NULL COMMENT '项目id' ,
`state` VARCHAR(50) NOT NULL COMMENT '状态' ,
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人' ,

View File

@ -0,0 +1,34 @@
package io.metersphere.sdk.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class ExportMsgDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* fileId
*/
private String fileId;
/**
* 任务id
*/
private String taskId;
/**
* 数量
*/
private int count;
/**
* 消息类型LINK-链接标识HEARTBEAT-心跳检查标识EXEC_START-开始执行标识EXEC_RESULT-执行结果标识
*/
private String msgType;
}

View File

@ -287,7 +287,7 @@ public class FunctionalCaseController {
@Operation(summary = "用例管理-功能用例-下载文件")
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_EXPORT)
public ResponseEntity<byte[]> downloadImgById(@PathVariable String projectId, @PathVariable String fileId) {
return functionalCaseFileService.downloadFile(projectId, fileId);
return functionalCaseFileService.downloadFile(projectId, fileId, SessionUtils.getUserId());
}
@ -297,4 +297,11 @@ public class FunctionalCaseController {
public void caseExportXmind(@Validated @RequestBody FunctionalCaseExportRequest request) {
functionalCaseXmindService.exportFunctionalCaseXmind(request, SessionUtils.getUserId());
}
@GetMapping(value = "/check/export-task")
@Operation(summary = "用例管理-功能用例-导出任务校验")
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_EXPORT)
public String checkExportTask() {
return functionalCaseFileService.checkExportTask(SessionUtils.getCurrentProjectId(), SessionUtils.getUserId());
}
}

View File

@ -33,7 +33,7 @@ import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.project.service.ProjectTemplateService;
import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.dto.SocketMsgDTO;
import io.metersphere.sdk.dto.ExportMsgDTO;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.file.FileRequest;
import io.metersphere.sdk.util.*;
@ -106,8 +106,8 @@ public class FunctionalCaseFileService {
private ExportTaskManager exportTaskManager;
@Resource
private ExportTaskMapper exportTaskMapper;
private static final String XMIND = ".xmind";
private static final String XLSX = ".xlsx";
private static final String XLSX = "xlsx";
private static final String ZIP = "zip";
/**
* 下载excel导入模板
@ -340,7 +340,7 @@ public class FunctionalCaseFileService {
if (preparedCount > 0) {
throw new MSException(Translator.get("export_case_task_existed"));
}
exportTaskManager.exportAsyncTask(request.getProjectId(), userId, ExportConstants.ExportType.CASE.toString(), request, t -> exportFunctionalCaseZip(request, userId));
exportTaskManager.exportAsyncTask(request.getProjectId(), request.getFileId(), userId, ExportConstants.ExportType.CASE.toString(), request, t -> exportFunctionalCaseZip(request, userId));
} catch (InterruptedException e) {
LogUtils.error("导出失败:" + e);
throw new MSException(e);
@ -356,39 +356,47 @@ public class FunctionalCaseFileService {
public String exportFunctionalCaseZip(FunctionalCaseExportRequest request, String userId) {
File tmpDir = null;
Project project = projectMapper.selectByPrimaryKey(request.getProjectId());
String fileType = "";
try {
tmpDir = new File(getClass().getClassLoader().getResource(StringUtils.EMPTY).getPath() +
EXPORT_CASE_TMP_DIR + File.separatorChar + EXPORT_CASE_TMP_DIR + "_" + IDGenerator.nextStr());
// 生成tmp随机目录
MsFileUtils.deleteDir(tmpDir.getPath());
tmpDir.mkdirs();
//获取导出的ids集合
List<File> batchExcels = new ArrayList<>();
List<String> ids = functionalCaseService.doSelectIds(request, request.getProjectId());
if (CollectionUtils.isEmpty(ids)) {
return null;
}
// 生成EXCEL
List<File> batchExcels = generateCaseExportExcel(tmpDir.getPath(), request, project);
batchExcels = generateCaseExportExcel(batchExcels, ids, tmpDir.getPath(), request, project);
if (batchExcels.size() > 1) {
// EXCEL -> ZIP (EXCEL数目大于1)
File zipFile = CompressUtils.zipFilesToPath(tmpDir.getPath() + File.separatorChar + "Metersphere_case_" + project.getName() + ".zip", batchExcels);
uploadFileToMinio(zipFile, request.getFileId());
fileType = ZIP;
uploadFileToMinio(fileType, zipFile, request.getFileId());
} else {
// EXCEL (EXCEL数目等于1)
File singeFile = batchExcels.get(0);
uploadFileToMinio(singeFile, request.getFileId());
fileType = XLSX;
uploadFileToMinio(fileType, singeFile, request.getFileId());
}
functionalCaseLogService.exportExcelLog(request);
List<ExportTask> exportTasks = getExportTasks(request.getProjectId(), userId);
String taskId;
if (CollectionUtils.isNotEmpty(exportTasks)) {
taskId = exportTasks.getFirst().getId();
updateExportTask(ExportConstants.ExportState.SUCCESS.name(), taskId, request.getFileId());
updateExportTask(ExportConstants.ExportState.SUCCESS.name(), taskId, fileType);
} else {
taskId = MsgType.CONNECT.name();
}
SocketMsgDTO socketMsgDTO = new SocketMsgDTO(request.getFileId(), "", MsgType.CONNECT.name(), taskId);
socketMsgDTO.setReportId(request.getFileId());
ExportWebSocketHandler.sendMessageSingle(socketMsgDTO);
ExportMsgDTO exportMsgDTO = new ExportMsgDTO(request.getFileId(), taskId, ids.size(), MsgType.CONNECT.name());
ExportWebSocketHandler.sendMessageSingle(exportMsgDTO);
} catch (Exception e) {
List<ExportTask> exportTasks = getExportTasks(request.getProjectId(), userId);
if (CollectionUtils.isNotEmpty(exportTasks)) {
updateExportTask(ExportConstants.ExportState.ERROR.name(), exportTasks.getFirst().getId(), request.getFileId());
updateExportTask(ExportConstants.ExportState.ERROR.name(), exportTasks.getFirst().getId(), fileType);
}
LogUtils.error(e);
throw new MSException(e);
@ -404,17 +412,17 @@ public class FunctionalCaseFileService {
return exportTaskMapper.selectByExample(exportTaskExample);
}
public void updateExportTask(String state, String taskId, String fileId) {
public void updateExportTask(String state, String taskId, String fileType) {
ExportTask exportTask = new ExportTask();
exportTask.setState(state);
exportTask.setFileid(fileId);
exportTask.setFileType(fileType);
exportTask.setId(taskId);
exportTaskMapper.updateByPrimaryKeySelective(exportTask);
}
public void uploadFileToMinio(File file, String fileId) {
public void uploadFileToMinio(String fileType, File file, String fileId) {
FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(fileId);
fileRequest.setFileName(fileId.concat(".").concat(fileType));
fileRequest.setFolder(DefaultRepositoryDir.getExportExcelTempDir());
fileRequest.setStorage(StorageType.MINIO.name());
try {
@ -425,15 +433,10 @@ public class FunctionalCaseFileService {
}
}
private List<File> generateCaseExportExcel(String tmpZipPath, FunctionalCaseExportRequest request, Project project) {
List<File> tmpExportExcelList = new ArrayList<>();
private List<File> generateCaseExportExcel(List<File> tmpExportExcelList, List<String> ids, String tmpZipPath, FunctionalCaseExportRequest request, Project project) {
//excel表头
List<List<String>> headList = getFunctionalCaseExportHeads(request);
//获取导出的ids集合
List<String> ids = functionalCaseService.doSelectIds(request, request.getProjectId());
if (CollectionUtils.isEmpty(ids)) {
return tmpExportExcelList;
}
//获取当前项目下默认模板的自定义字段属性
List<TemplateCustomFieldDTO> customFields = getCustomFields(request.getProjectId());
//默认字段+自定义字段的 options集合
@ -785,11 +788,16 @@ public class FunctionalCaseFileService {
return functionalCaseExportColumns;
}
public ResponseEntity<byte[]> downloadFile(String projectId, String fileId) {
public ResponseEntity<byte[]> downloadFile(String projectId, String fileId, String userId) {
List<ExportTask> exportTasks = getExportTasksByFileId(projectId, userId, fileId);
if (CollectionUtils.isEmpty(exportTasks)) {
throw new MSException("任务不存在");
}
ExportTask tasksFirst = exportTasks.getFirst();
Project project = projectMapper.selectByPrimaryKey(projectId);
byte[] bytes;
FileRequest fileRequest = new FileRequest();
fileRequest.setFileName(fileId);
fileRequest.setFileName(tasksFirst.getFileId().concat(tasksFirst.getFileType()));
fileRequest.setFolder(DefaultRepositoryDir.getExportExcelTempDir());
fileRequest.setStorage(StorageType.MINIO.name());
try {
@ -797,13 +805,7 @@ public class FunctionalCaseFileService {
} catch (Exception e) {
throw new MSException("get file error");
}
String fileName = "";
if (StringUtils.endsWith(fileId, XMIND)) {
fileName = "Metersphere_case_" + project.getName() + XMIND;
}
if (StringUtils.endsWith(fileId, XLSX)) {
fileName = "Metersphere_case_" + project.getName() + XLSX;
}
String fileName = "Metersphere_case_" + project.getName() + tasksFirst.getFileType();
try {
return ResponseEntity.ok()
@ -815,7 +817,24 @@ public class FunctionalCaseFileService {
}
}
private List<ExportTask> getExportTasksByFileId(String projectId, String userId, String fileId) {
ExportTaskExample exportTaskExample = new ExportTaskExample();
exportTaskExample.createCriteria().andTypeEqualTo(ExportConstants.ExportType.CASE.toString()).andStateEqualTo(ExportConstants.ExportState.SUCCESS.toString())
.andCreateUserEqualTo(userId).andProjectIdEqualTo(projectId).andFileIdEqualTo(fileId);
exportTaskExample.setOrderByClause("create_time desc");
return exportTaskMapper.selectByExample(exportTaskExample);
}
public void stopExport(String taskId, String userId) {
exportTaskManager.sendStopMessage(taskId, userId);
}
public String checkExportTask(String projectId, String userId) {
List<ExportTask> exportTasks = getExportTasks(projectId, userId);
if (CollectionUtils.isNotEmpty(exportTasks)) {
return exportTasks.getFirst().getFileId();
} else {
return StringUtils.EMPTY;
}
}
}

View File

@ -11,7 +11,7 @@ import io.metersphere.functional.xmind.domain.FunctionalCaseXmindData;
import io.metersphere.functional.xmind.utils.XmindExportUtil;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.MsgType;
import io.metersphere.sdk.dto.SocketMsgDTO;
import io.metersphere.sdk.dto.ExportMsgDTO;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
@ -59,6 +59,7 @@ public class FunctionalCaseXmindService {
private ExportTaskManager exportTaskManager;
@Resource
private FunctionalCaseLogService functionalCaseLogService;
private static final String XMIND = "xmind";
public void downloadXmindTemplate(String projectId, HttpServletResponse response) {
List<TemplateCustomFieldDTO> customFields = functionalCaseFileService.getCustomFields(projectId);
@ -96,7 +97,7 @@ public class FunctionalCaseXmindService {
*/
public void exportFunctionalCaseXmind(FunctionalCaseExportRequest request, String userId) {
try {
exportTaskManager.exportAsyncTask(request.getProjectId(), userId, ExportConstants.ExportType.CASE.toString(), request, t -> exportXmind(request, userId));
exportTaskManager.exportAsyncTask(request.getProjectId(), request.getFileId(), userId, ExportConstants.ExportType.CASE.toString(), request, t -> exportXmind(request, userId));
} catch (InterruptedException e) {
LogUtils.error("导出失败:" + e);
throw new MSException(e);
@ -118,24 +119,23 @@ public class FunctionalCaseXmindService {
List<TemplateCustomFieldDTO> templateCustomFields = functionalCaseFileService.getCustomFields(request.getProjectId());
TemplateCustomFieldDTO templateCustomFieldDTO = templateCustomFields.stream().filter(item -> StringUtils.equalsIgnoreCase(item.getFieldName(), Translator.get("custom_field.functional_priority"))).findFirst().get();
XmindExportUtil.export(xmindData, request, tmpFile, templateCustomFieldDTO);
functionalCaseFileService.uploadFileToMinio(tmpFile, request.getFileId());
functionalCaseFileService.uploadFileToMinio(XMIND, tmpFile, request.getFileId());
functionalCaseLogService.exportExcelLog(request);
List<ExportTask> exportTasks = functionalCaseFileService.getExportTasks(request.getProjectId(), userId);
String taskId;
if (CollectionUtils.isNotEmpty(exportTasks)) {
taskId = exportTasks.getFirst().getId();
functionalCaseFileService.updateExportTask(ExportConstants.ExportState.SUCCESS.name(), taskId, request.getFileId());
functionalCaseFileService.updateExportTask(ExportConstants.ExportState.SUCCESS.name(), taskId, XMIND);
} else {
taskId = MsgType.CONNECT.name();
}
SocketMsgDTO socketMsgDTO = new SocketMsgDTO(request.getFileId(), "", MsgType.CONNECT.name(), taskId);
socketMsgDTO.setReportId(request.getFileId());
ExportWebSocketHandler.sendMessageSingle(socketMsgDTO);
ExportMsgDTO exportMsgDTO = new ExportMsgDTO(request.getFileId(), taskId, ids.size(), MsgType.CONNECT.name());
ExportWebSocketHandler.sendMessageSingle(exportMsgDTO);
} catch (Exception e) {
List<ExportTask> exportTasks = functionalCaseFileService.getExportTasks(request.getProjectId(), userId);
if (CollectionUtils.isNotEmpty(exportTasks)) {
functionalCaseFileService.updateExportTask(ExportConstants.ExportState.ERROR.name(), exportTasks.getFirst().getId(), request.getFileId());
functionalCaseFileService.updateExportTask(ExportConstants.ExportState.ERROR.name(), exportTasks.getFirst().getId(), XMIND);
}
LogUtils.error(e);
throw new MSException(e);

View File

@ -1,7 +1,7 @@
package io.metersphere.functional.socket;
import io.metersphere.sdk.constants.MsgType;
import io.metersphere.sdk.dto.SocketMsgDTO;
import io.metersphere.sdk.dto.ExportMsgDTO;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import jakarta.websocket.*;
@ -22,7 +22,7 @@ public class ExportWebSocketHandler {
public static final Map<String, Session> ONLINE_EXPORT_EXCEL_SESSIONS = new ConcurrentHashMap<>();
public static void sendMessage(Session session, SocketMsgDTO message) {
public static void sendMessage(Session session, ExportMsgDTO message) {
if (session == null) {
return;
}
@ -35,8 +35,8 @@ public class ExportWebSocketHandler {
async.sendText(JSON.toJSONString(message));
}
public static void sendMessageSingle(SocketMsgDTO dto) {
sendMessage(ONLINE_EXPORT_EXCEL_SESSIONS.get(Optional.ofNullable(dto.getReportId())
public static void sendMessageSingle(ExportMsgDTO dto) {
sendMessage(ONLINE_EXPORT_EXCEL_SESSIONS.get(Optional.ofNullable(dto.getFileId())
.orElse(StringUtils.EMPTY)), dto);
}
@ -49,7 +49,7 @@ public class ExportWebSocketHandler {
ONLINE_EXPORT_EXCEL_SESSIONS.put(fileId, session);
RemoteEndpoint.Async async = session.getAsyncRemote();
if (async != null) {
async.sendText(JSON.toJSONString(new SocketMsgDTO(fileId, "", MsgType.CONNECT.name(), MsgType.CONNECT.name())));
async.sendText(JSON.toJSONString(new ExportMsgDTO(fileId, "", 0, MsgType.CONNECT.name())));
session.setMaxIdleTimeout(180000);
}
LogUtils.info("客户端: [" + fileId + "] : 连接成功!" + ExportWebSocketHandler.ONLINE_EXPORT_EXCEL_SESSIONS.size(), fileId);
@ -61,7 +61,7 @@ public class ExportWebSocketHandler {
@OnMessage
public void onMessage(@PathParam("fileId") String fileId, String message) {
LogUtils.info("服务器收到:[" + fileId + "] : " + message);
SocketMsgDTO dto = JSON.parseObject(message, SocketMsgDTO.class);
ExportMsgDTO dto = JSON.parseObject(message, ExportMsgDTO.class);
ExportWebSocketHandler.sendMessageSingle(dto);
}
@ -92,7 +92,7 @@ public class ExportWebSocketHandler {
@Scheduled(fixedRate = 60000)
public void heartbeatCheck() {
ExportWebSocketHandler.sendMessageSingle(
new SocketMsgDTO(MsgType.HEARTBEAT.name(), MsgType.HEARTBEAT.name(), MsgType.HEARTBEAT.name(), "heartbeat check")
new ExportMsgDTO(MsgType.HEARTBEAT.name(), MsgType.HEARTBEAT.name(), 0, "heartbeat check")
);
}
}

View File

@ -92,6 +92,7 @@ public class FunctionalCaseControllerTests extends BaseTest {
public static final String DOWNLOAD_FILE_URL = "/functional/case/download/file/";
public static final String STOP_EXPORT_URL = "/functional/case/stop/";
public static final String EXPORT_XMIND_URL = "/functional/case/export/xmind";
public static final String EXPORT_XMIND_CHECK_URL = "/functional/case/check/export-task";
@Resource
private NotificationMapper notificationMapper;
@ -906,4 +907,11 @@ public class FunctionalCaseControllerTests extends BaseTest {
request.setSelectIds(List.of("TEST_FUNCTIONAL_CASE_ID_8"));
this.requestPost(EXPORT_XMIND_URL, request);
}
@Test
@Order(4)
public void checkExportTask() throws Exception {
this.requestGetExcel( EXPORT_XMIND_CHECK_URL);
}
}

View File

@ -34,8 +34,8 @@ public class ExportTaskManager {
public static final String EXPORT_CONSUME = "export_consume";
public <T> void exportAsyncTask(String projectId, String userId, String type, T t, Function<Object, Object> selectListFunc) throws InterruptedException {
ExportTask exportTask = buildExportTask(projectId, userId, type);
public <T> void exportAsyncTask(String projectId, String fileId, String userId, String type, T t, Function<Object, Object> selectListFunc) throws InterruptedException {
ExportTask exportTask = buildExportTask(projectId, fileId, userId, type);
ExecutorService executorService = Executors.newFixedThreadPool(1);
Future<?> future = executorService.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
@ -48,7 +48,7 @@ public class ExportTaskManager {
map.put(exportTask.getId(), future);
}
private ExportTask buildExportTask(String projectId, String userId, String type) {
private ExportTask buildExportTask(String projectId, String fileId, String userId, String type) {
ExportTask exportTask = new ExportTask();
exportTask.setId(IDGenerator.nextStr());
exportTask.setType(type);
@ -58,6 +58,7 @@ public class ExportTaskManager {
exportTask.setUpdateUser(userId);
exportTask.setUpdateTime(System.currentTimeMillis());
exportTask.setProjectId(projectId);
exportTask.setFileType(fileId);
exportTaskMapper.insert(exportTask);
return exportTask;
}