refactor(接口测试): 场景最大化页面优化

This commit is contained in:
fit2-zhao 2022-03-11 17:04:47 +08:00 committed by fit2-zhao
parent 5a25fc5123
commit 7d06c74b33
7 changed files with 420 additions and 466 deletions

View File

@ -279,37 +279,10 @@
<!--步骤最大化--> <!--步骤最大化-->
<ms-drawer :visible="drawer" :size="100" @close="close" direction="default" :show-full-screen="false" :is-show-close="false" style="overflow: hidden" v-if="drawer"> <ms-drawer :visible="drawer" :size="100" @close="close" direction="default" :show-full-screen="false" :is-show-close="false" style="overflow: hidden" v-if="drawer">
<template v-slot:header>
<scenario-header
:currentScenario="currentScenario"
:projectEnvMap="projectEnvMap"
:projectIds.sync="projectIds"
:projectList="projectList"
:scenarioDefinition="scenarioDefinition"
:enableCookieShare="enableCookieShare"
:onSampleError="onSampleError"
:environment-type="environmentType"
:group-id="envGroupId"
:execDebug="stopDebug"
:isFullUrl.sync="isFullUrl"
:clearMessage="clearMessage"
@setEnvType="setEnvType"
@envGroupId="setEnvGroup"
@closePage="close"
@unFullScreen="unFullScreen"
@showAllBtn="showAllBtn"
@runDebug="runDebug"
@handleCommand="handleCommand"
@setProjectEnvMap="setProjectEnvMap"
@showScenarioParameters="showScenarioParameters"
@setCookieShare="setCookieShare"
@setSampleError="setSampleError"
@stop="stop"
ref="maximizeHeader"/>
</template>
<maximize-scenario <maximize-scenario
:scenario-definition="scenarioDefinition" :scenario-definition="scenarioDefinition"
:projectIds.sync="projectIds"
:projectList="projectList"
:envMap="projectEnvMap" :envMap="projectEnvMap"
:moduleOptions="moduleOptions" :moduleOptions="moduleOptions"
:req-error="reqError" :req-error="reqError"
@ -318,10 +291,22 @@
:req-total-time="reqTotalTime" :req-total-time="reqTotalTime"
:currentScenario="currentScenario" :currentScenario="currentScenario"
:type="type" :type="type"
:debug="debug" :debug="debugLoading"
:reloadDebug="reloadDebug" :reloadDebug="reloadDebug"
:stepReEnable="stepEnable" :stepReEnable="stepEnable"
:message="message" :message="message"
@setEnvType="setEnvType"
@envGroupId="setEnvGroup"
@closePage="close"
@unFullScreen="unFullScreen"
@showAllBtn="showAllBtn"
@runDebug="runDebug"
@handleCommand="handleCommand"
@setProjectEnvMap="setProjectEnvMap"
@showScenarioParameters="showScenarioParameters"
@setCookieShare="setCookieShare"
@setSampleError="setSampleError"
@stop="stop"
@openScenario="openScenario" @openScenario="openScenario"
@runScenario="runDebug" @runScenario="runDebug"
@stopScenario="stop" @stopScenario="stop"
@ -414,7 +399,6 @@ export default {
ApiImport: () => import("../../definition/components/import/ApiImport"), ApiImport: () => import("../../definition/components/import/ApiImport"),
EnvPopover: () => import("@/business/components/api/automation/scenario/EnvPopover"), EnvPopover: () => import("@/business/components/api/automation/scenario/EnvPopover"),
MaximizeScenario: () => import("./maximize/MaximizeScenario"), MaximizeScenario: () => import("./maximize/MaximizeScenario"),
ScenarioHeader: () => import("./maximize/ScenarioHeader"),
MsDrawer: () => import("../../../common/components/MsDrawer"), MsDrawer: () => import("../../../common/components/MsDrawer"),
MsSelectTree: () => import("../../../common/select-tree/SelectTree"), MsSelectTree: () => import("../../../common/select-tree/SelectTree"),
MsChangeHistory: () => import("../../../history/ChangeHistory"), MsChangeHistory: () => import("../../../history/ChangeHistory"),
@ -614,7 +598,6 @@ export default {
this.isBatchProcess = true; this.isBatchProcess = true;
this.expandedNode = []; this.expandedNode = [];
this.hideAllTreeNode(this.scenarioDefinition); this.hideAllTreeNode(this.scenarioDefinition);
this.$refs.stepTree.root.expanded = true;
this.reloadTreeStatus(); this.reloadTreeStatus();
}, },
cancelBatchProcessing() { cancelBatchProcessing() {

View File

@ -6,9 +6,10 @@
<div class="el-step__icon-inner" :key="$store.state.forceRerenderIndex">{{ data.index }}</div> <div class="el-step__icon-inner" :key="$store.state.forceRerenderIndex">{{ data.index }}</div>
</div> </div>
<slot name="behindHeaderLeft" v-if="!isMax"></slot> <slot name="behindHeaderLeft" v-if="!isMax"></slot>
<el-tag class="ms-left-btn" size="small" :style="{'color': color, 'background-color': backgroundColor}">{{ title }}</el-tag> <el-tag class="ms-left-btn" size="mini" :style="{'color': color, 'background-color': backgroundColor}">{{ title }}</el-tag>
</slot> </slot>
<span>
<span v-show="!isMax">
<slot name="headerLeft"> <slot name="headerLeft">
<i class="icon el-icon-arrow-right" :class="{'is-active': data.active}" @click="active(data)" v-if="data.type!='scenario' && !isMax " @click.stop/> <i class="icon el-icon-arrow-right" :class="{'is-active': data.active}" @click="active(data)" v-if="data.type!='scenario' && !isMax " @click.stop/>
<span @click.stop v-if="isShowInput && isShowNameInput"> <span @click.stop v-if="isShowInput && isShowNameInput">
@ -25,9 +26,14 @@
</span> </span>
</slot> </slot>
</span> </span>
<span v-show="isMax">
<slot name="headerLeft">
<span style="font-size: 12px" class="ms-step-name-width">{{ data.name }}</span>
</slot>
</span>
<div v-if="!ifFromVariableAdvance" class="header-right" @click.stop> <div v-if="!ifFromVariableAdvance" class="header-right" @click.stop>
<slot name="message"></slot> <slot name="message" v-show="!isMax"></slot>
<slot name="debugStepCode"></slot> <slot name="debugStepCode"></slot>
<el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top" v-if="showBtn"> <el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top" v-if="showBtn">
<el-switch v-model="data.enable" class="enable-switch" size="mini" :disabled="(data.disabled && !data.root) || !showVersion" style="width: 30px"/> <el-switch v-model="data.enable" class="enable-switch" size="mini" :disabled="(data.disabled && !data.root) || !showVersion" style="width: 30px"/>
@ -240,9 +246,8 @@ export default {
} }
.ms-left-btn { .ms-left-btn {
font-size: 13px; margin-right: 5px;
margin-right: 15px; margin-left: 0px;
margin-left: 10px;
} }
.header-right { .header-right {
@ -384,13 +389,13 @@ fieldset {
.ms-step-name-width { .ms-step-name-width {
display: inline-block; display: inline-block;
margin: 0 5px; margin: 0 0px;
overflow-x: hidden; overflow-x: hidden;
padding-bottom: 0; padding-bottom: 0;
text-overflow: ellipsis; text-overflow: ellipsis;
vertical-align: middle; vertical-align: middle;
white-space: nowrap; white-space: nowrap;
width: 400px; width: 60px;
} }
.ms-step-selected { .ms-step-selected {

View File

@ -131,7 +131,7 @@
text-overflow: ellipsis; text-overflow: ellipsis;
vertical-align: middle; vertical-align: middle;
white-space: nowrap; white-space: nowrap;
width: 100px; width: 80px;
} }
.ms-test-running { .ms-test-running {
color: #6D317C; color: #6D317C;

View File

@ -449,7 +449,7 @@ export default {
text-overflow: ellipsis; text-overflow: ellipsis;
vertical-align: middle; vertical-align: middle;
white-space: nowrap; white-space: nowrap;
width: 100px; width: 80px;
} }
.ms-form-create >>> .el-select { .ms-form-create >>> .el-select {

View File

@ -187,7 +187,7 @@ export default {
text-overflow: ellipsis; text-overflow: ellipsis;
vertical-align: middle; vertical-align: middle;
white-space: nowrap; white-space: nowrap;
width: 100px; width: 80px;
} }
.ms-test-running { .ms-test-running {
color: #6D317C; color: #6D317C;

View File

@ -1,30 +1,74 @@
<template> <template>
<div> <div style="width: 100%;overflow: hidden">
<div class="ms-header">
<el-row>
<el-col :span="1" v-show="scenarioDefinition.length > 1">
<div class="ms-div" style="margin-left: 10px">
<el-tooltip :content="$t('test_track.case.batch_operate')" placement="top" effect="light" v-show="!isBatchProcess">
<font-awesome-icon class="ms-batch-btn" :icon="['fa', 'bars']" v-prevent-re-click @click="batchProcessing"/>
</el-tooltip>
<el-checkbox v-show="isBatchProcess" v-model="isCheckedAll" @change="checkedAll"/>
<el-tooltip :content="$t('commons.cancel')" placement="top" effect="light" v-show="isBatchProcess">
<font-awesome-icon class="ms-batch-btn" :icon="['fa', 'times']" v-prevent-re-click @click="cancelBatchProcessing"/>
</el-tooltip>
</div>
</el-col>
<el-col :span="9">
<div class="ms-div" @click="showAll">
<!-- 调试部分 -->
<el-row>
<el-col :span="8">
<el-tooltip placement="top" :content="currentScenario.name">
<span style="margin-left: 10px">{{ currentScenario.name }}</span>
</el-tooltip>
</el-col>
<el-col :span="8">
{{ $t('api_test.automation.step_total') }}{{ scenarioDefinition.length }}
</el-col>
<el-col :span="8">
<el-link class="head" @click="showScenarioParameters">{{ $t('api_test.automation.scenario_total') }}</el-link>
{{ getVariableSize() }}
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="12">
<el-checkbox v-model="cookieShare" @change="setCookieShare">共享cookie</el-checkbox>
<el-checkbox v-model="sampleError" @change="setOnSampleError" style="margin-right: 10px">{{ $t('commons.failure_continues') }}</el-checkbox>
<env-popover :disabled="scenarioDefinition.length < 1" :isReadOnly="scenarioDefinition.length < 1"
:env-map="projectEnvMap" :project-ids="projectIds" @setProjectEnvMap="setProjectEnvMap"
:environment-type.sync="envType" :group-id="envGroupId"
@showPopover="showPopover" :project-list="projectList" ref="envPopover" class="ms-right" :has-option-group="true"
:result="envResult"/>
<el-dropdown split-button type="primary" @click="debugScenario" style="margin:0px 10px 0px" size="mini" @command="handleCommand" v-show="!debugLoading">
{{ $t('api_test.request.debug') }}
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>{{ $t('api_test.automation.generate_report') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button size="mini" type="primary" style="margin:0px 10px 0px" v-show="debugLoading" @click="stop">{{ $t('report.stop_btn') }}</el-button>
</el-col>
<font-awesome-icon class="ms-min-alt-ico" :icon="['fa', 'compress-alt']" size="lg" @click="unFullScreen"/>
</el-row>
</div>
<!-- 场景步骤--> <!-- 场景步骤-->
<ms-container :class="{'maximize-container': !asideHidden}"> <ms-container :class="{'maximize-container': !asideHidden}">
<ms-aside-container @setAsideHidden="setAsideHidden" style="padding-top: 0px"> <ms-aside-container @setAsideHidden="setAsideHidden" style="padding-top: 0px;overflow: hidden">
<!-- 场景步骤内容 --> <div class="ms-debug-result" v-if="reqTotal > 0">
<div v-loading="loading" v-if="!asideHidden"> <span style="float: right">
<el-tooltip :content="$t('api_test.automation.open_expansion')" placement="top" effect="light"> <span class="ms-message-right"> {{ reqTotalTime }} ms </span>
<i class="el-icon-circle-plus-outline ms-open-btn ms-open-btn-left" v-prevent-re-click @click="openExpansion"/>
</el-tooltip>
<el-tooltip :content="$t('api_test.automation.close_expansion')" placement="top" effect="light">
<i class="el-icon-remove-outline ms-open-btn" size="mini" @click="closeExpansion"/>
</el-tooltip>
<el-tooltip :content="$t('api_test.scenario.disable')" placement="top" effect="light" v-if="!stepEnable">
<font-awesome-icon class="ms-open-btn" :icon="['fas', 'toggle-off']" @click="enableAll"/>
</el-tooltip>
<el-tooltip :content="$t('api_test.scenario.enable')" placement="top" effect="light" v-else>
<font-awesome-icon class="ms-open-btn" :icon="['fas', 'toggle-on']" @click="disableAll"/>
</el-tooltip>
<span class="ms-debug-result" v-if="debug">
<div class="ms-debug-result" v-if="debug">
<span class="ms-message-right"> {{ reqTotalTime }} ms </span>
<span class="ms-message-right">{{ $t('api_test.automation.request_total') }} {{ reqTotal }}</span> <span class="ms-message-right">{{ $t('api_test.automation.request_total') }} {{ reqTotal }}</span>
<span class="ms-message-right">{{ $t('api_test.automation.request_success') }} {{ reqSuccess }}</span> <span class="ms-message-right">{{ $t('api_test.automation.request_success') }} {{ reqSuccess }}</span>
<span class="ms-message-right"> {{ $t('api_test.automation.request_error') }} {{ reqError }}</span> <span class="ms-message-right"> {{ $t('api_test.automation.request_error') }} {{ reqError }}</span>
</div>
</span> </span>
</div>
<!-- 场景步骤内容 -->
<div v-loading="loading" v-if="!asideHidden">
<el-tree node-key="resourceId" <el-tree node-key="resourceId"
v-if="showHideTree && !asideHidden" v-if="showHideTree && !asideHidden"
:props="props" :props="props"
@ -32,15 +76,19 @@
:default-expanded-keys="expandedNode" :default-expanded-keys="expandedNode"
:expand-on-click-node="false" :expand-on-click-node="false"
highlight-current highlight-current
:show-checkbox="isBatchProcess"
@node-expand="nodeExpand" @node-expand="nodeExpand"
@node-collapse="nodeCollapse" @node-collapse="nodeCollapse"
:allow-drop="allowDrop" @node-drag-end="allowDrag" @node-click="nodeClick" class="ms-tree"> :allow-drop="allowDrop" @node-drag-end="allowDrag" @node-click="nodeClick" class="ms-tree" ref="maxStepTree">
<el-row class="custom-tree-node" :gutter="18" type="flex" align="middle" slot-scope="{node, data}" style="width: 100%"> <el-row class="custom-tree-node" :gutter="18" type="flex" align="middle" slot-scope="{node, data}" style="width: 98%">
<el-col class="custom-tree-node-col" style="padding-left:0px;padding-right:0px" v-if="node && data.hashTree && data.hashTree.length > 0 && !data.isLeaf"> <el-col class="custom-tree-node-col" style="padding-left:0px;padding-right:0px" v-show="node && data.hashTree && data.hashTree.length > 0 && !data.isLeaf">
<span v-if="!node.expanded" class="el-icon-circle-plus-outline custom-node_e" @click="openOrClose(node)"/> <span v-show="!node.expanded" class="el-icon-circle-plus-outline custom-node_e" @click="openOrClose(node)"/>
<span v-else class="el-icon-remove-outline custom-node_e" @click="openOrClose(node)"/> <span v-show="node.expanded" class="el-icon-remove-outline custom-node_e" @click="openOrClose(node)"/>
</el-col> </el-col>
<el-col class="custom-tree-node-col" style="padding-left:0px;padding-right:0px" v-else> <!-- 批量操作 -->
<el-col :class="data.checkBox? 'custom-tree-node-hide' : 'custom-tree-node-col'" style="padding-left: 0px; padding-right: 0px;"
v-show="(data.hashTree && data.hashTree.length === 0 )|| data.isLeaf">
<show-more-btn :is-show="node.checked" :buttons="batchOperators" :size="selectDataCounts" v-show="data.checkBox" style="margin-right: 3px"/>
</el-col> </el-col>
<el-col> <el-col>
<!-- 步骤组件--> <!-- 步骤组件-->
@ -169,7 +217,7 @@
import {API_STATUS, PRIORITY} from "../../../definition/model/JsonData"; import {API_STATUS, PRIORITY} from "../../../definition/model/JsonData";
import {parseEnvironment} from "../../../definition/model/EnvironmentModel"; import {parseEnvironment} from "../../../definition/model/EnvironmentModel";
import {ELEMENT_TYPE, STEP} from "../Setting"; import {ELEMENT_TYPE, STEP} from "../Setting";
import {getCurrentProjectID, getUUID, hasLicense, strMapToObj} from "@/common/js/utils"; import {exportPdf, getCurrentProjectID, getUUID, hasLicense, strMapToObj} from "@/common/js/utils";
import "@/common/css/material-icons.css" import "@/common/css/material-icons.css"
import OutsideClick from "@/common/js/outside-click"; import OutsideClick from "@/common/js/outside-click";
import {handleCtrlSEvent} from "../../../../../../common/js/utils"; import {handleCtrlSEvent} from "../../../../../../common/js/utils";
@ -178,6 +226,7 @@ import {buttons, setComponent} from '../menu/Menu';
import MsContainer from "../../../../common/components/MsContainer"; import MsContainer from "../../../../common/components/MsContainer";
import MsMainContainer from "../../../../common/components/MsMainContainer"; import MsMainContainer from "../../../../common/components/MsMainContainer";
import MsAsideContainer from "@/business/components/common/components/MsAsideContainer"; import MsAsideContainer from "@/business/components/common/components/MsAsideContainer";
import html2canvas from "html2canvas";
// import MsAsideContainer from "./MsLeftContainer"; // import MsAsideContainer from "./MsLeftContainer";
let jsonPath = require('jsonpath'); let jsonPath = require('jsonpath');
@ -197,6 +246,10 @@ export default {
reqError: Number, reqError: Number,
reqTotalTime: Number, reqTotalTime: Number,
message: String, message: String,
environmentType: String,
groupId: String,
projectIds: Set,
projectList: Array,
}, },
components: { components: {
MsAsideContainer, MsAsideContainer,
@ -213,12 +266,14 @@ export default {
ApiImport: () => import("../../../definition/components/import/ApiImport"), ApiImport: () => import("../../../definition/components/import/ApiImport"),
MsComponentConfig: () => import("../component/ComponentConfig"), MsComponentConfig: () => import("../component/ComponentConfig"),
EnvPopover: () => import("@/business/components/api/automation/scenario/EnvPopover"), EnvPopover: () => import("@/business/components/api/automation/scenario/EnvPopover"),
ShowMoreBtn: () => import( "@/business/components/track/case/components/ShowMoreBtn"),
}, },
data() { data() {
return { return {
props: { props: {
label: "label", label: "label",
children: "hashTree" children: "hashTree",
disabled: false
}, },
rules: { rules: {
name: [ name: [
@ -231,6 +286,7 @@ export default {
principal: [{required: true, message: this.$t('api_test.definition.request.responsible'), trigger: 'change'}], principal: [{required: true, message: this.$t('api_test.definition.request.responsible'), trigger: 'change'}],
}, },
environments: [], environments: [],
projectEnvMap: Map,
currentEnvironmentId: "", currentEnvironmentId: "",
maintainerOptions: [], maintainerOptions: [],
value: API_STATUS[0].id, value: API_STATUS[0].id,
@ -257,16 +313,51 @@ export default {
spacing: 30 spacing: 30
}, },
response: {}, response: {},
projectIds: new Set,
projectEnvMap: new Map,
projectList: [],
debugResult: new Map, debugResult: new Map,
expandedStatus: false, expandedStatus: false,
stepEnable: true, stepEnable: true,
debugLoading: false, debugLoading: false,
buttonData: [], buttonData: [],
stepFilter: new STEP, stepFilter: new STEP,
asideHidden: false asideHidden: false,
selectDataCounts: 0,
batchOperators: [
{
name: this.$t('api_test.automation.bulk_activation_steps'),
handleClick: this.enableAll,
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
{
name: this.$t('api_test.automation.batch_disable_steps'),
handleClick: this.disableAll,
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
{
name: this.$t('api_test.automation.open_expansion'),
handleClick: this.openExpansion,
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
{
name: this.$t('api_test.automation.close_expansion'),
handleClick: this.closeExpansion,
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
{
name: this.$t('api_test.definition.request.batch_delete') + "步骤",
handleClick: this.handleDeleteBatch,
permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
},
],
reloadKey: "",
envType: this.environmentType,
envGroupId: this.groupId,
cookieShare: false,
sampleError: true,
envResult: {
loading: false
},
isBatchProcess: false,
isCheckedAll: false,
} }
}, },
created() { created() {
@ -274,22 +365,22 @@ export default {
this.currentScenario.apiScenarioModuleId = ""; this.currentScenario.apiScenarioModuleId = "";
} }
this.operatingElements = this.stepFilter.get("ALL"); this.operatingElements = this.stepFilter.get("ALL");
this.projectEnvMap = this.envMap;
this.stepEnable = this.stepReEnable; this.stepEnable = this.stepReEnable;
this.initPlugins(); this.initPlugins();
this.buttonData = buttons(this); this.buttonData = buttons(this);
this.projectEnvMap = this.envMap;
}, },
mounted() { mounted() {
this.$refs.refFab.openMenu(); this.$refs.refFab.openMenu();
}, },
watch: { watch: {
envMap() {
this.projectEnvMap = this.envMap;
},
reloadDebug() { reloadDebug() {
this.reload(); this.reload();
} },
debug() {
this.debugLoading = this.debug;
},
}, },
directives: {OutsideClick}, directives: {OutsideClick},
computed: { computed: {
@ -516,6 +607,7 @@ export default {
this.reload(); this.reload();
this.initProjectIds(); this.initProjectIds();
this.scenarioVisible = false; this.scenarioVisible = false;
this.cancelBatchProcessing();
}, },
setApiParameter(item, refType, referenced) { setApiParameter(item, refType, referenced) {
let request = {}; let request = {};
@ -557,6 +649,7 @@ export default {
this.sort(); this.sort();
this.reload(); this.reload();
this.initProjectIds(); this.initProjectIds();
this.cancelBatchProcessing();
}, },
openTagConfig() { openTagConfig() {
if (!this.projectId) { if (!this.projectId) {
@ -626,6 +719,10 @@ export default {
this.loading = false this.loading = false
}) })
}, },
debugScenario() {
this.debugLoading = true;
this.$emit('runDebug');
},
runDebug() { runDebug() {
/*触发执行操作*/ /*触发执行操作*/
let sign = this.$refs.envPopover.checkEnv(); let sign = this.$refs.envPopover.checkEnv();
@ -633,29 +730,31 @@ export default {
this.errorRefresh(); this.errorRefresh();
return; return;
} }
this.$refs['currentScenario'].validate((valid) => { if (this.$refs['currentScenario']) {
if (valid) { this.$refs['currentScenario'].validate((valid) => {
Promise.all([ if (valid) {
this.editScenario()]).then(val => { Promise.all([
if (val) { this.editScenario()]).then(val => {
this.debugData = { if (val) {
id: this.currentScenario.id, this.debugData = {
name: this.currentScenario.name, id: this.currentScenario.id,
type: "scenario", name: this.currentScenario.name,
variables: this.currentScenario.variables, type: "scenario",
referenced: 'Created', variables: this.currentScenario.variables,
enableCookieShare: this.enableCookieShare, referenced: 'Created',
headers: this.currentScenario.headers, enableCookieShare: this.enableCookieShare,
environmentMap: this.projectEnvMap, headers: this.currentScenario.headers,
hashTree: this.scenarioDefinition environmentMap: this.projectEnvMap,
}; hashTree: this.scenarioDefinition
this.reportId = getUUID().substring(0, 8); };
} this.reportId = getUUID().substring(0, 8);
}); }
} else { });
this.errorRefresh(); } else {
} this.errorRefresh();
}) }
})
}
}, },
getEnvironments() { getEnvironments() {
if (this.projectId) { if (this.projectId) {
@ -899,13 +998,15 @@ export default {
openExpansion() { openExpansion() {
this.expandedNode = []; this.expandedNode = [];
this.expandedStatus = true; this.expandedStatus = true;
this.changeNodeStatus(this.scenarioDefinition); let resourceIds = this.getAllResourceIds();
this.changeNodeStatus(resourceIds, this.scenarioDefinition);
}, },
closeExpansion() { closeExpansion() {
this.expandedStatus = false; this.expandedStatus = false;
this.expandedNode = []; this.expandedNode = [];
this.changeNodeStatus(this.scenarioDefinition); let resourceIds = this.getAllResourceIds();
this.showHide(); this.changeNodeStatus(resourceIds, this.scenarioDefinition);
this.forceRerender();
}, },
stepNode() { stepNode() {
// //
@ -918,10 +1019,12 @@ export default {
} }
} }
}, },
stepStatus(nodes) { stepStatus(resourceIds, nodes) {
for (let i in nodes) { for (let i in nodes) {
if (nodes[i]) { if (nodes[i]) {
nodes[i].enable = this.stepEnable; if (resourceIds.indexOf(nodes[i].resourceId) !== -1) {
nodes[i].enable = this.stepEnable;
}
if (nodes[i].hashTree != undefined && nodes[i].hashTree.length > 0) { if (nodes[i].hashTree != undefined && nodes[i].hashTree.length > 0) {
this.stepStatus(nodes[i].hashTree); this.stepStatus(nodes[i].hashTree);
} }
@ -930,11 +1033,48 @@ export default {
}, },
enableAll() { enableAll() {
this.stepEnable = true; this.stepEnable = true;
this.stepNode(); let resourceIds = this.getAllResourceIds();
this.stepStatus(resourceIds, this.scenarioDefinition);
}, },
disableAll() { disableAll() {
this.stepEnable = false; this.stepEnable = false;
this.stepNode(); let resourceIds = this.getAllResourceIds();
this.stepStatus(resourceIds, this.scenarioDefinition);
},
handleDeleteBatch() {
this.getAllResourceIds().forEach(item => {
this.recursionDelete(item, this.scenarioDefinition);
});
this.sort();
this.forceRerender();
},
recursionDelete(resourceId, nodes) {
for (let i in nodes) {
if (nodes[i]) {
if (resourceId === nodes[i].resourceId) {
nodes.splice(i, 1);
} else {
if (nodes[i].hashTree != undefined && nodes[i].hashTree.length > 0) {
this.recursionDelete(resourceId, nodes[i].hashTree);
}
}
}
}
},
forceRerender() {
this.$nextTick(() => {
this.$store.state.forceRerenderIndex = getUUID();
});
},
getAllResourceIds() {
let selectValueArr = [];
if (this.$refs.maxStepTree) {
let checkNodes = this.$refs.maxStepTree.getCheckedNodes();
for (let node of checkNodes) {
selectValueArr.push(node.resourceId);
}
}
return selectValueArr;
}, },
runScenario(scenario) { runScenario(scenario) {
this.$emit('runScenario', scenario); this.$emit('runScenario', scenario);
@ -945,47 +1085,148 @@ export default {
editScenarioAdvance(data) { editScenarioAdvance(data) {
this.$emit('editScenarioAdvance', data); this.$emit('editScenarioAdvance', data);
}, },
}
batchProcessing() {
this.isBatchProcess = true;
this.expandedNode = [];
this.hideAllTreeNode(this.scenarioDefinition);
if (this.$refs.maxStepTree && this.$refs.maxStepTree.root && this.$refs.maxStepTree.root.childNodes) {
this.stepCheckedAll(true, this.$refs.maxStepTree.root.childNodes);
}
if (this.$refs.maxStepTree && this.$refs.maxStepTree.root && this.$refs.maxStepTree.root.childNodes) {
this.stepCheckedAll(false, this.$refs.maxStepTree.root.childNodes);
}
this.reload();
},
cancelBatchProcessing() {
this.isBatchProcess = false;
this.isCheckedAll = false;
if (this.$refs.maxStepTree && this.$refs.maxStepTree.root && this.$refs.maxStepTree.root.childNodes) {
this.stepCheckedAll(true, this.$refs.maxStepTree.root.childNodes);
}
if (this.$refs.maxStepTree && this.$refs.maxStepTree.root && this.$refs.maxStepTree.root.childNodes) {
this.stepCheckedAll(false, this.$refs.maxStepTree.root.childNodes);
}
this.selectDataCounts = 0;
this.commandTreeNode();
this.reload();
},
commandTreeNode(node, array) {
if (!array) {
array = this.scenarioDefinition;
}
let isLeaf = true;
array.forEach(item => {
item.checkBox = false;
if (isLeaf && this.stepFilter.get('ALlSamplerStep').indexOf(item.type) === -1) {
isLeaf = false;
}
if (item.hashTree && item.hashTree.length > 0) {
this.commandTreeNode(item, item.hashTree);
}
})
if (node) {
node.isBatchProcess = this.isBatchProcess;
node.checkBox = false;
node.isLeaf = isLeaf;
}
},
checkedAll(v) {
if (this.$refs.maxStepTree && this.$refs.maxStepTree.root && this.$refs.maxStepTree.root.childNodes) {
this.stepCheckedAll(v, this.$refs.maxStepTree.root.childNodes);
}
},
stepCheckedAll(v, array) {
if (array) {
array.forEach(item => {
if (item.childNodes && item.childNodes.length > 0) {
this.stepCheckedAll(v, item.childNodes);
}
item.checked = v;
})
}
},
reloadTreeStatus() {
this.reloadKey = "";
this.$nextTick(() => {
this.reloadKey = "reload";
let row = {resourceId: "ms-reload-max-test"};
if (this.$refs.maxStepTree && this.$refs.maxStepTree.root.data) {
this.$refs.maxStepTree.root.data.push(row);
this.$refs.maxStepTree.root.data.splice(this.$refs.maxStepTree.root.data.length - 1, 1);
}
});
},
hideAllTreeNode(array) {
array.forEach(item => {
if (item.hashTree && item.hashTree.length > 0) {
this.hideAllTreeNode(item.hashTree);
}
item.isLeaf = this.isBatchProcess;
item.isBatchProcess = this.isBatchProcess;
item.checkBox = this.isBatchProcess;
})
},
handleExport() {
let name = this.$t('commons.report_statistics.test_case_analysis');
this.$nextTick(function () {
setTimeout(() => {
html2canvas(document.getElementById('reportAnalysis'), {
scale: 2
}).then(function (canvas) {
exportPdf(name, [canvas]);
});
}, 1000);
});
},
stop() {
this.debugLoading = false;
this.$emit('stop');
},
close() {
this.$emit('closePage', this.currentScenario.name);
},
unFullScreen() {
this.$emit('unFullScreen');
},
handleCommand() {
this.debug = false;
this.debugLoading = false;
this.$emit('handleCommand');
},
setCookieShare() {
this.$emit('setCookieShare', this.cookieShare);
},
setOnSampleError() {
this.$emit('setSampleError', this.sampleError);
},
showPopover() {
let definition = JSON.parse(JSON.stringify(this.currentScenario));
definition.hashTree = this.scenarioDefinition;
this.envResult.loading = true;
this.getEnv(JSON.stringify(definition)).then(() => {
this.$refs.envPopover.openEnvSelect();
this.envResult.loading = false;
})
},
getEnv(definition) {
return new Promise((resolve) => {
this.$post("/api/automation/getApiScenarioEnv", {definition: definition}, res => {
if (res.data) {
res.data.projectIds.push(this.projectId);
this.$emit("update:projectIds", new Set(res.data.projectIds));
this.$emit("update:isFullUrl", res.data.fullUrl);
}
resolve();
})
});
},
},
} }
</script> </script>
<style scoped> <style scoped>
.card-content {
height: calc(100vh - 196px);
overflow-y: auto;
}
.ms-scenario-input {
width: 100%;
}
.ms-main-div {
background-color: white;
}
.ms-debug-div {
border: 1px #DCDFE6 solid;
border-radius: 4px;
margin-right: 20px;
}
.ms-scenario-button {
margin-left: 20px;
padding: 7px;
}
.ms-api-col {
background-color: #7C3985;
border-color: #7C3985;
margin-right: 10px;
color: white;
}
.ms-font {
color: #303133;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
font-size: 13px;
}
.ms-col-one { .ms-col-one {
margin-top: 10px; margin-top: 10px;
@ -1075,53 +1316,15 @@ export default {
display: none; display: none;
} }
.scenario-aside {
min-width: 400px;
position: relative;
border-radius: 4px;
border: 1px solid #EBEEF5;
box-sizing: border-box;
}
.scenario-main {
position: relative;
margin-left: 20px;
border: 1px solid #EBEEF5;
}
.scenario-list {
overflow-y: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 28px;
}
.father:hover .child { .father:hover .child {
display: block; display: block;
} }
.ms-open-btn {
margin: 5px 5px 0px;
color: #6D317C;
font-size: 20px;
}
.ms-open-btn:hover {
background-color: #F2F9EE;
cursor: pointer;
color: #67C23A;
}
.ms-open-btn-left {
margin-left: 30px;
}
.ms-debug-result { .ms-debug-result {
float: right; font-size: 12px;
margin-right: 30px; margin-right: 20px;
margin-top: 3px; margin-top: 3px;
height: 20px;
} }
.ms-message-right { .ms-message-right {
@ -1129,7 +1332,13 @@ export default {
} }
.maximize-container .ms-aside-container { .maximize-container .ms-aside-container {
min-width: 680px; min-width: 500px;
}
.custom-tree-node-hide {
width: 10px;
padding: 0px;
vertical-align: center;
} }
.ms-aside-container { .ms-aside-container {
@ -1142,7 +1351,40 @@ export default {
} }
.custom-tree-node-col { .custom-tree-node-col {
width: 20px; width: 10px;
padding: 0px; padding: 0px;
} }
.ms-header {
border-bottom: 1px solid #E6E6E6;
width: 100%;
height: 36px;
background-color: #FFF;
font-size: 12px;
}
.ms-div {
margin-top: 10px;
}
.ms-min-alt-ico {
font-size: 15px;
margin: 10px 10px 0px;
float: right;
color: #8c939d;
}
.ms-min-alt-ico:hover {
color: black;
cursor: pointer;
}
.ms-batch-btn {
margin-left: 5px;
}
.ms-batch-btn:hover {
cursor: pointer;
color: #6D317C;
}
</style> </style>

View File

@ -1,276 +0,0 @@
<template>
<div class="ms-header">
<el-row>
<el-col :span="10">
<div class="ms-div" v-loading="loading" @click="showAll">
<!-- 调试部分 -->
<el-row class="ms-header-margin">
<el-col :span="8">
<el-tooltip placement="top" :content="currentScenario.name">
<span class="ms-scenario-name">{{ currentScenario.name }}</span>
</el-tooltip>
</el-col>
<el-col :span="8">
{{ $t('api_test.automation.step_total') }}{{ scenarioDefinition.length }}
</el-col>
<el-col :span="8">
<el-link class="head" @click="showScenarioParameters">{{ $t('api_test.automation.scenario_total') }}</el-link>
{{ varSize }}
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="14">
<div class="ms-header-right">
<el-checkbox v-model="cookieShare" @change="setCookieShare">共享cookie</el-checkbox>
<el-checkbox v-model="sampleError" @change="setOnSampleError" style="margin-right: 10px">{{ $t('commons.failure_continues') }}</el-checkbox>
<env-popover :disabled="scenarioDefinition.length < 1" :isReadOnly="scenarioDefinition.length < 1"
:env-map="envMap" :project-ids="projectIds" @setProjectEnvMap="setProjectEnvMap"
:environment-type.sync="envType" :group-id="envGroupId"
@showPopover="showPopover" :project-list="projectList" ref="envPopover" class="ms-right" :has-option-group="true"
:result="envResult"/>
<el-dropdown split-button type="primary" @click="runDebug" style="margin-right: 10px" size="mini" @command="handleCommand" v-if="!debug">
{{ $t('api_test.request.debug') }}
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>{{ $t('api_test.automation.generate_report') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button size="mini" type="primary" v-else @click="stop">{{ $t('report.stop_btn') }}</el-button>
<font-awesome-icon class="ms-alt-ico" :icon="['fa', 'compress-alt']" size="lg" @click="unFullScreen"/>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import {exportPdf, getCurrentProjectID} from "@/common/js/utils";
import html2canvas from 'html2canvas';
import EnvPopover from "../../scenario/EnvPopover";
export default {
name: "ScenarioHeader",
components: {EnvPopover},
props: {
currentScenario: {}, scenarioDefinition: Array, enableCookieShare: Boolean, onSampleError: Boolean,
projectEnvMap: Map,
environmentType: String,
groupId: String,
projectIds: Set,
projectList: Array,
isFullUrl: Boolean,
execDebug: String,
clearMessage: String,
},
data() {
return {
envMap: new Map,
envType: this.environmentType,
envGroupId: this.groupId,
loading: false,
varSize: 0,
cookieShare: false,
sampleError: true,
envResult: {
loading: false
},
debugLoading: false,
reqTotal: 0,
reqSuccess: 0,
reqError: 0,
reqTotalTime: 0,
debug: false,
}
},
computed: {
projectId() {
return getCurrentProjectID();
},
},
watch: {
envType(value) {
this.$emit("setEnvType", value);
},
envGroupId(value) {
this.$emit("setEnvGroupId", value);
},
execDebug() {
this.debug = false;
},
clearMessage() {
this.debug = false;
this.debugLoading = false;
}
},
mounted() {
this.envMap = this.projectEnvMap;
this.getVariableSize();
this.cookieShare = this.enableCookieShare;
this.sampleError = this.onSampleError;
},
methods: {
handleExport() {
let name = this.$t('commons.report_statistics.test_case_analysis');
this.$nextTick(function () {
setTimeout(() => {
html2canvas(document.getElementById('reportAnalysis'), {
scale: 2
}).then(function (canvas) {
exportPdf(name, [canvas]);
});
}, 1000);
});
},
stop() {
this.debug = false;
this.debugLoading = false;
this.$emit('stop');
},
showAll() {
this.$emit('showAllBtn');
},
close() {
this.$emit('closePage', this.currentScenario.name);
},
unFullScreen() {
this.$emit('unFullScreen');
},
runDebug() {
this.debug = true;
this.debugLoading = true;
this.$emit('runDebug');
},
handleCommand() {
this.debug = false;
this.debugLoading = false;
this.$emit('handleCommand');
},
setCookieShare() {
this.$emit('setCookieShare', this.cookieShare);
},
setOnSampleError() {
this.$emit('setSampleError', this.sampleError);
},
showScenarioParameters() {
this.$emit('showScenarioParameters');
},
getVariableSize() {
let size = 0;
if (this.currentScenario.variables) {
size += this.currentScenario.variables.length;
}
if (this.currentScenario.headers && this.currentScenario.headers.length > 1) {
size += this.currentScenario.headers.length - 1;
}
this.varSize = size;
this.reload();
},
reload() {
this.loading = true
this.$nextTick(() => {
this.loading = false
})
},
setProjectEnvMap(projectEnvMap) {
this.$emit('setProjectEnvMap', projectEnvMap);
this.envMap = projectEnvMap;
},
showPopover() {
let definition = JSON.parse(JSON.stringify(this.currentScenario));
definition.hashTree = this.scenarioDefinition;
this.envResult.loading = true;
this.getEnv(JSON.stringify(definition)).then(() => {
this.$refs.envPopover.openEnvSelect();
this.envResult.loading = false;
})
},
getEnv(definition) {
return new Promise((resolve) => {
this.$post("/api/automation/getApiScenarioEnv", {definition: definition}, res => {
if (res.data) {
res.data.projectIds.push(this.projectId);
this.$emit("update:projectIds", new Set(res.data.projectIds));
this.$emit("update:isFullUrl", res.data.fullUrl);
}
resolve();
})
});
},
},
}
</script>
<style scoped>
.ms-header {
border-bottom: 1px solid #E6E6E6;
height: 50px;
background-color: #FFF;
}
.ms-div {
float: left;
width: 60%;
margin-left: 20px;
margin-top: 12px;
}
.ms-header-right {
float: right;
margin-top: 4px;
z-index: 1;
}
.alt-ico-close {
font-size: 18px;
margin: 10px 10px 10px;
}
.alt-ico-close:hover {
color: black;
cursor: pointer;
}
.ms-alt-ico {
color: #8c939d;
font-size: 16px;
margin: 10px 30px 0px;
}
.ms-alt-ico:hover {
color: black;
cursor: pointer;
}
.ms-header-margin {
margin-top: 3px;
}
.ms-right {
margin-right: 40px;
}
.head {
border-bottom: 1px solid #303133;
color: #303133;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
font-size: 13px;
}
.ms-scenario-name {
display: inline-block;
margin: 0 5px;
overflow-x: hidden;
padding-bottom: 0;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
width: 200px;
}
</style>