fix(ui报告): 修改ui报告的样式

--bug=1024353 --user=宋天阳 【测试跟踪】测试计划执行报告,UI报告展示没有对齐
https://www.tapd.cn/55049933/s/1349610
This commit is contained in:
song-tianyang 2023-03-14 15:42:28 +08:00 committed by 建国
parent 094ca0b791
commit 96d88ba2de
3 changed files with 624 additions and 332 deletions

View File

@ -3,85 +3,147 @@
<el-row> <el-row>
<el-col> <el-col>
<span v-if="!debug"> <span v-if="!debug">
<el-input v-if="nameIsEdit" size="mini" @blur="handleSave(report.name)" @keyup.enter.native="handleSaveKeyUp" <el-input
style="width: 200px" v-model="report.name" maxlength="60" show-word-limit/> v-if="nameIsEdit"
size="mini"
@blur="handleSave(report.name)"
@keyup.enter.native="handleSaveKeyUp"
style="width: 200px"
v-model="report.name"
maxlength="60"
show-word-limit
/>
<span v-else> <span v-else>
<router-link v-if="isSingleScenario" <router-link
:to="{name: isUi ? 'uiAutomation' : 'ApiAutomation', params: { dataSelectRange: 'edit:' + scenarioId }}"> v-if="isSingleScenario"
:to="{
name: isUi ? 'uiAutomation' : 'ApiAutomation',
params: { dataSelectRange: 'edit:' + scenarioId },
}"
>
{{ report.name }} {{ report.name }}
</router-link> </router-link>
<span v-else> <span v-else>
{{ report.name }} {{ report.name }}
</span> </span>
<i v-if="showCancelButton" class="el-icon-edit" style="cursor:pointer" @click="nameIsEdit = true" <i
@click.stop/> v-if="showCancelButton"
class="el-icon-edit"
style="cursor: pointer"
@click="nameIsEdit = true"
@click.stop
/>
</span> </span>
</span> </span>
<span v-if="report.endTime || report.createTime"> <span v-if="report.endTime || report.createTime">
<span style="margin-left: 10px">{{ $t('report.test_start_time') }}</span> <span style="margin-left: 10px"
>{{ $t("report.test_start_time") }}</span
>
<span class="time"> {{ report.createTime | datetimeFormat }}</span> <span class="time"> {{ report.createTime | datetimeFormat }}</span>
<span style="margin-left: 10px">{{ $t('report.test_end_time') }}</span> <span style="margin-left: 10px"
>{{ $t("report.test_end_time") }}</span
>
<span class="time"> {{ report.endTime | datetimeFormat }}</span> <span class="time"> {{ report.endTime | datetimeFormat }}</span>
</span> </span>
<div style="float: right"> <div style="float: right">
<el-button v-if="!isPlan && (!debug || exportFlag) && !isTemplate && !isUi" <el-button
v-permission="['PROJECT_API_REPORT:READ+EXPORT']" :disabled="isReadOnly" class="export-button" v-if="!isPlan && (!debug || exportFlag) && !isTemplate && !isUi"
plain type="primary" size="mini" @click="handleExport(report.name)" style="margin-right: 10px"> v-permission="['PROJECT_API_REPORT:READ+EXPORT']"
{{ $t('test_track.plan_view.export_report') }} :disabled="isReadOnly"
class="export-button"
plain
type="primary"
size="mini"
@click="handleExport(report.name)"
style="margin-right: 10px"
>
{{ $t("test_track.plan_view.export_report") }}
</el-button> </el-button>
<el-popover <el-popover
v-if="!isPlan && (!debug || exportFlag) && !isTemplate" v-if="!isPlan && (!debug || exportFlag) && !isTemplate"
v-permission="['PROJECT_PERFORMANCE_REPORT:READ+EXPORT']" v-permission="['PROJECT_PERFORMANCE_REPORT:READ+EXPORT']"
style="margin-right: 10px;float: right;" style="margin-right: 10px; float: right"
placement="bottom" placement="bottom"
width="300"> width="300"
>
<p>{{ shareUrl }}</p> <p>{{ shareUrl }}</p>
<span style="color: red;float: left;margin-left: 10px;" v-if="application.typeValue">{{ <span
$t('commons.validity_period') + application.typeValue style="color: red; float: left; margin-left: 10px"
}}</span> v-if="application.typeValue"
>{{ $t("commons.validity_period") + application.typeValue }}</span
>
<div style="text-align: right; margin: 0"> <div style="text-align: right; margin: 0">
<el-button type="primary" size="mini" :disabled="!shareUrl" <el-button
v-clipboard:copy="shareUrl">{{ $t("commons.copy") }} type="primary"
size="mini"
:disabled="!shareUrl"
v-clipboard:copy="shareUrl"
>{{ $t("commons.copy") }}
</el-button> </el-button>
</div> </div>
<el-button slot="reference" :disabled="isReadOnly" type="danger" plain size="mini" <el-button
@click="handleShare(report)"> slot="reference"
{{ $t('test_track.plan_view.share_report') }} :disabled="isReadOnly"
type="danger"
plain
size="mini"
@click="handleShare(report)"
>
{{ $t("test_track.plan_view.share_report") }}
</el-button> </el-button>
</el-popover> </el-popover>
<el-button v-if="showRerunButton" class="rerun-button" plain size="mini" @click="rerun"> <el-button
{{ $t('api_test.automation.rerun') }} v-if="showRerunButton"
class="rerun-button"
plain
size="mini"
@click="rerun"
>
{{ $t("api_test.automation.rerun") }}
</el-button> </el-button>
<el-button v-if="showCancelButton" class="export-button" plain size="mini" @click="returnView"> <el-button
{{ $t('commons.cancel') }} v-if="showCancelButton"
class="export-button"
plain
size="mini"
@click="returnView"
>
{{ $t("commons.cancel") }}
</el-button> </el-button>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<el-row v-if="showProjectEnv" type="flex"> <el-row v-if="showProjectEnv" type="flex">
<span> {{ $t('commons.environment') + ':' }} </span> <span> {{ $t("commons.environment") + ":" }} </span>
<div v-for="(values,key) in projectEnvMap" :key="key" style="margin-right: 10px"> <div
v-for="(values, key) in projectEnvMap"
:key="key"
style="margin-right: 10px"
>
{{ key + ":" }} {{ key + ":" }}
<ms-tag v-for="(item,index) in values" :key="index" type="success" :content="item" <ms-tag
style="margin-left: 2px"/> v-for="(item, index) in values"
:key="index"
type="success"
:content="item"
style="margin-left: 2px"
/>
</div> </div>
</el-row> </el-row>
</header> </header>
</template> </template>
<script> <script>
import { generateShareInfoWithExpired, getShareRedirectUrl } from "@/api/share";
import {generateShareInfoWithExpired, getShareRedirectUrl} from "@/api/share";
import MsTag from "metersphere-frontend/src/components/MsTag"; import MsTag from "metersphere-frontend/src/components/MsTag";
import {getCurrentProjectID} from "@/business/utils/sdk-utils"; import { getCurrentProjectID } from "@/business/utils/sdk-utils";
export default { export default {
name: "MsApiReportViewHeader", name: "MsApiReportViewHeader",
components: {MsTag}, components: { MsTag },
props: { props: {
report: {}, report: {},
projectEnvMap: {}, projectEnvMap: {},
@ -99,17 +161,17 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
isPlan: Boolean isPlan: Boolean,
}, },
computed: { computed: {
showProjectEnv() { showProjectEnv() {
return this.projectEnvMap && JSON.stringify(this.projectEnvMap) !== '{}'; return this.projectEnvMap && JSON.stringify(this.projectEnvMap) !== "{}";
}, },
path() { path() {
return "/api/test/edit?id=" + this.report.testId; return "/api/test/edit?id=" + this.report.testId;
}, },
scenarioId() { scenarioId() {
if (typeof this.report.scenarioId === 'string') { if (typeof this.report.scenarioId === "string") {
return this.report.scenarioId; return this.report.scenarioId;
} else { } else {
return ""; return "";
@ -132,46 +194,45 @@ export default {
isReadOnly: false, isReadOnly: false,
nameIsEdit: false, nameIsEdit: false,
shareUrl: "", shareUrl: "",
application: {} application: {},
} };
},
created() {
}, },
created() {},
methods: { methods: {
handleExport(name) { handleExport(name) {
this.$emit('reportExport', name); this.$emit("reportExport", name);
}, },
handleSave(name) { handleSave(name) {
this.nameIsEdit = false; this.nameIsEdit = false;
this.$emit('reportSave', name); this.$emit("reportSave", name);
}, },
handleSaveKeyUp($event) { handleSaveKeyUp($event) {
$event.target.blur(); $event.target.blur();
}, },
rerun() { rerun() {
let type = this.report.reportType; let type = this.report.reportType;
let rerunObj = {type: type, reportId: this.report.id} let rerunObj = { type: type, reportId: this.report.id };
this.$post('/api/test/exec/rerun', rerunObj, res => { this.$post("/api/test/exec/rerun", rerunObj, (res) => {
if (res.data !== 'SUCCESS') { if (res.data !== "SUCCESS") {
this.$error(res.data); this.$error(res.data);
} else { } else {
this.$success(this.$t('api_test.automation.rerun_success')); this.$success(this.$t("api_test.automation.rerun_success"));
this.returnView(); this.returnView();
} }
}); });
}, },
returnView() { returnView() {
if (this.isUi) { if (this.isUi) {
this.$router.push('/ui/report'); this.$router.push("/ui/report");
} else { } else {
this.$router.push('/api/automation/report'); this.$router.push("/api/automation/report");
} }
}, },
handleShare(report) { handleShare(report) {
this.getProjectApplication(); this.getProjectApplication();
let pram = {}; let pram = {};
pram.customData = report.id; pram.customData = report.id;
pram.shareType = 'UI_REPORT'; pram.shareType = "UI_REPORT";
let thisHost = window.location.host; let thisHost = window.location.host;
generateShareInfoWithExpired(pram).then((res) => { generateShareInfoWithExpired(pram).then((res) => {
this.shareUrl = getShareRedirectUrl(res.data); this.shareUrl = getShareRedirectUrl(res.data);
@ -179,32 +240,41 @@ export default {
}, },
getProjectApplication() { getProjectApplication() {
let path = "/API_SHARE_REPORT_TIME"; let path = "/API_SHARE_REPORT_TIME";
if(this.isUi){ if (this.isUi) {
path = "/UI_SHARE_REPORT_TIME"; path = "/UI_SHARE_REPORT_TIME";
} }
this.$get('/project_application/get/' + getCurrentProjectID() + path).then(res => { this.$get(
"/project_application/get/" + getCurrentProjectID() + path
).then((res) => {
if (res.data && res.data.typeValue) { if (res.data && res.data.typeValue) {
let quantity = res.data.typeValue.substring(0, res.data.typeValue.length - 1); let quantity = res.data.typeValue.substring(
let unit = res.data.typeValue.substring(res.data.typeValue.length - 1); 0,
if (unit === 'H') { res.data.typeValue.length - 1
res.data.typeValue = quantity + this.$t('commons.date_unit.hour'); );
} else if (unit === 'D') { let unit = res.data.typeValue.substring(
res.data.typeValue = quantity + this.$t('commons.date_unit.day'); res.data.typeValue.length - 1
} else if (unit === 'M') { );
res.data.typeValue = quantity + this.$t('commons.workspace_unit') + this.$t('commons.date_unit.month'); if (unit === "H") {
} else if (unit === 'Y') { res.data.typeValue = quantity + this.$t("commons.date_unit.hour");
res.data.typeValue = quantity + this.$t('commons.date_unit.year'); } else if (unit === "D") {
res.data.typeValue = quantity + this.$t("commons.date_unit.day");
} else if (unit === "M") {
res.data.typeValue =
quantity +
this.$t("commons.workspace_unit") +
this.$t("commons.date_unit.month");
} else if (unit === "Y") {
res.data.typeValue = quantity + this.$t("commons.date_unit.year");
} }
this.application = res.data; this.application = res.data;
} }
}); });
}, },
} },
} };
</script> </script>
<style scoped> <style scoped>
.export-button { .export-button {
float: right; float: right;
margin-right: 10px; margin-right: 10px;
@ -213,7 +283,10 @@ export default {
.rerun-button { .rerun-button {
float: right; float: right;
margin-right: 10px; margin-right: 10px;
background-color: #F2F9EF; background-color: #f2f9ef;
color: #87C45D; color: #87c45d;
}
.report-header {
min-width: 1200px;
} }
</style> </style>

View File

@ -10,129 +10,251 @@
</el-row> </el-row>
<div v-if="isExport"> <div v-if="isExport">
<span class="ms-req ms-req-error" <span
v-if="(content.error && content.error>0 )|| (content.errorCode && content.errorCode>0)|| (content.unExecute && content.unExecute>0)"> class="ms-req ms-req-error"
<span class="ms-req-span"> {{ content.success + content.error + content.errorCode + content.unExecute }} {{ v-if="
isUi ? '指令' : $t('api_report.request') (content.error && content.error > 0) ||
}}</span> (content.errorCode && content.errorCode > 0) ||
(content.unExecute && content.unExecute > 0)
"
>
<span class="ms-req-span">
{{
content.success +
content.error +
content.errorCode +
content.unExecute
}}
{{ isUi ? "指令" : $t("api_report.request") }}</span
>
</span> </span>
<span class="ms-req ms-req-success" v-else> <span class="ms-req ms-req-success" v-else>
<span class="ms-req-span"> {{ <span class="ms-req-span">
content.success ? content.success + content.error : 0 {{ content.success ? content.success + content.error : 0 }}
}} {{ isUi ? '指令' : $t('api_report.request') }}</span> {{ isUi ? "指令" : $t("api_report.request") }}</span
>
</span> </span>
</div> </div>
<ms-chart id="chart" ref="chart" :options="options" :height="220" style="margin-right: 10px" <ms-chart
:autoresize="true" v-else/> id="chart"
<el-row type="flex" justify="center" align="middle" style="width: 150px"> ref="chart"
:options="options"
:height="220"
style="margin-right: 10px"
:autoresize="true"
v-else
/>
<el-row
type="flex"
justify="center"
align="middle"
style="width: 150px"
>
<div> <div>
<div class="metric-icon-box" style="height: 26px"> <div class="metric-icon-box" style="height: 26px">
<span class="ms-point-success" style="margin: 7px;float: left;"/> <span
class="ms-point-success"
style="margin: 7px; float: left"
/>
<div class="metric-box"> <div class="metric-box">
<div class="value" style="font-size: 12px">{{ content.success }} {{ $t('api_report.success') }}</div> <div class="value" style="font-size: 12px">
{{ content.success }} {{ $t("api_report.success") }}
</div>
</div> </div>
</div> </div>
<el-divider></el-divider> <el-divider></el-divider>
<div class="metric-icon-box" style="height: 26px"> <div class="metric-icon-box" style="height: 26px">
<span class="ms-point-error" style="margin: 7px;float: left;"/> <span class="ms-point-error" style="margin: 7px; float: left" />
<div class="metric-box"> <div class="metric-box">
<div class="value" style="font-size: 12px">{{ content.error }} {{ $t('api_report.fail') }}</div> <div class="value" style="font-size: 12px">
{{ content.error }} {{ $t("api_report.fail") }}
</div>
</div> </div>
</div> </div>
<el-divider v-if="content.errorCode > 0"></el-divider> <el-divider v-if="content.errorCode > 0"></el-divider>
<div class="metric-icon-box" v-if="content.errorCode > 0" style="height: 26px"> <div
<span class="ms-point-error-code" style="margin: 7px;float: left;"/> class="metric-icon-box"
v-if="content.errorCode > 0"
style="height: 26px"
>
<span
class="ms-point-error-code"
style="margin: 7px; float: left"
/>
<div class="metric-box" v-if="content.errorCode > 0"> <div class="metric-box" v-if="content.errorCode > 0">
<div class="value" style="font-size: 12px">{{ content.errorCode }} <div class="value" style="font-size: 12px">
{{ $t('error_report_library.option.name') }} {{ content.errorCode }}
{{ $t("error_report_library.option.name") }}
</div> </div>
</div> </div>
</div> </div>
<el-divider v-if="content.unExecute > 0"></el-divider> <el-divider v-if="content.unExecute > 0"></el-divider>
<div class="metric-icon-box" style="height: 26px" v-if="content.unExecute > 0"> <div
<span class="ms-point-unexecute" style="margin: 7px;float: left;"/> class="metric-icon-box"
style="height: 26px"
v-if="content.unExecute > 0"
>
<span
class="ms-point-unexecute"
style="margin: 7px; float: left"
/>
<div class="metric-box"> <div class="metric-box">
<div class="value" style="font-size: 12px">{{ content.unExecute }} <div class="value" style="font-size: 12px">
{{ $t('api_test.home_page.detail_card.unexecute') }} {{ content.unExecute }}
{{ $t("api_test.home_page.detail_card.unexecute") }}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</el-row> </el-row>
</el-row> </el-row>
</div> </div>
<div class="split"></div> <div class="split"></div>
<!-- 场景统计 --> <!-- 场景统计 -->
<div style="width: 50%"> <div style="width: 50%">
<el-row type="flex" justify="center" align="middle" v-if="report.reportType !== 'API_INTEGRATED'"> <el-row
type="flex"
justify="center"
align="middle"
v-if="report.reportType !== 'API_INTEGRATED'"
>
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioTotal ? content.scenarioTotal : 0 }}</div> <div class="value">
<div class="name">{{ $t('api_test.scenario.scenario') }}</div> {{ content.scenarioTotal ? content.scenarioTotal : 0 }}
</div> </div>
<span class="ms-point-success"/> <div class="name">{{ $t("api_test.scenario.scenario") }}</div>
</div>
<span class="ms-point-success" />
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioSuccess ? content.scenarioSuccess : 0 }}</div> <div class="value">
<div class="name">{{ $t('api_report.success') }}</div> {{ content.scenarioSuccess ? content.scenarioSuccess : 0 }}
</div> </div>
<span class="ms-point-error"/> <div class="name">{{ $t("api_report.success") }}</div>
</div>
<span class="ms-point-error" />
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioError ? content.scenarioError : 0 }}</div> <div class="value">
<div class="name">{{ $t('api_report.fail') }}</div> {{ content.scenarioError ? content.scenarioError : 0 }}
</div> </div>
<span class="ms-point-error-code" <div class="name">{{ $t("api_report.fail") }}</div>
v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 "/>
<div class="metric-box" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 ">
<div class="value">{{ content.scenarioErrorReport ? content.scenarioErrorReport : 0 }}</div>
<div class="name">{{ $t('error_report_library.option.name') }}</div>
</div> </div>
<span v-show="showUnExecuteReport" class="ms-point-unexecute"/> <span
class="ms-point-error-code"
v-if="
content.scenarioErrorReport > 0 ||
content.scenarioStepErrorReport > 0
"
/>
<div
class="metric-box"
v-if="
content.scenarioErrorReport > 0 ||
content.scenarioStepErrorReport > 0
"
>
<div class="value">
{{
content.scenarioErrorReport ? content.scenarioErrorReport : 0
}}
</div>
<div class="name">{{ $t("error_report_library.option.name") }}</div>
</div>
<span v-show="showUnExecuteReport" class="ms-point-unexecute" />
<div v-show="showUnExecuteReport" class="metric-box"> <div v-show="showUnExecuteReport" class="metric-box">
<div class="value">{{ content.scenarioUnExecute ? content.scenarioUnExecute : 0 }}</div> <div class="value">
<div class="name">{{ $t('api_test.home_page.detail_card.unexecute') }}</div> {{ content.scenarioUnExecute ? content.scenarioUnExecute : 0 }}
</div>
<div class="name">
{{ $t("api_test.home_page.detail_card.unexecute") }}
</div>
</div> </div>
</el-row> </el-row>
<el-divider v-if="report.reportType !== 'API_INTEGRATED'"/> <el-divider v-if="report.reportType !== 'API_INTEGRATED'" />
<el-row type="flex" justify="center" align="middle"> <el-row type="flex" justify="center" align="middle">
<el-row type="flex" justify="center" align="middle"> <el-row type="flex" justify="center" align="middle">
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioStepTotal ? content.scenarioStepTotal : 0 }}</div> <div class="value">
{{ content.scenarioStepTotal ? content.scenarioStepTotal : 0 }}
</div>
<div class="name" v-if="report.reportType === 'API_INTEGRATED'"> <div class="name" v-if="report.reportType === 'API_INTEGRATED'">
{{ $t('api_test.definition.request.case') }} {{ $t("api_test.definition.request.case") }}
</div> </div>
<div class="name" v-else>{{ $t('test_track.plan_view.step') }}</div> <div class="name" v-else>
{{ $t("test_track.plan_view.step") }}
</div> </div>
<span class="ms-point-success"/> </div>
<span class="ms-point-success" />
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioStepSuccess ? content.scenarioStepSuccess : 0 }}</div> <div class="value">
<div class="name">{{ $t('api_report.success') }}</div> {{
content.scenarioStepSuccess ? content.scenarioStepSuccess : 0
}}
</div> </div>
<span class="ms-point-error"/> <div class="name">{{ $t("api_report.success") }}</div>
</div>
<span class="ms-point-error" />
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioStepError ? content.scenarioStepError : 0 }}</div> <div class="value">
<div class="name">{{ $t('api_report.fail') }}</div> {{ content.scenarioStepError ? content.scenarioStepError : 0 }}
</div> </div>
<span class="ms-point-error-code" <div class="name">{{ $t("api_report.fail") }}</div>
v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 "/>
<div class="metric-box" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 ">
<div class="value">{{ content.scenarioStepErrorReport ? content.scenarioStepErrorReport : 0 }}</div>
<div class="name">{{ $t('error_report_library.option.name') }}</div>
</div> </div>
<span v-show="showUnExecuteReport && !isUi" class="ms-point-unexecute"/> <span
class="ms-point-error-code"
v-if="
content.scenarioErrorReport > 0 ||
content.scenarioStepErrorReport > 0
"
/>
<div
class="metric-box"
v-if="
content.scenarioErrorReport > 0 ||
content.scenarioStepErrorReport > 0
"
>
<div class="value">
{{
content.scenarioStepErrorReport
? content.scenarioStepErrorReport
: 0
}}
</div>
<div class="name">
{{ $t("error_report_library.option.name") }}
</div>
</div>
<span
v-show="showUnExecuteReport && !isUi"
class="ms-point-unexecute"
/>
<div v-show="showUnExecuteReport && !isUi" class="metric-box"> <div v-show="showUnExecuteReport && !isUi" class="metric-box">
<div class="value">{{ <div class="value">
content.scenarioStepUnExecuteReport ? content.scenarioStepUnExecuteReport : 0 {{
content.scenarioStepUnExecuteReport
? content.scenarioStepUnExecuteReport
: 0
}} }}
</div> </div>
<div class="name">{{ $t('api_test.home_page.detail_card.unexecute') }}</div> <div class="name">
{{ $t("api_test.home_page.detail_card.unexecute") }}
</div> </div>
<span v-show="showUnExecuteReport && isUi" class="ms-point-unexecute"/> </div>
<span
v-show="showUnExecuteReport && isUi"
class="ms-point-unexecute"
/>
<div v-show="showUnExecuteReport && isUi" class="metric-box"> <div v-show="showUnExecuteReport && isUi" class="metric-box">
<div class="value">{{ <div class="value">
content.scenarioStepUnExecuteReport ? content.scenarioStepUnExecuteReport : 0 {{
content.scenarioStepUnExecuteReport
? content.scenarioStepUnExecuteReport
: 0
}} }}
</div> </div>
<div class="name">{{ $t('api_test.home_page.detail_card.unexecute') }}</div> <div class="name">
{{ $t("api_test.home_page.detail_card.unexecute") }}
</div>
</div> </div>
</el-row> </el-row>
</el-row> </el-row>
@ -144,22 +266,24 @@
<div class="metric-icon-box"> <div class="metric-icon-box">
<i class="el-icon-warning-outline fail"></i> <i class="el-icon-warning-outline fail"></i>
<div class="value">{{ fail }}</div> <div class="value">{{ fail }}</div>
<div class="name">{{ $t('api_report.fail') }}</div> <div class="name">{{ $t("api_report.fail") }}</div>
</div> </div>
<div class="metric-icon-box"> <div class="metric-icon-box">
<i class="el-icon-document-checked assertions"></i> <i class="el-icon-document-checked assertions"></i>
<div class="value">{{ assertions }}</div> <div class="value">{{ assertions }}</div>
<div class="name">{{ $t('api_report.assertions_pass') }}</div> <div class="name">{{ $t("api_report.assertions_pass") }}</div>
</div> </div>
<div class="metric-icon-box" v-if="content.errorCode > 0"> <div class="metric-icon-box" v-if="content.errorCode > 0">
<i class="el-icon-document-checked assertions"></i> <i class="el-icon-document-checked assertions"></i>
<div class="value">{{ errorCodeAssertions }}</div> <div class="value">{{ errorCodeAssertions }}</div>
<div class="name">{{ $t('error_report_library.assertion') }}</div> <div class="name">{{ $t("error_report_library.assertion") }}</div>
</div> </div>
<div class="metric-icon-box" v-if="!isUi"> <div class="metric-icon-box" v-if="!isUi">
<i class="el-icon-document-copy total"></i> <i class="el-icon-document-copy total"></i>
<div class="value">{{ this.content.total }}</div> <div class="value">{{ this.content.total }}</div>
<div class="name">{{ isUi ? '指令' : $t('api_report.request') }}</div> <div class="name">
{{ isUi ? "指令" : $t("api_report.request") }}
</div>
</div> </div>
</el-row> </el-row>
</div> </div>
@ -172,7 +296,7 @@ import MsChart from "metersphere-frontend/src/components/chart/MsChart";
export default { export default {
name: "MsMetricChart", name: "MsMetricChart",
components: {MsChart}, components: { MsChart },
props: { props: {
report: Object, report: Object,
content: Object, content: Object,
@ -180,7 +304,7 @@ export default {
isExport: { isExport: {
type: Boolean, type: Boolean,
default: false, default: false,
} },
}, },
data() { data() {
return { return {
@ -192,7 +316,7 @@ export default {
scenarioSuccess: 0, scenarioSuccess: 0,
scenarioError: 0, scenarioError: 0,
reqTotal: 0, reqTotal: 0,
} };
}, },
created() { created() {
this.initTime(); this.initTime();
@ -200,25 +324,25 @@ export default {
methods: { methods: {
initTime() { initTime() {
this.time = this.totalTime; this.time = this.totalTime;
this.seconds = (this.time) / 1000; this.seconds = this.time / 1000;
if (this.seconds >= 1) { if (this.seconds >= 1) {
if (this.seconds < 60) { if (this.seconds < 60) {
this.seconds = Math.round(this.seconds * 100 / 1) / 100; this.seconds = Math.round((this.seconds * 100) / 1) / 100;
this.time = this.seconds + "s" this.time = this.seconds + "s";
} }
if (this.seconds > 60) { if (this.seconds > 60) {
this.minutes = Math.round(this.seconds / 60) this.minutes = Math.round(this.seconds / 60);
this.seconds = Math.round(this.seconds * 100 % 60) / 100; this.seconds = Math.round((this.seconds * 100) % 60) / 100;
this.time = this.minutes + "min" + this.seconds + "s" this.time = this.minutes + "min" + this.seconds + "s";
} }
if (this.minutes > 60) { if (this.minutes > 60) {
this.hour = Math.round(this.minutes / 60) this.hour = Math.round(this.minutes / 60);
this.minutes = Math.round(this.minutes % 60) this.minutes = Math.round(this.minutes % 60);
this.time = this.hour + "hour" + this.minutes + "min" + this.seconds + "s" this.time =
this.hour + "hour" + this.minutes + "min" + this.seconds + "s";
} }
} else { } else {
this.time = this.totalTime + "ms" this.time = this.totalTime + "ms";
} }
}, },
}, },
@ -241,36 +365,38 @@ export default {
}, },
options() { options() {
return { return {
color: ['#67C23A', '#F56C6C', '#F6972A', '#9C9B9A'], color: ["#67C23A", "#F56C6C", "#F6972A", "#9C9B9A"],
tooltip: { tooltip: {
trigger: 'item', trigger: "item",
formatter: '{b}: {c} ({d}%)' formatter: "{b}: {c} ({d}%)",
}, },
title: [{ title: [
{
text: this.totalCount, text: this.totalCount,
subtext: this.isUi ? '指令' : this.$t('api_report.request'), subtext: this.isUi ? "指令" : this.$t("api_report.request"),
top: 'center', top: "center",
left: 'center', left: "center",
textStyle: { textStyle: {
rich: { rich: {
align: 'center', align: "center",
value: { value: {
fontSize: 32, fontSize: 32,
fontWeight: 'bold', fontWeight: "bold",
padding: [10, 0] padding: [10, 0],
}, },
name: { name: {
fontSize: 14, fontSize: 14,
fontWeight: 'normal', fontWeight: "normal",
color: '#7F7F7F', color: "#7F7F7F",
} },
} },
} },
}], },
],
series: [ series: [
{ {
type: 'pie', type: "pie",
radius: ['80%', '90%'], radius: ["80%", "90%"],
avoidLabelOverlap: false, avoidLabelOverlap: false,
hoverAnimation: false, hoverAnimation: false,
label: { label: {
@ -278,24 +404,33 @@ export default {
}, },
itemStyle: { itemStyle: {
borderColor: "#FFF", borderColor: "#FFF",
shadowColor: '#E1E1E1', shadowColor: "#E1E1E1",
shadowBlur: 10 shadowBlur: 10,
}, },
labelLine: { labelLine: {
show: false show: false,
}, },
data: [ data: [
{value: this.content.success, name: this.$t('api_report.success')}, {
{value: this.content.error, name: this.$t('api_report.fail')}, value: this.content.success,
{value: this.content.errorCode, name: this.$t('error_report_library.option.name')}, name: this.$t("api_report.success"),
{value: this.content.unExecute, name: this.$t('api_test.home_page.detail_card.unexecute')}, },
] { value: this.content.error, name: this.$t("api_report.fail") },
} {
] value: this.content.errorCode,
name: this.$t("error_report_library.option.name"),
},
{
value: this.content.unExecute,
name: this.$t("api_test.home_page.detail_card.unexecute"),
},
],
},
],
}; };
}, },
fail() { fail() {
return (this.content.error / this.content.total * 100).toFixed(0) + "%"; return ((this.content.error / this.content.total) * 100).toFixed(0) + "%";
}, },
assertions() { assertions() {
return this.content.passAssertions + " / " + this.content.totalAssertions; return this.content.passAssertions + " / " + this.content.totalAssertions;
@ -307,16 +442,22 @@ export default {
return this.report.reportType && this.report.reportType.startsWith("UI"); return this.report.reportType && this.report.reportType.startsWith("UI");
}, },
showUnExecuteReport() { showUnExecuteReport() {
return (this.content.scenarioStepUnExecuteReport && this.content.scenarioStepUnExecuteReport > 0) return (
|| (this.content.scenarioUnExecute && this.content.scenarioUnExecute > 0) || (this.content.unExecute && this.content.unExecute > 0); (this.content.scenarioStepUnExecuteReport &&
this.content.scenarioStepUnExecuteReport > 0) ||
(this.content.scenarioUnExecute &&
this.content.scenarioUnExecute > 0) ||
(this.content.unExecute && this.content.unExecute > 0)
);
}, },
}, },
} };
</script> </script>
<style scoped> <style scoped>
.metric-container { .metric-container {
padding: 5px 10px; padding: 5px 10px;
min-width: 1200px;
} }
.metric-container #chart { .metric-container #chart {
@ -328,25 +469,25 @@ export default {
.metric-container .split { .metric-container .split {
margin: 20px; margin: 20px;
height: 100px; height: 100px;
border-left: 1px solid #D8DBE1; border-left: 1px solid #d8dbe1;
} }
.metric-container .circle { .metric-container .circle {
width: 12px; width: 12px;
height: 12px; height: 12px;
border-radius: 50%; border-radius: 50%;
box-shadow: 0 0 20px 1px rgba(200, 216, 226, .42); box-shadow: 0 0 20px 1px rgba(200, 216, 226, 0.42);
display: inline-block; display: inline-block;
margin-right: 10px; margin-right: 10px;
vertical-align: middle; vertical-align: middle;
} }
.metric-container .circle.success { .metric-container .circle.success {
background-color: #67C23A; background-color: #67c23a;
} }
.metric-container .circle.fail { .metric-container .circle.fail {
background-color: #F56C6C; background-color: #f56c6c;
} }
.metric-box { .metric-box {
@ -358,18 +499,18 @@ export default {
.metric-box .value { .metric-box .value {
font-size: 32px; font-size: 32px;
font-weight: 600; font-weight: 600;
letter-spacing: -.5px; letter-spacing: -0.5px;
} }
.metric-time .value { .metric-time .value {
font-size: 25px; font-size: 25px;
font-weight: 400; font-weight: 400;
letter-spacing: -.5px; letter-spacing: -0.5px;
} }
.metric-box .name { .metric-box .name {
font-size: 16px; font-size: 16px;
letter-spacing: -.2px; letter-spacing: -0.2px;
color: #404040; color: #404040;
} }
@ -381,7 +522,7 @@ export default {
.metric-icon-box .value { .metric-icon-box .value {
font-size: 20px; font-size: 20px;
font-weight: 600; font-weight: 600;
letter-spacing: -.4px; letter-spacing: -0.4px;
line-height: 28px; line-height: 28px;
vertical-align: middle; vertical-align: middle;
} }
@ -389,12 +530,12 @@ export default {
.metric-icon-box .name { .metric-icon-box .name {
font-size: 13px; font-size: 13px;
letter-spacing: 1px; letter-spacing: 1px;
color: #BFBFBF; color: #bfbfbf;
line-height: 18px; line-height: 18px;
} }
.metric-icon-box .fail { .metric-icon-box .fail {
color: #F56C6C; color: #f56c6c;
font-size: 40px; font-size: 40px;
} }
@ -416,11 +557,11 @@ export default {
} }
.ms-req-error { .ms-req-error {
border: 5px #F56C6C solid; border: 5px #f56c6c solid;
} }
.ms-req-success { .ms-req-success {
border: 5px #67C23A solid; border: 5px #67c23a solid;
} }
.ms-req-span { .ms-req-span {
@ -440,7 +581,7 @@ export default {
vertical-align: top; vertical-align: top;
margin-left: 20px; margin-left: 20px;
margin-right: 20px; margin-right: 20px;
background-color: #67C23A; background-color: #67c23a;
} }
.ms-point-error { .ms-point-error {
@ -452,7 +593,7 @@ export default {
vertical-align: top; vertical-align: top;
margin-left: 20px; margin-left: 20px;
margin-right: 20px; margin-right: 20px;
background-color: #F56C6C; background-color: #f56c6c;
} }
.ms-point-error-code { .ms-point-error-code {
@ -464,7 +605,7 @@ export default {
vertical-align: top; vertical-align: top;
margin-left: 20px; margin-left: 20px;
margin-right: 20px; margin-right: 20px;
background-color: #F6972A; background-color: #f6972a;
} }
.ms-point-unexecute { .ms-point-unexecute {
@ -476,6 +617,6 @@ export default {
vertical-align: top; vertical-align: top;
margin-left: 20px; margin-left: 20px;
margin-right: 20px; margin-right: 20px;
background-color: #9C9B9A; background-color: #9c9b9a;
} }
</style> </style>

View File

@ -13,14 +13,22 @@
:report="report" :report="report"
:project-env-map="projectEnvMap" :project-env-map="projectEnvMap"
@reportExport="handleExport" @reportExport="handleExport"
@reportSave="handleSave"/> @reportSave="handleSave"
/>
<!-- content --> <!-- content -->
<main v-if="isNotRunning"> <main v-if="isNotRunning">
<!-- content header chart --> <!-- content header chart -->
<ms-metric-chart :content="content" :totalTime="totalTime" :report="report"/> <ms-metric-chart
:content="content"
<el-tabs v-model="activeName" @tab-click="handleClick"> :totalTime="totalTime"
:report="report"
/>
<el-tabs
v-model="activeName"
@tab-click="handleClick"
style="min-width: 1200px"
>
<!-- all step--> <!-- all step-->
<el-tab-pane :label="$t('api_report.total')" name="total"> <el-tab-pane :label="$t('api_report.total')" name="total">
<ms-scenario-results <ms-scenario-results
@ -31,12 +39,13 @@
:is-share="isShare" :is-share="isShare"
:share-id="shareId" :share-id="shareId"
v-on:requestResult="requestResult" v-on:requestResult="requestResult"
ref="resultsTree"/> ref="resultsTree"
/>
</el-tab-pane> </el-tab-pane>
<!-- fail step --> <!-- fail step -->
<el-tab-pane name="fail"> <el-tab-pane name="fail">
<template slot="label"> <template slot="label">
<span class="fail">{{ $t('api_report.fail') }}</span> <span class="fail">{{ $t("api_report.fail") }}</span>
</template> </template>
<ms-scenario-results <ms-scenario-results
v-on:requestResult="requestResult" v-on:requestResult="requestResult"
@ -45,14 +54,16 @@
:is-share="isShare" :is-share="isShare"
:is-template="isTemplate" :is-template="isTemplate"
:share-id="shareId" :share-id="shareId"
:treeData="fullTreeNodes" ref="failsTree" :treeData="fullTreeNodes"
:errorReport="content.error"/> ref="failsTree"
:errorReport="content.error"
/>
</el-tab-pane> </el-tab-pane>
<!--error step --> <!--error step -->
<el-tab-pane name="errorReport" v-if="content.errorCode > 0"> <el-tab-pane name="errorReport" v-if="content.errorCode > 0">
<template slot="label"> <template slot="label">
<span class="fail" style="color: #F6972A"> <span class="fail" style="color: #f6972a">
{{ $t('error_report_library.option.name') }} {{ $t("error_report_library.option.name") }}
</span> </span>
</template> </template>
<ms-scenario-results <ms-scenario-results
@ -62,14 +73,15 @@
:is-template="isTemplate" :is-template="isTemplate"
:share-id="shareId" :share-id="shareId"
:console="content.console" :console="content.console"
:treeData="fullTreeNodes" ref="errorReportTree"/> :treeData="fullTreeNodes"
ref="errorReportTree"
/>
</el-tab-pane> </el-tab-pane>
<!-- Not performed step --> <!-- Not performed step -->
<el-tab-pane name="unExecute" v-if="content.unExecute > 0"> <el-tab-pane name="unExecute" v-if="content.unExecute > 0">
<template slot="label"> <template slot="label">
<span class="fail" <span class="fail" style="color: #9c9b9a">
style="color: #9C9B9A"> {{ $t("api_test.home_page.detail_card.unexecute") }}
{{ $t('api_test.home_page.detail_card.unexecute') }}
</span> </span>
</template> </template>
<ms-scenario-results <ms-scenario-results
@ -79,18 +91,23 @@
:is-template="isTemplate" :is-template="isTemplate"
:share-id="shareId" :share-id="shareId"
:console="content.console" :console="content.console"
:treeData="fullTreeNodes" ref="unExecuteTree"/> :treeData="fullTreeNodes"
ref="unExecuteTree"
/>
</el-tab-pane> </el-tab-pane>
<!-- console --> <!-- console -->
<el-tab-pane name="console"> <el-tab-pane name="console">
<template slot="label"> <template slot="label">
<span class="console">{{ $t('api_test.definition.request.console') }}</span> <span class="console">{{
$t("api_test.definition.request.console")
}}</span>
</template> </template>
<ms-code-edit <ms-code-edit
:mode="'text'" :mode="'text'"
:read-only="true" :read-only="true"
:data.sync="content.console" :data.sync="content.console"
height="calc(100vh - 500px)"/> height="calc(100vh - 500px)"
/>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</main> </main>
@ -101,7 +118,6 @@
</template> </template>
<script> <script>
import MsRequestResult from "./RequestResult"; import MsRequestResult from "./RequestResult";
import MsRequestResultTail from "./RequestResultTail"; import MsRequestResultTail from "./RequestResultTail";
import MsScenarioResult from "./ScenarioResult"; import MsScenarioResult from "./ScenarioResult";
@ -110,10 +126,19 @@ import MsScenarioResults from "./ScenarioResults";
import MsContainer from "metersphere-frontend/src/components/MsContainer"; import MsContainer from "metersphere-frontend/src/components/MsContainer";
import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer"; import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer";
import MsApiReportViewHeader from "./ApiReportViewHeader"; import MsApiReportViewHeader from "./ApiReportViewHeader";
import {STEP} from "./Setting"; import { STEP } from "./Setting";
import MsCodeEdit from "metersphere-frontend/src/components/MsCodeEdit"; import MsCodeEdit from "metersphere-frontend/src/components/MsCodeEdit";
import {getCurrentProjectID, getUUID, hasLicense, windowPrint} from "@/business/utils/sdk-utils"; import {
import {getScenarioReport, getScenarioReportAll, getShareScenarioReport} from "@/api/ui-report"; getCurrentProjectID,
getUUID,
hasLicense,
windowPrint,
} from "@/business/utils/sdk-utils";
import {
getScenarioReport,
getScenarioReportAll,
getShareScenarioReport,
} from "@/api/ui-report";
export default { export default {
name: "UiShareReportDetail", name: "UiShareReportDetail",
@ -121,7 +146,12 @@ export default {
MsApiReportViewHeader, MsApiReportViewHeader,
MsMainContainer, MsMainContainer,
MsCodeEdit, MsCodeEdit,
MsContainer, MsScenarioResults, MsRequestResultTail, MsMetricChart, MsScenarioResult, MsRequestResult MsContainer,
MsScenarioResults,
MsRequestResultTail,
MsMetricChart,
MsScenarioResult,
MsRequestResult,
}, },
data() { data() {
return { return {
@ -139,11 +169,11 @@ export default {
reportExportVisible: false, reportExportVisible: false,
fullTreeNodes: [], fullTreeNodes: [],
showRerunButton: false, showRerunButton: false,
stepFilter: new STEP, stepFilter: new STEP(),
exportReportIsOk: false, exportReportIsOk: false,
tempResult: [], tempResult: [],
projectEnvMap: {}, projectEnvMap: {},
} };
}, },
activated() { activated() {
this.isRequestResult = false; this.isRequestResult = false;
@ -160,8 +190,8 @@ export default {
isPlan: Boolean, isPlan: Boolean,
showCancelButton: { showCancelButton: {
type: Boolean, type: Boolean,
default: true default: true,
} },
}, },
watch: { watch: {
reportId() { reportId() {
@ -173,7 +203,7 @@ export default {
if (this.isTemplate) { if (this.isTemplate) {
this.getReport(); this.getReport();
} }
} },
}, },
methods: { methods: {
filter(index) { filter(index) {
@ -198,20 +228,32 @@ export default {
this.showRerunButton = false; this.showRerunButton = false;
}, },
rerunVerify() { rerunVerify() {
if (hasLicense() && this.fullTreeNodes && this.fullTreeNodes.length > 0 && !this.isShare) { if (
this.fullTreeNodes.forEach(item => { hasLicense() &&
this.fullTreeNodes &&
this.fullTreeNodes.length > 0 &&
!this.isShare
) {
this.fullTreeNodes.forEach((item) => {
item.redirect = true; item.redirect = true;
if (item.totalStatus === 'fail' || item.totalStatus === 'error' || item.unExecuteTotal > 0 if (
|| (item.type === "API" && item.totalStatus === 'unexecute')) { item.totalStatus === "fail" ||
item.totalStatus === "error" ||
item.unExecuteTotal > 0 ||
(item.type === "API" && item.totalStatus === "unexecute")
) {
this.showRerunButton = true; this.showRerunButton = true;
} }
} });
)
} }
}, },
handleClick(tab, event) { handleClick(tab, event) {
this.isRequestResult = false; this.isRequestResult = false;
if (this.report && this.report.reportVersion && this.report.reportVersion > 1) { if (
this.report &&
this.report.reportVersion &&
this.report.reportVersion > 1
) {
this.filter(tab.index); this.filter(tab.index);
} }
}, },
@ -219,28 +261,28 @@ export default {
this.isActive = !this.isActive; this.isActive = !this.isActive;
}, },
formatResult(res) { formatResult(res) {
let resMap = new Map; let resMap = new Map();
let array = []; let array = [];
if (res && res.scenarios) { if (res && res.scenarios) {
res.scenarios.forEach(item => { res.scenarios.forEach((item) => {
if (item && item.requestResults) { if (item && item.requestResults) {
item.requestResults.forEach(req => { item.requestResults.forEach((req) => {
req.responseResult.console = res.console; req.responseResult.console = res.console;
resMap.set(req.id + req.name, req); resMap.set(req.id + req.name, req);
req.name = item.name + "^@~@^" + req.name + "UUID=" + getUUID(); req.name = item.name + "^@~@^" + req.name + "UUID=" + getUUID();
array.push(req); array.push(req);
}) });
} }
}) });
} }
this.formatTree(array, this.fullTreeNodes); this.formatTree(array, this.fullTreeNodes);
this.sort(this.fullTreeNodes); this.sort(this.fullTreeNodes);
this.$emit('refresh', resMap); this.$emit("refresh", resMap);
}, },
formatTree(array, tree) { formatTree(array, tree) {
array.map((item) => { array.map((item) => {
let key = item.name; let key = item.name;
let nodeArray = key.split('^@~@^'); let nodeArray = key.split("^@~@^");
let children = tree; let children = tree;
//1 //1
//hashTreeID //hashTreeID
@ -263,11 +305,13 @@ export default {
label: nodeArray[i], label: nodeArray[i],
value: item, value: item,
}; };
if (i !== (nodeArray.length - 1)) { if (i !== nodeArray.length - 1) {
node.children = []; node.children = [];
} else { } else {
if (item.subRequestResults && item.subRequestResults.length > 0) { if (item.subRequestResults && item.subRequestResults.length > 0) {
let itemChildren = this.deepFormatTreeNode(item.subRequestResults); let itemChildren = this.deepFormatTreeNode(
item.subRequestResults
);
node.children = itemChildren; node.children = itemChildren;
if (node.label.indexOf("UUID=")) { if (node.label.indexOf("UUID=")) {
node.label = node.label.split("UUID=")[0]; node.label = node.label.split("UUID=")[0];
@ -281,7 +325,6 @@ export default {
let isExist = false; let isExist = false;
for (let j in children) { for (let j in children) {
if (children[j].label === node.label) { if (children[j].label === node.label) {
let idIsPath = true; let idIsPath = true;
//ID //ID
// //
@ -312,7 +355,8 @@ export default {
if (i !== nodeArray.length - 1 && !children[j].children) { if (i !== nodeArray.length - 1 && !children[j].children) {
children[j].children = []; children[j].children = [];
} }
children = (i === nodeArray.length - 1 ? children : children[j].children); children =
i === nodeArray.length - 1 ? children : children[j].children;
isExist = true; isExist = true;
break; break;
} }
@ -320,21 +364,27 @@ export default {
} }
if (!isExist) { if (!isExist) {
children.push(node); children.push(node);
if (i !== nodeArray.length - 1 && !children[children.length - 1].children) { if (
i !== nodeArray.length - 1 &&
!children[children.length - 1].children
) {
children[children.length - 1].children = []; children[children.length - 1].children = [];
} }
children = (i === nodeArray.length - 1 ? children : children[children.length - 1].children); children =
i === nodeArray.length - 1
? children
: children[children.length - 1].children;
} }
} }
}) });
}, },
deepFormatTreeNode(array) { deepFormatTreeNode(array) {
let returnChildren = []; let returnChildren = [];
array.map((item) => { array.map((item) => {
let children = []; let children = [];
let key = item.name.split('^@~@^')[0]; let key = item.name.split("^@~@^")[0];
let nodeArray = key.split('<->'); let nodeArray = key.split("<->");
//1 //1
//hashTreeID //hashTreeID
let scenarioId = ""; let scenarioId = "";
@ -351,17 +401,16 @@ export default {
let node = { let node = {
label: nodeArray[0], label: nodeArray[0],
value: item, value: item,
children: [] children: [],
}; };
if (item.subRequestResults && item.subRequestResults.length > 0) { if (item.subRequestResults && item.subRequestResults.length > 0) {
let itemChildren = this.deepFormatTreeNode(item.subRequestResults); let itemChildren = this.deepFormatTreeNode(item.subRequestResults);
node.children = itemChildren; node.children = itemChildren;
} }
children.push(node); children.push(node);
children.forEach(itemNode => { children.forEach((itemNode) => {
returnChildren.push(itemNode); returnChildren.push(itemNode);
}); });
}); });
return returnChildren; return returnChildren;
}, },
@ -380,7 +429,10 @@ export default {
// //
if (scenarioDefinition[i]) { if (scenarioDefinition[i]) {
scenarioDefinition[i].index = Number(i) + 1; scenarioDefinition[i].index = Number(i) + 1;
if (scenarioDefinition[i].children && scenarioDefinition[i].children.length > 0) { if (
scenarioDefinition[i].children &&
scenarioDefinition[i].children.length > 0
) {
this.recursiveSorting(scenarioDefinition[i].children); this.recursiveSorting(scenarioDefinition[i].children);
} }
} }
@ -390,7 +442,7 @@ export default {
if (this.exportReportIsOk) { if (this.exportReportIsOk) {
this.startExport(); this.startExport();
} else { } else {
getScenarioReportAll(this.reportId).then(data => { getScenarioReportAll(this.reportId).then((data) => {
if (data && data.data.content) { if (data && data.data.content) {
let report = JSON.parse(data.data.content); let report = JSON.parse(data.data.content);
if (report.projectEnvMap) { if (report.projectEnvMap) {
@ -400,7 +452,8 @@ export default {
this.fullTreeNodes = report.steps; this.fullTreeNodes = report.steps;
this.content.console = report.console; this.content.console = report.console;
this.content.error = report.error; this.content.error = report.error;
let successCount = (report.total - report.error - report.errorCode - report.unExecute); let successCount =
report.total - report.error - report.errorCode - report.unExecute;
this.content.success = successCount; this.content.success = successCount;
if (this.report.endTime > 0) { if (this.report.endTime > 0) {
this.totalTime = this.report.endTime - this.report.createTime; this.totalTime = this.report.endTime - this.report.createTime;
@ -409,7 +462,7 @@ export default {
} }
} }
this.exportReportIsOk = true; this.exportReportIsOk = true;
setTimeout(this.startExport, 500) setTimeout(this.startExport, 500);
}); });
} }
}, },
@ -426,13 +479,13 @@ export default {
} }
} else if (this.isShare) { } else if (this.isShare) {
if (this.reportId) { if (this.reportId) {
getShareScenarioReport(this.shareId, this.reportId).then(data => { getShareScenarioReport(this.shareId, this.reportId).then((data) => {
this.checkReport(data.data); this.checkReport(data.data);
this.handleGetScenarioReport(data.data); this.handleGetScenarioReport(data.data);
}); });
} }
} else { } else {
getScenarioReport(this.reportId).then(data => { getScenarioReport(this.reportId).then((data) => {
this.checkReport(data.data); this.checkReport(data.data);
this.handleGetScenarioReport(data.data); this.handleGetScenarioReport(data.data);
}); });
@ -441,7 +494,7 @@ export default {
checkReport(data) { checkReport(data) {
if (!data) { if (!data) {
this.$emit('reportNotExist'); this.$emit("reportNotExist");
} }
}, },
handleGetScenarioReport(data) { handleGetScenarioReport(data) {
@ -450,7 +503,7 @@ export default {
if (this.report.reportVersion && this.report.reportVersion > 1) { if (this.report.reportVersion && this.report.reportVersion > 1) {
this.report.status = data.status; this.report.status = data.status;
if (!this.isNotRunning) { if (!this.isNotRunning) {
setTimeout(this.getReport, 2000) setTimeout(this.getReport, 2000);
} else { } else {
if (data.content) { if (data.content) {
let report = JSON.parse(data.content); let report = JSON.parse(data.content);
@ -472,7 +525,11 @@ export default {
} }
this.content.console = report.console; this.content.console = report.console;
this.content.error = report.error; this.content.error = report.error;
let successCount = (report.total - report.error - report.errorCode - report.unExecute); let successCount =
report.total -
report.error -
report.errorCode -
report.unExecute;
this.content.success = successCount; this.content.success = successCount;
if (this.report.endTime > 0) { if (this.report.endTime > 0) {
this.totalTime = this.report.endTime - this.report.createTime; this.totalTime = this.report.endTime - this.report.createTime;
@ -481,7 +538,11 @@ export default {
} }
} }
// //
if (this.report && this.report.reportType === 'SCENARIO_INTEGRATED' || this.report.reportType === 'API_INTEGRATED') { if (
(this.report &&
this.report.reportType === "SCENARIO_INTEGRATED") ||
this.report.reportType === "API_INTEGRATED"
) {
this.rerunVerify(); this.rerunVerify();
} }
this.loading = false; this.loading = false;
@ -490,8 +551,8 @@ export default {
this.buildReport(); this.buildReport();
} }
} else { } else {
this.$emit('invisible'); this.$emit("invisible");
this.$warning(this.$t('commons.report_delete')); this.$warning(this.$t("commons.report_delete"));
} }
}, },
checkOrder(origin) { checkOrder(origin) {
@ -500,36 +561,42 @@ export default {
} }
if (Array.isArray(origin)) { if (Array.isArray(origin)) {
this.sortChildren(origin); this.sortChildren(origin);
origin.forEach(v => { origin.forEach((v) => {
if (v.children) { if (v.children) {
this.checkOrder(v.children) this.checkOrder(v.children);
} }
}) });
} }
}, },
sortChildren(source) { sortChildren(source) {
if (!source) { if (!source) {
return; return;
} }
source.forEach(item => { source.forEach((item) => {
let children = item.children; let children = item.children;
if (children && children.length > 0) { if (children && children.length > 0) {
let tempArr = new Array(children.length); let tempArr = new Array(children.length);
let tempMap = new Map(); let tempMap = new Map();
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
if (!children[i].value || !children[i].value.startTime || children[i].value.startTime === 0) { if (
!children[i].value ||
!children[i].value.startTime ||
children[i].value.startTime === 0
) {
//valuestep //valuestep
tempArr[i] = children[i]; tempArr[i] = children[i];
// //
tempMap.set(children[i].stepId, children[i]) tempMap.set(children[i].stepId, children[i]);
} }
} }
//step //step
let arr = children.filter(m => { let arr = children
.filter((m) => {
return !tempMap.get(m.stepId); return !tempMap.get(m.stepId);
}).sort((m, n) => { })
.sort((m, n) => {
// //
return m.value.startTime - n.value.startTime; return m.value.startTime - n.value.startTime;
}); });
@ -548,36 +615,35 @@ export default {
// //
item.children = tempArr; item.children = tempArr;
} }
}) });
}, },
buildReport() { buildReport() {
if (this.report) { if (this.report) {
if (this.isNotRunning) { if (this.isNotRunning) {
this.content = JSON.parse(this.report.content); this.content = JSON.parse(this.report.content);
if (!this.content) { if (!this.content) {
this.content = {scenarios: []}; this.content = { scenarios: [] };
} }
this.formatResult(this.content); this.formatResult(this.content);
this.getFails(); this.getFails();
this.computeTotalTime(); this.computeTotalTime();
this.loading = false; this.loading = false;
} else { } else {
setTimeout(this.getReport, 2000) setTimeout(this.getReport, 2000);
} }
} else { } else {
this.loading = false; this.loading = false;
this.$error(this.$t('api_report.not_exist')); this.$error(this.$t("api_report.not_exist"));
} }
}, },
getFails() { getFails() {
if (this.isNotRunning) { if (this.isNotRunning) {
this.fails = []; this.fails = [];
let array = []; let array = [];
this.totalTime = 0 this.totalTime = 0;
if (this.content.scenarios) { if (this.content.scenarios) {
this.content.scenarios.forEach((scenario) => { this.content.scenarios.forEach((scenario) => {
this.totalTime = this.totalTime + Number(scenario.responseTime) this.totalTime = this.totalTime + Number(scenario.responseTime);
let failScenario = Object.assign({}, scenario); let failScenario = Object.assign({}, scenario);
if (scenario.error > 0) { if (scenario.error > 0) {
this.fails.push(failScenario); this.fails.push(failScenario);
@ -588,9 +654,9 @@ export default {
failScenario.requestResults.push(failRequest); failScenario.requestResults.push(failRequest);
array.push(request); array.push(request);
} }
}) });
} }
}) });
} }
this.formatTree(array, this.failsTreeNodes); this.formatTree(array, this.failsTreeNodes);
this.sort(this.failsTreeNodes); this.sort(this.failsTreeNodes);
@ -611,14 +677,14 @@ export default {
} }
let resTime; let resTime;
if (startTime === 0 || endTime === 0) { if (startTime === 0 || endTime === 0) {
resTime = 0 resTime = 0;
} else { } else {
resTime = endTime - startTime resTime = endTime - startTime;
} }
requestTime = requestTime + resTime; requestTime = requestTime + resTime;
}) });
}) });
this.totalTime = requestTime this.totalTime = requestTime;
} }
}, },
requestResult(requestResult) { requestResult(requestResult) {
@ -631,8 +697,11 @@ export default {
}); });
}, },
formatExportApi(array, scenario) { formatExportApi(array, scenario) {
array.forEach(item => { array.forEach((item) => {
if (this.stepFilter && this.stepFilter.get("AllSamplerProxy").indexOf(item.type) !== -1) { if (
this.stepFilter &&
this.stepFilter.get("AllSamplerProxy").indexOf(item.type) !== -1
) {
if (item.errorCode) { if (item.errorCode) {
item.value.errorCode = item.errorCode; item.value.errorCode = item.errorCode;
} }
@ -641,72 +710,82 @@ export default {
if (item.children && item.children.length > 0) { if (item.children && item.children.length > 0) {
this.formatExportApi(item.children, scenario); this.formatExportApi(item.children, scenario);
} }
}) });
}, },
handleExport() { handleExport() {
this.getReportByExport(); this.getReportByExport();
}, },
startExport() { startExport() {
if (this.report.reportVersion && this.report.reportVersion > 1) { if (this.report.reportVersion && this.report.reportVersion > 1) {
if (this.report.reportType === 'API_INTEGRATED' || this.report.reportType === 'UI_INTEGRATED') { if (
let scenario = {name: "", requestResults: []}; this.report.reportType === "API_INTEGRATED" ||
this.report.reportType === "UI_INTEGRATED"
) {
let scenario = { name: "", requestResults: [] };
this.content.scenarios = [scenario]; this.content.scenarios = [scenario];
this.formatExportApi(this.fullTreeNodes, scenario); this.formatExportApi(this.fullTreeNodes, scenario);
} else { } else {
if (this.fullTreeNodes) { if (this.fullTreeNodes) {
this.fullTreeNodes.forEach(item => { this.fullTreeNodes.forEach((item) => {
if (item.type === "scenario" || item.type === "UiScenario") { if (item.type === "scenario" || item.type === "UiScenario") {
let scenario = {name: item.label, requestResults: []}; let scenario = { name: item.label, requestResults: [] };
if (this.content.scenarios && this.content.scenarios.length > 0) { if (
this.content.scenarios &&
this.content.scenarios.length > 0
) {
this.content.scenarios.push(scenario); this.content.scenarios.push(scenario);
} else { } else {
this.content.scenarios = [scenario]; this.content.scenarios = [scenario];
} }
this.formatExportApi(item.children, scenario); this.formatExportApi(item.children, scenario);
} }
}) });
} }
} }
} }
this.reportExportVisible = true; this.reportExportVisible = true;
let reset = this.exportReportReset; let reset = this.exportReportReset;
this.$nextTick(() => { this.$nextTick(() => {
windowPrint('apiTestReport', 0.57); windowPrint("apiTestReport", 0.57);
reset(); reset();
}); });
}, },
handleSave() { handleSave() {
if (!this.report.name) { if (!this.report.name) {
this.$warning(this.$t('api_test.automation.report_name_info')); this.$warning(this.$t("api_test.automation.report_name_info"));
return; return;
} }
this.loading = true; this.loading = true;
let url = "/ui/scenario/report/reName"; let url = "/ui/scenario/report/reName";
this.result = this.$post(url, { this.result = this.$post(
url,
{
id: this.report.id, id: this.report.id,
name: this.report.name, name: this.report.name,
reportType: this.report.reportType reportType: this.report.reportType,
}, response => { },
this.$success(this.$t('commons.save_success')); (response) => {
this.$success(this.$t("commons.save_success"));
this.loading = false; this.loading = false;
this.$emit('refresh'); this.$emit("refresh");
}, error => { },
(error) => {
this.loading = false; this.loading = false;
}); }
);
}, },
exportReportReset() { exportReportReset() {
this.$router.go(0); this.$router.go(0);
}, },
handleProjectChange() { handleProjectChange() {
this.$router.push('/api/automation/report'); this.$router.push("/api/automation/report");
}, },
}, },
created() { created() {
this.getReport(); this.getReport();
}, },
destroyed() { destroyed() {},
},
computed: { computed: {
path() { path() {
return "/api/test/edit?id=" + this.report.testId; return "/api/test/edit?id=" + this.report.testId;
@ -717,8 +796,8 @@ export default {
projectId() { projectId() {
return getCurrentProjectID(); return getCurrentProjectID();
}, },
} },
} };
</script> </script>
<style> <style>
.report-container .el-tabs__header { .report-container .el-tabs__header {
@ -727,7 +806,6 @@ export default {
</style> </style>
<style scoped> <style scoped>
.report-container { .report-container {
height: calc(100vh - 155px); height: calc(100vh - 155px);
min-height: 600px; min-height: 600px;
@ -748,7 +826,7 @@ export default {
} }
.report-container .fail { .report-container .fail {
color: #F56C6C; color: #f56c6c;
} }
.report-container .is-active .fail { .report-container .is-active .fail {
@ -768,7 +846,7 @@ export default {
transform: rotate(90deg); transform: rotate(90deg);
} }
.report-body{ .report-body {
min-width: 750px!important; min-width: 750px !important;
} }
</style> </style>