swagger已实现文档的参数和返回值查看
This commit is contained in:
@@ -128,19 +128,4 @@ public class SwaggerDocumentController {
|
|||||||
swaggerDocService.updateById(swaggerDocUp);
|
swaggerDocService.updateById(swaggerDocUp);
|
||||||
return DocResponseJson.ok();
|
return DocResponseJson.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取文档内容
|
|
||||||
*
|
|
||||||
* @return 文档内容
|
|
||||||
* @author 暮光:城中城
|
|
||||||
* @since 2021年10月16日
|
|
||||||
*/
|
|
||||||
@ResponseBody
|
|
||||||
@PostMapping(value = "/content")
|
|
||||||
public ResponseJson<List<SwaggerDoc>> content(HttpServletRequest request, String docUrl) {
|
|
||||||
String contentStr = swaggerHttpRequestService.requestUrl(request, docUrl);
|
|
||||||
return DocResponseJson.ok(contentStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|||||||
import com.zyplayer.doc.core.annotation.AuthMan;
|
import com.zyplayer.doc.core.annotation.AuthMan;
|
||||||
import com.zyplayer.doc.core.json.DocResponseJson;
|
import com.zyplayer.doc.core.json.DocResponseJson;
|
||||||
import com.zyplayer.doc.core.json.ResponseJson;
|
import com.zyplayer.doc.core.json.ResponseJson;
|
||||||
|
import com.zyplayer.doc.data.config.security.DocUserDetails;
|
||||||
|
import com.zyplayer.doc.data.config.security.DocUserUtil;
|
||||||
import com.zyplayer.doc.data.repository.manage.entity.SwaggerDoc;
|
import com.zyplayer.doc.data.repository.manage.entity.SwaggerDoc;
|
||||||
import com.zyplayer.doc.data.repository.manage.entity.SwaggerGlobalParam;
|
import com.zyplayer.doc.data.repository.manage.entity.SwaggerGlobalParam;
|
||||||
import com.zyplayer.doc.data.service.manage.SwaggerGlobalParamService;
|
import com.zyplayer.doc.data.service.manage.SwaggerGlobalParamService;
|
||||||
@@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -60,17 +63,15 @@ public class SwaggerGlobalParamController {
|
|||||||
*/
|
*/
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@PostMapping(value = "/update")
|
@PostMapping(value = "/update")
|
||||||
public ResponseJson<List<SwaggerDoc>> update(String globalParam) {
|
public ResponseJson<List<SwaggerDoc>> update(SwaggerGlobalParam globalParam) {
|
||||||
List<SwaggerGlobalParam> newParamList = JSON.parseArray(globalParam, SwaggerGlobalParam.class);
|
if (globalParam.getId() == null) {
|
||||||
QueryWrapper<SwaggerGlobalParam> queryWrapper = new QueryWrapper<>();
|
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
|
||||||
queryWrapper.eq("yn", 1);
|
globalParam.setYn(1);
|
||||||
List<SwaggerGlobalParam> queryParamList = swaggerGlobalParamService.list(queryWrapper);
|
globalParam.setCreateTime(new Date());
|
||||||
List<Long> newIdList = newParamList.stream().map(SwaggerGlobalParam::getId).filter(Objects::nonNull).collect(Collectors.toList());
|
globalParam.setCreateUserId(currentUser.getUserId());
|
||||||
List<Long> deletedList = queryParamList.stream().map(SwaggerGlobalParam::getId).filter(id -> !newIdList.contains(id)).collect(Collectors.toList());
|
globalParam.setCreateUserName(currentUser.getUsername());
|
||||||
// 删除不存在的
|
}
|
||||||
swaggerGlobalParamService.removeByIds(deletedList);
|
swaggerGlobalParamService.saveOrUpdate(globalParam);
|
||||||
// 保存或更新的
|
|
||||||
swaggerGlobalParamService.saveOrUpdateBatch(newParamList);
|
|
||||||
return DocResponseJson.ok();
|
return DocResponseJson.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.zyplayer.doc.swaggerplus.service;
|
|||||||
import cn.hutool.http.HttpRequest;
|
import cn.hutool.http.HttpRequest;
|
||||||
import com.zyplayer.doc.data.repository.manage.entity.SwaggerGlobalParam;
|
import com.zyplayer.doc.data.repository.manage.entity.SwaggerGlobalParam;
|
||||||
import com.zyplayer.doc.data.service.manage.SwaggerGlobalParamService;
|
import com.zyplayer.doc.data.service.manage.SwaggerGlobalParamService;
|
||||||
|
import org.apache.commons.collections.MapUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -27,25 +28,26 @@ public class SwaggerHttpRequestService {
|
|||||||
.collect(Collectors.toMap(SwaggerGlobalParam::getParamKey, SwaggerGlobalParam::getParamValue));
|
.collect(Collectors.toMap(SwaggerGlobalParam::getParamKey, SwaggerGlobalParam::getParamValue));
|
||||||
Map<String, String> globalHeaderParamMap = globalParamList.stream().filter(item -> Objects.equals(item.getParamType(), 2))
|
Map<String, String> globalHeaderParamMap = globalParamList.stream().filter(item -> Objects.equals(item.getParamType(), 2))
|
||||||
.collect(Collectors.toMap(SwaggerGlobalParam::getParamKey, SwaggerGlobalParam::getParamValue));
|
.collect(Collectors.toMap(SwaggerGlobalParam::getParamKey, SwaggerGlobalParam::getParamValue));
|
||||||
|
Map<String, String> globalCookieParamMap = globalParamList.stream().filter(item -> Objects.equals(item.getParamType(), 3))
|
||||||
|
.collect(Collectors.toMap(SwaggerGlobalParam::getParamKey, SwaggerGlobalParam::getParamValue));
|
||||||
|
// 执行请求
|
||||||
String resultStr = HttpRequest.get(docUrl)
|
String resultStr = HttpRequest.get(docUrl)
|
||||||
.form(globalFormParamMap)
|
.form(globalFormParamMap)
|
||||||
.header("Accept", "application/json, text/javascript, */*; q=0.01")
|
.header("Accept", "application/json, text/javascript, */*; q=0.01")
|
||||||
.header("User-Agent", request.getHeader("User-Agent"))
|
.header("User-Agent", request.getHeader("User-Agent"))
|
||||||
.addHeaders(globalHeaderParamMap)
|
.addHeaders(globalHeaderParamMap)
|
||||||
.cookie(this.getHttpCookie(request))
|
.cookie(this.getHttpCookie(request, globalCookieParamMap))
|
||||||
.timeout(5000).execute().body();
|
.timeout(5000).execute().body();
|
||||||
return resultStr;
|
return resultStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<HttpCookie> getHttpCookie(HttpServletRequest request) {
|
private List<HttpCookie> getHttpCookie(HttpServletRequest request, Map<String, String> globalCookieParamMap) {
|
||||||
List<HttpCookie> httpCookies = new LinkedList<>();
|
List<HttpCookie> httpCookies = new LinkedList<>();
|
||||||
for (Cookie cookie : request.getCookies()) {
|
for (Cookie cookie : request.getCookies()) {
|
||||||
HttpCookie httpCookie = new HttpCookie(cookie.getName(), cookie.getValue());
|
httpCookies.add(new HttpCookie(cookie.getName(), cookie.getValue()));
|
||||||
httpCookie.setDomain(cookie.getDomain());
|
}
|
||||||
httpCookie.setPath(cookie.getPath());
|
if (MapUtils.isNotEmpty(globalCookieParamMap)) {
|
||||||
httpCookie.setMaxAge(cookie.getMaxAge());
|
globalCookieParamMap.forEach((key, value) -> httpCookies.add(new HttpCookie(key, value)));
|
||||||
httpCookies.add(httpCookie);
|
|
||||||
}
|
}
|
||||||
return httpCookies;
|
return httpCookies;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,7 @@ export const zyplayerApi = {
|
|||||||
swaggerDocList: data => apiClient({url: '/doc-swagger/doc/list', method: 'post', data: data}),
|
swaggerDocList: data => apiClient({url: '/doc-swagger/doc/list', method: 'post', data: data}),
|
||||||
swaggerDocAdd: data => apiClient({url: '/doc-swagger/doc/add', method: 'post', data: data}),
|
swaggerDocAdd: data => apiClient({url: '/doc-swagger/doc/add', method: 'post', data: data}),
|
||||||
swaggerDocUpdate: data => apiClient({url: '/doc-swagger/doc/update', method: 'post', data: data}),
|
swaggerDocUpdate: data => apiClient({url: '/doc-swagger/doc/update', method: 'post', data: data}),
|
||||||
|
docSwaggerGlobalParamList: data => apiClient({url: '/doc-swagger/global-param/list', method: 'post', data: data}),
|
||||||
|
docSwaggerGlobalParamUpdate: data => apiClient({url: '/doc-swagger/global-param/update', method: 'post', data: data}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
228
zyplayer-doc-ui/swagger-ui/src/assets/utils/SwaggerAnalysis.js
Normal file
228
zyplayer-doc-ui/swagger-ui/src/assets/utils/SwaggerAnalysis.js
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
import formatjson from '../../assets/utils/formatjson'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数解析
|
||||||
|
* @author 暮光:城中城
|
||||||
|
* @since 2017年5月7日
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
getRequestParamList(parameters, definitionsDataMap) {
|
||||||
|
if (!parameters) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
formatjson.annotationObject = {};
|
||||||
|
let requestParamList = [], requestParamExample = [];
|
||||||
|
Object.keys(parameters).forEach(key => {
|
||||||
|
let tempParameters = parameters[key];
|
||||||
|
let htmlStr = "", htmlStrExample = "";
|
||||||
|
let responsesJson = [];
|
||||||
|
let responsesExample = [];
|
||||||
|
let required = tempParameters.required;
|
||||||
|
let paramName = tempParameters.name || '';
|
||||||
|
let paramType = tempParameters.type || '';
|
||||||
|
let paramDesc = tempParameters.description || '';
|
||||||
|
let paramIn = tempParameters.in || '';
|
||||||
|
let example = tempParameters.example || tempParameters.default || '';
|
||||||
|
if (tempParameters.items) {
|
||||||
|
htmlStr = paramName + "[0]";
|
||||||
|
htmlStrExample = paramName + "[0]";
|
||||||
|
} else if (tempParameters.schema) {
|
||||||
|
if ("array" === tempParameters.schema.type) {
|
||||||
|
let responsesObj = definitionsDataMap[tempParameters.schema.items.$ref];
|
||||||
|
if (responsesObj != null) {
|
||||||
|
responsesJson[0] = this.getResponsesJson(responsesObj, "", false, 1, definitionsDataMap);
|
||||||
|
responsesExample[0] = this.getResponsesJson(responsesObj, "", true, 1, definitionsDataMap);
|
||||||
|
} else {
|
||||||
|
responsesJson = [""];
|
||||||
|
responsesExample = [""];
|
||||||
|
if (tempParameters.schema.items.type === "boolean") {
|
||||||
|
responsesJson = [true];
|
||||||
|
responsesExample = [true];
|
||||||
|
} else if (tempParameters.schema.items.type === "integer") {
|
||||||
|
responsesJson = [0];
|
||||||
|
responsesExample = [0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tempParameters.schema.$ref) {
|
||||||
|
let arrTmp = tempParameters.schema.$ref.split("/");
|
||||||
|
paramType = arrTmp[arrTmp.length - 1];
|
||||||
|
}
|
||||||
|
htmlStr = formatjson.processObjectToHtmlPre(responsesJson, 0, false, false, false, true);
|
||||||
|
htmlStrExample = formatjson.processObjectToHtmlPre(responsesExample, 0, false, false, false, false);
|
||||||
|
} else if (tempParameters.schema.$ref) {
|
||||||
|
let responsesObj = definitionsDataMap[tempParameters.schema.$ref];
|
||||||
|
if (tempParameters.schema.$ref) {
|
||||||
|
let arrTmp = tempParameters.schema.$ref.split("/");
|
||||||
|
paramType = arrTmp[arrTmp.length - 1];
|
||||||
|
}
|
||||||
|
if (responsesObj) {
|
||||||
|
responsesJson = this.getResponsesJson(responsesObj, "", false, 1, definitionsDataMap);
|
||||||
|
responsesExample = this.getResponsesJson(responsesObj, "", true, 1, definitionsDataMap);
|
||||||
|
htmlStr = formatjson.processObjectToHtmlPre(responsesJson, 0, false, false, false, true);
|
||||||
|
htmlStrExample = formatjson.processObjectToHtmlPre(responsesExample, 0, false, false, false, false);
|
||||||
|
} else {
|
||||||
|
htmlStr = paramName;
|
||||||
|
htmlStrExample = paramName;
|
||||||
|
}
|
||||||
|
} else if ("string" === tempParameters.schema.type) {
|
||||||
|
htmlStr = paramName;
|
||||||
|
htmlStrExample = paramName;
|
||||||
|
} else {
|
||||||
|
htmlStr = paramName;
|
||||||
|
htmlStrExample = paramName;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
htmlStr = paramName;
|
||||||
|
htmlStrExample = paramName;
|
||||||
|
}
|
||||||
|
requestParamList.push({htmlStr, paramDesc, paramType, paramIn, required});
|
||||||
|
requestParamExample.push({htmlStrExample, paramDesc, paramType, paramIn, required});
|
||||||
|
});
|
||||||
|
console.log(requestParamList);
|
||||||
|
console.log(requestParamExample);
|
||||||
|
return requestParamList;
|
||||||
|
},
|
||||||
|
getResponsesJson(responsesObj, prevRef, isExample, recursiveCount, definitionsDataMap) {
|
||||||
|
let responsesJson = {};
|
||||||
|
recursiveCount++;// 多层递归,最多递归10层,防止无限递归
|
||||||
|
if (!responsesObj || !responsesObj.properties || recursiveCount > 10) {
|
||||||
|
return responsesJson;
|
||||||
|
}
|
||||||
|
let requiredArr = responsesObj.required;
|
||||||
|
Object.keys(responsesObj.properties).forEach(prop => {
|
||||||
|
let tmpData = responsesObj.properties[prop];
|
||||||
|
if ("array" === tmpData.type) {// 数组
|
||||||
|
formatjson.annotationObject[prop] = tmpData.description || '';
|
||||||
|
if (prevRef !== tmpData.items.$ref) {
|
||||||
|
let tempObj = definitionsDataMap[tmpData.items.$ref];
|
||||||
|
if (tempObj != null) {
|
||||||
|
let tempArr = responsesJson[prop] = [];
|
||||||
|
tempArr[0] = this.getResponsesJson(tempObj, tmpData.items.$ref, isExample, recursiveCount, definitionsDataMap);
|
||||||
|
} else {
|
||||||
|
let responsesJsonSub = [];
|
||||||
|
let bodyFor = responsesJsonSub;
|
||||||
|
let items = tmpData.items;
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
if ("array" === items.type) {
|
||||||
|
bodyFor = bodyFor[0] = [];
|
||||||
|
items = items.items;
|
||||||
|
} else {
|
||||||
|
tempObj = definitionsDataMap[items.$ref];
|
||||||
|
if (tempObj != null) {
|
||||||
|
bodyFor[0] = this.getResponsesJson(tempObj, items.$ref, isExample, recursiveCount, definitionsDataMap);
|
||||||
|
} else {
|
||||||
|
if (items.type === "boolean") {
|
||||||
|
bodyFor[0] = true;
|
||||||
|
} else if (items.type === "integer") {
|
||||||
|
bodyFor[0] = 0;
|
||||||
|
} else {
|
||||||
|
bodyFor[0] = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
responsesJson[prop] = responsesJsonSub;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
responsesJson[prop] = "{}" + (tmpData.description || '');
|
||||||
|
}
|
||||||
|
} else if (tmpData.$ref) {// 对象
|
||||||
|
formatjson.annotationObject[prop] = tmpData.description || '';
|
||||||
|
if (prevRef !== tmpData.$ref) {
|
||||||
|
let tempObj = definitionsDataMap[tmpData.$ref];
|
||||||
|
responsesJson[prop] = this.getResponsesJson(tempObj, tmpData.$ref, isExample, recursiveCount, definitionsDataMap);
|
||||||
|
} else {
|
||||||
|
responsesJson[prop] = "{}" + (tmpData.description || '');
|
||||||
|
}
|
||||||
|
} else {// 字段
|
||||||
|
let enumExample = "";
|
||||||
|
let enumObj = tmpData["enum"];
|
||||||
|
if (enumObj && enumObj.length > 0) {
|
||||||
|
enumExample = "枚举值:";
|
||||||
|
for (let i = 0; i < enumObj.length; i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
enumExample += "、";
|
||||||
|
}
|
||||||
|
enumExample += enumObj[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let typeStr = tmpData.format || tmpData.type || '';
|
||||||
|
if (isExample) {
|
||||||
|
let tempVal = tmpData.example || '';
|
||||||
|
if (tempVal && enumExample) {
|
||||||
|
tempVal = tempVal + "," + enumExample;
|
||||||
|
}
|
||||||
|
responsesJson[prop] = tempVal;
|
||||||
|
} else {
|
||||||
|
if (requiredArr && requiredArr.indexOf(prop) >= 0) {
|
||||||
|
typeStr = (typeStr ? typeStr + "," : "") + "required";
|
||||||
|
}
|
||||||
|
if (typeStr) {
|
||||||
|
typeStr = "(" + typeStr + ")";
|
||||||
|
}
|
||||||
|
let descriptionStr = typeStr + tmpData.description || '';
|
||||||
|
if (descriptionStr && enumExample) {
|
||||||
|
descriptionStr = descriptionStr + "," + enumExample;
|
||||||
|
}
|
||||||
|
responsesJson[prop] = descriptionStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return responsesJson;
|
||||||
|
},
|
||||||
|
getResponseParamList(responses, definitionsDataMap) {
|
||||||
|
if (!responses) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
let responsesList = [];
|
||||||
|
formatjson.annotationObject = {};
|
||||||
|
Object.keys(responses).forEach(key => {
|
||||||
|
let tempRespones = responses[key];
|
||||||
|
if (tempRespones.schema) {
|
||||||
|
let responsesJson, responsesExample;
|
||||||
|
if ("array" === tempRespones.schema.type) {
|
||||||
|
responsesJson = [];
|
||||||
|
responsesExample = [];
|
||||||
|
let responsesObj = definitionsDataMap[tempRespones.schema.items.$ref];
|
||||||
|
if (responsesObj != null) {
|
||||||
|
responsesJson[0] = this.getResponsesJson(responsesObj, "", false, 1, definitionsDataMap);
|
||||||
|
responsesExample[0] = this.getResponsesJson(responsesObj, "", true, 1, definitionsDataMap);
|
||||||
|
} else {
|
||||||
|
responsesJson = [""];
|
||||||
|
responsesExample = [""];
|
||||||
|
if (tempRespones.schema.items.type === "boolean") {
|
||||||
|
responsesJson = [true];
|
||||||
|
responsesExample = [true];
|
||||||
|
} else if (tempRespones.schema.items.type === "integer") {
|
||||||
|
responsesJson = [0];
|
||||||
|
responsesExample = [0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (tempRespones.schema.$ref) {
|
||||||
|
let responsesObj = definitionsDataMap[tempRespones.schema.$ref];
|
||||||
|
if (!responsesObj) {
|
||||||
|
let arrTmp = tempRespones.schema.$ref.split("/");
|
||||||
|
let lastObjName = arrTmp[arrTmp.length - 1];
|
||||||
|
responsesJson = lastObjName;
|
||||||
|
responsesExample = lastObjName;
|
||||||
|
} else {
|
||||||
|
responsesJson = this.getResponsesJson(responsesObj, "", false, 1, definitionsDataMap);
|
||||||
|
responsesExample = this.getResponsesJson(responsesObj, "", true, 1, definitionsDataMap);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
responsesJson = "";
|
||||||
|
responsesExample = "";
|
||||||
|
}
|
||||||
|
if (!responsesJson) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let htmlStr = formatjson.processObjectToHtmlPre(responsesJson, 0, false, false, false, true);
|
||||||
|
responsesList.push({code: key, desc: htmlStr});
|
||||||
|
htmlStr = formatjson.processObjectToHtmlPre(responsesExample, 0, false, false, false, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return responsesList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
146
zyplayer-doc-ui/swagger-ui/src/assets/utils/SwaggerAnalysisV2.js
Normal file
146
zyplayer-doc-ui/swagger-ui/src/assets/utils/SwaggerAnalysisV2.js
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
import {message} from 'ant-design-vue';
|
||||||
|
// 无需特殊处理的参数类型
|
||||||
|
let notNeedHandleTypeArr = ['file', 'string', 'integer', 'long', 'double', 'object', 'number', 'boolean'];
|
||||||
|
/**
|
||||||
|
* 参数解析
|
||||||
|
* @author 暮光:城中城
|
||||||
|
* @since 2017年5月7日
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
getRequestParamList(parameters, definitionsDataMap) {
|
||||||
|
if (!parameters) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
let indexKey = 1;
|
||||||
|
let requestParamList = [];
|
||||||
|
for (let i = 0; i < parameters.length; i++) {
|
||||||
|
let parameter = parameters[i];
|
||||||
|
let type = parameter.type;
|
||||||
|
let subType = undefined;
|
||||||
|
let children = undefined;
|
||||||
|
if (!type) {
|
||||||
|
if (parameter.schema && parameter.schema.type) {
|
||||||
|
type = parameter.schema.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type === 'array') {
|
||||||
|
// 解析parameter.items.$ref 或 parameter.items.originalRef {$ref: "#/definitions/Model", originalRef: "Model"}
|
||||||
|
// 解析parameter.items.type {type: 'file'}
|
||||||
|
if (parameter.items && parameter.items.originalRef) {
|
||||||
|
children = this.getParamDefinitions(parameter.items.originalRef, definitionsDataMap, indexKey, {}, 0);
|
||||||
|
} else if (parameter.schema && parameter.schema.items && parameter.schema.items.originalRef) {
|
||||||
|
children = this.getParamDefinitions(parameter.schema.items.originalRef, definitionsDataMap, indexKey, {}, 0);
|
||||||
|
} else if (parameter.items && parameter.items.type) {
|
||||||
|
subType = parameter.items.type;
|
||||||
|
} else {
|
||||||
|
console.log('001-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
|
||||||
|
message.error('001-遇到未处理的类型,请联系开发人员修改:' + type);
|
||||||
|
}
|
||||||
|
} else if (!type) {
|
||||||
|
if (parameter.schema && parameter.schema.originalRef) {
|
||||||
|
// 解析parameter.schema {originalRef: "Model", $ref: "#/definitions/Model"}
|
||||||
|
type = parameter.schema.originalRef;
|
||||||
|
children = this.getParamDefinitions(type, definitionsDataMap, indexKey, {}, 0);
|
||||||
|
} else {
|
||||||
|
console.log('002-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
|
||||||
|
message.error('002-遇到未处理的类型,请联系开发人员修改:' + type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (notNeedHandleTypeArr.indexOf(type) >= 0) {
|
||||||
|
// 无需特殊处理的类型
|
||||||
|
} else {
|
||||||
|
console.log('003-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
|
||||||
|
message.error('003-遇到未处理的类型,请联系开发人员修改:' + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requestParamList.push({
|
||||||
|
type: type,
|
||||||
|
key: indexKey,
|
||||||
|
in: parameter.in,
|
||||||
|
name: parameter.name,
|
||||||
|
required: parameter.required ? '是' : '否',
|
||||||
|
description: parameter.description,
|
||||||
|
children: children,
|
||||||
|
});
|
||||||
|
indexKey++;
|
||||||
|
}
|
||||||
|
return requestParamList;
|
||||||
|
},
|
||||||
|
getResponseParamList(responses, definitionsDataMap) {
|
||||||
|
let responsesList = [];
|
||||||
|
let indexKey = 1;
|
||||||
|
Object.keys(responses).forEach(code => {
|
||||||
|
let codeResponses = responses[code];
|
||||||
|
let type = undefined;
|
||||||
|
let children = undefined;
|
||||||
|
if (codeResponses.schema && codeResponses.schema.originalRef) {
|
||||||
|
type = codeResponses.schema.originalRef;
|
||||||
|
children = this.getParamDefinitions(codeResponses.schema.originalRef, definitionsDataMap, indexKey, {}, 0);
|
||||||
|
}
|
||||||
|
responsesList.push({
|
||||||
|
code: code,
|
||||||
|
type: type,
|
||||||
|
key: indexKey,
|
||||||
|
desc: codeResponses.description,
|
||||||
|
schemas: children,
|
||||||
|
});
|
||||||
|
indexKey++;
|
||||||
|
});
|
||||||
|
return responsesList;
|
||||||
|
},
|
||||||
|
getParamDefinitions(ref, definitionsDataMap, indexKey, parentRef, deep) {
|
||||||
|
let definition = definitionsDataMap[ref];
|
||||||
|
// 层级大于5层 或 父节点已经解析过此类型了 或者 没有类型定义
|
||||||
|
if (deep >= 5 || parentRef[ref] || !definition) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
parentRef[ref] = 1;
|
||||||
|
let paramList = [];
|
||||||
|
let type = definition.type;
|
||||||
|
let properties = definition.properties;
|
||||||
|
let indexSub = 1;
|
||||||
|
if (type === 'object') {
|
||||||
|
Object.keys(properties).forEach(key => {
|
||||||
|
let parameter = properties[key];
|
||||||
|
let type = parameter.type;
|
||||||
|
let keySub = indexKey + '_' + indexSub;
|
||||||
|
let children = undefined;
|
||||||
|
if (type === 'array') {
|
||||||
|
// 解析parameter.items {originalRef: "Model", $ref: "#/definitions/Model"}
|
||||||
|
if (parameter.items && parameter.items.originalRef) {
|
||||||
|
children = this.getParamDefinitions(parameter.items.originalRef, definitionsDataMap, keySub, parentRef, deep + 1);
|
||||||
|
} else {
|
||||||
|
console.log('004-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
|
||||||
|
message.error('004-遇到未处理的类型,请联系开发人员修改:' + type);
|
||||||
|
}
|
||||||
|
} else if (!type) {
|
||||||
|
if (parameter.originalRef) {
|
||||||
|
type = parameter.originalRef;
|
||||||
|
children = this.getParamDefinitions(parameter.originalRef, definitionsDataMap, keySub, parentRef, deep + 1);
|
||||||
|
} else {
|
||||||
|
console.log('005-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
|
||||||
|
message.error('005-遇到未处理的类型,请联系开发人员修改:' + type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (notNeedHandleTypeArr.indexOf(type) >= 0) {
|
||||||
|
// 无需特殊处理的类型
|
||||||
|
} else {
|
||||||
|
console.log('006-遇到未处理的类型,请联系开发人员修改:' + type, parameter);
|
||||||
|
message.error('006-遇到未处理的类型,请联系开发人员修改:' + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paramList.push({
|
||||||
|
type: type,
|
||||||
|
name: key,
|
||||||
|
key: keySub,
|
||||||
|
description: parameter.description,
|
||||||
|
children: children,
|
||||||
|
});
|
||||||
|
indexSub++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return paramList.length > 0 ? paramList : undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
125
zyplayer-doc-ui/swagger-ui/src/assets/utils/formatjson.js
Normal file
125
zyplayer-doc-ui/swagger-ui/src/assets/utils/formatjson.js
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* 将对象处理成json格式化和着色的html
|
||||||
|
* @author 暮光:城中城
|
||||||
|
* @since 2017年5月7日
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
// 需要在对象或列表后面添加注释的对象,例:{userList: "用户列表"}
|
||||||
|
// 那么在名字为userList的对象或列表后面都会加上:“用户列表” 这个注释
|
||||||
|
annotationObject: {},
|
||||||
|
tabStr: " ",
|
||||||
|
isArray: function(obj) {
|
||||||
|
return obj && typeof obj === 'object' && typeof obj.length === 'number'
|
||||||
|
&& !(obj.propertyIsEnumerable('length'));
|
||||||
|
},
|
||||||
|
processObjectToHtmlPre: function(obj, indent, addComma, isArray, isPropertyContent, showAnnotation) {
|
||||||
|
let htmlStr = this.processObject(obj, "", indent, addComma, isArray, isPropertyContent, showAnnotation);
|
||||||
|
htmlStr = '<pre class="json">' + htmlStr + '</pre>';
|
||||||
|
return htmlStr;
|
||||||
|
},
|
||||||
|
processObject: function(obj, keyName, indent, addComma, isArray, isPropertyContent, showAnnotation) {
|
||||||
|
let html = "";
|
||||||
|
let comma = (addComma) ? "<span class='comma'>,</span> " : "";
|
||||||
|
let type = typeof obj;
|
||||||
|
if (this.isArray(obj)) {
|
||||||
|
if (obj.length === 0) {
|
||||||
|
html += this.getRow(indent, "<span class='array-brace'>[ ]</span>" + comma, isPropertyContent);
|
||||||
|
} else {
|
||||||
|
let clpsHtml = '<span><img class="option-img" src="webjars/mg-ui/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
|
||||||
|
let annotation = '';
|
||||||
|
if(showAnnotation && keyName && this.annotationObject[keyName]) {
|
||||||
|
annotation = '<span class="annotation">// '+this.annotationObject[keyName]+'</span>';
|
||||||
|
}
|
||||||
|
html += this.getRow(indent, "<span class='array-brace'>[</span>"+clpsHtml+annotation, isPropertyContent);
|
||||||
|
for (let i = 0; i < obj.length; i++) {
|
||||||
|
html += this.processObject(obj[i], "", indent + 1, i < (obj.length - 1), true, false, showAnnotation);
|
||||||
|
}
|
||||||
|
clpsHtml = "</span>";
|
||||||
|
html += this.getRow(indent, clpsHtml + "<span class='array-brace'>]</span>" + comma);
|
||||||
|
}
|
||||||
|
} else if (type === 'object' && obj == null) {
|
||||||
|
html += this.formatLiteral("null", "", comma, indent, isArray, "null");
|
||||||
|
} else if (type === 'object') {
|
||||||
|
let numProps = 0;
|
||||||
|
for ( let prop in obj) {
|
||||||
|
numProps++;
|
||||||
|
}
|
||||||
|
if (numProps === 0) {
|
||||||
|
html += this.getRow(indent, "<span class='object-brace'>{ }</span>" + comma, isPropertyContent);
|
||||||
|
} else {
|
||||||
|
let clpsHtml = '<span><img class="option-img" src="webjars/mg-ui/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
|
||||||
|
let annotation = '';
|
||||||
|
if(showAnnotation && keyName && this.annotationObject[keyName]) {
|
||||||
|
annotation = '<span class="annotation">// '+this.annotationObject[keyName]+'</span>';
|
||||||
|
}
|
||||||
|
html += this.getRow(indent, "<span class='object-brace'>{</span>"+clpsHtml+annotation, isPropertyContent);
|
||||||
|
let j = 0;
|
||||||
|
for ( let prop in obj) {
|
||||||
|
let processStr = '<span class="property-name">"' + prop + '"</span>: ' + this.processObject(obj[prop], prop, indent + 1, ++j < numProps, false, true, showAnnotation);
|
||||||
|
html += this.getRow(indent + 1, processStr);
|
||||||
|
}
|
||||||
|
clpsHtml = "</span>";
|
||||||
|
html += this.getRow(indent, clpsHtml + "<span class='object-brace'>}</span>" + comma);
|
||||||
|
}
|
||||||
|
} else if (type === 'number') {
|
||||||
|
html += this.formatLiteral(obj, "", comma, indent, isArray, "number");
|
||||||
|
} else if (type === 'boolean') {
|
||||||
|
html += this.formatLiteral(obj, "", comma, indent, isArray, "boolean");
|
||||||
|
} else if (type === 'function') {
|
||||||
|
obj = this.formatFunction(indent, obj);
|
||||||
|
html += this.formatLiteral(obj, "", comma, indent, isArray, "function");
|
||||||
|
} else if (type === 'undefined') {
|
||||||
|
html += this.formatLiteral("undefined", "", comma, indent, isArray, "null");
|
||||||
|
} else {
|
||||||
|
html += this.formatLiteral(obj, "\"", comma, indent, isArray, "string");
|
||||||
|
}
|
||||||
|
return html;
|
||||||
|
},
|
||||||
|
expImgClicked: function(img){
|
||||||
|
let container = img.parentNode.nextSibling;
|
||||||
|
if(!container) return;
|
||||||
|
let disp = "none";
|
||||||
|
let src = "webjars/mg-ui/img/collapsed.png";
|
||||||
|
if(container.style.display === "none"){
|
||||||
|
disp = "inline";
|
||||||
|
src = "webjars/mg-ui/img/expanded.png";
|
||||||
|
}
|
||||||
|
container.style.display = disp;
|
||||||
|
img.src = src;
|
||||||
|
},
|
||||||
|
formatLiteral: function(literal, quote, comma, indent, isArray, style) {
|
||||||
|
if (typeof literal == 'string') {
|
||||||
|
literal = literal.split("<").join("<").split(">").join(">");
|
||||||
|
}
|
||||||
|
let str = "<span class='" + style + "'>" + quote + literal + quote + comma + "</span>";
|
||||||
|
if (isArray) {
|
||||||
|
str = this.getRow(indent, str);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
formatFunction: function(indent, obj) {
|
||||||
|
let tabs = "";
|
||||||
|
for (let i = 0; i < indent; i++) {
|
||||||
|
tabs += this.tabStr;
|
||||||
|
}
|
||||||
|
let funcStrArray = obj.toString().split("\n");
|
||||||
|
let str = "";
|
||||||
|
for (let i = 0; i < funcStrArray.length; i++) {
|
||||||
|
str += ((i === 0) ? "" : tabs) + funcStrArray[i] + "\n";
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
getRow: function(indent, data, isPropertyContent) {
|
||||||
|
let tabs = "";
|
||||||
|
for (let i = 0; i < indent && !isPropertyContent; i++) {
|
||||||
|
tabs += this.tabStr;
|
||||||
|
}
|
||||||
|
if (data != null && data.length > 0 && data.charAt(data.length - 1) !== "\n") {
|
||||||
|
data = data + "\n";
|
||||||
|
}
|
||||||
|
return tabs + data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -75,6 +75,11 @@
|
|||||||
if (matched.length >= 1) {
|
if (matched.length >= 1) {
|
||||||
this.openKeys = [matched[1].path];
|
this.openKeys = [matched[1].path];
|
||||||
}
|
}
|
||||||
|
// 加载初始化的地址
|
||||||
|
if (this.$route.path === '/doc/view' && this.$route.query.url) {
|
||||||
|
this.swaggerDocChoice = this.$route.query.url;
|
||||||
|
this.swaggerDocChoiceChange();
|
||||||
|
}
|
||||||
this.getSwaggerResourceList();
|
this.getSwaggerResourceList();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -111,10 +116,10 @@
|
|||||||
}
|
}
|
||||||
this.$store.commit('setSwaggerDoc', v2Doc);
|
this.$store.commit('setSwaggerDoc', v2Doc);
|
||||||
let metaInfo = {url};
|
let metaInfo = {url};
|
||||||
let treeData = createTreeViewByTag(v2Doc);
|
let treeData = createTreeViewByTag(v2Doc, '');
|
||||||
this.treeData = getTreeDataForTag(v2Doc, treeData.pathIndex, metaInfo);
|
this.treeData = getTreeDataForTag(v2Doc, treeData.pathData, metaInfo);
|
||||||
this.$store.commit('setSwaggerTreePathMap', treeData.treePathDataMap);
|
this.$store.commit('setSwaggerTreePathMap', treeData.pathDataMap);
|
||||||
setTimeout(() => this.treeDataLoading = false, 300);
|
setTimeout(() => this.treeDataLoading = false, 100);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
toJsonObj(value) {
|
toJsonObj(value) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ let routers = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/doc/manage',
|
path: '/doc/manage',
|
||||||
name: '文档管理',
|
name: '文档地址管理',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'FileTextOutlined'
|
icon: 'FileTextOutlined'
|
||||||
},
|
},
|
||||||
@@ -37,9 +37,17 @@ let routers = [
|
|||||||
},
|
},
|
||||||
component: EmptyLayout,
|
component: EmptyLayout,
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
path: '/doc/setting/globalParam',
|
||||||
|
name: '全局参数',
|
||||||
|
component: () => import('./views/doc/GlobalParam.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/doc/setting/view',
|
path: '/doc/setting/view',
|
||||||
name: '展示配置',
|
name: '展示配置',
|
||||||
|
meta: {
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
component: () => import('./views/common/SettingView.vue')
|
component: () => import('./views/common/SettingView.vue')
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,146 +1,95 @@
|
|||||||
export function getDefinitions(definitions) {
|
const methodArray = ["get", "head", "post", "put", "patch", "delete", "options", "trace"];
|
||||||
if (!definitions) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
let swaggerDefinitions = {};
|
|
||||||
Object.keys(definitions).forEach((key) => {
|
|
||||||
swaggerDefinitions["#/definitions/" + key] = definitions[key];
|
|
||||||
});
|
|
||||||
return swaggerDefinitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createTreeViewByTag(swagger, keywords) {
|
|
||||||
let pathIndex = {}, treePathDataMap = {};
|
|
||||||
let paths = swagger.paths;
|
|
||||||
let domain = swagger.domainUrl;// 服务器代理会返回此属性
|
|
||||||
let rewriteDomainUrl = swagger.rewriteDomainUrl;// 服务器代理会返回此属性
|
|
||||||
if (!paths) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!domain) {
|
|
||||||
domain = "http://" + swagger.host + swagger.basePath;
|
|
||||||
}
|
|
||||||
if (domain.substring(domain.length - 1) === "/") {
|
|
||||||
domain = domain.substring(0, domain.length - 1);
|
|
||||||
}
|
|
||||||
//console.log(paths);
|
|
||||||
Object.keys(paths).forEach(key => {
|
|
||||||
//console.log(key, paths[key]);
|
|
||||||
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "get", treePathDataMap);
|
|
||||||
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "head", treePathDataMap);
|
|
||||||
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "post", treePathDataMap);
|
|
||||||
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "put", treePathDataMap);
|
|
||||||
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "patch", treePathDataMap);
|
|
||||||
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "delete", treePathDataMap);
|
|
||||||
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "options", treePathDataMap);
|
|
||||||
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "trace", treePathDataMap);
|
|
||||||
});
|
|
||||||
// console.log(pathIndex);
|
|
||||||
// console.log(treePathDataMap);
|
|
||||||
// console.log(treeData);
|
|
||||||
return {pathIndex: pathIndex, treePathDataMap: treePathDataMap};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置对象的各种请求方式,存在则复制
|
* 通过tag创建文档树
|
||||||
* @param source 资源,原始json的paths的指定对象
|
* @param swagger 文档内容
|
||||||
* @param pathObj 当前的待赋值对象
|
* @param keywords 搜索内容
|
||||||
* @param url url绝对路径
|
* @returns {{pathDataMap: {}, pathData: {}}}
|
||||||
* @param method 请求方式,post、get...
|
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
function setRequestMethodForTag(rewriteDomainUrl, domain, source, pathObj, url, method, treePathDataMap) {
|
export function createTreeViewByTag(swagger, keywords) {
|
||||||
if (!source[method] || !source[method].tags) {
|
let pathData = {}, pathDataMap = {};
|
||||||
return;
|
let swaggerPaths = swagger.paths;
|
||||||
|
if (!swaggerPaths) {
|
||||||
|
return {pathDataMap, pathData};
|
||||||
}
|
}
|
||||||
source[method].tags.forEach(function(val, index) {
|
//console.log(swaggerPaths);
|
||||||
let tempObj = pathObj[val];
|
Object.keys(swaggerPaths).forEach(url => {
|
||||||
if(!tempObj) {
|
//console.log(key, swaggerPaths[key]);
|
||||||
tempObj = pathObj[val] = {};
|
let pathMethods = swaggerPaths[url];
|
||||||
|
for (let method of methodArray) {
|
||||||
|
if (!pathMethods[method] || !pathMethods[method].tags) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pathMethods[method].tags.forEach(tag => {
|
||||||
|
let pathTag = pathData[tag];
|
||||||
|
if (!pathTag) {
|
||||||
|
pathTag = pathData[tag] = {};
|
||||||
|
}
|
||||||
|
let pathTagUrl = pathTag[url];
|
||||||
|
if (!pathTagUrl) {
|
||||||
|
pathTagUrl = pathTag[url] = {};
|
||||||
|
}
|
||||||
|
let tempPath = url + "." + method;
|
||||||
|
pathTagUrl[method] = pathMethods[method];
|
||||||
|
pathTagUrl[method].path = tempPath;
|
||||||
|
pathTagUrl[method].url = url;
|
||||||
|
pathTagUrl[method].method = method;
|
||||||
|
// url对应文档的映射
|
||||||
|
pathDataMap[tempPath] = pathMethods[method];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
let tempUrlObj = tempObj[url];
|
|
||||||
if(!tempUrlObj) {
|
|
||||||
tempUrlObj = tempObj[url] = {};
|
|
||||||
}
|
|
||||||
let tempPath = url + "." + method;
|
|
||||||
tempUrlObj[method] = source[method];
|
|
||||||
tempUrlObj[method].path = tempPath;
|
|
||||||
tempUrlObj[method].url = url;
|
|
||||||
tempUrlObj[method].method = method;
|
|
||||||
tempUrlObj[method].domain = domain;
|
|
||||||
tempUrlObj[method].rewriteDomainUrl = rewriteDomainUrl;
|
|
||||||
treePathDataMap[tempPath] = source[method];
|
|
||||||
});
|
});
|
||||||
|
return {pathData, pathDataMap};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTreeDataForTag(swagger, pathData, metaInfo) {
|
export function getTreeDataForTag(swagger, pathData, metaInfo) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
key: 'main',
|
||||||
title: swagger.title || 'Swagger接口文档',
|
title: swagger.title || 'Swagger接口文档',
|
||||||
key: '0-0',
|
children: getTreeHtmlForTag(swagger.tags, pathData, metaInfo)
|
||||||
children: getTreeHtmlForTag(pathData, 0, metaInfo)
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTreeHtmlForTag(pathData, treeId, metaInfo) {
|
function getTreeHtmlForTag(swaggerTags, pathData, metaInfo) {
|
||||||
let treeData = [];
|
let treeData = [];
|
||||||
let indexNow = 1;
|
let indexTag = 1;
|
||||||
// get, head, post, put, patch, delete, options, trace
|
// 遍历分组
|
||||||
let actionArrays = ["get", "head", "post", "put", "patch", "delete", "options", "trace"];
|
swaggerTags.forEach(tag => {
|
||||||
Object.keys(pathData).forEach(key => {
|
let indexUrl = 1;
|
||||||
let tempNode = pathData[key];
|
let urlTree = [];
|
||||||
let tempTreeId = treeId + "_" + indexNow;
|
let pathTagNode = pathData[tag.name];
|
||||||
// 只有一个子元素,而且有method元素,说明是只有一个节点
|
if (!pathTagNode) {
|
||||||
let nodeSub = getObjectFirstAttributeIfOnly(tempNode);
|
return;
|
||||||
if (nodeSub && nodeSub.method) {
|
|
||||||
nodeSub.treeId = tempTreeId;
|
|
||||||
let title = nodeSub.summary || nodeSub.path;
|
|
||||||
treeData.push({
|
|
||||||
title: title,
|
|
||||||
key: tempTreeId,
|
|
||||||
isLeaf: true,
|
|
||||||
method: nodeSub.method,
|
|
||||||
query: {
|
|
||||||
...metaInfo,
|
|
||||||
path: nodeSub.url,
|
|
||||||
method: nodeSub.method,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (actionArrays.indexOf(key) >= 0) {
|
|
||||||
tempNode.treeId = tempTreeId;
|
|
||||||
let title = tempNode.summary || tempNode.path;
|
|
||||||
treeData.push({
|
|
||||||
title: title,
|
|
||||||
key: tempTreeId,
|
|
||||||
isLeaf: true,
|
|
||||||
method: tempNode.method,
|
|
||||||
query: {
|
|
||||||
...metaInfo,
|
|
||||||
path: tempNode.url,
|
|
||||||
method: tempNode.method,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
treeData.push({title: key, key: key, children: getTreeHtmlForTag(tempNode, tempTreeId, metaInfo)});
|
|
||||||
}
|
}
|
||||||
indexNow++;
|
// 遍历路劲
|
||||||
|
Object.keys(pathTagNode).forEach(url => {
|
||||||
|
let indexMethod = 1;
|
||||||
|
let pathUrlNode = pathTagNode[url];
|
||||||
|
// 遍历方法
|
||||||
|
Object.keys(pathUrlNode).forEach(method => {
|
||||||
|
let tempTreeId = indexTag + "_" + indexUrl + "_" + indexMethod;
|
||||||
|
let methodNode = pathUrlNode[method];
|
||||||
|
methodNode.treeId = tempTreeId;
|
||||||
|
let title = methodNode.summary || methodNode.path;
|
||||||
|
urlTree.push({
|
||||||
|
title: title,
|
||||||
|
key: tempTreeId,
|
||||||
|
isLeaf: true,
|
||||||
|
method: methodNode.method,
|
||||||
|
query: {
|
||||||
|
...metaInfo,
|
||||||
|
path: methodNode.url,
|
||||||
|
method: methodNode.method,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
indexMethod++;
|
||||||
|
});
|
||||||
|
indexUrl++;
|
||||||
|
});
|
||||||
|
treeData.push({title: tag.name, key: indexTag, children: urlTree});
|
||||||
|
indexTag++;
|
||||||
});
|
});
|
||||||
return treeData;
|
return treeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 如果对象只有一个属性则返回第一个属性,否则返回null
|
|
||||||
* @param data
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function getObjectFirstAttributeIfOnly(data) {
|
|
||||||
let len = 0, value = "";
|
|
||||||
for (let key in data) {
|
|
||||||
if (++len > 1) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
value = data[key];
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {createStore} from 'vuex'
|
import {createStore} from 'vuex'
|
||||||
import {getDefinitions, createTreeViewByTag} from './SwaggerDocUtil'
|
import {createTreeViewByTag} from './SwaggerDocUtil'
|
||||||
|
|
||||||
export default createStore({
|
export default createStore({
|
||||||
state() {
|
state() {
|
||||||
@@ -9,7 +9,7 @@ export default createStore({
|
|||||||
pageTabNameMap: {},
|
pageTabNameMap: {},
|
||||||
swaggerDoc: {},
|
swaggerDoc: {},
|
||||||
swaggerDefinitions: {},
|
swaggerDefinitions: {},
|
||||||
swaggerTreePathMap: [],
|
swaggerTreePathMap: {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
@@ -21,7 +21,7 @@ export default createStore({
|
|||||||
},
|
},
|
||||||
setSwaggerDoc(state, swaggerDoc) {
|
setSwaggerDoc(state, swaggerDoc) {
|
||||||
state.swaggerDoc = swaggerDoc;
|
state.swaggerDoc = swaggerDoc;
|
||||||
state.swaggerDefinitions = getDefinitions(swaggerDoc.definitions);
|
state.swaggerDefinitions = swaggerDoc.definitions || {};
|
||||||
},
|
},
|
||||||
setSwaggerTreePathMap(state, swaggerTreePathMap) {
|
setSwaggerTreePathMap(state, swaggerTreePathMap) {
|
||||||
state.swaggerTreePathMap = swaggerTreePathMap;
|
state.swaggerTreePathMap = swaggerTreePathMap;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
<a-table :dataSource="docList" :columns="docListColumns" size="middle"
|
<a-table :dataSource="docList" :columns="docListColumns" size="middle"
|
||||||
:loading="docListLoading"
|
:loading="docListLoading" :pagination="false"
|
||||||
:scroll="{ x: 1400, y: 'calc(100vh - 340px)' }">
|
:scroll="{ x: 1400, y: 'calc(100vh - 340px)' }">
|
||||||
<template #bodyCell="{ column, text, record }">
|
<template #bodyCell="{ column, text, record }">
|
||||||
<template v-if="column.dataIndex === 'operation'">
|
<template v-if="column.dataIndex === 'operation'">
|
||||||
@@ -158,39 +158,14 @@
|
|||||||
docStatus: [{type: 'number', required: true, message: '请选择文档状态', trigger: 'change'}],
|
docStatus: [{type: 'number', required: true, message: '请选择文档状态', trigger: 'change'}],
|
||||||
},
|
},
|
||||||
docListColumns: [
|
docListColumns: [
|
||||||
{
|
{title: 'ID', dataIndex: 'id', width: 70},
|
||||||
title: 'ID',
|
{title: '文档名称', dataIndex: 'name', width: 150},
|
||||||
dataIndex: 'id',
|
{title: '文档类型', dataIndex: 'docType', width: 90},
|
||||||
width: 70,
|
{title: '开放访问', dataIndex: 'openVisit', width: 90},
|
||||||
}, {
|
{title: '状态', dataIndex: 'docStatus', width: 90},
|
||||||
title: '文档名称',
|
{title: '文档地址', dataIndex: 'docUrl'},
|
||||||
dataIndex: 'name',
|
{title: '目标域名', dataIndex: 'rewriteDomain', width: 250},
|
||||||
width: 150,
|
{title: '操作', dataIndex: 'operation', fixed: 'right', width: 170},
|
||||||
}, {
|
|
||||||
title: '文档类型',
|
|
||||||
dataIndex: 'docType',
|
|
||||||
width: 90,
|
|
||||||
}, {
|
|
||||||
title: '开放访问',
|
|
||||||
dataIndex: 'openVisit',
|
|
||||||
width: 90,
|
|
||||||
}, {
|
|
||||||
title: '状态',
|
|
||||||
dataIndex: 'docStatus',
|
|
||||||
width: 90,
|
|
||||||
}, {
|
|
||||||
title: '文档地址',
|
|
||||||
dataIndex: 'docUrl',
|
|
||||||
}, {
|
|
||||||
title: '目标域名',
|
|
||||||
dataIndex: 'rewriteDomain',
|
|
||||||
width: 250,
|
|
||||||
}, {
|
|
||||||
title: '操作',
|
|
||||||
dataIndex: 'operation',
|
|
||||||
fixed: 'right',
|
|
||||||
width: 170,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,38 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-tabs v-model:activeKey="activePage" closable @tab-click="changePage" style="padding: 5px 10px 0;">
|
<a-tabs v-model:activeKey="activePage" closable @tab-click="changePage" style="padding: 5px 10px 0;">
|
||||||
<a-tab-pane tab="接口说明" key="doc">
|
<a-tab-pane tab="接口说明" key="doc">
|
||||||
{{activePage}}
|
<a-form :label-col="{span: 4}" :wrapper-col="{span: 20}">
|
||||||
|
<a-form-item label="接口地址">{{docInfoShow.url}}</a-form-item>
|
||||||
|
<a-form-item label="说明">{{docInfoShow.description}}</a-form-item>
|
||||||
|
<a-form-item label="请求方式">{{docInfoShow.method}}</a-form-item>
|
||||||
|
<a-form-item label="请求数据类型">{{docInfoShow.consumes}}</a-form-item>
|
||||||
|
<a-form-item label="响应数据类型">{{docInfoShow.produces}}</a-form-item>
|
||||||
|
<a-form-item label="请求参数">
|
||||||
|
<a-table :dataSource="requestParamList" :columns="requestParamListColumns" size="small" :pagination="false" defaultExpandAllRows>
|
||||||
|
<template #bodyCell="{ column, text, record }">
|
||||||
|
<template v-if="column.dataIndex === 'htmlStr'">
|
||||||
|
<div v-html="text"></div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="返回结果">
|
||||||
|
<a-table :dataSource="responseParamList" :columns="responseCodeListColumns" size="small" :pagination="false" defaultExpandAllRows>
|
||||||
|
<template #bodyCell="{ column, text, record }">
|
||||||
|
<template v-if="column.dataIndex === 'desc'">
|
||||||
|
<div v-html="text"></div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template #expandedRowRender="{ record }">
|
||||||
|
<template v-if="record.schemas">
|
||||||
|
<a-table :dataSource="record.schemas" :columns="responseParamListColumns" size="small" :pagination="false" defaultExpandAllRows>
|
||||||
|
</a-table>
|
||||||
|
</template>
|
||||||
|
<div v-else style="text-align: center;padding: 10px 0;">无参数说明</div>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane tab="在线调试" key="debug">
|
<a-tab-pane tab="在线调试" key="debug">
|
||||||
{{activePage}}
|
{{activePage}}
|
||||||
@@ -10,35 +41,122 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {toRefs, ref, reactive, onMounted, onActivated} from 'vue';
|
import {toRefs, ref, reactive, onMounted, watch} from 'vue';
|
||||||
import { useRouter, useRoute } from "vue-router";
|
import { useRouter, useRoute } from "vue-router";
|
||||||
import {useStore} from 'vuex';
|
import {useStore} from 'vuex';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
|
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
|
||||||
|
import swaggerAnalysis from '../../assets/utils/SwaggerAnalysisV2'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup() {
|
setup() {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
let activePage = ref('doc');
|
let activePage = ref('doc');
|
||||||
onMounted(() => {
|
let requestParamList = ref([]);
|
||||||
console.log('DocView onMounted', route.query);
|
let responseParamList = ref([]);
|
||||||
|
let docInfoShow = ref({
|
||||||
|
url: '',
|
||||||
|
description: '',
|
||||||
|
method: '',
|
||||||
|
consumes: '',
|
||||||
|
produces: '',
|
||||||
|
});
|
||||||
|
let isLoadSuccess = ref(false);
|
||||||
|
let intervalNum = 0;
|
||||||
|
let intervalTimer = undefined;
|
||||||
|
const initLoadDocument = () => {
|
||||||
let path = route.query.path + '.' + route.query.method;
|
let path = route.query.path + '.' + route.query.method;
|
||||||
|
if (Object.keys(store.state.swaggerTreePathMap).length <= 0) {
|
||||||
|
console.log('文档尚未加载,等待加载完成');
|
||||||
|
if (!intervalTimer) {
|
||||||
|
intervalTimer = setInterval(() => {
|
||||||
|
if (isLoadSuccess.value || intervalNum++ > 50) {
|
||||||
|
clearInterval(intervalTimer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Object.keys(store.state.swaggerTreePathMap).length > 0) {
|
||||||
|
console.log('文档内容改变,重新加载文档');
|
||||||
|
initLoadDocument();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
let docInfo = store.state.swaggerTreePathMap[path];
|
let docInfo = store.state.swaggerTreePathMap[path];
|
||||||
if (!docInfo) {
|
if (!docInfo) {
|
||||||
message.error('没有找到对应的文档');
|
message.error('没有找到对应的文档');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
isLoadSuccess.value = true;
|
||||||
store.commit('addTableName', {key: route.fullPath, val: docInfo.summary});
|
store.commit('addTableName', {key: route.fullPath, val: docInfo.summary});
|
||||||
|
// 解析接口说明
|
||||||
|
let consumes = '', produces = '';
|
||||||
|
if (docInfo.consumes && docInfo.consumes.length > 0) {
|
||||||
|
consumes = docInfo.consumes.join(' ');
|
||||||
|
}
|
||||||
|
if (docInfo.produces && docInfo.produces.length > 0) {
|
||||||
|
produces = docInfo.produces.join(' ');
|
||||||
|
}
|
||||||
|
docInfoShow.value = {
|
||||||
|
url: docInfo.url,
|
||||||
|
description: (docInfo.description || docInfo.summary),
|
||||||
|
method: docInfo.method || '',
|
||||||
|
consumes: consumes,
|
||||||
|
produces: produces,
|
||||||
|
};
|
||||||
|
// 解析请求参数
|
||||||
|
let definitionsDataMap = store.state.swaggerDefinitions;
|
||||||
|
requestParamList.value = swaggerAnalysis.getRequestParamList(docInfo.parameters, definitionsDataMap);
|
||||||
|
responseParamList.value = swaggerAnalysis.getResponseParamList(docInfo.responses, definitionsDataMap);
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
initLoadDocument();
|
||||||
});
|
});
|
||||||
const changePage = () => {
|
const changePage = () => {
|
||||||
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
docInfoShow,
|
||||||
activePage,
|
activePage,
|
||||||
changePage,
|
changePage,
|
||||||
|
requestParamList,
|
||||||
|
requestParamListColumns: [
|
||||||
|
{title: '参数名', dataIndex: 'name', width: 200},
|
||||||
|
{title: '说明', dataIndex: 'description'},
|
||||||
|
{title: '类型', dataIndex: 'type'},
|
||||||
|
{title: '参数位置', dataIndex: 'in'},
|
||||||
|
{title: '是否必填', dataIndex: 'required'},
|
||||||
|
],
|
||||||
|
responseParamList,
|
||||||
|
responseCodeListColumns: [
|
||||||
|
{title: '状态码', dataIndex: 'code', width: 100},
|
||||||
|
{title: '说明', dataIndex: 'desc'},
|
||||||
|
{title: '类型', dataIndex: 'type'},
|
||||||
|
],
|
||||||
|
responseParamListColumns: [
|
||||||
|
{title: '参数名', dataIndex: 'name', width: 200},
|
||||||
|
{title: '说明', dataIndex: 'description'},
|
||||||
|
{title: '类型', dataIndex: 'type'},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* S-JSON展示的样式 */
|
||||||
|
pre.json{margin-top:0px;margin-bottom:0px;}
|
||||||
|
pre.json .canvas{font:10pt georgia;background-color:#ececec;color:#000000;border:1px solid #cecece;}
|
||||||
|
pre.json .object-brace{color:#00aa00;font-weight:bold;}
|
||||||
|
pre.json .array-brace{color:#0033ff;font-weight:bold;}
|
||||||
|
pre.json .property-name{color:#cc0000;font-weight:bold;}
|
||||||
|
pre.json .string{color:#007777;}
|
||||||
|
pre.json .number{color:#aa00aa;}
|
||||||
|
pre.json .boolean{color:#0000ff;}
|
||||||
|
pre.json .function{color:#aa6633;text-decoration:italic;}
|
||||||
|
pre.json .null{color:#0000ff;}
|
||||||
|
pre.json .comma{color:#000000;font-weight:bold;}
|
||||||
|
pre.json .annotation{color:#aaa;}
|
||||||
|
pre img{cursor: pointer;}
|
||||||
|
/* E-JSON展示的样式 */
|
||||||
|
</style>
|
||||||
|
|||||||
119
zyplayer-doc-ui/swagger-ui/src/views/doc/GlobalParam.vue
Normal file
119
zyplayer-doc-ui/swagger-ui/src/views/doc/GlobalParam.vue
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
<template>
|
||||||
|
<div style="margin-bottom: 10px;text-align: right;">
|
||||||
|
<a-button @click="searchDocList" type="primary">刷新</a-button>
|
||||||
|
<a-button @click="addDocLine">新建</a-button>
|
||||||
|
</div>
|
||||||
|
<a-table :dataSource="docList" :columns="docListColumns" size="middle"
|
||||||
|
:loading="docListLoading" :pagination="false"
|
||||||
|
:scroll="{ x: 1000, y: 'calc(100vh - 340px)' }">
|
||||||
|
<template #bodyCell="{ column, text, record }">
|
||||||
|
<template v-if="column.dataIndex === 'paramKey'">
|
||||||
|
<a-input v-if="record.isEdit" placeholder="请输入参数名称" v-model:value="docEdit.paramKey"></a-input>
|
||||||
|
<span v-else>{{text}}</span>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.dataIndex === 'paramValue'">
|
||||||
|
<a-textarea v-if="record.isEdit" :rows="1" placeholder="请输入参数值" v-model:value="docEdit.paramValue"></a-textarea>
|
||||||
|
<span v-else>{{text}}</span>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.dataIndex === 'paramType'">
|
||||||
|
<template v-if="record.isEdit">
|
||||||
|
<a-select placeholder="参数位置" v-model:value="docEdit.paramType" style="width: 110px;">
|
||||||
|
<a-select-option :value="1">Form</a-select-option>
|
||||||
|
<a-select-option :value="2">Header</a-select-option>
|
||||||
|
<a-select-option :value="3">Cookie</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<a-tag color="green" v-if="text === 1">Form</a-tag>
|
||||||
|
<a-tag color="pink" v-else-if="text === 2">Header</a-tag>
|
||||||
|
<a-tag color="pink" v-else-if="text === 3">Cookie</a-tag>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.dataIndex === 'operation'">
|
||||||
|
<template v-if="record.isEdit">
|
||||||
|
<a-button type="link" @click="cancelEditDoc(record)">取消</a-button>
|
||||||
|
<a-button type="link" @click="saveEditDoc(record)">保存</a-button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<a-button type="link" @click="editDoc(record)">编辑</a-button>
|
||||||
|
<a-popconfirm title="确定要删除吗?" @confirm="deleteDoc(record)">
|
||||||
|
<a-button type="link" danger>删除</a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { toRefs, ref, reactive, onMounted } from 'vue';
|
||||||
|
import {zyplayerApi} from '../../api';
|
||||||
|
import {useStore} from 'vuex';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const store = useStore()
|
||||||
|
let docList = ref([]);
|
||||||
|
let docListLoading = ref(false);
|
||||||
|
const searchDocList = async () => {
|
||||||
|
docListLoading.value = true;
|
||||||
|
zyplayerApi.docSwaggerGlobalParamList().then(res => {
|
||||||
|
setTimeout(() => docListLoading.value = false, 500);
|
||||||
|
docList.value = res.data || [];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let docEdit = ref({});
|
||||||
|
const addDocLine = () => {
|
||||||
|
if (docEdit.value.isEdit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let newLine = {isEdit: true};
|
||||||
|
docList.value.push(newLine);
|
||||||
|
docEdit.value = newLine;
|
||||||
|
};
|
||||||
|
const editDoc = (record) => {
|
||||||
|
record.isEdit = true;
|
||||||
|
docEdit.value = {...record};
|
||||||
|
};
|
||||||
|
const cancelEditDoc = (record) => {
|
||||||
|
record.isEdit = false;
|
||||||
|
if (!record.id) {
|
||||||
|
docList.value = docList.value.filter(item => item !== record);
|
||||||
|
}
|
||||||
|
docEdit.value = {};
|
||||||
|
};
|
||||||
|
const saveEditDoc = (record) => {
|
||||||
|
zyplayerApi.docSwaggerGlobalParamUpdate(docEdit.value).then(res => {
|
||||||
|
record.isEdit = false;
|
||||||
|
searchDocList();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const deleteDoc = async (record) => {
|
||||||
|
zyplayerApi.docSwaggerGlobalParamUpdate({id: record.id, yn: 0}).then(res => {
|
||||||
|
searchDocList();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
searchDocList();
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
docList,
|
||||||
|
docListLoading,
|
||||||
|
docEdit,
|
||||||
|
searchDocList,
|
||||||
|
deleteDoc,
|
||||||
|
editDoc,
|
||||||
|
saveEditDoc,
|
||||||
|
cancelEditDoc,
|
||||||
|
addDocLine,
|
||||||
|
docListColumns: [
|
||||||
|
{title: '参数名称', dataIndex: 'paramKey', width: 250},
|
||||||
|
{title: '参数值', dataIndex: 'paramValue'},
|
||||||
|
{title: '参数位置', dataIndex: 'paramType', width: 120},
|
||||||
|
{title: '操作', dataIndex: 'operation', fixed: 'right', width: 170},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user