fix(测试跟踪): 功能用例脑图保存遮罩

This commit is contained in:
baiqi 2024-11-11 11:44:18 +08:00 committed by Craftsman
parent 197a6a7d9e
commit e8c7978301
2 changed files with 519 additions and 303 deletions

View File

@ -1,24 +1,49 @@
<template>
<ms-container v-if="renderComponent" v-loading="loading">
<!-- operate-button -->
<div class="top-btn-group-layout" v-if="!showPublicNode && !showTrashNode" style="margin-bottom: 16px">
<el-button size="small" v-permission="['PROJECT_TRACK_CASE:READ+CREATE']" @click="handleCreateCase" type="primary">
<svg-icon icon-class="icon_add_outlined_white"/>
{{$t('test_track.case.create_case')}}
<div
class="top-btn-group-layout"
v-if="!showPublicNode && !showTrashNode"
style="margin-bottom: 16px"
>
<el-button
size="small"
v-permission="['PROJECT_TRACK_CASE:READ+CREATE']"
@click="handleCreateCase"
type="primary"
>
<svg-icon icon-class="icon_add_outlined_white" />
{{ $t("test_track.case.create_case") }}
</el-button>
<el-dropdown @command="handleImportCommand" placement="bottom-start" style="margin-left: 12px" class="btn-dropdown">
<el-button size="small" v-permission="['PROJECT_TRACK_CASE:READ+IMPORT']">
<svg-icon icon-class="icon_upload_outlined"/>
{{$t('commons.import')}}
<el-dropdown
@command="handleImportCommand"
placement="bottom-start"
style="margin-left: 12px"
class="btn-dropdown"
>
<el-button
size="small"
v-permission="['PROJECT_TRACK_CASE:READ+IMPORT']"
>
<svg-icon icon-class="icon_upload_outlined" />
{{ $t("commons.import") }}
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="excel">
<span class="export-model">{{$t('test_track.case.import.import_by_excel')}}</span>
<span class="export-tips">{{$t('test_track.case.export.export_to_excel_tips1')}}</span>
<span class="export-model">{{
$t("test_track.case.import.import_by_excel")
}}</span>
<span class="export-tips">{{
$t("test_track.case.export.export_to_excel_tips1")
}}</span>
</el-dropdown-item>
<el-dropdown-item style="margin-top: 10px" command="xmind" divided>
<span class="export-model">{{$t('test_track.case.import.import_by_xmind')}}</span>
<span class="export-tips">{{$t('test_track.case.export.export_to_xmind_tips')}}</span>
<span class="export-model">{{
$t("test_track.case.import.import_by_xmind")
}}</span>
<span class="export-tips">{{
$t("test_track.case.export.export_to_xmind_tips")
}}</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
@ -26,20 +51,31 @@
<!-- public, trash back header -->
<div v-show="showPublicNode || showTrashNode" class="back-layout">
<i class="el-icon-back" style="float: left;position: relative;top: 15px;left: 21px;" @click="backDefault"/>
<span class="back-content">{{showPublicNode? $t('project.case_public') : $t('commons.trash')}}</span>
<i
class="el-icon-back"
style="float: left; position: relative; top: 15px; left: 21px"
@click="backDefault"
/>
<span class="back-content">{{
showPublicNode ? $t("project.case_public") : $t("commons.trash")
}}</span>
</div>
<div style="display: flex; height: calc(100vh - 130px)" class = "test-case-aside-layout">
<div
style="display: flex; height: calc(100vh - 130px)"
class="test-case-aside-layout"
>
<!-- case-aside-container -->
<ms-aside-container v-show="isAsideHidden"
page-key="TEST_CASE_LIST"
:enable-remember-width="true"
:min-width="'0'"
:enable-aside-hidden.sync="enableAsideHidden">
<ms-aside-container
v-show="isAsideHidden"
page-key="TEST_CASE_LIST"
:enable-remember-width="true"
:min-width="'0'"
:enable-aside-hidden.sync="enableAsideHidden"
>
<test-case-node-tree
:type="'edit'"
:total='total'
:total="total"
:show-operator="false"
:public-total="publicTotal"
:case-condition="condition"
@ -54,7 +90,8 @@
@importChangeConfirm="importChangeConfirm"
@createCase="handleCaseSimpleCreate($event, 'add')"
@nodeSelectEvent="handleCaseNodeSelect"
ref="nodeTree"/>
ref="nodeTree"
/>
</ms-aside-container>
<!-- public-case-aside-container -->
@ -63,7 +100,8 @@
:show-operator="false"
:case-condition="publicCondition"
@nodeSelectEvent="publicNodeChange"
ref="publicNodeTree"/>
ref="publicNodeTree"
/>
</ms-aside-container>
<!-- trash-case-aside-container -->
@ -72,7 +110,8 @@
:show-operator="false"
:case-condition="trashCondition"
@nodeSelectEvent="trashNodeChange"
ref="trashNodeTree"/>
ref="trashNodeTree"
/>
</ms-aside-container>
<!-- case-main-container -->
@ -86,7 +125,8 @@
:right-tip="$t('test_track.case.minder')"
:right-icon-class="'icon_mindnote_outlined'"
:right-icon-active-class="'icon_mindnote_outlined_active'"
:middle-button-enable="false">
:middle-button-enable="false"
>
<test-case-list
v-if="activeDom === 'left'"
:isRedirectEdit="isRedirectEdit"
@ -103,24 +143,25 @@
@setCondition="setCondition"
@decrease="decrease"
@refreshTree="refreshTreeByCaseFilter"
ref="testCaseList">
ref="testCaseList"
>
</test-case-list>
<test-case-minder
v-if="isMinderMode"
:default-version="currentVersion"
:tree-nodes="treeNodes"
:project-id="projectId"
:condition="condition"
:active-name="activeName"
@versionChange="changeVersion"
@refresh="minderSaveRefresh"
@toggleMinderFullScreen="toggleMinderFullScreen"
ref="minder"/>
<div v-if="isMinderMode" style="height: 100%">
<test-case-minder
:default-version="currentVersion"
:tree-nodes="treeNodes"
:project-id="projectId"
:condition="condition"
:active-name="activeName"
@versionChange="changeVersion"
@refresh="minderSaveRefresh"
@toggleMinderFullScreen="toggleMinderFullScreen"
ref="minder"
/>
</div>
</ms-tab-button>
<is-change-confirm
@confirm="changeConfirm"
ref="isChangeConfirm"/>
<is-change-confirm @confirm="changeConfirm" ref="isChangeConfirm" />
</ms-main-container>
<!-- public-main-container -->
@ -135,7 +176,8 @@
@refreshPublic="refreshPublic"
@setCondition="setPublicCondition"
@refreshTree="refreshTreeByCaseFilter"
ref="testCasePublicList"/>
ref="testCasePublicList"
/>
</el-card>
</ms-main-container>
@ -152,14 +194,15 @@
@refreshAll="refreshAll"
@setCondition="setTrashCondition"
@refreshTree="refreshTreeByCaseFilter"
ref="testCaseTrashList">
ref="testCaseTrashList"
>
</test-case-list>
</el-card>
</ms-main-container>
</div>
<!-- import case -->
<test-case-common-import-new ref="caseImport" @refreshAll="refreshAll"/>
<test-case-common-import-new ref="caseImport" @refreshAll="refreshAll" />
</ms-container>
</template>
@ -171,32 +214,53 @@ import MsContainer from "metersphere-frontend/src/components/new-ui/MsContainer"
import MsAsideContainer from "metersphere-frontend/src/components/new-ui/MsAsideContainer";
import MsMainContainer from "metersphere-frontend/src/components/new-ui/MsMainContainer";
import MsMainButtonGroup from "metersphere-frontend/src/components/new-ui/MsMainButtonGroup";
import {getCurrentProjectID, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
import {hasLicense, hasPermission} from "metersphere-frontend/src/utils/permission";
import {
getCurrentProjectID,
getCurrentWorkspaceId,
} from "metersphere-frontend/src/utils/token";
import {
hasLicense,
hasPermission,
} from "metersphere-frontend/src/utils/permission";
import TestCaseNodeTree from "@/business/module/TestCaseNodeTree";
import MsTabButton from "metersphere-frontend/src/components/new-ui/MsTabButton";
import TestCaseMinder from "../common/minder/TestCaseMinder";
import IsChangeConfirm from "metersphere-frontend/src/components/IsChangeConfirm";
import {openMinderConfirm} from "../common/minder/minderUtils";
import {PROJECT_ID} from "metersphere-frontend/src/utils/constants";
import { openMinderConfirm } from "../common/minder/minderUtils";
import { PROJECT_ID } from "metersphere-frontend/src/utils/constants";
import MxVersionSelect from "metersphere-frontend/src/components/version/MxVersionSelect";
import {useStore} from "@/store";
import {testCaseNodePublicCount, testCaseNodeTrashCount} from "@/api/test-case-node";
import {getProjectApplicationConfig} from "@/api/project-application";
import {versionEnableByProjectId} from "@/api/project";
import { useStore } from "@/store";
import {
testCaseNodePublicCount,
testCaseNodeTrashCount,
} from "@/api/test-case-node";
import { getProjectApplicationConfig } from "@/api/project-application";
import { versionEnableByProjectId } from "@/api/project";
import TestCasePublicNodeTree from "@/business/module/TestCasePublicNodeTree";
import TestCaseTrashNodeTree from "@/business/module/TestCaseTrashNodeTree";
import PublicTestCaseList from "@/business/case/components/public/PublicTestCaseList";
import {openCaseCreate} from "@/business/case/test-case";
import merge from 'webpack-merge';
import { openCaseCreate } from "@/business/case/test-case";
import merge from "webpack-merge";
const store = useStore();
export default {
name: "TestCase",
components: {
PublicTestCaseList, TestCaseTrashNodeTree, TestCasePublicNodeTree, IsChangeConfirm, TestCaseMinder, MsTabButton, TestCaseNodeTree,
MsMainContainer, MsAsideContainer, MsContainer, TestCaseList, SelectMenu, 'VersionSelect': MxVersionSelect,
MsMainButtonGroup, TestCaseCommonImportNew
PublicTestCaseList,
TestCaseTrashNodeTree,
TestCasePublicNodeTree,
IsChangeConfirm,
TestCaseMinder,
MsTabButton,
TestCaseNodeTree,
MsMainContainer,
MsAsideContainer,
MsContainer,
TestCaseList,
SelectMenu,
VersionSelect: MxVersionSelect,
MsMainButtonGroup,
TestCaseCommonImportNew,
},
comments: {},
data() {
@ -211,12 +275,12 @@ export default {
condition: {},
trashCondition: {},
publicCondition: {},
activeName: 'default',
currentActiveName: '',
activeName: "default",
currentActiveName: "",
renderComponent: true,
loading: false,
type: '',
activeDom: 'left',
type: "",
activeDom: "left",
tmpActiveDom: null,
total: 0,
publicTotal: 0,
@ -227,14 +291,14 @@ export default {
isAsideHidden: true,
ignoreTreeNodes: false,
hasRefreshDefault: true,
enableAsideHidden: false
enableAsideHidden: false,
};
},
created() {
let projectId = this.$route.params.projectId;
if (projectId) {
this.ignoreTreeNodes = true;
if (projectId !== getCurrentProjectID() && projectId !== 'all') {
if (projectId !== getCurrentProjectID() && projectId !== "all") {
sessionStorage.setItem(PROJECT_ID, projectId);
}
}
@ -254,11 +318,11 @@ export default {
},
watch: {
activeName(newVal, oldVal) {
this.isAsideHidden = this.activeName === 'default';
if (oldVal !== 'default' && newVal === 'default' && this.$refs.minder) {
this.isAsideHidden = this.activeName === "default";
if (oldVal !== "default" && newVal === "default" && this.$refs.minder) {
this.$refs.minder.refresh();
}
if (oldVal === 'trash' && newVal === 'default') {
if (oldVal === "trash" && newVal === "default") {
this.condition.filters.status = [];
//
if (!this.hasRefreshDefault) {
@ -267,13 +331,13 @@ export default {
} else {
this.refresh();
}
} else if (newVal === 'default') {
} else if (newVal === "default") {
this.refresh();
}
},
trashEnable() {
if (this.trashEnable) {
this.activeName = 'trash';
this.activeName = "trash";
this.publicEnable = false;
this.$nextTick(() => {
this.$refs.trashNodeTree.list();
@ -282,31 +346,31 @@ export default {
},
publicEnable() {
if (this.publicEnable) {
this.activeName = 'public';
this.activeName = "public";
this.$nextTick(() => {
this.$refs.publicNodeTree.list();
});
this.trashEnable = false;
}
},
'$store.state.temWorkspaceId'() {
"$store.state.temWorkspaceId"() {
if (this.$store.state.temWorkspaceId) {
this.$refs.isChangeConfirm.open(null, this.$store.state.temWorkspaceId);
}
},
routeModuleId() {
return this.$route.query.moduleId;
}
},
},
computed: {
isRedirectEdit: function () {
return this.$route.params.dataSelectRange;
},
showPublicNode() {
return this.activeName === 'public';
return this.activeName === "public";
},
showTrashNode() {
return this.activeName === 'trash';
return this.activeName === "trash";
},
projectId() {
return getCurrentProjectID();
@ -321,16 +385,22 @@ export default {
return store.testCaseModuleOptions;
},
isMinderMode() {
return this.activeDom === 'right';
}
return this.activeDom === "right";
},
},
methods: {
hasPermission,
handleCreateCase(){
openCaseCreate({
projectId: this.projectId,
createNodeId: this.selectNode.data && this.selectNode.data.id !== 'root' ? this.selectNode.data.id : ""
}, this);
handleCreateCase() {
openCaseCreate(
{
projectId: this.projectId,
createNodeId:
this.selectNode.data && this.selectNode.data.id !== "root"
? this.selectNode.data.id
: "",
},
this
);
},
handleImportCommand(e) {
switch (e) {
@ -343,19 +413,17 @@ export default {
}
},
getTrashList() {
testCaseNodeTrashCount(this.projectId)
.then(response => {
this.total = response.data;
});
testCaseNodeTrashCount(this.projectId).then((response) => {
this.total = response.data;
});
},
getPublicList() {
testCaseNodePublicCount(getCurrentWorkspaceId())
.then(response => {
this.publicTotal = response.data;
});
testCaseNodePublicCount(getCurrentWorkspaceId()).then((response) => {
this.publicTotal = response.data;
});
},
updateActiveDom(activeDom) {
openMinderConfirm(this, activeDom, 'PROJECT_TRACK_CASE:READ');
openMinderConfirm(this, activeDom, "PROJECT_TRACK_CASE:READ");
},
importChangeConfirm(isSave) {
store.isTestCaseMinderChanged = false;
@ -382,7 +450,7 @@ export default {
this.$nextTick(() => {
if (this.tmpPath) {
this.$router.push({
path: this.tmpPath
path: this.tmpPath,
});
this.tmpPath = null;
}
@ -390,12 +458,12 @@ export default {
if (temWorkspaceId) {
//
this.$EventBus.$emit('changeWs', temWorkspaceId);
this.$EventBus.$emit("changeWs", temWorkspaceId);
}
},
validateProjectId() {
if (!this.projectId) {
this.$warning(this.$t('commons.check_project_tip'));
this.$warning(this.$t("commons.check_project_tip"));
return false;
}
return true;
@ -413,7 +481,7 @@ export default {
handleCaseNodeSelect(node, nodeIds, pNodes) {
if (node.data.id !== this.routeModuleId) {
this.$router.push({
query: merge(this.$route.query, {'moduleId': node.data.id})
query: merge(this.$route.query, { moduleId: node.data.id }),
});
}
},
@ -429,10 +497,10 @@ export default {
}
},
handleCaseSimpleCreate(data, type) {
if ('default-module' === data.nodeId) {
if ("default-module" === data.nodeId) {
for (let i = 0; i < this.moduleOptions.length; i++) {
let item = this.moduleOptions[i];
if (item.path.indexOf('未规划用例') > -1) {
if (item.path.indexOf("未规划用例") > -1) {
data.nodeId = item.id;
break;
}
@ -469,7 +537,7 @@ export default {
if (this.$refs.testCaseList) {
this.$refs.testCaseList.initTableData();
}
if(this.$refs.nodeTree){
if (this.$refs.nodeTree) {
this.$refs.nodeTree.list();
}
},
@ -477,8 +545,8 @@ export default {
this.refreshAll();
if (this.$refs.testCaseEdit && this.$refs.testCaseEdit.length > 0) {
setTimeout(() => {
this.$info(this.$t('test_track.case.import.import_refresh_tips'));
}, 3000)
this.$info(this.$t("test_track.case.import.import_refresh_tips"));
}, 3000);
}
},
minderSaveRefresh() {
@ -489,7 +557,6 @@ export default {
},
toggleMinderFullScreen(isFullScreen) {
this.enableAsideHidden = isFullScreen;
},
refreshPublic() {
if (this.$refs.testCasePublicList) {
@ -510,24 +577,23 @@ export default {
this.condition = data;
},
getProject() {
getProjectApplicationConfig('CASE_CUSTOM_NUM')
.then(result => {
let data = result.data;
if (data && data.typeValue === 'true') {
store.currentProjectIsCustomNum = true;
} else {
store.currentProjectIsCustomNum = false;
}
});
getProjectApplicationConfig("CASE_CUSTOM_NUM").then((result) => {
let data = result.data;
if (data && data.typeValue === "true") {
store.currentProjectIsCustomNum = true;
} else {
store.currentProjectIsCustomNum = false;
}
});
},
backDefault() {
//
this.activeName = 'default';
this.activeName = "default";
this.trashEnable = false;
this.publicEnable = false;
//
this.$router.push({
query: merge(this.$route.query, {'moduleId': 'root'})
query: merge(this.$route.query, { moduleId: "root" }),
});
},
enableTrash(data) {
@ -535,20 +601,20 @@ export default {
this.trashEnable = !data;
this.$nextTick(() => {
this.trashEnable = data;
})
});
},
enablePublic(data) {
//
this.publicEnable = !data;
this.$nextTick(() => {
this.publicEnable = data;
})
});
},
toPublic(data) {
if (data === 'public') {
this.activeName = "public"
if (data === "public") {
this.activeName = "public";
} else {
this.activeName = "trash"
this.activeName = "trash";
}
},
changeVersion(currentVersion) {
@ -559,18 +625,18 @@ export default {
return;
}
if (hasLicense()) {
versionEnableByProjectId(this.projectId)
.then(response => {
this.versionEnable = response.data;
});
versionEnableByProjectId(this.projectId).then((response) => {
this.versionEnable = response.data;
});
}
},
}
},
};
</script>
<style scoped>
<style lang="scss" scoped>
:deep(.el-card__body) {
height: -webkit-fill-available;
padding: 24px;
}
@ -604,14 +670,14 @@ export default {
}
.export-model {
font-family: 'PingFang SC';
font-family: "PingFang SC";
font-style: normal;
font-weight: 400;
font-size: 14px;
line-height: 22px;
display: flex;
align-items: center;
color: #1F2329;
color: #1f2329;
flex: none;
order: 0;
align-self: stretch;
@ -619,14 +685,14 @@ export default {
}
.export-tips {
font-family: 'PingFang SC';
font-family: "PingFang SC";
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 20px;
display: block;
align-items: center;
color: #8F959E;
color: #8f959e;
flex: none;
order: 1;
align-self: stretch;
@ -635,13 +701,13 @@ export default {
/* 创建用例按钮样式 */
.el-button--small {
height: 32px;
border-radius: 4px;
height: 32px;
border-radius: 4px;
}
.back-layout {
height: 48px;
background-color: #FFFFFF;;
background-color: #ffffff;
border-bottom: 1px solid rgba(31, 35, 41, 0.15);
border-radius: 4px 4px 0 0;
}
@ -652,12 +718,12 @@ export default {
left: 35px;
width: 80px;
height: 24px;
font-family: 'PingFang SC';
font-family: "PingFang SC";
font-style: normal;
font-weight: 500;
font-size: 16px;
line-height: 24px;
color: #1F2329;
color: #1f2329;
flex: none;
order: 1;
flex-grow: 0;
@ -677,7 +743,7 @@ export default {
.back-layout :deep(.el-button--small span),
.top-btn-group-layout :deep(.el-button--small span),
.export-case-layout :deep(.el-button--small span) {
font-family: 'PingFang SC';
font-family: "PingFang SC";
font-style: normal;
font-weight: 400;
font-size: 14px;
@ -685,8 +751,8 @@ export default {
position: relative;
top: -5px;
}
.edit-layout :deep(.el-button--small span){
font-family: 'PingFang SC';
.edit-layout :deep(.el-button--small span) {
font-family: "PingFang SC";
font-style: normal;
font-weight: 400;
font-size: 14px;
@ -702,6 +768,9 @@ export default {
}
.el-dropdown-menu__item:hover {
background-color: rgba(31, 35, 41, 0.1)!important;
background-color: rgba(31, 35, 41, 0.1) !important;
}
.card-content {
height: 100% !important;
}
</style>

View File

@ -1,52 +1,58 @@
<template>
<div>
<div style="height: 100%">
<div class="case-main-layout-left" style="display: inline-block">
<ms-table-count-bar :count-content="$t('case.all_case_content') + '(' + caseNum + ')'"></ms-table-count-bar>
<ms-table-count-bar
:count-content="$t('case.all_case_content') + '(' + caseNum + ')'"
></ms-table-count-bar>
</div>
<div class="case-main-layout-right" style="float: right; display: flex">
<version-select v-xpack :default-version="defaultVersion" :project-id="projectId" @changeVersion="changeVersion" />
<version-select
v-xpack
:default-version="defaultVersion"
:project-id="projectId"
@changeVersion="changeVersion"
/>
</div>
<ms-module-minder
v-loading="result.loading"
minder-key="TEST_CASE"
:tree-nodes="treeNodes"
:tags="tags"
:select-node="selectNode"
:distinct-tags="tags"
:module-disable="false"
:show-module-tag="true"
:move-confirm="moveConfirm"
:tag-edit-check="tagEditCheck()"
:priority-disable-check="priorityDisableCheck()"
:disabled="disabled"
:get-extra-node-count="getMinderTreeExtraNodeCount()"
:del-confirm="handleDeleteConfirm"
@afterMount="handleAfterMount"
@toggleMinderFullScreen="toggleMinderFullScreen"
@save="save"
ref="minder"
/>
<div style="height: 100%" v-loading="true">
<ms-module-minder
minder-key="TEST_CASE"
:tree-nodes="treeNodes"
:tags="tags"
:select-node="selectNode"
:distinct-tags="tags"
:module-disable="false"
:show-module-tag="true"
:move-confirm="moveConfirm"
:tag-edit-check="tagEditCheck()"
:priority-disable-check="priorityDisableCheck()"
:disabled="disabled"
:get-extra-node-count="getMinderTreeExtraNodeCount()"
:del-confirm="handleDeleteConfirm"
@afterMount="handleAfterMount"
@toggleMinderFullScreen="toggleMinderFullScreen"
@save="save"
ref="minder"
/>
</div>
<IssueRelateList
:case-id="getCurCaseId()"
@refresh="refreshRelateIssue"
ref="issueRelate"/>
ref="issueRelate"
/>
<test-plan-issue-edit
:is-minder="true"
:plan-id="null"
:case-id="getCurCaseId()"
@refresh="refreshIssue"
ref="issueEdit"/>
<is-change-confirm
@confirm="changeConfirm"
ref="isChangeConfirm"/>
ref="issueEdit"
/>
<is-change-confirm @confirm="changeConfirm" ref="isChangeConfirm" />
</div>
</template>
<script>
@ -54,7 +60,10 @@ import {
getChildNodeId,
handleAfterSave,
handleExpandToLevel,
handleMinderIssueDelete, handlePasteAfter, handlePasteTip, handleSaveError,
handleMinderIssueDelete,
handlePasteAfter,
handlePasteTip,
handleSaveError,
handleTestCaseAdd,
handTestCaeEdit,
isCaseNodeData,
@ -62,44 +71,60 @@ import {
isModuleNodeData,
listenBeforeExecCommand,
listenDblclick,
listenNodeSelected, loadNode,
listenNodeSelected,
loadNode,
loadSelectNodes,
priorityDisableCheck,
tagEditCheck,
} from "@/business/common/minder/minderUtils";
import {getNodePath, getUUID} from "metersphere-frontend/src/utils";
import {hasPermission} from "metersphere-frontend/src/utils/permission";
import { getNodePath, getUUID } from "metersphere-frontend/src/utils";
import { hasPermission } from "metersphere-frontend/src/utils/permission";
import {
getTestCasesForMinder,
getMinderExtraNode,
getMinderTreeExtraNodeCount,
testCaseMinderEdit
testCaseMinderEdit,
} from "@/api/testCase";
import {addIssueHotBox, getSelectedNodeData, handleIssueAdd, handleIssueBatch} from "./minderUtils";
import {
addIssueHotBox,
getSelectedNodeData,
handleIssueAdd,
handleIssueBatch,
} from "./minderUtils";
import IssueRelateList from "@/business/case/components/IssueRelateList";
import TestPlanIssueEdit from "@/business/case/components/TestPlanIssueEdit";
import {setPriorityView} from "vue-minder-editor-plus/src/script/tool/utils";
import { setPriorityView } from "vue-minder-editor-plus/src/script/tool/utils";
import IsChangeConfirm from "metersphere-frontend/src/components/IsChangeConfirm";
import MsModuleMinder from "@/business/common/minder/MsModuleMinder";
import MsTableCountBar from 'metersphere-frontend/src/components/table/MsTableCountBar';
import MsTableCountBar from "metersphere-frontend/src/components/table/MsTableCountBar";
import MxVersionSelect from "metersphere-frontend/src/components/version/MxVersionSelect";
import {useStore} from "@/store"
import {mapState} from "pinia";
import {getCurrentWorkspaceId} from "@/business/utils/sdk-utils";
import {getIssuesForMinder} from "@/api/issue";
import { useStore } from "@/store";
import { mapState } from "pinia";
import { getCurrentWorkspaceId } from "@/business/utils/sdk-utils";
import { getIssuesForMinder } from "@/api/issue";
export default {
name: "TestCaseMinder",
components: {MsModuleMinder, IsChangeConfirm, TestPlanIssueEdit, IssueRelateList, MsTableCountBar, 'VersionSelect': MxVersionSelect},
components: {
MsModuleMinder,
IsChangeConfirm,
TestPlanIssueEdit,
IssueRelateList,
MsTableCountBar,
VersionSelect: MxVersionSelect,
},
data() {
return {
testCase: [],
dataMap: new Map(),
tags: [this.$t('api_test.definition.request.case'), this.$t('test_track.case.prerequisite'), this.$t('commons.remark'), this.$t('test_track.module.module')],
result: {loading: false},
tags: [
this.$t("api_test.definition.request.case"),
this.$t("test_track.case.prerequisite"),
this.$t("commons.remark"),
this.$t("test_track.module.module"),
],
result: { loading: false },
needRefresh: false,
noRefreshMinder: false,
noRefreshMinderForSelectNode: false,
@ -111,29 +136,29 @@ export default {
extraNodeChanged: [], //
currentVersion: null,
caseNum: 0,
}
};
},
props: {
treeNodes: {
type: Array,
default() {
return []
}
return [];
},
},
condition: Object,
projectId: String,
activeName: String,
defaultVersion: String
defaultVersion: String,
},
computed: {
...mapState(useStore, {
selectNodeIds: 'testCaseSelectNodeIds',
selectNode: 'testCaseSelectNode',
moduleOptions: 'testCaseModuleOptions',
testCaseDefaultValue: 'testCaseDefaultValue',
selectNodeIds: "testCaseSelectNodeIds",
selectNode: "testCaseSelectNode",
moduleOptions: "testCaseModuleOptions",
testCaseDefaultValue: "testCaseDefaultValue",
}),
disabled() {
return !hasPermission('PROJECT_TRACK_CASE_MINDER:OPERATE');
return !hasPermission("PROJECT_TRACK_CASE_MINDER:OPERATE");
},
moveEnable() {
//
@ -141,12 +166,12 @@ export default {
},
workspaceId() {
return getCurrentWorkspaceId();
}
},
},
watch: {
//
treeNodes(newVal, oldVal) {
if (newVal !== oldVal && this.activeName === 'default') {
if (newVal !== oldVal && this.activeName === "default") {
// tab
this.handleNodeUpdateForMinder();
}
@ -165,19 +190,21 @@ export default {
},
currentVersion() {
this.$refs.minder.initData();
}
},
},
mounted() {
this.currentVersion = this.defaultVersion || null;
this.setIsChange(false);
let moduleNum = 0;
this.treeNodes.forEach(node => {
this.treeNodes.forEach((node) => {
moduleNum += node.caseNum;
})
});
this.caseNum = moduleNum;
if (this.selectNode && this.selectNode.data) {
if (this.$refs.minder) {
let importJson = this.$refs.minder.getImportJsonBySelectNode(this.selectNode.data);
let importJson = this.$refs.minder.getImportJsonBySelectNode(
this.selectNode.data
);
this.$refs.minder.setJsonImport(importJson);
}
}
@ -185,7 +212,7 @@ export default {
methods: {
changeVersion(currentVersion) {
this.currentVersion = currentVersion || null;
this.$emit('versionChange', currentVersion);
this.$emit("versionChange", currentVersion);
},
handleNodeUpdateForMinder() {
if (this.noRefreshMinder) {
@ -229,24 +256,32 @@ export default {
handleAfterMount() {
listenNodeSelected(() => {
//
loadSelectNodes(this.getParam(), getTestCasesForMinder, null, getMinderExtraNode);
loadSelectNodes(
this.getParam(),
getTestCasesForMinder,
null,
getMinderExtraNode
);
});
listenDblclick(() => {
let minder = window.minder;
let selectNodes = minder.getSelectedNodes();
let isNotDisableNode = false;
selectNodes.forEach(node => {
selectNodes.forEach((node) => {
//
if (!node.data.disable) {
isNotDisableNode = true;
}
if (node.data.type === 'issue') {
getIssuesForMinder(node.data.id, this.projectId, this.workspaceId)
.then((r) => {
let data = r.data;
this.$refs.issueEdit.open(data);
})
if (node.data.type === "issue") {
getIssuesForMinder(
node.data.id,
this.projectId,
this.workspaceId
).then((r) => {
let data = r.data;
this.$refs.issueEdit.open(data);
});
}
});
if (isNotDisableNode) {
@ -255,31 +290,54 @@ export default {
});
listenBeforeExecCommand((even) => {
if (even.commandName === 'expandtolevel') {
if (even.commandName === "expandtolevel") {
let level = Number.parseInt(even.commandArgs);
handleExpandToLevel(level, even.minder.getRoot(), this.getParam(), getTestCasesForMinder, null, getMinderExtraNode);
handleExpandToLevel(
level,
even.minder.getRoot(),
this.getParam(),
getTestCasesForMinder,
null,
getMinderExtraNode
);
}
if (handleMinderIssueDelete(even.commandName)) return; //
if (['priority', 'resource', 'removenode', 'appendchildnode', 'appendparentnode', 'appendsiblingnode', 'paste'].indexOf(even.commandName) > -1) {
if (
[
"priority",
"resource",
"removenode",
"appendchildnode",
"appendparentnode",
"appendsiblingnode",
"paste",
].indexOf(even.commandName) > -1
) {
//
this.setIsChange(true);
}
if ('paste' === even.commandName) {
if ("paste" === even.commandName) {
handlePasteTip(window.minder.getSelectedNode());
handlePasteAfter(window.minder.getSelectedNode());
}
if ('resource' === even.commandName) {
if ("resource" === even.commandName) {
//
setTimeout(() => setPriorityView(true, 'P'), 100);
setTimeout(() => setPriorityView(true, "P"), 100);
}
if ('movetoparent' === even.commandName) {
if ("movetoparent" === even.commandName) {
//
loadNode(even.commandArgs[1], this.getParam(), getTestCasesForMinder, null, getMinderExtraNode);
loadNode(
even.commandArgs[1],
this.getParam(),
getTestCasesForMinder,
null,
getMinderExtraNode
);
}
});
@ -293,23 +351,23 @@ export default {
request: {
projectId: this.projectId,
versionId: this.currentVersion,
orders: this.condition.orders
orders: this.condition.orders,
},
result: this.result,
isDisable: false
}
isDisable: false,
};
},
moveConfirm() {
let selectNodes = minder.getSelectedNodes();
for (let node of selectNodes) {
//
if (isModuleNode(node)) {
this.$warning(this.$t('case.minder_module_move_confirm_tip'));
this.$warning(this.$t("case.minder_module_move_confirm_tip"));
return false;
}
//
if (!this.moveEnable && isCaseNodeData(node.data)) {
this.$warning(this.$t('case.minder_move_confirm_tip'));
this.$warning(this.$t("case.minder_move_confirm_tip"));
return false;
}
}
@ -317,25 +375,29 @@ export default {
},
handleDeleteConfirm() {
let selectNodes = minder.getSelectedNodes();
let moduleName = '';
selectNodes.forEach(node => {
let moduleName = "";
selectNodes.forEach((node) => {
if (isModuleNode(node)) {
moduleName += node.data.text + ' ';
moduleName += node.data.text + " ";
}
});
if (moduleName.length > 0) {
let title = this.$t('commons.confirm_delete') + ': ' + this.$t("project.project_file.file_module_type.module") + moduleName + "?";
this.$confirm(this.$t('test_track.module.delete_tip'), title, {
cancelButtonText: this.$t("commons.cancel"),
confirmButtonText: this.$t("commons.confirm"),
customClass: 'custom-confirm-delete',
callback: action => {
if (action === "confirm") {
minder.forceRemoveNode();
}
let title =
this.$t("commons.confirm_delete") +
": " +
this.$t("project.project_file.file_module_type.module") +
moduleName +
"?";
this.$confirm(this.$t("test_track.module.delete_tip"), title, {
cancelButtonText: this.$t("commons.cancel"),
confirmButtonText: this.$t("commons.confirm"),
customClass: "custom-confirm-delete",
callback: (action) => {
if (action === "confirm") {
minder.forceRemoveNode();
}
}
);
},
});
} else {
minder.forceRemoveNode();
}
@ -345,7 +407,7 @@ export default {
return;
}
useStore().$patch({
isTestCaseMinderChanged: isChanged
isTestCaseMinderChanged: isChanged,
});
},
save(callback) {
@ -356,41 +418,41 @@ export default {
this.saveModuleNodeMap = new Map();
this.buildSaveParam(window.minder.getRoot());
this.saveModules.forEach(module => {
this.saveModules.forEach((module) => {
let nodeIds = [];
getChildNodeId(this.saveModuleNodeMap.get(module.id), nodeIds);
module.nodeIds = nodeIds;
});
// null
this.deleteNodes = this.deleteNodes.filter(i => i);
this.deleteNodes = this.deleteNodes.filter((i) => i);
let param = {
projectId: this.projectId,
data: this.saveCases,
ids: this.deleteNodes.map(item => item.id),
ids: this.deleteNodes.map((item) => item.id),
testCaseNodes: this.saveModules,
extraNodeRequest: {
groupId: this.projectId,
type: "TEST_CASE",
data: this.saveExtraNode,
}
}
},
};
// id
param.ids = param.ids.filter(id => id);
param.ids = param.ids.filter((id) => id);
this.result.loading = true;
testCaseMinderEdit(param)
.then(() => {
this.result.loading = false;
this.$success(this.$t('commons.save_success'), false);
this.$success(this.$t("commons.save_success"), false);
handleAfterSave(window.minder.getRoot());
this.extraNodeChanged.forEach(item => {
this.extraNodeChanged.forEach((item) => {
item.isExtraNode = false;
});
this.extraNodeChanged = [];
this.$emit('refresh');
this.$emit("refresh");
if (!this.noRefreshMinder) {
//
@ -412,7 +474,7 @@ export default {
})
.catch(() => {
this.result.loading = false;
});
});
},
buildSaveParam(root, parent, preNode, nextNode) {
let data = root.data;
@ -424,16 +486,17 @@ export default {
this.deleteNodes.push(...deleteChild);
}
if (data.type !== 'tmp' && data.changed) {
if (data.type !== "tmp" && data.changed) {
if (isModuleNodeData(data)) {
if (data.contextChanged && data.id !== 'root') {
if (data.contextChanged && data.id !== "root") {
this.buildSaveModules(root, data, parent);
root.children && root.children.forEach(i => {
if (isModuleNode(i)) {
i.data.changed = true;
i.data.contextChanged = true; // level
}
});
root.children &&
root.children.forEach((i) => {
if (isModuleNode(i)) {
i.data.changed = true;
i.data.contextChanged = true; // level
}
});
}
} else {
//
@ -463,21 +526,27 @@ export default {
}
let pId = parent ? (parent.newId ? parent.newId : parent.id) : null;
if (!parent && this.selectNode && this.selectNode.data
&& this.selectNode.data.id === data.id) {
if (
!parent &&
this.selectNode &&
this.selectNode.data &&
this.selectNode.data.id === data.id
) {
// parent, parentId
pId = this.selectNode.data.parentId;
}
if (parent && !isModuleNodeData(parent)) {
this.throwError(this.$t('test_track.case.minder_not_module_tip', [data.text]));
this.throwError(
this.$t("test_track.case.minder_not_module_tip", [data.text])
);
}
let module = {
id: data.id,
name: data.text,
level: parent ? parent.level + 1 : data.level,
parentId: pId
parentId: pId,
};
data.level = module.level;
@ -497,7 +566,7 @@ export default {
}
}
if (data.type === 'case') {
if (data.type === "case") {
//
this.pushDeleteNode(data);
module.id = null;
@ -509,18 +578,31 @@ export default {
module.isEdit = false; //
module.id = getUUID();
data.newId = module.id;
this.moduleOptions.push({id: data.newId, path: getNodePath(pId, this.moduleOptions) + '/' + module.name});
this.moduleOptions.push({
id: data.newId,
path: getNodePath(pId, this.moduleOptions) + "/" + module.name,
});
}
this.saveModuleNodeMap.set(module.id, node);
if (module.name.trim().length > 100) {
this.throwError( this.$t('test_track.module.name') + this.$t('test_track.length_less_than') + 100);
this.throwError(
this.$t("test_track.module.name") +
this.$t("test_track.length_less_than") +
100
);
}
this.saveModules.push(module);
},
buildExtraNode(data, parent, root) {
if (data.type !== 'node' && data.type !== 'tmp' && parent && isModuleNodeData(parent) && data.changed === true) {
if (
data.type !== "node" &&
data.type !== "tmp" &&
parent &&
isModuleNodeData(parent) &&
data.changed === true
) {
//
let pId = parent.newId ? parent.newId : parent.id;
let nodes = this.saveExtraNode[pId];
@ -532,16 +614,20 @@ export default {
}
},
validate(parent, data) {
if (parent.id === 'root') {
this.throwError(this.$t('test_track.case.minder_all_module_tip'));
if (parent.id === "root") {
this.throwError(this.$t("test_track.case.minder_all_module_tip"));
}
if (parent.isExtraNode && !isModuleNodeData(parent)) {
this.throwError(this.$t('test_track.case.minder_tem_node_tip', [parent.text]));
this.throwError(
this.$t("test_track.case.minder_tem_node_tip", [parent.text])
);
}
if (data.type === 'node') {
this.throwError(this.$t('test_track.case.minder_is_module_tip', [data.text]));
if (data.type === "node") {
this.throwError(
this.$t("test_track.case.minder_is_module_tip", [data.text])
);
}
},
buildSaveCase(node, parent, preNode, nextNode) {
@ -557,9 +643,11 @@ export default {
let nodeId = parent ? (parent.newId ? parent.newId : parent.id) : "";
let priorityDefaultValue;
if (data.priority) {
priorityDefaultValue = 'P' + (data.priority - 1);
priorityDefaultValue = "P" + (data.priority - 1);
} else {
priorityDefaultValue = this.testCaseDefaultValue['用例等级'] ? this.testCaseDefaultValue['用例等级'] : 'P' + 0;
priorityDefaultValue = this.testCaseDefaultValue["用例等级"]
? this.testCaseDefaultValue["用例等级"]
: "P" + 0;
}
let testCase = {
@ -567,47 +655,83 @@ export default {
name: data.text,
nodeId: nodeId,
nodePath: getNodePath(nodeId, this.moduleOptions),
type: data.type ? data.type : 'functional',
method: data.method ? data.method : 'manual',
maintainer: this.testCaseDefaultValue['责任人'] ? this.testCaseDefaultValue['责任人'] : data.maintainer,
type: data.type ? data.type : "functional",
method: data.method ? data.method : "manual",
maintainer: this.testCaseDefaultValue["责任人"]
? this.testCaseDefaultValue["责任人"]
: data.maintainer,
priority: priorityDefaultValue,
prerequisite: "",
remark: "",
stepDescription: "",
expectedResult: "",
status: this.testCaseDefaultValue['用例状态'] ? this.testCaseDefaultValue['用例状态'] : 'Prepare',
steps: [{
num: 1,
desc: '',
result: ''
}],
status: this.testCaseDefaultValue["用例状态"]
? this.testCaseDefaultValue["用例状态"]
: "Prepare",
steps: [
{
num: 1,
desc: "",
result: "",
},
],
tags: "[]",
stepModel: "STEP"
stepModel: "STEP",
};
if (data.changed) isChange = true;
let steps = [];
let stepNum = 1;
if (node.children) {
let prerequisiteNodes = node.children.filter(childNode => childNode.data.resource && childNode.data.resource.indexOf(this.$t('test_track.case.prerequisite')) > -1);
let prerequisiteNodes = node.children.filter(
(childNode) =>
childNode.data.resource &&
childNode.data.resource.indexOf(
this.$t("test_track.case.prerequisite")
) > -1
);
if (prerequisiteNodes.length > 1) {
this.throwError('[' + testCase.name + ']' + this.$t('test_track.case.exists_multiple_prerequisite_node'));
this.throwError(
"[" +
testCase.name +
"]" +
this.$t("test_track.case.exists_multiple_prerequisite_node")
);
}
let remarkNodes = node.children.filter(childNode => childNode.data.resource && childNode.data.resource.indexOf(this.$t('commons.remark')) > -1);
let remarkNodes = node.children.filter(
(childNode) =>
childNode.data.resource &&
childNode.data.resource.indexOf(this.$t("commons.remark")) > -1
);
if (remarkNodes.length > 1) {
this.throwError('[' + testCase.name + ']' + this.$t('test_track.case.exists_multiple_remark_node'));
this.throwError(
"[" +
testCase.name +
"]" +
this.$t("test_track.case.exists_multiple_remark_node")
);
}
node.children.forEach((childNode) => {
let childData = childNode.data;
if (childData.type === 'issue') return;
if (childData.resource && childData.resource.indexOf(this.$t('test_track.case.prerequisite')) > -1) {
if (childData.type === "issue") return;
if (
childData.resource &&
childData.resource.indexOf(
this.$t("test_track.case.prerequisite")
) > -1
) {
testCase.prerequisite = childData.text;
if (childNode.children && childNode.children.length > 0) {
this.throwError('[' + testCase.name + ']前置条件下不能添加子节点!');
this.throwError(
"[" + testCase.name + "]前置条件下不能添加子节点!"
);
}
} else if (childData.resource && childData.resource.indexOf(this.$t('commons.remark')) > -1) {
} else if (
childData.resource &&
childData.resource.indexOf(this.$t("commons.remark")) > -1
) {
testCase.remark = childData.text;
if (childNode.children && childNode.children.length > 0) {
this.throwError('[' + testCase.name + ']备注下不能添加子节点!');
this.throwError("[" + testCase.name + "]备注下不能添加子节点!");
}
} else {
//
@ -621,12 +745,12 @@ export default {
if (child.data.changed) {
isChange = true;
}
})
});
step.result = result;
}
steps.push(step);
if (data.stepModel === 'TEXT') {
if (data.stepModel === "TEXT") {
testCase.stepDescription = step.desc;
testCase.expectedResult = step.result;
}
@ -637,10 +761,12 @@ export default {
childNode.children.forEach((child) => {
if (child.children && child.children.length > 0) {
this.throwError('[' + testCase.name + ']用例下子节点不能超过两层!');
this.throwError(
"[" + testCase.name + "]用例下子节点不能超过两层!"
);
}
});
})
});
}
testCase.steps = JSON.stringify(steps);
@ -652,7 +778,6 @@ export default {
}
if (isChange) {
testCase.targetId = null; //
if (this.moveEnable) {
@ -660,15 +785,15 @@ export default {
let preId = preNode.data.id;
if (preId && preId.length > 15) {
testCase.targetId = preId;
testCase.moveMode = 'AFTER';
testCase.moveMode = "AFTER";
} else {
testCase.moveMode = 'APPEND';
testCase.moveMode = "APPEND";
}
} else if (this.isCaseNode(nextNode) && !nextNode.data.isExtraNode) {
let nextId = nextNode.data.id;
if (nextId && nextId.length > 15) {
testCase.targetId = nextId;
testCase.moveMode = 'BEFORE';
testCase.moveMode = "BEFORE";
}
}
}
@ -682,12 +807,24 @@ export default {
}
if (testCase.name.length > 255) {
this.throwError( this.$t('api_test.home_page.failed_case_list.table_coloum.case_name') + this.$t('test_track.length_less_than') + 255);
this.throwError(
this.$t(
"api_test.home_page.failed_case_list.table_coloum.case_name"
) +
this.$t("test_track.length_less_than") +
255
);
}
this.saveCases.push(testCase);
}
if (testCase.nodeId !== 'root' && testCase.nodeId.length < 15) {
this.throwError(this.$t('test_track.case.create_case') + "'" + testCase.name + "'" + this.$t('test_track.case.minder_create_tip'));
if (testCase.nodeId !== "root" && testCase.nodeId.length < 15) {
this.throwError(
this.$t("test_track.case.create_case") +
"'" +
testCase.name +
"'" +
this.$t("test_track.case.minder_create_tip")
);
}
},
pushDeleteNode(data) {
@ -698,7 +835,13 @@ export default {
data.id = "";
},
isCaseNode(node) {
if (node && node.data.resource && node.data.resource.indexOf(this.$t('api_test.definition.request.case')) > -1) {
if (
node &&
node.data.resource &&
node.data.resource.indexOf(
this.$t("api_test.definition.request.case")
) > -1
) {
return true;
}
return false;
@ -720,8 +863,12 @@ export default {
}
if (node.children) {
nodeData.children = [];
node.children.forEach(item => {
if (!isCaseNodeData(item.data) && !isModuleNodeData(item.data) && item.data.type !== 'tmp') {
node.children.forEach((item) => {
if (
!isCaseNodeData(item.data) &&
!isModuleNodeData(item.data) &&
item.data.type !== "tmp"
) {
//
nodeData.children.push(this._buildExtraNode(item));
}
@ -731,7 +878,7 @@ export default {
return nodeData;
},
throwError(tip) {
this.$error(tip)
this.$error(tip);
handleSaveError(window.minder.getRoot());
throw new Error(tip);
},
@ -743,7 +890,7 @@ export default {
},
// tab
addCase(data, type) {
if (type === 'edit') {
if (type === "edit") {
handTestCaeEdit(data);
} else {
handleTestCaseAdd(data.nodeId, data);
@ -771,9 +918,9 @@ export default {
},
refreshRelateIssue(issues) {
handleIssueBatch(issues);
}
}
}
},
},
};
</script>
<style scoped>