feat(用例评审): 用例评审关联的用例列表支持拖拽排序

This commit is contained in:
guoyuqi 2023-12-15 14:49:54 +08:00 committed by 刘瑞斌
parent 5878905eab
commit 3069df28cf
7 changed files with 122 additions and 10 deletions

View File

@ -6,9 +6,11 @@ import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.functional.dto.ReviewFunctionalCaseDTO;
import io.metersphere.functional.request.BaseReviewCaseBatchRequest;
import io.metersphere.functional.request.CaseReviewFunctionalCasePosRequest;
import io.metersphere.functional.request.ReviewFunctionalCasePageRequest;
import io.metersphere.functional.service.CaseReviewFunctionalCaseService;
import io.metersphere.functional.service.CaseReviewLogService;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.utils.PageUtils;
@ -17,6 +19,7 @@ import io.metersphere.system.utils.SessionUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -60,4 +63,11 @@ public class CaseReviewFunctionalCaseController {
caseReviewFunctionalCaseService.disassociate(request);
}
@PostMapping("/edit/pos")
@Operation(summary = "用例管理-功能用例-评审列表-评审详情-列表-拖拽排序")
@RequiresPermissions(PermissionConstants.CASE_REVIEW_READ_UPDATE)
public void editPos(@Validated @RequestBody CaseReviewFunctionalCasePosRequest request) {
caseReviewFunctionalCaseService.editPos(request);
}
}

View File

