Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
9a6b47051b
|
@ -14,9 +14,9 @@ import java.util.List;
|
|||
public class SwaggerApiExportResult extends ApiExportResult{
|
||||
private String openapi;
|
||||
private SwaggerInfo info;
|
||||
private String externalDocs;
|
||||
private JSONObject externalDocs;
|
||||
private List<String> servers;
|
||||
private List<SwaggerTag> tags;
|
||||
private JSONObject paths; // Map<String, Object>, Object 里放 Operation 对象
|
||||
private List<String> components;
|
||||
private JSONObject components;
|
||||
}
|
||||
|
|
|
@ -231,6 +231,9 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
|||
MediaType mediaType = content.get(contentType);
|
||||
if (mediaType == null) {
|
||||
Set<String> contentTypes = content.keySet();
|
||||
if(contentTypes.size() == 0) { // 防止空指针
|
||||
return;
|
||||
}
|
||||
contentType = contentTypes.iterator().next();
|
||||
if (StringUtils.isBlank(contentType)) {
|
||||
return;
|
||||
|
@ -410,26 +413,34 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
|||
result.setInfo(new SwaggerInfo());
|
||||
result.setServers(new ArrayList<>());
|
||||
result.setTags(new ArrayList<>());
|
||||
result.setComponents(new ArrayList<>());
|
||||
result.setComponents(new JSONObject());
|
||||
result.setExternalDocs(new JSONObject());
|
||||
|
||||
JSONObject paths = new JSONObject();
|
||||
JSONObject swaggerPath = new JSONObject();
|
||||
for(ApiDefinitionWithBLOBs apiDefinition : apiDefinitionList) {
|
||||
SwaggerApiInfo swaggerApiInfo = new SwaggerApiInfo(); // {tags:, summary:, description:, parameters:}
|
||||
swaggerApiInfo.setSummary(apiDefinition.getName());
|
||||
// 设置导入后的模块名 (根据 api 的 moduleID 查库获得所属模块,作为导出的模块名)
|
||||
ApiModuleService apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class);
|
||||
String moduleName = apiModuleService.getNode(apiDefinition.getModuleId()).getName();
|
||||
String moduleName = "";
|
||||
if(apiDefinition.getModuleId() != null) { // module_id 可能为空
|
||||
moduleName = apiModuleService.getNode(apiDefinition.getModuleId()).getName();
|
||||
}
|
||||
swaggerApiInfo.setTags(Arrays.asList(moduleName));
|
||||
// 设置请求体
|
||||
JSONObject requestObject = JSON.parseObject(apiDefinition.getRequest()); // 将api的request属性转换成JSON对象以便获得参数
|
||||
JSONObject requestBody = buildRequestBody(requestObject);
|
||||
swaggerApiInfo.setRequestBody(requestBody);
|
||||
// 设置响应体
|
||||
swaggerApiInfo.setResponses(new JSONObject());
|
||||
// 设置请求参数列表
|
||||
List<JSONObject> paramsList = buildParameters(requestObject);
|
||||
swaggerApiInfo.setParameters(paramsList);
|
||||
swaggerPath.put(apiDefinition.getMethod().toLowerCase(), JSON.parseObject(JSON.toJSONString(swaggerApiInfo))); // 设置api的请求类型和api定义、参数
|
||||
paths.put(apiDefinition.getPath(), swaggerPath);
|
||||
JSONObject methodDetail = JSON.parseObject(JSON.toJSONString(swaggerApiInfo));
|
||||
if(paths.getJSONObject(apiDefinition.getPath()) == null) {
|
||||
paths.put(apiDefinition.getPath(), new JSONObject());
|
||||
} // 一个路径下有多个发方法,如post,get,因此是一个 JSONObject 类型
|
||||
paths.getJSONObject(apiDefinition.getPath()).put(apiDefinition.getMethod().toLowerCase(), methodDetail);
|
||||
}
|
||||
result.setPaths(paths);
|
||||
return result;
|
||||
|
@ -477,7 +488,9 @@ public class Swagger3Parser extends SwaggerAbstractParser {
|
|||
schema.put("format", null);
|
||||
typeName.put("schema", schema);
|
||||
JSONObject content = new JSONObject();
|
||||
content.put(typeMap.get(type), typeName);
|
||||
if (type != null && StringUtils.isNotBlank(type)) {
|
||||
content.put(typeMap.get(type), typeName);
|
||||
}
|
||||
requestBody.put("content", content);
|
||||
return requestBody;
|
||||
}
|
||||
|
|
|
@ -14,4 +14,5 @@ public class SwaggerApiInfo {
|
|||
private String summary; // 对应 API 的名字
|
||||
private List<JSONObject> parameters; // 对应 API 的请求参数
|
||||
private JSONObject requestBody;
|
||||
private JSONObject responses;
|
||||
}
|
||||
|
|
|
@ -162,6 +162,7 @@
|
|||
|
||||
.script-content {
|
||||
height: calc(100vh - 570px);
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
.script-index {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<el-dialog :close-on-click-modal="false" width="60%" class="schedule-edit" :visible.sync="dialogVisible" :append-to-body='true'
|
||||
<el-dialog :close-on-click-modal="false" width="60%" class="schedule-edit" :visible.sync="dialogVisible"
|
||||
:append-to-body='true'
|
||||
@close="close">
|
||||
<template>
|
||||
<div>
|
||||
|
@ -18,12 +19,10 @@
|
|||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<schedule-switch :schedule="schedule" @scheduleChange="scheduleChange"></schedule-switch>
|
||||
<schedule-switch :schedule="schedule" :corn-value="form.cronValue" @resultListChange="getExecuteTimeTemplate" @scheduleChange="scheduleChange"></schedule-switch>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-link :disabled="isReadOnly" type="primary" @click="showCronDialog">
|
||||
|
@ -66,7 +65,13 @@ const noticeTemplate = requireComponent.keys().length > 0 ? requireComponent("./
|
|||
|
||||
export default {
|
||||
name: "MsScheduleMaintain",
|
||||
components: {CrontabResult, ScheduleSwitch,Crontab, MsScheduleNotification, "NoticeTemplate": noticeTemplate.default},
|
||||
components: {
|
||||
CrontabResult,
|
||||
ScheduleSwitch,
|
||||
Crontab,
|
||||
MsScheduleNotification,
|
||||
"NoticeTemplate": noticeTemplate.default
|
||||
},
|
||||
|
||||
props: {
|
||||
customValidate: {
|
||||
|
@ -111,7 +116,7 @@ export default {
|
|||
form: {
|
||||
cronValue: ""
|
||||
},
|
||||
paramRow:{},
|
||||
paramRow: {},
|
||||
activeName: 'first',
|
||||
rules: {
|
||||
cronValue: [{required: true, validator: validateCron, trigger: 'blur'}],
|
||||
|
@ -122,19 +127,19 @@ export default {
|
|||
currentUser: () => {
|
||||
return getCurrentUser();
|
||||
},
|
||||
scheduleChange(){
|
||||
scheduleChange() {
|
||||
let flag = this.schedule.enable;
|
||||
let param = {};
|
||||
param.taskID = this.schedule.id;
|
||||
param.enable = flag;
|
||||
let that = this;
|
||||
if(flag == false) {
|
||||
if (flag == false) {
|
||||
this.$confirm(this.$t('api_test.home_page.running_task_list.confirm.close_title'), this.$t('commons.prompt'), {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
cancelButtonText: this.$t('commons.cancel'),
|
||||
type: 'warning',
|
||||
beforeClose(action, instance, done) {
|
||||
if(action == 'cancel') { // 否则在 messageBox 点击取消后,switch 按钮仍然会被关闭
|
||||
if (action == 'cancel') { // 否则在 messageBox 点击取消后,switch 按钮仍然会被关闭
|
||||
that.schedule.enable = param.enable = true;
|
||||
}
|
||||
done(); // done 是关闭 messageBox 的行为
|
||||
|
@ -143,12 +148,11 @@ export default {
|
|||
this.updateTask(param);
|
||||
}).catch(() => {
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.updateTask(param);
|
||||
}
|
||||
},
|
||||
updateTask(param){
|
||||
updateTask(param) {
|
||||
this.result = this.$post('/api/schedule/updateEnableByPrimyKey', param, response => {
|
||||
let paramTestId = "";
|
||||
if (this.paramRow.redirectFrom == 'testPlan') {
|
||||
|
@ -203,7 +207,7 @@ export default {
|
|||
findSchedule() {
|
||||
var scheduleResourceID = this.testId;
|
||||
var taskType = this.scheduleTaskType;
|
||||
this.result = this.$get("/schedule/findOne/" + scheduleResourceID + "/" +taskType, response => {
|
||||
this.result = this.$get("/schedule/findOne/" + scheduleResourceID + "/" + taskType, response => {
|
||||
if (response.data != null) {
|
||||
this.schedule = response.data;
|
||||
} else {
|
||||
|
@ -240,14 +244,14 @@ export default {
|
|||
param = this.schedule;
|
||||
param.resourceId = this.testId;
|
||||
let url = '/api/automation/schedule/create';
|
||||
if(this.scheduleTaskType === "TEST_PLAN_TEST"){
|
||||
if (this.scheduleTaskType === "TEST_PLAN_TEST") {
|
||||
param.scheduleFrom = "testPlan";
|
||||
//测试计划页面跳转的创建
|
||||
url = '/schedule/create';
|
||||
if (param.id) {
|
||||
url = '/schedule/update';
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
param.scheduleFrom = "scenario";
|
||||
if (param.id) {
|
||||
url = '/api/automation/schedule/update';
|
||||
|
@ -297,7 +301,9 @@ export default {
|
|||
let time2 = new Date(resultList[1]);
|
||||
return time2 - time1;
|
||||
},
|
||||
|
||||
getExecuteTimeTemplate(executeTileArr){
|
||||
alert(executeTileArr);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isTesterPermission() {
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
<i class="el-icon-date" size="small"></i>
|
||||
<span class="character">SCHEDULER</span>
|
||||
</span>
|
||||
<!-- <el-switch :disabled="!schedule.value || isReadOnly" v-model="schedule.enable" @change="scheduleChange"/>-->
|
||||
<!-- <el-switch :disabled="!schedule.value || isReadOnly" v-model="schedule.enable" />-->
|
||||
<el-switch :disabled="!schedule.value" v-model="schedule.enable" @change="scheduleChange"/>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -14,7 +12,7 @@
|
|||
{{ $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"/>
|
||||
<crontab-result v-if="schedule.enable" :enable-simple-mode="true" :ex="cornValue" ref="crontabResult"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -33,6 +31,7 @@ export default {
|
|||
props: {
|
||||
testId: String,
|
||||
schedule: Object,
|
||||
cornValue:String,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{{ description }}
|
||||
</span>
|
||||
<el-row>
|
||||
<el-checkbox v-model="isSelectAll" v-if="items.length > 1"/>
|
||||
<el-checkbox v-model="isSelectAll" v-if="isShowEnable === true && items.length > 1"/>
|
||||
</el-row>
|
||||
<div class="kv-row item" v-for="(item, index) in items" :key="index">
|
||||
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
|
||||
|
@ -52,7 +52,6 @@
|
|||
valuePlaceholder: String,
|
||||
isShowEnable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
description: String,
|
||||
items: Array,
|
||||
|
|
|
@ -155,6 +155,11 @@
|
|||
created() {
|
||||
this.getEnvironments();
|
||||
},
|
||||
computed: {
|
||||
projectId() {
|
||||
return this.$store.state.projectId
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addPre() {
|
||||
let jsr223PreProcessor = createComponent("JSR223PreProcessor");
|
||||
|
@ -210,7 +215,8 @@
|
|||
|
||||
getEnvironments() {
|
||||
this.environments = [];
|
||||
this.$get('/api/environment/list/' + getCurrentProjectID(), response => {
|
||||
let id = this.request.projectId ? this.request.projectId : this.projectId;
|
||||
this.$get('/api/environment/list/' + id, response => {
|
||||
this.environments = response.data;
|
||||
this.environments.forEach(environment => {
|
||||
parseEnvironment(environment);
|
||||
|
|
|
@ -2,19 +2,24 @@
|
|||
<el-dialog class="user-casecader" :title="title" :visible.sync="dialogVisible"
|
||||
@close="close">
|
||||
<div class="block" >
|
||||
<!-- <el-row>-->
|
||||
<!-- <span class="demonstration" v-html="lable"></span>-->
|
||||
<!-- </el-row>-->
|
||||
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
|
||||
<el-form-item prop="workspace" label-width="0px">
|
||||
<el-cascader
|
||||
:options="options"
|
||||
:props="props"
|
||||
v-model="selectedIds"
|
||||
ref="cascaderSelector"
|
||||
style="width:100%"
|
||||
:key="isResouceShow"
|
||||
clearable></el-cascader>
|
||||
<!-- <el-cascader-->
|
||||
<!-- :options="options"-->
|
||||
<!-- :props="props"-->
|
||||
<!-- v-model="selectedIds"-->
|
||||
<!-- ref="cascaderSelector"-->
|
||||
<!-- style="width:100%;"-->
|
||||
<!-- :key="isResouceShow"-->
|
||||
<!-- clearable></el-cascader>-->
|
||||
|
||||
<el-cascader-panel :options="options"
|
||||
:props="props"
|
||||
v-model="selectedIds"
|
||||
ref="cascaderSelector"
|
||||
style="width:100%;"
|
||||
:key="isResouceShow"
|
||||
clearable></el-cascader-panel>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
@ -37,7 +42,7 @@ export default {
|
|||
components: {ElUploadList, MsTableButton,MsDialogFooter},
|
||||
data() {
|
||||
var validateSelect = (rule, value, callback) => {
|
||||
let checkNodes = this.$refs.cascaderSelector.checkedNodes;
|
||||
let checkNodes = this.$refs.cascaderSelector.getCheckedNodes(true);
|
||||
if(checkNodes.length==0){
|
||||
callback(new Error(this.$t('workspace.select')));
|
||||
}
|
||||
|
@ -95,7 +100,7 @@ export default {
|
|||
confirm(){
|
||||
this.$refs.ruleForm.validate((valid) => {
|
||||
if (valid) {
|
||||
let checkNodes = this.$refs.cascaderSelector.checkedNodes;
|
||||
let checkNodes = this.$refs.cascaderSelector.getCheckedNodes(true);
|
||||
let selectValueArr = [];
|
||||
for (let i = 0; i < checkNodes.length; i++) {
|
||||
selectValueArr.push(checkNodes[i].value);
|
||||
|
@ -116,9 +121,19 @@ export default {
|
|||
<style scoped>
|
||||
|
||||
.user-casecader >>> .el-dialog {
|
||||
width: 400px;
|
||||
width: 600px;
|
||||
}
|
||||
/deep/ .el-form-item__content{
|
||||
margin-left: 0px;
|
||||
}
|
||||
/*.el-cascader-menu {*/
|
||||
/* height: 300px;*/
|
||||
/*}*/
|
||||
/*.el-cascader >>> .el-input--suffix {*/
|
||||
/* max-height: 200px;*/
|
||||
/*}*/
|
||||
/*.el-cascader >>> .el-cascader__tags {*/
|
||||
/* max-height: 190px;*/
|
||||
/* overflow: auto;*/
|
||||
/*}*/
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue