feat(测试跟踪): 测试计划测试阶段支持添加选项

This commit is contained in:
chenjianxing 2021-11-19 13:03:10 +08:00 committed by jianxing
parent 8957af586b
commit d793d0314f
11 changed files with 78 additions and 37 deletions

View File

@ -1,5 +1,6 @@
package io.metersphere.track.controller; package io.metersphere.track.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page; import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
@ -74,6 +75,11 @@ public class TestPlanController {
return testPlanService.listTestAllPlan(request); return testPlanService.listTestAllPlan(request);
} }
@GetMapping("/get/stage/option/{workspaceId}")
public JSONArray getStageOption(@PathVariable("workspaceId") String workspaceId) {
return testPlanService.getStageOption(workspaceId);
}
@GetMapping("recent/{count}/{id}") @GetMapping("recent/{count}/{id}")
public List<TestPlan> recentTestPlans(@PathVariable("count") int count, @PathVariable("id") String projectId) { public List<TestPlan> recentTestPlans(@PathVariable("count") int count, @PathVariable("id") String projectId) {
PageHelper.startPage(1, count, true); PageHelper.startPage(1, count, true);

View File

@ -125,7 +125,7 @@ public class TestPlanService {
@Resource @Resource
UserMapper userMapper; UserMapper userMapper;
@Resource @Resource
private NoticeSendService noticeSendService; private CustomFieldMapper customFieldMapper;
@Resource @Resource
private SystemParameterService systemParameterService; private SystemParameterService systemParameterService;
@Resource @Resource
@ -2105,4 +2105,23 @@ public class TestPlanService {
public boolean isAllowedRepeatCase(String planId) { public boolean isAllowedRepeatCase(String planId) {
return testPlanMapper.selectByPrimaryKey(planId).getRepeatCase(); return testPlanMapper.selectByPrimaryKey(planId).getRepeatCase();
} }
public JSONArray getStageOption(String workspaceId) {
CustomFieldExample example = new CustomFieldExample();
example.createCriteria()
.andWorkspaceIdEqualTo(workspaceId)
.andSceneEqualTo("PLAN")
.andNameEqualTo("测试阶段");
List<CustomField> customFields = customFieldMapper.selectByExampleWithBLOBs(example);
if (CollectionUtils.isEmpty(customFields)) {
example.clear();
example.createCriteria()
.andGlobalEqualTo(true)
.andSceneEqualTo("PLAN")
.andNameEqualTo("测试阶段");
customFields = customFieldMapper.selectByExampleWithBLOBs(example);
}
return JSONArray.parseArray(customFields.get(0).getOptions());
}
} }

View File

@ -23,3 +23,6 @@ VALUES (UUID(), 'project_group', 'PROJECT_GROUP:READ+SETTING_PERMISSION', 'PROJE
alter table test_plan_load_case alter table test_plan_load_case
add advanced_configuration TEXT null; add advanced_configuration TEXT null;
INSERT INTO custom_field (id,name,scene,`type`,remark,`options`,`system`,`global`,workspace_id,create_time,update_time)
VALUES ('e392af07-fdfe-4475-a459-87d59f0b1625','测试阶段','PLAN','select','','[{"text":"test_track.plan.smoke_test","value":"smoke","system": true},{"text":"test_track.plan.system_test","value":"system","system": true},{"text":"test_track.plan.regression_test","value":"regression","system": true}]',1,1,'global',unix_timestamp() * 1000,unix_timestamp() * 1000);

View File

@ -67,7 +67,7 @@
:label="$t('test_track.plan.plan_stage')" :label="$t('test_track.plan.plan_stage')"
show-overflow-tooltip> show-overflow-tooltip>
<template v-slot:default="scope"> <template v-slot:default="scope">
<plan-stage-table-item :stage="scope.row.stage"/> <plan-stage-table-item :option="stageOption" :stage="scope.row.stage"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -156,6 +156,7 @@ import {_filter, _sort} from "@/common/js/tableUtils";
import EnvPopover from "@/business/components/track/common/EnvPopover"; import EnvPopover from "@/business/components/track/common/EnvPopover";
import TestPlanEdit from "@/business/components/track/plan/components/TestPlanEdit"; import TestPlanEdit from "@/business/components/track/plan/components/TestPlanEdit";
import TestPlansEdit from "@/business/components/api/automation/scenario/testplan/TestPlansEdit"; import TestPlansEdit from "@/business/components/api/automation/scenario/testplan/TestPlansEdit";
import {getPlanStageOption} from "@/network/test-plan";
export default { export default {
name: "TestPlanList", name: "TestPlanList",
@ -203,6 +204,7 @@ export default {
projectList: [], projectList: [],
projectIds: new Set(), projectIds: new Set(),
map: new Map(), map: new Map(),
stageOption: []
} }
}, },
watch: { watch: {
@ -215,6 +217,9 @@ export default {
created() { created() {
this.projectId = this.$route.params.projectId; this.projectId = this.$route.params.projectId;
this.isTestManagerOrTestUser = true; this.isTestManagerOrTestUser = true;
getPlanStageOption((data) => {
this.stageOption = data;
});
this.initTableData(); this.initTableData();
this.setScenarioSelectRows(this.row); this.setScenarioSelectRows(this.row);
this.getWsProjects(); this.getWsProjects();

View File

@ -38,7 +38,7 @@
v-model="element.value"/> v-model="element.value"/>
<span class="text-item" v-else> <span class="text-item" v-else>
<span v-if="element.system"> <span v-if="element.system">
{{$t(element.value)}} {{$t(element.text)}}
</span> </span>
<span v-else> <span v-else>
{{ (element.value && isKv ? '(' : '') + element.value + (element.value && isKv ? ')' : '')}} {{ (element.value && isKv ? '(' : '') + element.value + (element.value && isKv ? ')' : '')}}

View File

@ -20,7 +20,7 @@
<el-form-item :label="$t('custom_field.scene')" prop="type" :label-width="labelWidth"> <el-form-item :label="$t('custom_field.scene')" prop="type" :label-width="labelWidth">
<el-select :disabled="isSystem || isTemplateEdit" filterable v-model="form.scene" :placeholder="$t('custom_field.scene')"> <el-select :disabled="isSystem || isTemplateEdit" filterable v-model="form.scene" :placeholder="$t('custom_field.scene')">
<el-option <el-option
v-for="item in sceneOptions" v-for="item in (form.scene === 'PLAN' ? planSceneOptions : sceneOptions)"
:key="item.value" :key="item.value"
:label="item.text" :label="item.text"
:value="item.value"> :value="item.value">
@ -59,6 +59,7 @@ import MsEditDialog from "@/business/components/common/components/MsEditDialog";
import MsSingleHandleDrag from "@/business/components/common/components/MsSingleHandleDrag"; import MsSingleHandleDrag from "@/business/components/common/components/MsSingleHandleDrag";
import {getCurrentWorkspaceId} from "@/common/js/utils"; import {getCurrentWorkspaceId} from "@/common/js/utils";
import {CUSTOM_FIELD_SCENE_OPTION, CUSTOM_FIELD_TYPE_OPTION, SYSTEM_FIELD_NAME_MAP} from "@/common/js/table-constants"; import {CUSTOM_FIELD_SCENE_OPTION, CUSTOM_FIELD_TYPE_OPTION, SYSTEM_FIELD_NAME_MAP} from "@/common/js/table-constants";
import i18n from "@/i18n/i18n";
export default { export default {
name: "CustomFieldEdit", name: "CustomFieldEdit",
components: {MsSingleHandleDrag, MsEditDialog}, components: {MsSingleHandleDrag, MsEditDialog},
@ -92,6 +93,11 @@ export default {
sceneOptions() { sceneOptions() {
return CUSTOM_FIELD_SCENE_OPTION; return CUSTOM_FIELD_SCENE_OPTION;
}, },
planSceneOptions() {
let tmp = [...CUSTOM_FIELD_SCENE_OPTION];
tmp.push( {value: 'PLAN',text: i18n.t('workstation.table_name.track_plan')});//
return tmp;
},
showOptions() { showOptions() {
if (['select', 'multipleSelect', 'radio', 'checkbox'].indexOf(this.form.type) > -1) { if (['select', 'multipleSelect', 'radio', 'checkbox'].indexOf(this.form.type) > -1) {
return true; return true;

View File

@ -1,11 +1,10 @@
<template> <template>
<div> <div>
<span v-if="stage == 'smoke'">{{$t('test_track.plan.smoke_test')}}</span> <span v-for="item in option" :key="item.value">
<span v-if="stage == 'functional'">{{$t('test_track.plan.functional_test')}}</span> <span v-if="stage == item.value">
<span v-if="stage == 'integration'">{{$t('test_track.plan.integration_testing')}}</span> {{$t(item.text)}}
<span v-if="stage == 'system'">{{$t('test_track.plan.system_test')}}</span> </span>
<span v-if="stage == 'regression'">{{$t('test_track.plan.regression_test')}}</span> </span>
<span v-if="stage == 'version'">{{$t('test_track.plan.version_validation')}}</span>
</div> </div>
</template> </template>
@ -16,7 +15,8 @@
props: { props: {
stage: { stage: {
type: String type: String
} },
option: []
} }
} }
</script> </script>

View File

@ -47,9 +47,7 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="$t('test_track.plan.plan_stage')" :label-width="formLabelWidth" prop="stage"> <el-form-item :label="$t('test_track.plan.plan_stage')" :label-width="formLabelWidth" prop="stage">
<el-select v-model="form.stage" clearable :placeholder="$t('test_track.plan.input_plan_stage')" style="width: 100%;" :size="itemSize"> <el-select v-model="form.stage" clearable :placeholder="$t('test_track.plan.input_plan_stage')" style="width: 100%;" :size="itemSize">
<el-option :label="$t('test_track.plan.smoke_test')" value="smoke"></el-option> <el-option v-for="item in stageOption" :key="item.value" :label="$t(item.text)" :value="item.value"/>
<el-option :label="$t('test_track.plan.system_test')" value="system"></el-option>
<el-option :label="$t('test_track.plan.regression_test')" value="regression"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -100,24 +98,6 @@
</el-col> </el-col>
</el-row> </el-row>
<!-- <el-row type="flex" justify="left" :gutter="20">
<el-col :span="12">
<el-form-item :label="$t('test_track.plan.follow_people')" :label-width="formLabelWidth"
prop="follows">
<el-select v-model="form.follows"
clearable
:placeholder="$t('test_track.plan.follow_people')" filterable multiple size="small">
<el-option
v-for="(item) in principalOptions"
:key="item.id"
:label="item.name + '(' + item.id + ')'"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>-->
<el-row type="flex" justify="left" :gutter="20"> <el-row type="flex" justify="left" :gutter="20">
<el-col :span="24"> <el-col :span="24">
<el-form-item :label="$t('commons.description')" :label-width="formLabelWidth" prop="description"> <el-form-item :label="$t('commons.description')" :label-width="formLabelWidth" prop="description">
@ -173,6 +153,7 @@ import TestPlanStatusButton from "../common/TestPlanStatusButton";
import {getCurrentProjectID, getCurrentWorkspaceId, listenGoBack, removeGoBackListener} from "@/common/js/utils"; import {getCurrentProjectID, getCurrentWorkspaceId, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag"; import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag";
import MsInstructionsIcon from "@/business/components/common/components/MsInstructionsIcon"; import MsInstructionsIcon from "@/business/components/common/components/MsInstructionsIcon";
import {getPlanStageOption} from "@/network/test-plan";
export default { export default {
name: "TestPlanEdit", name: "TestPlanEdit",
@ -207,11 +188,15 @@ export default {
formLabelWidth: "100px", formLabelWidth: "100px",
operationType: '', operationType: '',
principalOptions: [], principalOptions: [],
stageOption: []
}; };
}, },
created() { created() {
// //
this.form.stage = 'smoke'; this.form.stage = 'smoke';
getPlanStageOption((data) => {
this.stageOption = data;
});
}, },
methods: { methods: {
reload() { reload() {

View File

@ -92,7 +92,7 @@
:min-width="110" :min-width="110"
:key="index"> :key="index">
<template v-slot:default="scope"> <template v-slot:default="scope">
<plan-stage-table-item :stage="scope.row.stage"/> <plan-stage-table-item :option="stageOption" :stage="scope.row.stage"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -274,10 +274,16 @@ import HeaderCustom from "@/business/components/common/head/HeaderCustom";
import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOperate"; import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOperate";
import MsTag from "@/business/components/common/components/MsTag"; import MsTag from "@/business/components/common/components/MsTag";
import MsTestPlanScheduleMaintain from "@/business/components/track/plan/components/ScheduleMaintain"; import MsTestPlanScheduleMaintain from "@/business/components/track/plan/components/ScheduleMaintain";
import {getCurrentProjectID, getCurrentUser, getCurrentUserId, hasPermission} from "@/common/js/utils"; import {
getCurrentProjectID,
getCurrentUser,
getCurrentUserId,
hasPermission
} from "@/common/js/utils";
import PlanRunModeWithEnv from "@/business/components/track/plan/common/PlanRunModeWithEnv"; import PlanRunModeWithEnv from "@/business/components/track/plan/common/PlanRunModeWithEnv";
import TestPlanReportReview from "@/business/components/track/report/components/TestPlanReportReview"; import TestPlanReportReview from "@/business/components/track/report/components/TestPlanReportReview";
import MsTaskCenter from "@/business/components/task/TaskCenter"; import MsTaskCenter from "@/business/components/task/TaskCenter";
import {getPlanStageOption} from "@/network/test-plan";
export default { export default {
name: "TestPlanList", name: "TestPlanList",
@ -326,7 +332,8 @@ export default {
{text: this.$t('test_track.plan.system_test'), value: 'system'}, {text: this.$t('test_track.plan.system_test'), value: 'system'},
{text: this.$t('test_track.plan.regression_test'), value: 'regression'}, {text: this.$t('test_track.plan.regression_test'), value: 'regression'},
], ],
currentPlanId: "" currentPlanId: "",
stageOption: []
}; };
}, },
watch: { watch: {
@ -343,7 +350,9 @@ export default {
} }
this.hasEditPermission = hasPermission('PROJECT_TRACK_PLAN:READ+EDIT'); this.hasEditPermission = hasPermission('PROJECT_TRACK_PLAN:READ+EDIT');
this.condition.orders = getLastTableSortField(this.tableHeaderKey); this.condition.orders = getLastTableSortField(this.tableHeaderKey);
getPlanStageOption((data) => {
this.stageOption = data;
});
this.initTableData(); this.initTableData();
}, },
methods: { methods: {

View File

@ -50,7 +50,8 @@ export const FIELD_TYPE_MAP = {
export const SCENE_MAP = { export const SCENE_MAP = {
ISSUE: 'workspace.issue_template_manage', ISSUE: 'workspace.issue_template_manage',
TEST_CASE: 'workspace.case_template_manage' TEST_CASE: 'workspace.case_template_manage',
PLAN: 'workstation.table_name.track_plan'
}; };
export const SYSTEM_FIELD_NAME_MAP = { export const SYSTEM_FIELD_NAME_MAP = {
@ -63,6 +64,8 @@ export const SYSTEM_FIELD_NAME_MAP = {
处理人: 'custom_field.issue_processor', 处理人: 'custom_field.issue_processor',
状态: 'custom_field.issue_status', 状态: 'custom_field.issue_status',
严重程度: 'custom_field.issue_severity', 严重程度: 'custom_field.issue_severity',
// 测试计划
测试阶段: 'test_track.plan.plan_stage'
} }

View File

@ -2,6 +2,7 @@ import {post, get} from "@/common/js/ajax";
import {success} from "@/common/js/message"; import {success} from "@/common/js/message";
import i18n from "@/i18n/i18n"; import i18n from "@/i18n/i18n";
import {baseGet, basePost} from "@/network/base-network"; import {baseGet, basePost} from "@/network/base-network";
import {getCurrentWorkspaceId} from "@/common/js/utils";
export function getTestPlanReport(planId, callback) { export function getTestPlanReport(planId, callback) {
if (planId) { if (planId) {
@ -139,3 +140,7 @@ export function editTestPlanScenarioCaseOrder(request, callback) {
export function editTestPlanLoadCaseOrder(request, callback) { export function editTestPlanLoadCaseOrder(request, callback) {
return basePost('/test/plan/load/case/edit/order', request, callback); return basePost('/test/plan/load/case/edit/order', request, callback);
} }
export function getPlanStageOption(callback) {
return baseGet('/test/plan/get/stage/option/' + getCurrentWorkspaceId(), callback);
}