@ -27,6 +27,10 @@ public interface ExtCaseReviewFunctionalCaseMapper {
Long getPos(@Param("reviewId") String reviewId);
Long getPrePos(@Param("reviewId") String reviewId, @Param("basePos") Long basePos);
Long getLastPos(@Param("reviewId") String reviewId, @Param("basePos") Long basePos);
List<String> getIds(@Param("request") BaseReviewCaseBatchRequest request, @Param("userId") String userId, @Param("deleted") boolean deleted);
List<CaseReviewFunctionalCase> getList(@Param("reviewId") String reviewId, @Param("reviewIds") List<String> reviewIds, @Param("deleted") boolean deleted);

View File

@ -305,4 +305,21 @@
</if>
</select>
<select id="getPrePos" resultType="java.lang.Long">
select `pos` from case_review_functional_case where review_id = #{reviewId}
<if test="basePos != null">
and `pos` &lt; #{basePos}
</if>
order by `pos` desc limit 1;
</select>
<select id="getLastPos" resultType="java.lang.Long">
select `pos` from case_review_functional_case where review_id = #{reviewId}
<if test="basePos != null">
and `pos` &gt; #{basePos}
</if>
order by `pos` desc limit 1;
</select>
</mapper>

View File

@ -0,0 +1,14 @@
package io.metersphere.functional.request;
import io.metersphere.system.dto.sdk.request.PosRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class CaseReviewFunctionalCasePosRequest extends PosRequest {
@Schema(description = "用例评审Id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{case_review_functional_case.review_id.not_blank}")
private String reviewId;
}

View File

@ -8,6 +8,7 @@ import io.metersphere.functional.dto.ReviewFunctionalCaseDTO;
import io.metersphere.functional.dto.ReviewsDTO;
import io.metersphere.functional.mapper.*;
import io.metersphere.functional.request.BaseReviewCaseBatchRequest;
import io.metersphere.functional.request.CaseReviewFunctionalCasePosRequest;
import io.metersphere.functional.request.FunctionalCaseEditRequest;
import io.metersphere.functional.request.ReviewFunctionalCasePageRequest;
import io.metersphere.functional.utils.CaseListenerUtils;
@ -19,6 +20,7 @@ import io.metersphere.project.mapper.ProjectApplicationMapper;
import io.metersphere.sdk.constants.ProjectApplicationType;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@ -26,7 +28,10 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -170,8 +175,6 @@ public class CaseReviewFunctionalCaseService {
/**
* 用例更新 更新状态为重新评审
*
* @param request
* @param blob
*/
public void reReviewedCase(FunctionalCaseEditRequest request, FunctionalCaseBlob blob, String name) {
ProjectApplicationExample example = new ProjectApplicationExample();
@ -224,4 +227,16 @@ public class CaseReviewFunctionalCaseService {
functionalCase.setReviewStatus(FunctionalCaseReviewStatus.RE_REVIEWED.name());
functionalCaseMapper.updateByPrimaryKeySelective(functionalCase);
}
/**
* 拖拽关联用例的排序
*/
public void editPos(CaseReviewFunctionalCasePosRequest request) {
ServiceUtils.updatePosField(request,
CaseReviewFunctionalCase.class,
caseReviewFunctionalCaseMapper::selectByPrimaryKey,
extCaseReviewFunctionalCaseMapper::getPrePos,
extCaseReviewFunctionalCaseMapper::getLastPos,
caseReviewFunctionalCaseMapper::updateByPrimaryKeySelective);
}
}

View File

@ -1,13 +1,14 @@
package io.metersphere.functional.controller;
import io.metersphere.functional.request.BaseReviewCaseBatchRequest;
import io.metersphere.functional.request.FunctionalCaseAddRequest;
import io.metersphere.functional.request.FunctionalCasePageRequest;
import io.metersphere.functional.request.ReviewFunctionalCasePageRequest;
import io.metersphere.functional.domain.CaseReviewFunctionalCase;
import io.metersphere.functional.domain.CaseReviewFunctionalCaseExample;
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseMapper;
import io.metersphere.functional.request.*;
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.BaseCondition;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
@ -32,6 +33,11 @@ public class CaseReviewFunctionalCaseControllerTests extends BaseTest {
public static final String BATCH_DELETE_URL = "/case/review/detail/batch/disassociate";
public static final String FUNCTIONAL_CASE_ADD_URL = "/functional/case/add";
public static final String REVIEW_FUNCTIONAL_CASE_POS = "/case/review/detail/edit/pos";
@Resource
private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper;
@Test
@Order(1)
public void testGetCaseIds() throws Exception {
@ -129,6 +135,46 @@ public class CaseReviewFunctionalCaseControllerTests extends BaseTest {
Assertions.assertNotNull(resultHolder);
}
@Test
@Order(6)
public void testPos() throws Exception {
List<CaseReviewFunctionalCase> caseReviewList = getCaseReviewFunctionalCase("wx_review_id_1");
CaseReviewFunctionalCase caseReviews = caseReviewList.get(0);
CaseReviewFunctionalCase caseReviews2 = caseReviewList.get(1);
Long pos = caseReviews.getPos();
Long pos2 = caseReviews2.getPos();
CaseReviewFunctionalCasePosRequest posRequest = new CaseReviewFunctionalCasePosRequest();
posRequest.setProjectId("wx_test_project");
posRequest.setTargetId(caseReviews.getId());
posRequest.setMoveId(caseReviews2.getId());
posRequest.setMoveMode("AFTER");
posRequest.setReviewId("wx_review_id_1");
this.requestPostWithOkAndReturn(REVIEW_FUNCTIONAL_CASE_POS, posRequest);
caseReviewList = getCaseReviewFunctionalCase("wx_review_id_1");
caseReviews = caseReviewList.get(1);
caseReviews2 = caseReviewList.get(0);
Long pos3 = caseReviews.getPos();
Long pos4 = caseReviews2.getPos();
Assertions.assertTrue(Objects.equals(pos, pos3));
Assertions.assertTrue(pos2 > pos4);
posRequest.setMoveMode("BEFORE");
this.requestPostWithOkAndReturn(REVIEW_FUNCTIONAL_CASE_POS, posRequest);
caseReviewList = getCaseReviewFunctionalCase("wx_review_id_1");
caseReviews = caseReviewList.get(0);
caseReviews2 = caseReviewList.get(1);
Long pos5 = caseReviews.getPos();
Long pos6 = caseReviews2.getPos();
Assertions.assertTrue(Objects.equals(pos5, pos3));
Assertions.assertTrue(pos6 > pos4);
}
private List<CaseReviewFunctionalCase> getCaseReviewFunctionalCase(String reviewId) {
CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample();
caseReviewFunctionalCaseExample.createCriteria().andReviewIdEqualTo(reviewId);
caseReviewFunctionalCaseExample.setOrderByClause("pos asc");
return caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample);
}
private FunctionalCaseAddRequest creatFunctionalCase() {
FunctionalCaseAddRequest functionalCaseAddRequest = new FunctionalCaseAddRequest();

View File

@ -4,8 +4,13 @@ VALUES ('wx_case_id_1', 100, 'TEST_MODULE_ID', 'wx_test_project', '100001', '测
INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time)
VALUES ('wx_case_id_2', 101, 'TEST_MODULE_ID', 'wx_test_project', '100001', '测试多版本', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL);
INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time)
VALUES ('gyq_case_id_3', 102, 'TEST_MODULE_ID', 'wx_test_project', '100001', '测试多版本', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL);
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('wx_case_id_1', 'STEP', '1111', '', '', 'TEST');
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('wx_case_id_2', 'STEP', '1111', '', '', '1111');
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('gyq_case_id_3', 'STEP', '1111', '', '', '1111');
INSERT INTO functional_case_custom_field(case_id, field_id, value) VALUES ('wx_case_id_1', '100548878725546079', '22');
@ -18,9 +23,10 @@ INSERT INTO case_review(id, num, name, module_id, project_id, status, review_pas
VALUES ('wx_review_id_1',10001,'wx1', 'wx_module_1', 'wx_test_project', 'COMPLETED', 'SINGLE', 001, null, null, 1,100.00,null,null,1698058347559,'admin',1698058347559,'admin'),
('wx_review_id_2',10002,'wx2', 'wx_module_2', 'wx_test_project', 'COMPLETED', 'SINGLE', 001, null, null, 1,100.00,null,null,1698058347559,'admin',1698058347559,'admin');
INSERT INTO case_review_functional_case(id, review_id, case_id, status, create_time, create_user, update_time)
VALUES ('wx_test_1', 'wx_review_id_1', 'wx_case_id_1', 'PASS', 1698058347559,'admin',1698058347559),
('wx_test_2', 'wx_review_id_2', 'wx_case_id_2', 'PASS', 1698058347559,'admin',1698058347559);
INSERT INTO case_review_functional_case(id, review_id, case_id, status, create_time, create_user, update_time, pos)
VALUES ('wx_test_1', 'wx_review_id_1', 'wx_case_id_1', 'PASS', 1698058347559,'admin',1698058347559, 1000),
('gyq_test_3', 'wx_review_id_1', 'gyq_case_id_3', 'PASS', 1698058347559,'admin',1698058347559, 1500),
('wx_test_2', 'wx_review_id_2', 'wx_case_id_2', 'PASS', 1698058347559,'admin',1698058347559, 3000);
INSERT INTO functional_case_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) VALUES ('wx_module_1', 'wx_test_project', '测试所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin');