Merge branch 'master' of github.com:fit2cloudrd/metersphere-server

This commit is contained in:
Captain.B 2020-08-07 17:37:45 +08:00
commit fa13003865
24 changed files with 156 additions and 40 deletions

View File

@ -49,7 +49,6 @@ public class APITestController {
return apiTestService.getApiTestByProjectId(projectId); return apiTestService.getApiTestByProjectId(projectId);
} }
@PostMapping(value = "/schedule/update") @PostMapping(value = "/schedule/update")
public void updateSchedule(@RequestBody Schedule request) { public void updateSchedule(@RequestBody Schedule request) {
apiTestService.updateSchedule(request); apiTestService.updateSchedule(request);
@ -90,6 +89,11 @@ public class APITestController {
return apiTestService.run(request); return apiTestService.run(request);
} }
@PostMapping(value = "/run/independent", consumes = {"multipart/form-data"})
public String runIndependent(@RequestBody SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> files) {
return apiTestService.runIndependent(request, files);
}
@PostMapping(value = "/import", consumes = {"multipart/form-data"}) @PostMapping(value = "/import", consumes = {"multipart/form-data"})
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public ApiTest testCaseImport(@RequestPart(value = "file", required = false) MultipartFile file, @RequestPart("request") ApiTestImportRequest request) { public ApiTest testCaseImport(@RequestPart(value = "file", required = false) MultipartFile file, @RequestPart("request") ApiTestImportRequest request) {

View File

@ -10,6 +10,7 @@ public class Scenario {
private String name; private String name;
private String url; private String url;
private String environmentId; private String environmentId;
private Boolean enableCookieShare;
private List<KeyValue> variables; private List<KeyValue> variables;
private List<KeyValue> headers; private List<KeyValue> headers;
private List<Request> requests; private List<Request> requests;

View File

@ -101,7 +101,12 @@ public class APIReportService {
if (running != null) { if (running != null) {
return running.getId(); return running.getId();
} }
ApiTestReport report = buildReport(test, triggerMode, APITestStatus.Running.name());
apiTestReportMapper.insert(report);
return report.getId();
}
public ApiTestReport buildReport(ApiTest test, String triggerMode, String status) {
ApiTestReport report = new ApiTestReport(); ApiTestReport report = new ApiTestReport();
report.setId(UUID.randomUUID().toString()); report.setId(UUID.randomUUID().toString());
report.setTestId(test.getId()); report.setTestId(test.getId());
@ -110,11 +115,9 @@ public class APIReportService {
report.setDescription(test.getDescription()); report.setDescription(test.getDescription());
report.setCreateTime(System.currentTimeMillis()); report.setCreateTime(System.currentTimeMillis());
report.setUpdateTime(System.currentTimeMillis()); report.setUpdateTime(System.currentTimeMillis());
report.setStatus(APITestStatus.Running.name()); report.setStatus(status);
report.setUserId(test.getUserId()); report.setUserId(test.getUserId());
apiTestReportMapper.insert(report); return report;
return report.getId();
} }
public ApiTestReport getRunningReport(String testId) { public ApiTestReport getRunningReport(String testId) {

View File

@ -37,6 +37,7 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -299,8 +300,8 @@ public class APITestService {
if (info.length > 1) { if (info.length > 1) {
provider.setVersion(info[1]); provider.setVersion(info[1]);
} }
provider.setService(info[0]); provider.setService(p);
provider.setServiceInterface(p); provider.setServiceInterface(info[0]);
Map<String, URL> services = providerService.findByService(p); Map<String, URL> services = providerService.findByService(p);
if (services != null && !services.isEmpty()) { if (services != null && !services.isEmpty()) {
String[] methods = services.values().stream().findFirst().get().getParameter(CommonConstants.METHODS_KEY).split(","); String[] methods = services.values().stream().findFirst().get().getParameter(CommonConstants.METHODS_KEY).split(",");
@ -314,6 +315,7 @@ public class APITestService {
} }
public List<ScheduleDao> listSchedule(QueryScheduleRequest request) { public List<ScheduleDao> listSchedule(QueryScheduleRequest request) {
request.setEnable(true);
List<ScheduleDao> schedules = scheduleService.list(request); List<ScheduleDao> schedules = scheduleService.list(request);
List<String> resourceIds = schedules.stream() List<String> resourceIds = schedules.stream()
.map(Schedule::getResourceId) .map(Schedule::getResourceId)
@ -327,4 +329,29 @@ public class APITestService {
} }
return schedules; return schedules;
} }
public String runIndependent(SaveAPITestRequest request, List<MultipartFile> files) {
if (files == null || files.isEmpty()) {
throw new IllegalArgumentException(Translator.get("file_cannot_be_null"));
}
// ApiTest test = createTest(request);
// saveFile(test.getId(), files);
MultipartFile file = files.get(0);
InputStream is = null;
try {
is = new ByteArrayInputStream(file.getBytes());
} catch (IOException e) {
LogUtil.error(e);
}
APITestResult apiTest = get(request.getId());
if (SessionUtils.getUser() == null) {
apiTest.setUserId(request.getUserId());
}
String reportId = apiReportService.create(apiTest, request.getTriggerMode());
changeStatus(request.getId(), APITestStatus.Running);
jMeterService.run(request.getId(), is);
return reportId;
}
} }

View File

@ -10,6 +10,9 @@
<if test="request.workspaceId != null"> <if test="request.workspaceId != null">
and schedule.workspace_id = #{request.workspaceId} and schedule.workspace_id = #{request.workspaceId}
</if> </if>
<if test="request.enable != null">
and schedule.enable = #{request.enable}
</if>
<if test="request.filters != null and request.filters.size() > 0"> <if test="request.filters != null and request.filters.size() > 0">
<foreach collection="request.filters.entrySet()" index="key" item="values"> <foreach collection="request.filters.entrySet()" index="key" item="values">
<if test="values != null and values.size() > 0"> <if test="values != null and values.size() > 0">

View File

@ -420,6 +420,7 @@ public class PerformanceTestService {
} }
public List<ScheduleDao> listSchedule(QueryScheduleRequest request) { public List<ScheduleDao> listSchedule(QueryScheduleRequest request) {
request.setEnable(true);
List<ScheduleDao> schedules = scheduleService.list(request); List<ScheduleDao> schedules = scheduleService.list(request);
List<String> resourceIds = schedules.stream() List<String> resourceIds = schedules.stream()
.map(Schedule::getResourceId) .map(Schedule::getResourceId)

View File

@ -11,7 +11,7 @@
<template v-slot:title>{{$t('commons.project')}}</template> <template v-slot:title>{{$t('commons.project')}}</template>
<ms-recent-list :options="projectRecent"/> <ms-recent-list :options="projectRecent"/>
<el-divider class="menu-divider"/> <el-divider class="menu-divider"/>
<ms-show-all :index="'/api/project'"/> <ms-show-all :index="'/api/project/all'"/>
<ms-create-button v-permission="['test_manager','test_user']" :index="'/api/project/create'" <ms-create-button v-permission="['test_manager','test_user']" :index="'/api/project/create'"
:title="$t('project.create')"/> :title="$t('project.create')"/>
</el-submenu> </el-submenu>
@ -20,7 +20,7 @@
<template v-slot:title>{{$t('commons.test')}}</template> <template v-slot:title>{{$t('commons.test')}}</template>
<ms-recent-list :options="testRecent"/> <ms-recent-list :options="testRecent"/>
<el-divider class="menu-divider"/> <el-divider class="menu-divider"/>
<ms-show-all :index="'/api/test/list'"/> <ms-show-all :index="'/api/test/list/all'"/>
<ms-create-button v-permission="['test_manager','test_user']" :index="'/api/test/create'" <ms-create-button v-permission="['test_manager','test_user']" :index="'/api/test/create'"
:title="$t('load_test.create')"/> :title="$t('load_test.create')"/>
</el-submenu> </el-submenu>
@ -29,7 +29,7 @@
<template v-slot:title>{{$t('commons.report')}}</template> <template v-slot:title>{{$t('commons.report')}}</template>
<ms-recent-list :options="reportRecent"/> <ms-recent-list :options="reportRecent"/>
<el-divider class="menu-divider"/> <el-divider class="menu-divider"/>
<ms-show-all :index="'/api/report/list'"/> <ms-show-all :index="'/api/report/list/all'"/>
</el-submenu> </el-submenu>
</el-menu> </el-menu>
</el-col> </el-col>
@ -60,7 +60,7 @@
title: this.$t('project.recent'), title: this.$t('project.recent'),
url: "/project/recent/5", url: "/project/recent/5",
index: function (item) { index: function (item) {
return '/api/' + item.id; return '/api/test/list/' + item.id;
}, },
router: function (item) { router: function (item) {
return {name: 'ApiTestList', params: {projectId: item.id, projectName: item.name}} return {name: 'ApiTestList', params: {projectId: item.id, projectName: item.name}}

View File

@ -14,7 +14,7 @@
<ms-test-heatmap :values="values"/> <ms-test-heatmap :values="values"/>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<ms-api-test-schedule-list :group="'API_TEST'"/> <ms-schedule-list :group="'API_TEST'"/>
</el-col> </el-col>
</el-row> </el-row>
</ms-main-container> </ms-main-container>
@ -28,13 +28,13 @@
import MsApiTestRecentList from "./ApiTestRecentList"; import MsApiTestRecentList from "./ApiTestRecentList";
import MsApiReportRecentList from "./ApiReportRecentList"; import MsApiReportRecentList from "./ApiReportRecentList";
import MsTestHeatmap from "../../common/components/MsTestHeatmap"; import MsTestHeatmap from "../../common/components/MsTestHeatmap";
import MsApiTestScheduleList from "./ApiTestScheduleList"; import MsScheduleList from "./ScheduleList";
export default { export default {
name: "ApiTestHome", name: "ApiTestHome",
components: { components: {
MsApiTestScheduleList, MsScheduleList,
MsTestHeatmap, MsApiReportRecentList, MsApiTestRecentList, MsMainContainer, MsContainer MsTestHeatmap, MsApiReportRecentList, MsApiTestRecentList, MsMainContainer, MsContainer
}, },

View File

@ -1,7 +1,7 @@
<template> <template>
<el-card class="table-card" v-loading="result.loading"> <el-card class="table-card" v-loading="result.loading">
<template v-slot:header> <template v-slot:header>
<span class="title">{{$t('commons.trigger_mode.schedule')}}</span> <span class="title">{{$t('schedule.running_task')}}</span>
</template> </template>
<el-table height="289" border :data="tableData" class="adjust-table table-content" @row-click="link"> <el-table height="289" border :data="tableData" class="adjust-table table-content" @row-click="link">
<el-table-column prop="resourceName" :label="$t('schedule.test_name')" width="150" show-overflow-tooltip/> <el-table-column prop="resourceName" :label="$t('schedule.test_name')" width="150" show-overflow-tooltip/>
@ -32,7 +32,7 @@
import {SCHEDULE_TYPE} from "../../../../common/js/constants"; import {SCHEDULE_TYPE} from "../../../../common/js/constants";
export default { export default {
name: "MsApiTestScheduleList", name: "MsScheduleList",
components: {CrontabResult}, components: {CrontabResult},
data() { data() {
return { return {

View File

@ -1,5 +1,5 @@
<template> <template>
<el-card> <el-card class="scenario-results">
<div class="scenario-header"> <div class="scenario-header">
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="16"> <el-col :span="16">

View File

@ -157,9 +157,11 @@
saveTest() { saveTest() {
this.save(() => { this.save(() => {
this.$success(this.$t('commons.save_success')); this.$success(this.$t('commons.save_success'));
this.$router.push({ if (this.create) {
path: '/api/test/edit?id=' + this.test.id this.$router.push({
}) path: '/api/test/edit?id=' + this.test.id
})
}
}) })
}, },
runTest() { runTest() {

View File

@ -21,6 +21,9 @@
</div> </div>
</template> </template>
</el-select> </el-select>
<el-form-item class="cookie-item">
<el-checkbox v-model="scenario.enableCookieShare">{{'共享 Cookie'}}</el-checkbox>
</el-form-item>
</el-form-item> </el-form-item>
<el-tabs v-model="activeName"> <el-tabs v-model="activeName">
@ -168,4 +171,8 @@
font-weight: 600; font-weight: 600;
} }
.cookie-item {
margin-top: 15px;
}
</style> </style>

View File

@ -1,15 +1,19 @@
<template> <template>
<component :is="component" :is-read-only="isReadOnly" :request="request"/> <div>
<component :is="component" :is-read-only="isReadOnly" :request="request"/>
<!-- <ms-scenario-results :scenarios="content.scenarios"/>-->
</div>
</template> </template>
<script> <script>
import {Request, RequestFactory} from "../../model/ScenarioModel"; import {Request, RequestFactory} from "../../model/ScenarioModel";
import MsApiHttpRequestForm from "./ApiHttpRequestForm"; import MsApiHttpRequestForm from "./ApiHttpRequestForm";
import MsApiDubboRequestForm from "./ApiDubboRequestForm"; import MsApiDubboRequestForm from "./ApiDubboRequestForm";
import MsScenarioResults from "../../../report/components/ScenarioResults";
export default { export default {
name: "MsApiRequestForm", name: "MsApiRequestForm",
components: {MsApiDubboRequestForm, MsApiHttpRequestForm}, components: {MsScenarioResults, MsApiDubboRequestForm, MsApiHttpRequestForm},
props: { props: {
request: Request, request: Request,
isReadOnly: { isReadOnly: {
@ -17,6 +21,12 @@
default: false default: false
} }
}, },
data() {
return {
reportId: "",
content:{}
}
},
computed: { computed: {
component({request: {type}}) { component({request: {type}}) {
let name; let name;
@ -29,10 +39,46 @@
} }
return name; return name;
} }
},
created() {
this.getReport();
},
methods: {
getReport() {
// // this.reportId = "00143d36-a58a-477e-a05a-556c1d48046c";
// if (this.reportId) {
// let url = "/api/report/get/" + this.reportId;
// this.$get(url, response => {
// let report = response.data || {};
// if (response.data) {
// // if (this.isNotRunning) {
// try {
// this.content = JSON.parse(report.content);
// } catch (e) {
// console.log(report.content)
// throw e;
// }
// // this.getFails();
// // this.loading = false;
// // }
// // else {
// // setTimeout(this.getReport, 2000)
// // }
// } else {
// this.loading = false;
// this.$error(this.$t('api_report.not_exist'));
// }
// });
// }
}
} }
} }
</script> </script>
<style scoped> <style scoped>
.scenario-results {
margin-top: 15px;
}
</style> </style>

View File

@ -328,6 +328,15 @@ export class HTTPSamplerArguments extends Element {
} }
} }
export class CookieManager extends DefaultTestElement {
constructor(testName) {
super('CookieManager', 'CookiePanel', 'CookieManager', testName);
this.collectionProp('CookieManager.cookies');
this.boolProp('CookieManager.clearEachIteration', false, false);
this.boolProp('CookieManager.controlledByThreadGroup', false, false);
}
}
export class DurationAssertion extends DefaultTestElement { export class DurationAssertion extends DefaultTestElement {
constructor(testName, duration) { constructor(testName, duration) {
super('DurationAssertion', 'DurationAssertionGui', 'DurationAssertion', testName); super('DurationAssertion', 'DurationAssertionGui', 'DurationAssertion', testName);

View File

@ -1,5 +1,5 @@
import { import {
Arguments, Arguments, CookieManager,
DubboSample, DubboSample,
DurationAssertion, DurationAssertion,
Element, Element,
@ -174,6 +174,7 @@ export class Scenario extends BaseConfig {
this.environmentId = undefined; this.environmentId = undefined;
this.dubboConfig = undefined; this.dubboConfig = undefined;
this.environment = undefined; this.environment = undefined;
this.enableCookieShare = false;
this.set(options); this.set(options);
this.sets({variables: KeyValue, headers: KeyValue, requests: RequestFactory}, options); this.sets({variables: KeyValue, headers: KeyValue, requests: RequestFactory}, options);
@ -765,6 +766,8 @@ class JMXGenerator {
this.addScenarioHeaders(threadGroup, scenario); this.addScenarioHeaders(threadGroup, scenario);
this.addScenarioCookieManager(threadGroup, scenario);
scenario.requests.forEach(request => { scenario.requests.forEach(request => {
if (!request.isValid()) return; if (!request.isValid()) return;
let sampler; let sampler;
@ -822,6 +825,12 @@ class JMXGenerator {
} }
} }
addScenarioCookieManager(threadGroup, scenario) {
if (scenario.enableCookieShare) {
threadGroup.put(new CookieManager(scenario.name));
}
}
addScenarioHeaders(threadGroup, scenario) { addScenarioHeaders(threadGroup, scenario) {
let environment = scenario.environment; let environment = scenario.environment;
if (environment) { if (environment) {

View File

@ -7,10 +7,14 @@
</span> </span>
<el-switch :disabled="!schedule.value || isReadOnly" v-model="schedule.enable" @change="scheduleChange"/> <el-switch :disabled="!schedule.value || isReadOnly" v-model="schedule.enable" @change="scheduleChange"/>
<ms-schedule-edit :is-read-only="isReadOnly" :schedule="schedule" :save="save" :custom-validate="customValidate" ref="scheduleEdit"/> <ms-schedule-edit :is-read-only="isReadOnly" :schedule="schedule" :save="save" :custom-validate="customValidate" ref="scheduleEdit"/>
<crontab-result v-show="false" :ex="schedule.value" ref="crontabResult" @resultListChange="resultListChange"/>
</div> </div>
<div> <div>
<span :class="{'disable-character': !schedule.enable}"> {{$t('schedule.next_execution_time')}}{{this.recentList.length > 0 && schedule.enable ? this.recentList[0] : $t('schedule.not_set')}} </span> <span>
{{$t('schedule.next_execution_time')}}
<span :class="{'disable-character': !schedule.enable}" v-if="!schedule.enable">{{$t('schedule.not_set')}}</span>
<crontab-result v-if="schedule.enable" :enable-simple-mode="true" :ex="schedule.value" ref="crontabResult"/>
</span>
</div> </div>
</div> </div>
</template> </template>
@ -59,9 +63,6 @@
scheduleChange() { scheduleChange() {
this.$emit('scheduleChange'); this.$emit('scheduleChange');
}, },
resultListChange(resultList) {
this.recentList = resultList;
},
flashResultList() { flashResultList() {
this.$refs.crontabResult.expressionChange(); this.$refs.crontabResult.expressionChange();
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <span>
<span v-if="enableSimpleMode">{{resultList && resultList.length > 0 ? resultList[0] : ''}}</span> <span v-if="enableSimpleMode">{{resultList && resultList.length > 0 ? resultList[0] : ''}}</span>
<div v-if="!enableSimpleMode" class="popup-result"> <div v-if="!enableSimpleMode" class="popup-result">
<p class="title">{{$t('schedule.cron.recent_run_time')}}</p> <p class="title">{{$t('schedule.cron.recent_run_time')}}</p>
@ -9,7 +9,7 @@
</template> </template>
</ul> </ul>
</div> </div>
</div> </span>
</template> </template>
<script> <script>

View File

@ -14,7 +14,7 @@
methods: { methods: {
changeRoute() { changeRoute() {
// //
this.$router.push(this.index + '/all'); this.$router.replace({path: this.index, query: {type: 'all'}});
} }
} }
} }

View File

@ -12,7 +12,7 @@
<template v-slot:title>{{$t('commons.project')}}</template> <template v-slot:title>{{$t('commons.project')}}</template>
<ms-recent-list :options="projectRecent"/> <ms-recent-list :options="projectRecent"/>
<el-divider/> <el-divider/>
<ms-show-all :index="'/performance/project'"/> <ms-show-all :index="'/performance/project/all'"/>
<ms-create-button v-permission="['test_manager','test_user']" :index="'/performance/project/create'" :title="$t('project.create')"/> <ms-create-button v-permission="['test_manager','test_user']" :index="'/performance/project/create'" :title="$t('project.create')"/>
</el-submenu> </el-submenu>
@ -21,7 +21,7 @@
<template v-slot:title>{{$t('commons.test')}}</template> <template v-slot:title>{{$t('commons.test')}}</template>
<ms-recent-list :options="testRecent"/> <ms-recent-list :options="testRecent"/>
<el-divider/> <el-divider/>
<ms-show-all :index="'/performance/test'"/> <ms-show-all :index="'/performance/test/all'"/>
<ms-create-button v-permission="['test_manager','test_user']" :index="'/performance/test/create'" :title="$t('load_test.create')"/> <ms-create-button v-permission="['test_manager','test_user']" :index="'/performance/test/create'" :title="$t('load_test.create')"/>
</el-submenu> </el-submenu>
@ -30,7 +30,7 @@
<template v-slot:title>{{$t('commons.report')}}</template> <template v-slot:title>{{$t('commons.report')}}</template>
<ms-recent-list :options="reportRecent"/> <ms-recent-list :options="reportRecent"/>
<el-divider/> <el-divider/>
<ms-show-all :index="'/performance/report'"/> <ms-show-all :index="'/performance/report/all'"/>
</el-submenu> </el-submenu>
</el-menu> </el-menu>
</el-col> </el-col>

View File

@ -14,7 +14,7 @@
<ms-test-heatmap :values="values"/> <ms-test-heatmap :values="values"/>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<ms-api-test-schedule-list :group="'PERFORMANCE_TEST'"/> <ms-schedule-list :group="'PERFORMANCE_TEST'"/>
</el-col> </el-col>
</el-row> </el-row>
</ms-main-container> </ms-main-container>
@ -28,12 +28,12 @@
import MsPerformanceTestRecentList from "./PerformanceTestRecentList" import MsPerformanceTestRecentList from "./PerformanceTestRecentList"
import MsPerformanceReportRecentList from "./PerformanceReportRecentList" import MsPerformanceReportRecentList from "./PerformanceReportRecentList"
import MsTestHeatmap from "../../common/components/MsTestHeatmap"; import MsTestHeatmap from "../../common/components/MsTestHeatmap";
import MsApiTestScheduleList from "../../api/home/ApiTestScheduleList"; import MsScheduleList from "../../api/home/ScheduleList";
export default { export default {
name: "PerformanceTestHome", name: "PerformanceTestHome",
components: { components: {
MsApiTestScheduleList, MsScheduleList,
MsTestHeatmap, MsTestHeatmap,
MsMainContainer, MsMainContainer,
MsContainer, MsContainer,

View File

@ -13,7 +13,7 @@
<template v-slot:title>{{$t('commons.project')}}</template> <template v-slot:title>{{$t('commons.project')}}</template>
<ms-recent-list :options="projectRecent"/> <ms-recent-list :options="projectRecent"/>
<el-divider/> <el-divider/>
<ms-show-all :index="'/track/project'"/> <ms-show-all :index="'/track/project/all'"/>
<ms-create-button v-permission="['test_manager','test_user']" :index="'/track/project/create'" :title="$t('project.create')"/> <ms-create-button v-permission="['test_manager','test_user']" :index="'/track/project/create'" :title="$t('project.create')"/>
</el-submenu> </el-submenu>
@ -22,7 +22,7 @@
<template v-slot:title>{{$t('test_track.case.test_case')}}</template> <template v-slot:title>{{$t('test_track.case.test_case')}}</template>
<ms-recent-list :options="caseRecent"/> <ms-recent-list :options="caseRecent"/>
<el-divider/> <el-divider/>
<ms-show-all :index="'/track/case'"/> <ms-show-all :index="'/track/case/all'"/>
<el-menu-item :index="testCaseEditPath" class="blank_item"></el-menu-item> <el-menu-item :index="testCaseEditPath" class="blank_item"></el-menu-item>
<el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item> <el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item>
<ms-create-button v-permission="['test_manager','test_user']" :index="'/track/case/create'" :title="$t('test_track.case.create_case')"/> <ms-create-button v-permission="['test_manager','test_user']" :index="'/track/case/create'" :title="$t('test_track.case.create_case')"/>
@ -32,7 +32,7 @@
<template v-slot:title>{{$t('test_track.plan.test_plan')}}</template> <template v-slot:title>{{$t('test_track.plan.test_plan')}}</template>
<ms-recent-list :options="planRecent"/> <ms-recent-list :options="planRecent"/>
<el-divider/> <el-divider/>
<ms-show-all :index="'/track/plan'"/> <ms-show-all :index="'/track/plan/all'"/>
<el-menu-item :index="testPlanViewPath" class="blank_item"></el-menu-item> <el-menu-item :index="testPlanViewPath" class="blank_item"></el-menu-item>
<ms-create-button v-permission="['test_manager','test_user']" :index="'/track/plan/create'" :title="$t('test_track.plan.create_plan')"/> <ms-create-button v-permission="['test_manager','test_user']" :index="'/track/plan/create'" :title="$t('test_track.plan.create_plan')"/>
</el-submenu> </el-submenu>

View File

@ -717,6 +717,7 @@ export default {
test_name: 'Test Name', test_name: 'Test Name',
running_rule: 'Rule', running_rule: 'Rule',
job_status: 'Status', job_status: 'Status',
running_task: 'Running Task',
please_input_cron_expression: "Please Input Cron Expression", please_input_cron_expression: "Please Input Cron Expression",
generate_expression: "Generate Expression", generate_expression: "Generate Expression",
cron_expression_format_error: "Cron Expression Format Error", cron_expression_format_error: "Cron Expression Format Error",

View File

@ -716,6 +716,7 @@ export default {
test_name: '测试名称', test_name: '测试名称',
running_rule: '运行规则', running_rule: '运行规则',
job_status: '任务状态', job_status: '任务状态',
running_task: '运行中的任务',
next_execution_time: "下次执行时间", next_execution_time: "下次执行时间",
edit_timer_task: "编辑定时任务", edit_timer_task: "编辑定时任务",
please_input_cron_expression: "请输入 Cron 表达式", please_input_cron_expression: "请输入 Cron 表达式",

View File

@ -715,6 +715,7 @@ export default {
test_name: '測試名稱', test_name: '測試名稱',
running_rule: '運行規則', running_rule: '運行規則',
job_status: '任務狀態', job_status: '任務狀態',
running_task: '運行中的任務',
please_input_cron_expression: "請輸入 Cron 表達式", please_input_cron_expression: "請輸入 Cron 表達式",
generate_expression: "生成表達式", generate_expression: "生成表達式",
cron_expression_format_error: "Cron 表達式格式錯誤", cron_expression_format_error: "Cron 表達式格式錯誤",