4 Commits

Author SHA1 Message Date
暮光:城中城
fc41ebdac1 本分支用于同步代码 2019-01-28 22:49:33 +08:00
暮光:城中城
c2b64d06e4 增加开放文档逻辑,优化文档展示 2019-01-28 22:26:34 +08:00
暮光:城中城
15eecc7ee0 优化文档存储,展示文档选择 2019-01-27 22:32:14 +08:00
暮光:城中城
c32fc3f05d 优化文档存储,展示文档选择 2019-01-27 22:28:35 +08:00
31 changed files with 4053 additions and 267 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# Created by .ignore support plugin (hsz.mobi)
.idea
*.iml
tmlog*.lck
tmlog*.log

View File

@@ -29,7 +29,7 @@
http://127.0.0.1:8082/zyplayer-doc-manage/statics/manage/home.html
未登录会进入登录页面登陆后自动跳回默认账号zyplayer 密码:123456
> 项目页面全是静态的html如果使用idea启动有可能访问不了静态页面需要在这里配置下工作目录然后重新启动即可
![](https://images.gitee.com/uploads/images/2019/0125/094619_7f8963bf_596905.png "配置工作目录")
![](https://images.gitee.com/uploads/images/2019/0127/222951_4ce343fe_596905.png "配置工作目录")
#### 功能介绍

View File

@@ -1,13 +1,11 @@
package com.zyplayer.doc.manage.framework.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.common.base.Predicates;
import com.zyplayer.doc.swagger.framework.configuration.EnableSwaggerMgUi;
import io.swagger.annotations.Api;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
@@ -15,7 +13,6 @@ import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 不需要管理本项目的文档,只需要开启@EnableSwaggerMgUi即可
@@ -26,8 +23,8 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
//@EnableSwagger2
@EnableSwaggerMgUi(
selfDoc = false,// 是否开启自身的文档
defaultResources = {// 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址
//"http://localhost:8080/swagger-resources"
defaultLocation = {// 启动后第一次访问没有数据情况下需要加载进来的/v2/doc地址
//"http://localhost:8080/v2/doc"
}
)
public class SwaggerConfiguration {

View File

@@ -5,6 +5,8 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.swagger.controller.vo.LocationListVo;
import com.zyplayer.doc.swagger.controller.vo.SwaggerLocationVo;
import com.zyplayer.doc.swagger.controller.vo.SwaggerResourcesInfoVo;
import com.zyplayer.doc.swagger.framework.configuration.EnableSwaggerMgUi;
import com.zyplayer.doc.swagger.framework.configuration.SpringContextUtil;
@@ -14,13 +16,13 @@ import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.swagger.web.SwaggerResource;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
@@ -30,22 +32,21 @@ import java.util.stream.Collectors;
/**
* 文档控制器
*
*
* @author 暮光:城中城
* @since 2018年8月21日
*/
@RestController
@RequestMapping("/swagger-mg-ui/document")
public class MgDocumentController {
private static Logger logger = LoggerFactory.getLogger(MgDocumentController.class);
@Autowired
@Resource
private MgStorageService storageService;
/**
* 获取所有的文档地址
*
*
* @author 暮光:城中城
* @since 2018年8月21日
* @return 文档内容
@@ -71,48 +72,33 @@ public class MgDocumentController {
@ResponseBody
@PostMapping(value = "/docs")
public void docs(HttpServletRequest request, HttpServletResponse response) {
boolean needRestorage = true;
String choiceDocList = request.getParameter("choiseDocList");
// 转成set防止重复
String choiceLocationList = request.getParameter("choiceLocationList");
List<SwaggerResourcesInfoVo> resourcesSet = new LinkedList<>();
Set<String> swaggerDocsDeleteSet = new HashSet<>();
List<LocationListVo> locationList = this.getLocationSet();
List<SwaggerResourcesInfoVo> resourcesList = new LinkedList<>();
String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST);
if (StringUtils.isNotBlank(swaggerResourcesStr)) {
resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class);
if (StringUtils.isNotBlank(choiceLocationList)) {
// 当前choiceLocationList只有一个可以这样搞
locationList = locationList.stream().filter(val -> Objects.equals(val.getLocation(), choiceLocationList)).collect(Collectors.toList());
}
if (StringUtils.isNotBlank(choiceDocList)) {
needRestorage = false;// 选择的则不再存入
Map<String, SwaggerResourcesInfoVo> infoVoMap = resourcesList.stream().collect(Collectors.toMap(SwaggerResourcesInfoVo::getUrl, val -> val));
for (String url : choiceDocList.split(",")) {
SwaggerResourcesInfoVo resourcesInfoVo = infoVoMap.get(url);
if (resourcesInfoVo != null) {
resourcesSet.add(resourcesInfoVo);
}
}
} else {
if (resourcesList.size() > 0) {
resourcesSet.addAll(resourcesList);
} else {
// 默认加上自身的文档
String serverPath = "http://" + request.getServerName() // 服务器地址
+ ":" + request.getServerPort() // 端口号
+ request.getContextPath();
// 是否加入自身的文档
Object object = SpringContextUtil.getBeanWithAnnotation(EnableSwaggerMgUi.class);
EnableSwaggerMgUi swaggerMgUi = object.getClass().getAnnotation(EnableSwaggerMgUi.class);
if (locationList.size() <= 0) {
// 默认加上自身的文档
String serverPath = "http://" + request.getServerName() // 服务器地址
+ ":" + request.getServerPort() // 端口号
+ request.getContextPath();
// 是否加入自身的文档
Object enableSwaggerMgUi = SpringContextUtil.getBeanWithAnnotation(EnableSwaggerMgUi.class);
if (enableSwaggerMgUi != null) {
EnableSwaggerMgUi swaggerMgUi = enableSwaggerMgUi.getClass().getAnnotation(EnableSwaggerMgUi.class);
if (swaggerMgUi == null) {
// 直接通过superclass去找
Class<?> superclass = object.getClass().getSuperclass();
Class<?> superclass = enableSwaggerMgUi.getClass().getSuperclass();
if (superclass != null) {
swaggerMgUi = superclass.getAnnotation(EnableSwaggerMgUi.class);
}
}
if (swaggerMgUi == null) {
// 再通过AopUtils去找
Class<?> targetClass = AopUtils.getTargetClass(object);
Class<?> targetClass = AopUtils.getTargetClass(enableSwaggerMgUi);
if (targetClass != null) {
swaggerMgUi = targetClass.getAnnotation(EnableSwaggerMgUi.class);
}
@@ -125,85 +111,197 @@ public class MgDocumentController {
}
// 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址
String[] defaultResources = swaggerMgUi.defaultResources();
if (defaultResources != null && defaultResources.length > 0) {
for (String url : defaultResources) {
resourcesSet.add(new SwaggerResourcesInfoVo(url));
}
for (String url : defaultResources) {
resourcesSet.add(new SwaggerResourcesInfoVo(url));
}
String[] defaultLocation = swaggerMgUi.defaultLocation();
for (String url : defaultLocation) {
locationList.add(new LocationListVo(url, ""));
}
}
}
if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) {
List<String> swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class);
swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
}
}
List<Map<String, Object>> swaggerResourceList = new LinkedList<>();
List<String> swaggerResourceStrList = new LinkedList<>();
for (SwaggerResourcesInfoVo resourcesInfoVo : resourcesSet) {
List<SwaggerResource> resourceList = null;
String resourcesUrl = resourcesInfoVo.getUrl();
try {
String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
} catch (Exception e) {
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
}
if (resourceList == null || resourceList.isEmpty()) {
continue;
}
resourcesInfoVo.setResourceList(resourceList);
resourcesUrl = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
for (SwaggerResource resource : resourceList) {
String location = resource.getLocation();
// 最后一个斜杠在resourcesUrl中已经加上替换掉后面的防止两根斜杠
location = location.startsWith("/") ? location.replaceFirst("/", "") : location;
if (location.indexOf("?") >= 0) {
try {
String encode = URLEncoder.encode(resource.getName(), "utf-8");
location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode;
} catch (Exception e) {
e.printStackTrace();
}
if (resourcesSet.size() > 0) {
List<LocationListVo> locationListStorage = this.getLocationSet();
for (SwaggerResourcesInfoVo resourcesInfoVo : resourcesSet) {
List<SwaggerResource> resourceList = null;
String resourcesUrl = resourcesInfoVo.getUrl();
try {
String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
} catch (Exception e) {
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
}
location = resourcesUrl + location;
// 已删除的则不处理
if (swaggerDocsDeleteSet.contains(location)) {
if (resourceList == null || resourceList.isEmpty()) {
continue;
}
try {
String resourceStr = HttpRequest.get(location).timeout(3000).execute().body();
Map<String, Object> jsonObject = JSON.parseObject(resourceStr, new TypeReference<HashMap<String, Object>>(){});
if (jsonObject == null || jsonObject.isEmpty()) {
continue;
}
jsonObject.put("fullUrl", location);
swaggerResourceList.add(jsonObject);
// 本来想转对象之后赋值但是在此转成JSON字符串之后格式就不是之前的了所有不能转。。。
// 直接字符串拼接,坑真多~
String rewriteDomainUrl = Optional.ofNullable(resourcesInfoVo.getRewriteDomainUrl()).orElse("");
resourceStr = resourceStr.substring(1);
resourceStr = "{\"fullUrl\":\"" + location + "\","
+ "\"domainUrl\":\"" + resourcesUrl + "\","
+ "\"rewriteDomainUrl\":\"" + rewriteDomainUrl + "\","
+ resourceStr;
swaggerResourceStrList.add(resourceStr);
} catch (Exception e) {
logger.error("获取文档失败:{}{}", location, e.getMessage());
resourcesInfoVo.setResourceList(resourceList);
String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
for (SwaggerResource swaggerResource : resourceList) {
String location = this.getLocationUrl(resourcesDomain, swaggerResource.getLocation(), swaggerResource.getName());
locationListStorage.add(new LocationListVo(location, resourcesUrl));
}
}
}
if (needRestorage) {
locationList.addAll(locationListStorage);
this.storageSwaggerLocationList(locationListStorage);
AtomicInteger idIndex = new AtomicInteger(1);
resourcesSet.forEach(val -> val.setId(idIndex.getAndIncrement()));
storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet));
}
List<String> swaggerResourceStrList = new LinkedList<>();
for (LocationListVo location : locationList) {
try {
String resourceStr = HttpRequest.get(location.getLocation()).timeout(3000).execute().body();
Map<String, Object> jsonObject = JSON.parseObject(resourceStr, new TypeReference<HashMap<String, Object>>(){});
if (jsonObject == null || jsonObject.isEmpty()) {
continue;
}
jsonObject.put("fullUrl", location);
String resourcesUrl = location.getLocation();
int indexV2 = location.getLocation().indexOf("/v2");
if (indexV2 >= 0) {
resourcesUrl = location.getLocation().substring(0, indexV2);
}
// 本来想转对象之后赋值但是在此转成JSON字符串之后格式就不是之前的了所有不能转。。。
// 直接字符串拼接,坑真多~
String rewriteDomainUrl = Optional.ofNullable(location.getRewriteDomainUrl()).orElse("");
resourceStr = resourceStr.substring(1);
resourceStr = "{\"fullUrl\":\"" + location.getLocation() + "\","
+ "\"domainUrl\":\"" + resourcesUrl + "\","
+ "\"rewriteDomainUrl\":\"" + rewriteDomainUrl + "\","
+ resourceStr;
swaggerResourceStrList.add(resourceStr);
} catch (Exception e) {
logger.error("获取文档失败:{}{}", location, e.getMessage());
}
}
// 用默认的json解析要内存溢出解析不了JSONObject、、就只有这样写了~
DocResponseJson.ok(swaggerResourceStrList).send(response);
}
/**
* 获取所有的文档
* @author 暮光:城中城
* @since 2018年8月21日
* @param request request
* @param response response
*/
@ResponseBody
@PostMapping(value = "/docsOld")
public void docsOld(HttpServletRequest request, HttpServletResponse response) {
// boolean needStorage = false;
// String choiceDocList = request.getParameter("choiceDocList");
// // 转成set防止重复
// List<SwaggerResourcesInfoVo> resourcesSet = new LinkedList<>();
//
// List<SwaggerResourcesInfoVo> resourcesList = new LinkedList<>();
// String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
// if (StringUtils.isNotBlank(swaggerResourcesStr)) {
// resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class);
// }
// if (StringUtils.isNotBlank(choiceDocList)) {
// Map<String, SwaggerResourcesInfoVo> infoVoMap = resourcesList.stream().collect(Collectors.toMap(SwaggerResourcesInfoVo::getUrl, val -> val));
// for (String url : choiceDocList.split(",")) {
// SwaggerResourcesInfoVo resourcesInfoVo = infoVoMap.get(url);
// if (resourcesInfoVo != null) {
// resourcesSet.add(resourcesInfoVo);
// }
// }
// } else if (resourcesList.size() > 0) {
// resourcesSet.addAll(resourcesList);
// } else {
// needStorage = true;
// // 默认加上自身的文档
// String serverPath = "http://" + request.getServerName() // 服务器地址
// + ":" + request.getServerPort() // 端口号
// + request.getContextPath();
// // 是否加入自身的文档
// Object enableSwaggerMgUi = SpringContextUtil.getBeanWithAnnotation(EnableSwaggerMgUi.class);
// if (enableSwaggerMgUi != null) {
// EnableSwaggerMgUi swaggerMgUi = enableSwaggerMgUi.getClass().getAnnotation(EnableSwaggerMgUi.class);
// if (swaggerMgUi == null) {
// // 直接通过superclass去找
// Class<?> superclass = enableSwaggerMgUi.getClass().getSuperclass();
// if (superclass != null) {
// swaggerMgUi = superclass.getAnnotation(EnableSwaggerMgUi.class);
// }
// }
// if (swaggerMgUi == null) {
// // 再通过AopUtils去找
// Class<?> targetClass = AopUtils.getTargetClass(enableSwaggerMgUi);
// if (targetClass != null) {
// swaggerMgUi = targetClass.getAnnotation(EnableSwaggerMgUi.class);
// }
// }
// if (swaggerMgUi == null) {
// resourcesSet.add(new SwaggerResourcesInfoVo(serverPath + "/swagger-resources"));
// } else {
// if (swaggerMgUi.selfDoc()) {
// resourcesSet.add(new SwaggerResourcesInfoVo(serverPath + "/swagger-resources"));
// }
// // 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址
// String[] defaultResources = swaggerMgUi.defaultResources();
// for (String url : defaultResources) {
// resourcesSet.add(new SwaggerResourcesInfoVo(url));
// }
// }
// }
// }
// List<String> swaggerResourceStrList = new LinkedList<>();
// for (SwaggerResourcesInfoVo resourcesInfoVo : resourcesSet) {
// List<SwaggerResource> resourceList = null;
// String resourcesUrl = resourcesInfoVo.getUrl();
// try {
// String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
// resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
// } catch (Exception e) {
// logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
// }
// if (resourceList == null || resourceList.isEmpty()) {
// continue;
// }
// resourcesInfoVo.setResourceList(resourceList);
// resourcesUrl = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
// for (SwaggerResource resource : resourceList) {
// String location = this.getLocationUrl(resourcesUrl, resource.getLocation(), resource.getName());
// try {
// String resourceStr = HttpRequest.get(location).timeout(3000).execute().body();
// Map<String, Object> jsonObject = JSON.parseObject(resourceStr, new TypeReference<HashMap<String, Object>>(){});
// if (jsonObject == null || jsonObject.isEmpty()) {
// continue;
// }
// jsonObject.put("fullUrl", location);
// // 本来想转对象之后赋值但是在此转成JSON字符串之后格式就不是之前的了所有不能转。。。
// // 直接字符串拼接,坑真多~
// String rewriteDomainUrl = Optional.ofNullable(resourcesInfoVo.getRewriteDomainUrl()).orElse("");
// resourceStr = resourceStr.substring(1);
// resourceStr = "{\"fullUrl\":\"" + location + "\","
// + "\"domainUrl\":\"" + resourcesUrl + "\","
// + "\"rewriteDomainUrl\":\"" + rewriteDomainUrl + "\","
// + resourceStr;
// swaggerResourceStrList.add(resourceStr);
// } catch (Exception e) {
// logger.error("获取文档失败:{}{}", location, e.getMessage());
// }
// }
// if (needStorage) {
// this.addSwaggerLocationList(resourceList, resourcesUrl);
// }
// }
// if (needStorage && resourcesSet.size() > 0) {
// AtomicInteger idIndex = new AtomicInteger(1);
// resourcesSet.forEach(val -> val.setId(idIndex.getAndIncrement()));
// storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet));
// }
// // 用默认的json解析要内存溢出解析不了JSONObject、、就只有这样写了~
// DocResponseJson.ok(swaggerResourceStrList).send(response);
}
/**
* 增加/swagger-resources地址
*
*
* @author 暮光:城中城
* @since 2018年8月21日
* @param resourcesUrl swagger-resources地址
@@ -212,71 +310,40 @@ public class MgDocumentController {
@PostMapping(value = "/addSwaggerResources")
public ResponseJson<Object> addSwaggerResources(String resourcesUrl, String rewriteDomainUrl, String oldUrl) {
String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST);
String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST);
Set<String> swaggerDocsDeleteSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) {
List<String> swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class);
swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
}
// 转成set防止重复
List<SwaggerResourcesInfoVo> resourcesList = new LinkedList<>();
if (StringUtils.isNotBlank(swaggerResourcesStr)) {
resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class);
// 如果是编辑,把之前的删除掉,再在后面添加
if (StringUtils.isNotBlank(oldUrl)) {
resourcesList = resourcesList.stream().filter(val -> !Objects.equals(val.getUrl(), oldUrl)).collect(Collectors.toList());
final String tempStr = oldUrl;
resourcesList = resourcesList.stream().filter(val -> !Objects.equals(val.getUrl(), tempStr)).collect(Collectors.toList());
}
}
try {
oldUrl = this.encodeUrlParam(oldUrl);
resourcesUrl = this.encodeUrlParam(resourcesUrl);
String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
List<SwaggerResource> resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
if (resourceList == null || resourceList.isEmpty()) {
return DocResponseJson.warn("该地址未找到文档");
}
// 重新加入的时候把之前的已删除的回恢复
String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
for (SwaggerResource swaggerResource : resourceList) {
String location = swaggerResource.getLocation();
// 最后一个斜杠在resourcesUrl中已经加上替换掉后面的防止两根斜杠
location = location.startsWith("/") ? location.replaceFirst("/", "") : location;
if (location.indexOf("?") >= 0) {
try {
String encode = URLEncoder.encode(swaggerResource.getName(), "utf-8");
location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode;
} catch (Exception e) {
e.printStackTrace();
}
boolean isLocation = this.addSwaggerLocationList(resourcesStr, rewriteDomainUrl, resourcesUrl, oldUrl);
if (!isLocation) {
List<SwaggerResource> resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
if (resourceList == null || resourceList.isEmpty()) {
return DocResponseJson.warn("该地址未找到文档");
}
location = resourcesDomain + location;
swaggerDocsDeleteSet.remove(location);
this.addSwaggerLocationList(resourceList, resourcesUrl);
SwaggerResourcesInfoVo resourcesInfoVo = new SwaggerResourcesInfoVo(resourcesUrl, resourceList);
resourcesInfoVo.setRewriteDomainUrl(rewriteDomainUrl);
resourcesList.add(resourcesInfoVo);
AtomicInteger idIndex = new AtomicInteger(1);
resourcesList.forEach(val -> val.setId(idIndex.getAndIncrement()));
}
SwaggerResourcesInfoVo resourcesInfoVo = new SwaggerResourcesInfoVo(resourcesUrl, resourceList);
resourcesInfoVo.setRewriteDomainUrl(rewriteDomainUrl);
resourcesList.add(resourcesInfoVo);
AtomicInteger idIndex = new AtomicInteger(1);
resourcesList.forEach(val -> val.setId(idIndex.getAndIncrement()));
} catch (Exception e) {
// 暂不想支持直接添加地址
// try {
// SwaggerLocationVo swaggerLocationVo = JSON.parseObject(resourcesStr, SwaggerLocationVo.class);
// if (StringUtils.isNotBlank(swaggerLocationVo.getSwagger())) {
// Set<String> locationSet = new HashSet<>();
// if (StringUtils.isNotBlank(swaggerLocationListStr)) {
// String swaggerLocationListStr = storageService.get(StorageKeys.SWAGGER_LOCATION_LIST);
// List<String> locationList = JSON.parseArray(swaggerLocationListStr, String.class);
// locationSet.addAll(locationList);
// storageService.put(StorageKeys.SWAGGER_LOCATION_LIST, JSON.toJSONString(locationSet));
// }
// } else {
// return DocResponseJson.warn("该地址查找文档失败");
// }
// } catch (Exception e2) {
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
return DocResponseJson.warn("该地址查找文档失败");
// }
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
return DocResponseJson.warn("该地址查找文档失败");
}
// 去重
resourcesList = resourcesList.stream().distinct().collect(Collectors.toList());
storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesList));
storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet));
return DocResponseJson.ok();
}
@@ -303,22 +370,6 @@ public class MgDocumentController {
if (resourceList == null || resourceList.isEmpty()) {
return DocResponseJson.warn("该地址未找到文档");
}
// 重新加入的时候把之前的已删除的回恢复
String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
for (SwaggerResource swaggerResource : resourceList) {
String location = swaggerResource.getLocation();
// 最后一个斜杠在resourcesUrl中已经加上替换掉后面的防止两根斜杠
location = location.startsWith("/") ? location.replaceFirst("/", "") : location;
if (location.indexOf("?") >= 0) {
try {
String encode = URLEncoder.encode(swaggerResource.getName(), "utf-8");
location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode;
} catch (Exception e) {
e.printStackTrace();
}
}
location = resourcesDomain + location;
}
resourcesSet.add(new SwaggerResourcesInfoVo(resourcesUrl));
} catch (Exception e) {
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
@@ -330,22 +381,146 @@ public class MgDocumentController {
/**
* 删除/v2/api-docs
*
*
* @author 暮光:城中城
* @since 2018年8月21日
* @param docUrl 文档地址
* @return 删除结果
*/
@Deprecated
@PostMapping(value = "/deleteSwaggerDoc")
public ResponseJson<Object> deleteSwaggerDoc(String docUrl) {
String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST);
Set<String> swaggerDocsDeleteSet = new HashSet<>();
if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) {
List<String> swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class);
swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
}
swaggerDocsDeleteSet.add(docUrl);
storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet));
// String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST);
// Set<String> swaggerDocsDeleteSet = new HashSet<>();
// if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) {
// List<String> swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class);
// swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList);
// }
// swaggerDocsDeleteSet.add(docUrl);
// storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet));
return DocResponseJson.ok();
}
/**
* 获取swaggerLocation列表
*
* @author 暮光:城中城
* @since 2018年8月21日
*/
@PostMapping(value = "/getLocationList")
public ResponseJson<List<LocationListVo>> getLocationList() {
List<LocationListVo> locationSet = this.getLocationSet();
return DocResponseJson.ok(locationSet);
}
/**
* 直接添加地址
*/
private boolean addSwaggerLocationList(String resourcesStr, String rewriteDomainUrl, String locationUrl, String oldUrl) {
try {
SwaggerLocationVo swaggerLocationVo = JSON.parseObject(resourcesStr, SwaggerLocationVo.class);
if (swaggerLocationVo != null && StringUtils.isNotBlank(swaggerLocationVo.getSwagger())) {
List<LocationListVo> locationList = this.getLocationSet();
locationList = locationList.stream().filter(val -> !Objects.equals(val.getLocation(), oldUrl)).collect(Collectors.toList());
LocationListVo locationListVo = new LocationListVo(locationUrl, "");
locationListVo.setRewriteDomainUrl(rewriteDomainUrl);
locationList.add(locationListVo);
this.storageSwaggerLocationList(locationList);
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 直接添加地址
*/
private void addSwaggerLocationList(List<SwaggerResource> resourceList, String resourcesUrl) {
List<LocationListVo> locationList = this.getLocationSet();
// 加入到location列表
String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1);
for (SwaggerResource swaggerResource : resourceList) {
String location = this.getLocationUrl(resourcesDomain, swaggerResource.getLocation(), swaggerResource.getName());
locationList.add(new LocationListVo(location, resourcesUrl));
}
this.storageSwaggerLocationList(locationList);
}
/**
* 保存location列表
*/
private void storageSwaggerLocationList(List<LocationListVo> locationSet) {
AtomicInteger idIndex = new AtomicInteger(1);
locationSet = locationSet.stream().distinct().collect(Collectors.toList());
locationSet.forEach(val -> val.setId(idIndex.getAndIncrement()));
storageService.put(StorageKeys.SWAGGER_LOCATION_LIST, JSON.toJSONString(locationSet));
}
/**
* 获取swaggerLocation列表
*/
private List<LocationListVo> getLocationSet() {
List<LocationListVo> locationList = new LinkedList<>();
String swaggerLocationListStr = storageService.get(StorageKeys.SWAGGER_LOCATION_LIST);
if (StringUtils.isNotBlank(swaggerLocationListStr)) {
locationList = JSON.parseArray(swaggerLocationListStr, LocationListVo.class);
}
return locationList;
}
/**
* 获取拼接好的location
*/
private String getLocationUrl(String resourcesDomain, String location, String resourceName) {
// 最后一个斜杠在resourcesUrl中已经加上替换掉后面的防止两根斜杠
location = location.startsWith("/") ? location.replaceFirst("/", "") : location;
if (location.contains("?")) {
try {
String encode = URLEncoder.encode(resourceName, "utf-8");
location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode;
} catch (Exception e) {
e.printStackTrace();
}
}
return resourcesDomain + location;
}
/**
* url编码参数
*/
private String encodeUrlParam(String resourcesUrl) {
if (StringUtils.isBlank(resourcesUrl)) {
return resourcesUrl;
}
resourcesUrl = resourcesUrl.trim();
int indexOf = resourcesUrl.indexOf("?");
if (indexOf < 0) {
return resourcesUrl;
}
StringBuilder baseUrl = new StringBuilder(resourcesUrl.substring(0, indexOf + 1));
String[] paramArr = resourcesUrl.substring(indexOf + 1).split("&");
for (int i = 0; i < paramArr.length; i++) {
String param = paramArr[i];
String[] split = param.split("=");
if (i > 0) {
baseUrl.append("&");
}
if (split.length == 2) {
String value = split[1];
try {
value = URLEncoder.encode(split[1], "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
baseUrl.append(split[0]).append("=").append(value);
} else {
baseUrl.append(param);
}
}
return baseUrl.toString();
}
}

View File

@@ -0,0 +1,103 @@
package com.zyplayer.doc.swagger.controller;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.swagger.controller.vo.LocationListVo;
import com.zyplayer.doc.swagger.controller.vo.SwaggerResourcesInfoVo;
import com.zyplayer.doc.swagger.framework.constant.StorageKeys;
import com.zyplayer.doc.swagger.framework.service.MgStorageService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;
/**
* 开放接口文档控制器
*
* @author 暮光:城中城
* @since 2019年1月27日
*/
@RestController
@RequestMapping("/swagger-mg-ui/open-doc")
public class MgOpenDocController {
private static Logger logger = LoggerFactory.getLogger(MgOpenDocController.class);
@Resource
private MgStorageService storageService;
/**
* @author 暮光:城中城
* @since 2019年1月27日
*/
@ResponseBody
@PostMapping(value = "/{source}")
public ResponseJson<List<SwaggerResourcesInfoVo>> resourcesList(@PathVariable("source") String source) {
return DocResponseJson.ok();
}
/**
* 获取所有的文档
* @author 暮光:城中城
* @since 2018年8月21日
* @param request request
* @param response response
*/
@ResponseBody
@PostMapping(value = "/docs")
public void docs(HttpServletRequest request, HttpServletResponse response) {
String choiceLocationList = request.getParameter("choiceLocationList");
List<LocationListVo> locationList = new LinkedList<>();
String swaggerLocationListStr = storageService.get(StorageKeys.SWAGGER_LOCATION_LIST);
if (StringUtils.isNotBlank(swaggerLocationListStr)) {
locationList = JSON.parseArray(swaggerLocationListStr, LocationListVo.class);
}
if (StringUtils.isNotBlank(choiceLocationList)) {
locationList = locationList.stream().filter(val -> Objects.equals(val.getUuid(), choiceLocationList)).collect(Collectors.toList());
} else {
DocResponseJson.ok().send(response);
}
if (locationList.size() <= 0) {
DocResponseJson.ok().send(response);
}
List<String> swaggerResourceStrList = new LinkedList<>();
for (LocationListVo location : locationList) {
try {
String resourceStr = HttpRequest.get(location.getLocation()).timeout(3000).execute().body();
Map<String, Object> jsonObject = JSON.parseObject(resourceStr, new TypeReference<HashMap<String, Object>>(){});
if (jsonObject == null || jsonObject.isEmpty()) {
continue;
}
jsonObject.put("fullUrl", location);
String resourcesUrl = location.getLocation();
int indexV2 = location.getLocation().indexOf("/v2");
if (indexV2 >= 0) {
resourcesUrl = location.getLocation().substring(0, indexV2);
}
// 本来想转对象之后赋值但是在此转成JSON字符串之后格式就不是之前的了所有不能转。。。
// 直接字符串拼接,坑真多~
String rewriteDomainUrl = Optional.ofNullable(location.getRewriteDomainUrl()).orElse("");
resourceStr = resourceStr.substring(1);
resourceStr = "{\"fullUrl\":\"" + location.getLocation() + "\","
+ "\"domainUrl\":\"" + resourcesUrl + "\","
+ "\"rewriteDomainUrl\":\"" + rewriteDomainUrl + "\","
+ resourceStr;
swaggerResourceStrList.add(resourceStr);
} catch (Exception e) {
logger.error("获取文档失败:{}{}", location, e.getMessage());
}
}
// 用默认的json解析要内存溢出解析不了JSONObject、、就只有这样写了~
DocResponseJson.ok(swaggerResourceStrList).send(response);
}
}

View File

@@ -0,0 +1,99 @@
package com.zyplayer.doc.swagger.controller.vo;
import cn.hutool.core.util.RandomUtil;
import java.net.URLDecoder;
import java.util.Objects;
public class LocationListVo {
private Integer id;
private String name;
private String uuid;
private String location;
private String resources;
private String rewriteDomainUrl;
public LocationListVo(){
}
public LocationListVo(String location, String resources) {
this.location = location;
this.resources = resources;
this.name = location;
this.uuid = RandomUtil.simpleUUID();
// 修正名字
int indexGroup = location.indexOf("group=");
int indexV2 = location.indexOf("/v2");
if (indexGroup >= 0 && location.length() > indexGroup) {
try {
this.name = URLDecoder.decode(location.substring(indexGroup + 6), "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
} else if (indexV2 >= 0) {
this.name = location.substring(indexV2 + 3);
}
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getResources() {
return resources;
}
public void setResources(String resources) {
this.resources = resources;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
return Objects.equals(this.location, ((LocationListVo) obj).getLocation());
}
@Override
public int hashCode() {
return location.hashCode();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRewriteDomainUrl() {
return rewriteDomainUrl;
}
public void setRewriteDomainUrl(String rewriteDomainUrl) {
this.rewriteDomainUrl = rewriteDomainUrl;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
}

View File

@@ -7,6 +7,7 @@ import springfox.documentation.swagger.web.SwaggerResource;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Objects;
public class SwaggerResourcesInfoVo implements Serializable {
private Integer id;
@@ -89,4 +90,17 @@ public class SwaggerResourcesInfoVo implements Serializable {
public void setRewriteDomainUrl(String rewriteDomainUrl) {
this.rewriteDomainUrl = rewriteDomainUrl;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
return Objects.equals(this.url, ((SwaggerResourcesInfoVo) obj).getUrl());
}
@Override
public int hashCode() {
return url.hashCode();
}
}

View File

@@ -1,12 +1,12 @@
package com.zyplayer.doc.swagger.framework.configuration;
import com.zyplayer.doc.swagger.framework.filter.ZyplayerProxyFilter;
import org.springframework.context.annotation.Import;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.zyplayer.doc.swagger.framework.filter.ZyplayerProxyFilter;
import org.springframework.context.annotation.Import;
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = {java.lang.annotation.ElementType.TYPE})
@Documented
@@ -26,4 +26,11 @@ public @interface EnableSwaggerMgUi {
* @return swagger-resources地址
*/
String[] defaultResources() default {};
/**
* 启动后第一次访问没有数据情况下需要加载进来的/v2/doc地址
*
* @return /v2/doc地址
*/
String[] defaultLocation() default {};
}

View File

@@ -9,8 +9,8 @@ package com.zyplayer.doc.swagger.framework.constant;
public class StorageKeys {
// 所有文档地址
public static final String SWAGGER_RESOURCES_LIST = "swagger-resources-list";
// 已删除的文档
public static final String SWAGGER_DOCS_DELETE_LIST = "swagger-docs-delete-list";
// 已删除的文档(废弃,不在支持删除)
// public static final String SWAGGER_DOCS_DELETE_LIST = "swagger-docs-delete-list";
// 所有详细文档地址
public static final String SWAGGER_LOCATION_LIST = "swagger-location-list";
// 文档的离线数据key

View File

@@ -17,6 +17,12 @@
<i class="icon icon-bars" id="changeContentWidth"></i>
</div>
<div class="scrollbar-hover left-container">
<div class="btn-group choice-location-list" id="choiceLocationList">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
<span class="choice-text"></span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu"></ul>
</div>
<!-- 样式类可选tree-menu tree-folders tree-chevrons tree-angles -->
<ul class="tree tree-lines tree-menu projects" data-ride="tree">
<li>
@@ -34,6 +40,7 @@
<li id="onlineDebugLi1" class="local-storage"><a href="javascript:void(0)" path=""><i class="icon-bug"></i> 在线调试管理</a></li>
<li><a href="#" class="page-nav" data-id="docShowConfig" data-href="webjars/zpages/docShowConfig.html" data-icon="icon-cog" data-reload="0"><i class="icon-cog"></i> 文档展示配置</a></li>
<li><a href="#" class="page-nav" data-id="docUrlConfig" data-href="webjars/zpages/docUrlConfig.html" data-icon="icon-list-ul" data-reload="1"><i class="icon-list-ul"></i> 文档地址管理</a></li>
<li><a href="#" class="page-nav" data-id="docUrlDetailConfig" data-href="webjars/zpages/docUrlDetailConfig.html" data-icon="icon-list-ul" data-reload="1"><i class="icon-list-ul"></i> 详细地址管理</a></li>
<li><a href="#" class="page-nav" data-id="globalParamConfig" data-href="webjars/zpages/globalParamConfig.html" data-icon="icon-globe" data-reload="1"><i class="icon-globe"></i> 全局参数管理</a></li>
<li><a href="#" class="page-nav" data-id="debugDataConfig" data-href="webjars/zpages/debugDataConfig.html" data-icon="icon-bug" data-reload="1"><i class="icon-bug"></i> 调试数据管理</a></li>
</ul>
@@ -48,7 +55,10 @@
<div class="right-container" id="rightContent">
<div class="right-container" id="rightContentMask"></div>
<div class="tab-page tab-home-page">
<div id="homePageDashboard" class="dashboard" data-height="320">
<div id="homePageDashboard">
<div class="dashboard" data-height="320"></div>
</div>
<div id="homePageDashboardTemplate" class="hidden">
<section class="row">
<div class="col-md-6 col-sm-6">
<div class="panel" data-id="1">

View File

@@ -0,0 +1,362 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>接口文档管理系统</title>
<link rel="shortcut icon" href="webjars/open-doc/img/api.ico"/>
<link rel="stylesheet" href="webjars/zui/css/zui.min.css" />
<link rel="stylesheet" href="webjars/zui/lib/dashboard/zui.dashboard.min.css" />
<link rel="stylesheet" href="webjars/zui/lib/tabs/zui.tabs.min.css" />
<link rel="stylesheet" href="webjars/open-doc/css/mg-ui.css" />
</head>
<body>
<div class="left-body" id="leftContent">
<div class="left-header">
<span class="logo" id="logoText">zyplayer-doc-swagger</span>
<i class="icon icon-bars" id="changeContentWidth"></i>
</div>
<div class="scrollbar-hover left-container">
<!-- 样式类可选tree-menu tree-folders tree-chevrons tree-angles -->
<ul class="tree tree-lines tree-menu projects" data-ride="tree">
<!--open-doc去掉了选择文档按钮-->
<li>
<div class="input-group">
<input type="text" class="form-control" id="searchDocInput">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="searchDocBt">搜索</button>
</span>
</div>
</li>
<li id="homePageLi"><a href="javascript:void(0)" path=""><i class="icon-home"></i> 控制台</a></li>
<!--open-doc去掉了不需要的按钮-->
</ul>
<div id="apiPathTree">
<ul class="tree tree-lines projects"></ul>
</div>
</div>
</div>
<div id="resizableLeftRight" class="ui-resizable-handle mgresizableW"></div>
<div class="right-container" id="rightContent">
<div class="right-container" id="rightContentMask"></div>
<div class="tab-page tab-home-page">
<div id="homePageDashboard">
<div class="dashboard" data-height="320"></div>
</div>
<div id="homePageDashboardTemplate" class="hidden">
<section class="row">
<div class="col-md-6 col-sm-6">
<div class="panel" data-id="1">
<div class="panel-heading">
<div class="title">工具介绍</div>
</div>
<div class="panel-body">
<div class="content about">
zyplayer-doc-swagger是swagger文档的管理工具使用简单、解析速度快、走心的设计
支持多项目同时展示,多种文档目录的展示方案,多种自定义配置,满足各种使用习惯。
本项目是完全从头写的所以有任何属性未解析到、UI上有何建议都能及时处理得到。
使用中您有任何的意见和建议都可到源码地址处反馈哦!<br/>
源码地址:<a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc">zyplayer-doc-swagger</a>(还有其他很多功能哦),
前端框架:<a target="_blank" href="http://zui.sexy">zui</a>(很不错),
我的网站:<a target="_blank" href="http://kongjianzhou.com">空间轴</a><a target="_blank" href="http://zyplayer.com">自由发挥</a>(都已很久未维护)
</div>
</div>
</div>
</div>
</section>
</div>
</div>
<div class="tab-page tab-zpages hide">
<div class="tabs" id="rightZpages"></div>
</div>
<div class="tab-page tab-document hide">
<ul class="nav nav-tabs">
<li class="active"><a data-tab href="#tabDocInfo">接口说明</a></li>
<li><a data-tab href="#tabOnlineDebug">在线调试</a></li>
<!--open-doc去掉模拟返回-->
</ul>
<div class="tab-content">
<div class="tab-pane tab-document-pane active" id="tabDocInfo">
<table class="table table-bordered doc-table">
<tr>
<td class="info">接口地址</td>
<td><span id="docUrl" class="label label-warning"></span></td>
</tr>
<tr>
<td class="info">说明</td>
<td id="docInfo"></td>
</tr>
<tr>
<td class="info">请求方式</td>
<td><span id="docRequestMethod" class="label label-warning"></span></td>
</tr>
<tr>
<td class="info">consumes</td>
<td><span id="docConsumes" class="label label-warning"></span></td>
</tr>
<tr>
<td class="info">produces</td>
<td><span id="docProduces" class="label label-warning"></span></td>
</tr>
<tr>
<td class="info">test</td>
<td><div id="htmlStrTemp"></div></td>
</tr>
<tr>
<td class="info">请求参数</td>
<td>
<ul class="nav nav-secondary gray">
<li class="active"><a data-tab href="#docRequestParam">说明</a></li>
<li><a data-tab href="#docRequestExample">例子</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane tab-param-type-pane active" id="docRequestParam">
<table class="table table-bordered table-condensed">
<thead>
<tr><th>参数名</th><th>说明</th><th>类型</th><th>参数位置</th><th>是否必填</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
<div class="tab-pane tab-param-type-pane" id="docRequestExample">
<table class="table table-bordered table-condensed">
<thead>
<tr><th>参数名</th><th>说明</th><th>类型</th><th>参数位置</th><th>是否必填</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</td>
</tr>
<tr>
<td class="info">响应Model</td>
<td>
<ul class="nav nav-secondary gray">
<li class="active"><a data-tab href="#docResponseModel">说明</a></li>
<li><a data-tab href="#docResponseExample">例子</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane tab-param-type-pane active" id="docResponseModel">
<table class="table table-bordered">
<thead>
<tr><th>状态码</th><th>说明</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
<div class="tab-pane tab-param-type-pane" id="docResponseExample">
<table class="table table-bordered">
<thead>
<tr><th>状态码</th><th>说明</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</td>
</tr>
</table>
</div>
<div class="tab-pane tab-document-pane" id="tabOnlineDebug">
<div class="post-url-box">
<div class="input-group">
<!-- <div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="options">参数模板</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu pull-left" role="menu">
<li><a href="javascript:void(0)">默认参数</a></li>
<li><a href="javascript:void(0);" class="save-request-template">+保存模板</a></li>
</ul>
</div> -->
<div class="input-group-btn" id="debugRequstType">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="options">GET</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu pull-left" role="menu">
<li><a href="javascript:void(0);">GET</a></li>
<li><a href="javascript:void(0);">POST</a></li>
<li><a href="javascript:void(0);">PUT</a></li>
<li><a href="javascript:void(0);">HEAD</a></li>
<li><a href="javascript:void(0);">PATCH</a></li>
<li><a href="javascript:void(0);">DELETE</a></li>
<li><a href="javascript:void(0);">OPTIONS</a></li>
<li><a href="javascript:void(0);">TRACE</a></li>
</ul>
</div>
<input type="text" class="form-control" id="postUrlInput" placeholder="请求的完整地址">
<span class="input-group-btn">
<button class="btn btn-default send-request" type="button">发送请求 <i class="icon icon-spin icon-spinner-snake hide"></i></button>
</span>
</div>
</div>
<div class="param-response-box">
<div class="param-box">
<div class="panel panel-default">
<div class="panel-heading" id="headingOne">
<h4 class="panel-title">
<a data-toggle="collapse" href="#tabParamHeader">请求头</a>
<label class="overwrite-label"><input type="checkbox" id="bulkEditHeaderCheck" value="1"> 批量编辑</label>
</h4>
</div>
<div id="tabParamHeader" class="panel-collapse collapse in">
<form id="requestHeaderForm">
<table class="table table-bordered param-table">
<tbody>
<tr class="base">
<td><input type="text" class="form-control" name="paramName" placeholder=""></td>
<td><input type="text" class="form-control" name="paramValue" placeholder=""></td>
<td><i class="icon-times"></i></td>
</tr>
</tbody>
</table>
<textarea class="hide form-control" id="bulkEditHeader" rows="6" placeholder="批量编辑请求头,使用英文冒号分隔,例:&#13;&#10;key:value&#13;&#10;key:value"></textarea>
</form>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" href="#tabParamBody">请求参数</a>
</h4>
</div>
<div id="tabParamBody" class="panel-collapse collapse in">
<form id="requestParamForm">
<ul class="nav nav-secondary">
<li class="active"><a data-tab href="#tabParamTypeForm">表单</a></li>
<li><a data-tab href="#tabParamTypeBody">数据流</a></li>
<li class="form-to-url"><label><input type="checkbox" name="formToUrl" value="1"> 参数拼在URL后面发送</label></li>
<li class="form-to-url"><label><input type="checkbox" id="bulkEditFormCheck" value="1"> 批量编辑</label></li>
</ul>
<div class="tab-content">
<div class="tab-pane tab-param-type-pane active" id="tabParamTypeForm">
<table class="table table-bordered param-table">
<tbody>
<tr class="base">
<td><input type="text" class="form-control" name="paramName" placeholder=""></td>
<td><input type="text" class="form-control" name="paramValue" placeholder=""></td>
<td><i class="icon-times"></i></td>
</tr>
</tbody>
</table>
<textarea class="hide form-control" id="bulkEditForm" rows="6" placeholder="批量编辑表单参数,使用英文冒号分隔,例:&#13;&#10;key:value&#13;&#10;key:value"></textarea>
</div>
<div class="tab-pane tab-param-type-pane" id="tabParamTypeBody">
<textarea class="form-control" name="paramBody" rows="6" placeholder=""></textarea>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="response-box">
<ul class="nav nav-secondary">
<li class="info"><span>结果集</span></li>
<li class="active"><a data-tab href="#tabResponseBody">Body</a></li>
<li class="local-storage"><a data-tab href="#tabResponseCookie">Cookie</a></li>
<li><a data-tab href="#tabResponseHeader">Header</a></li>
<li class="right"><span>状态:<i id="httpRequestStatus">200</i>,耗时:<i id="httpRequestTime">0ms</i></span></li>
</ul>
<div class="tab-content">
<div class="tab-pane tab-response-pane active" id="tabResponseBody">
<!-- <textarea class="form-control" id="responseBodyTextArea" rows="20" placeholder=""></textarea> -->
<div id="responseBodyJsonDiv"></div>
</div>
<div class="tab-pane tab-response-pane" id="tabResponseCookie">
<table class="table table-bordered param-table">
<thead>
<tr>
<th>名字</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div class="tab-pane tab-response-pane" id="tabResponseHeader">
<table class="table table-bordered param-table">
<thead>
<tr>
<th>名字</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
<!--open-doc去掉模拟返回-->
</div>
</div>
</div>
</div>
<!-- 导出文档 -->
<div class="modal fade" id="exportDocumentModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span><span class="sr-only">关闭</span>
</button>
<h4 class="modal-title">导出文档</h4>
</div>
<div class="modal-body">
<div class="alert alert-danger hidden">
1、请到 <a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc">源码处下载</a>《对外文档模板.zip》解压<br/>
2、复制以下文本内容覆盖至 /js/mg-ui-data.js 文件内<br/>
3、然后双击打开目录下的document.html 即可看到导出的文档
</div>
<div class="modal-table-box">
<ul id="exportDocumentUl" class="choise"></ul>
<textarea id="exportDocumentText" class="form-control hidden"></textarea>
</div>
<div align="center" class="bottom-box">
<button class="btn btn-primary" type="button" id="doExportBtn">确认导出</button>
</div>
</div>
</div>
</div>
</div>
<!-- 选择展示的项目 -->
<div class="modal fade" id="choiseDocModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">选择需要展示的文档</h4>
</div>
<div class="modal-body">
<div class="alert alert-danger">不选择则展示全部,展示接口过多会影响效率,建议只展示想看的文档</div>
<div class="modal-table-box">
<ul id="choiseDocListUl" class="choise"></ul>
</div>
<div align="center" class="bottom-box">
<button type="button" class="btn btn-primary" id="choiseDocBtn">  确定  </button>
</div>
</div>
</div>
</div>
</div>
</body>
<script type="text/javascript" src="webjars/open-doc/js/jquery-3.1.0.min.js"></script>
<script type="text/javascript" src="webjars/zui/js/zui.min.js"></script>
<script type="text/javascript" src="webjars/zui/lib/tabs/zui.tabs.min.js"></script>
<script type="text/javascript" src="webjars/zui/lib/dashboard/zui.dashboard.min.js"></script>
<!--
<script type="text/javascript" src="webjars/open-doc/js/mg-ui.min.js"></script>
-->
<script type="text/javascript" src="webjars/open-doc/js/formatjson.js"></script>
<script type="text/javascript" src="webjars/open-doc/js/toast.js"></script>
<script type="text/javascript" src="webjars/open-doc/js/common.js"></script>
<script type="text/javascript" src="webjars/open-doc/js/mgResizable.js"></script>
<script type="text/javascript" src="webjars/open-doc/js/mg-ui-tree.js"></script>
<script type="text/javascript" src="webjars/open-doc/js/mg-ui-tag.js"></script>
<script type="text/javascript" src="webjars/open-doc/js/mg-ui-debug.js"></script>
<script type="text/javascript" src="webjars/open-doc/js/mg-ui-export.js"></script>
<script type="text/javascript" src="webjars/open-doc/js/mg-ui-cache-keys.js"></script>
<script type="text/javascript" src="webjars/open-doc/js/mg-ui.js"></script>
</html>

View File

@@ -18,6 +18,11 @@ ul{list-style: none;list-style-type: none;}
.local-storage{display: none;}
.choice-location-list{margin-bottom: 10px; width: 100%;}
.choice-location-list .btn.dropdown-toggle{width: 100%; text-align: left;}
.choice-location-list .dropdown-menu{width: 100%;}
.choice-location-list .caret{float: right;margin-top: 8px;}
/**lable的覆盖样式*/
.label{font-size: 100%;}
.label-warning {background-color: #f9f5ee; color: #f1a325;}

View File

@@ -175,7 +175,7 @@ function getObjectFirstAttributeIfOnly(data) {
/**
* ajax处理事件模板
*
*
* @url 后台处理的url即action
* @dataSentType 数据发送的方式有postget方式
* @dataReceiveType 数据接收格式有html json text等
@@ -255,6 +255,13 @@ function getCookie(name) {
return null;
}
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
/**
* 字符串格式化
*/
@@ -280,7 +287,7 @@ String.prototype.format = function(args) {
} else {
return this;
}
}
};
String.prototype.endWith = function(str) {
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
@@ -395,4 +402,4 @@ function deleteStorage(key, success, fail) {
*/
function getExport(){
return window.parent.window.exports;
}
}

View File

@@ -4,6 +4,7 @@
var cacheKeys = {
userSettings: 'userSettings',
swaggerResourcesList: 'swagger-resources-list',
swaggerLocationList: 'swagger-location-list',
globalParamList: 'zyplayer-doc-global-param-list',
pRequestObjStart: 'p-request-obj-',
pSimulationResponse: 'p-simulation-response',

View File

@@ -116,7 +116,7 @@ $(document).ready(function(){
var afterSendTime = new Date().getTime();
//console.log(result);
var requestObj = result.data;
setStorage(cacheKeys.pRequestObjStart + docUrl, storeRequestParam);
// open-doc去掉存储
$("#httpRequestStatus").text(requestObj.status);
$("#httpRequestTime").text((afterSendTime - beforeSendTime) + "ms");
try {
@@ -224,23 +224,13 @@ $(document).ready(function(){
* 提交模拟返回值
*/
$("#simulationResultSubmit").click(function(){
var value = $("#simulationResultText").val();
value = getNotEmptyStr(value, "");
var docUrl = $("#simulationResultUrl").text();
setStorage(cacheKeys.pSimulationResponse + docUrl, value, function() {
Toast.warn("提交成功!");
}, function(msg) {
Toast.error("提交失败!" + msg);
});
// open-doc去掉存储
});
/**
* 获取模拟返回值
*/
$("#simulationResultGet").click(function(){
var docUrl = $("#simulationResultUrl").text();
getStorage(cacheKeys.pSimulationResponse + docUrl, function(data){
$("#simulationResultText").val(data);
});
// open-doc去掉获取存储
});
});
@@ -272,10 +262,8 @@ function createOnlineDebugParamTable() {
* @returns
*/
function createOnlineDebugRequestParam(requestParamObj, url) {
// 查询之前的调试参数信息
getStorage(cacheKeys.pRequestObjStart + url, function(data) {
createOnlineDebugRequestParamFun(data, requestParamObj, url);
});
// open-doc去掉获取存储
createOnlineDebugRequestParamFun({}, requestParamObj, url);
}
/**

View File

@@ -49,13 +49,13 @@ $(document).ready(function(){
ajaxTemp("swagger-mg-ui/storage/checkConfig", "post", "json", {
}, function(json){
}, function(msg){
}, function(xhr){
}, function (xhr) {
showGlobalLoadingMessage('服务检查完成,请稍候...', true);
var serverStorage = false;
if(!isEmptyObject(xhr.responseJSON)) {
if (!isEmptyObject(xhr.responseJSON)) {
serverStorage = (xhr.responseJSON.errCode == 200);
}
if(!serverStorage) {
if (!serverStorage) {
Toast.error("服务器端能力配置有误,新版本必须开启才能使用", 999999);
documentLoadFinish();
} else {
@@ -63,6 +63,7 @@ $(document).ready(function(){
}
}
);
// open-doc去掉定义配置的标签页
});
/**
@@ -70,33 +71,23 @@ $(document).ready(function(){
* @returns
*/
function getDocumentListByService() {
$("#choiseDocListUl").empty();
// open-doc整个方法不同
showGlobalLoadingMessage('获取文档列表中,请稍候...', true);
ajaxTemp("swagger-mg-ui/document/resourcesList", "post", "json", {}, function(json){
if(validateResult(json) && json.data.length > 1) {
showGlobalLoadingMessage('等待选择需展示的文档,请选择...', true);
for (var i = 0; i < json.data.length; i++) {
var item = json.data[i];
$("#choiseDocListUl").append('<li value="'+item.url+'">'+item.url+'</li>');
}
$('#choiseDocModal').modal({moveable:true, backdrop:'static', keyboard: false});
} else {
addDocumentByService();
}
});
var doc = getQueryString("doc");
addDocumentByLocationService(doc);
}
/**
* 增加文档-通过服务器接口
* @returns
*/
function addDocumentByService(choiseDocList) {
function addDocumentByService(choiceDocList) {
// 获取原始的swagger的json对象
showGlobalLoadingMessage('通过服务器端获取文档中,请稍候...', true);
ajaxTemp("swagger-mg-ui/document/docs", "post", "json", {choiseDocList: choiseDocList}, function(json){
ajaxTemp("swagger-mg-ui/document/docs", "post", "json", {choiceDocList: choiceDocList}, function(json){
//console.log(json);
showGlobalLoadingMessage('文档获取成功,解析中,请稍候...', true);
if(isEmptyObject(json) || json.errCode != 200) {
if(isEmptyObject(json) || json.errCode !== 200) {
Toast.error("获取文档错误,请检查!");
return;
}
@@ -121,6 +112,46 @@ function addDocumentByService(choiseDocList) {
});
}
/**
* 增加文档-通过服务器接口
* @returns
*/
function addDocumentByLocationService(choiceDocList) {
// 获取原始的swagger的json对象
globalLoadingMessager.show();
showGlobalLoadingMessage('通过服务器端获取文档中,请稍候...', true);
// open-doc请求地址不同
ajaxTemp("swagger-mg-ui/open-doc/docs", "post", "json", {choiceLocationList: choiceDocList}, function(json){
//console.log(json);
showGlobalLoadingMessage('文档获取成功,解析中,请稍候...', true);
if(isEmptyObject(json) || json.errCode !== 200) {
Toast.error("获取文档错误,请检查!");
return;
}
documentJsonArr = [];
initDashboard();
for (var i = 0; i < json.data.length; i++) {
showGlobalLoadingMessage('解析第' + (i + 1) + '份文档,请稍候...', true);
var tempDoc = deserialize(json.data[i]);
console.log(tempDoc);
documentJsonArr.push(tempDoc);// 加到所有文档
addHomePageDashboard(tempDoc, tempDoc.fullUrl);
createDefinitionsMapByJson(tempDoc);
if (userSettings.catalogShowType == 1) {
createTreeViewByTree(tempDoc);// url分成一层一层的展示
} else if (userSettings.catalogShowType == 2) {
createTreeViewByTag(tempDoc);// tag方式整个url显示为一层
} else {
createTreeViewByTree(tempDoc);// url分成一层一层的展示
}
}
documentLoadFinish();
}, function(msg){
Toast.error("获取文档失败,请检查!");
});
}
/**
* 自由拖动改变左右框架的宽度
*/
@@ -150,10 +181,21 @@ $("#changeContentWidth").click(function(){
changeContentWidth(isMinWidth ? 360 : 120);
});
/**
* 切换文档
*/
$("#choiceLocationList").on("click", ".dropdown-menu li", function(){
var text = $(this).find("a").text();
var location = $(this).find("a").data("location");
$("#choiceLocationList .choice-text").text(text);
// 切换文档
addDocumentByLocationService(location);
});
/**
* 搜索框回车事件
*/
$("#searchDocInput").keyup(function(e) {
$("#searchDocInput").keyup(function(e) {
if (e.keyCode == 13) {
searchDoc();
}
@@ -342,11 +384,7 @@ $("#apiPathTree").on("click", ".show-doc", function(){
$("#simulationResultUrlTest").text(data.domain + docUrl + "?zyplayerApiTest=1");
$("#simulationResultUrlTest").attr("href", data.domain + docUrl + "?zyplayerApiTest=1");
$("#simulationResultText").val("");
getStorage('p-simulation-response-' + docUrl, function(data){
var resultText = getNotEmptyStr(data);
resultText = (typeof resultText === 'string') ? resultText : JSON.stringify(resultText, null, 4);
$("#simulationResultText").val(resultText);
});
// open-doc去掉了模拟返回
// 处理在线文档
$("#docUrl").text(docUrl);
$("#docRequestMethod").text(getNotEmptyStr(data.method));
@@ -885,30 +923,9 @@ function addHomePageDashboard(json, fullUrl) {
);
}
/**
* 初始化用户的设置
* @param
* @returns
*/
function documentLoadFinish() {
showGlobalLoadingMessage('文档解析完成!', false);
// 定义配置的标签页
var tabsArr = [
{id: 'docShowConfig', url: 'webjars/zpages/docShowConfig.html', type: 'iframe', icon: 'icon-cog', forbidClose: true},
];
$('#rightZpages').tabs({tabs: tabsArr});
rightContentTabs = $('#rightZpages').data('zui.tabs');
// 隐藏提示框
setTimeout(function() {
globalLoadingMessager.hide();
}, 1000);
$('#apiPathTree .projects').tree();
$('#homePageDashboard').dashboard({draggable: false});
}
/**
* 修改树形菜单展示类型
* @param
* @param
* @returns
*/
function updateTreeShowType() {
@@ -935,11 +952,27 @@ function updateTreeShowType() {
}
}
/**
* 初始化用户的设置
* @param
* @returns
*/
function documentLoadFinish() {
showGlobalLoadingMessage('文档解析完成!', false);
// 隐藏提示框
setTimeout(function() {
globalLoadingMessager.hide();
}, 1000);
regeneratePathTree();
//$('#apiPathTree .projects').tree();
$('#homePageDashboard .dashboard').dashboard({draggable: false});
}
/**
* 存储用户设置
*/
function storeUserSettings() {
setStorage(cacheKeys.userSettings, userSettings);
// open-doc去掉存储设置
}
/**
@@ -951,23 +984,16 @@ function updateUserSettings(newSetting) {
/**
* 初始化用户的设置
* @param
* @param
* @returns
*/
function initUserSettings() {
getStorage(cacheKeys.userSettings, function(data) {
userSettings = data;
if(isEmpty(userSettings) || isEmptyObject(userSettings)) {
userSettings = defaultUserSettings;
}
changeContentWidth(userSettings.prevWNow);
updateTreeShowType();
// 增加文档
getDocumentListByService();
});
getStorage(cacheKeys.globalParamList, function(data) {
debugGlobalParam = data;
});
// open-doc去掉了获取配置和全局参数
userSettings = defaultUserSettings;
changeContentWidth(userSettings.prevWNow);
updateTreeShowType();
// 增加文档
getDocumentListByService();
}
function showGlobalLoadingMessage(text, loading) {
@@ -977,3 +1003,9 @@ function showGlobalLoadingMessage(text, loading) {
globalLoadingMessager.$.find(".messager-content").html(text);
}
function initDashboard(){
var template = $('#homePageDashboardTemplate').html();
$('#homePageDashboard').empty();
$('#homePageDashboard').append('<div class="dashboard" data-height="320"></div>');
$('#homePageDashboard .dashboard').append(template);
}

View File

@@ -0,0 +1,143 @@
body{width: 100%;height: 100%;margin: 0;padding: 0;}
a:focus{outline:none;}
ul{list-style: none;list-style-type: none;}
.tree li a{white-space: nowrap;}
.tree-menu li > ul{background-color: #f1f1f1;}
.tree-menu li li li li a{padding-left: 68px;}
.tree-menu li li li li li a{padding-left: 88px;}
.tree-menu li li li li li li a{padding-left: 108px;}
.tree-menu li li li li li li li a{padding-left: 128px;}
.tree-menu li li li li li li li li a{padding-left: 148px;}
.tree-menu li li li li li li li li li a{padding-left: 168px;}
.tree-menu li li li li li li li li li li a{padding-left: 188px;}
.table td, .table th {vertical-align: middle;}
#tabDocInfo{position: absolute; bottom: 0;top: 60px;overflow-y: auto; right: 0; left: 10px;}
#tabOnlineDebug .param-response-box{position: absolute; bottom: 0;top: 100px;overflow-y: auto; right: 0; left: 10px;padding-right: 10px;}
#tabOnlineDebug .panel{margin-bottom: 10px;}
#requestParamForm .nav > li > a{padding: 6px 15px;}
.local-storage{display: none;}
.choice-location-list{margin-bottom: 10px; width: 100%;}
.choice-location-list .btn.dropdown-toggle{width: 100%; text-align: left;}
.choice-location-list .dropdown-menu{width: 100%;}
.choice-location-list .caret{float: right;margin-top: 8px;}
/**lable的覆盖样式*/
.label{font-size: 100%;}
.label-warning {background-color: #f9f5ee; color: #f1a325;}
label{font-weight: normal;}
.overwrite-label{margin-bottom: 0;}
.nav.gray{background-color: #f1f1f1;margin-bottom: 10px;}
.doc-table tr .info{text-align: right; width: 100px;}
.setting-table tr .info{text-align: right; max-width: 150px;}
.show-doc span{color: #aaa;}
.mgresizableW{z-index: 90;height: 100%; width: 10px; cursor: e-resize;}
.ui-resizable-handle {display: block;font-size: 0.1px;position: absolute;}
#resizableLeftRight{left: 360px;}
.unselect{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
#homePageDashboard{overflow-y: auto;bottom: 0;top: 0;right: 0;left: 0;position: absolute;overflow-x: hidden;padding: 10px;}
#homePageDashboard .panel-body{padding: 10px;}
.content.about{line-height: 30px;}
#homePageLi{margin-top: 5px;}
.left-body{
width: 360px; height:100%; position: fixed; top: 0; bottom: 0; left: 0;
}
.left-header{
background: #3280fc;width: 100%; height:60px;line-height:60px;
position: absolute; top: 0; bottom: 0; left: 0;text-align: center;
}
.left-header .logo{
font-size: 30px;color: #fff;
}
.left-header .icon-bars{
font-size: 24px;float: right;margin: 18px 18px 0 0;color: #fff;cursor: pointer;
}
.left-container{
width: 100%;position: absolute;background: #f1f1f1;color: rgba(163, 175, 183, .9);
top: 60px; bottom: 0; left: 0; overflow-y: auto; padding: 10px;
}
.left-container .projects{border: 0px; border-radius: 0px;}
.right-container{
position: fixed;top: 0px; bottom: 0; left: 360px; right: 0;padding: 10px;
}
#docResponseModel td:first-child{width: 100px;}
#docResponseExample td:first-child{width: 100px;}
.modal-table-box{margin-top: 10px; max-height: 500px;overflow-y: auto;}
.modal-table-box{list-style: none;}
.modal-table-box ul{padding-left: 10px;}
.modal-table-box li{padding: 10px 15px; margin: 0 10px 10px 0; background-color: #f1f1f1;cursor: pointer;}
.modal-table-box li.checked{background-color: #8666b8;color:#fff;}
#exportDocumentText{height: 350px;}
#rightContentMask{background-color: rgba(0, 0, 0, 0);padding: 0;z-index:9999; height: 100%;display: none;position: absolute;top: 0;bottom: 0;left:0;right: 0;}
#rightZpages{height: 100%;position: relative;top: 0;bottom: 0;left:0;right: 0;}
/* 在线调试框样式 */
#tabParamBody .tab-content{padding-top: 10px;}
.post-url-box{padding: 10px 0;}
.post-url-box .input-group-btn:nth-child(2) button{border-right: 0;border-radius: 0;}
.post-url-box .send-request .hide{display: none;}
.param-box{}
.param-box .panel-collapse{padding: 10px 10px 0 10px;}
.param-box .nav{background-color: #f1f1f1;}
.param-box .table{margin-bottom: 0;}
/* .param-box .nav > li > *{padding: 8px 25px;} */
.param-box .nav > li > span{position: relative; display: block;background-color: #ccc;padding: 9px 25px;}
.param-box .nav > .form-to-url{position: relative; display: block;padding: 8px 0 0 25px;}
.param-box .nav > .form-to-url label{margin: 0;}
.param-box .nav > .form-to-url input{margin: 0;}
.param-box .tab-content .tab-param-pane{padding: 10px 10px 0 10px;}
.param-box .table.param-table td, .param-box .table.param-table th{padding: 4px 5px;}
.param-box .param-table td:first-child{width: 250px;}
.param-box .param-table tbody td:nth-child(2){border-right: 0;}
.param-box .param-table tbody td:nth-child(3){border-left: 0;padding: 0 10px 0 0;width: 10px;}
.param-box .param-table tbody td:nth-child(3) i{cursor: pointer;color: #ccc;}
.param-box .param-table tbody td:nth-child(3) i:hover{color: #888;}
.param-box .param-table tbody tr.base td:last-child i{display: none;}
#bulkEditHeaderCheck{margin: 0 0 0 10px;}
#bulkEditHeader,#bulkEditForm{display: none;}
.response-box{margin-top: 10px;}
.response-box .nav > li > *{padding: 8px 25px;}
.response-box .nav > li span{position: relative; display: block;padding: 9px 25px;}
.response-box .nav > li.info span{background-color: #ccc;}
.response-box .nav > li.right{float: right;}
.response-box .nav > li.right i{color: #3280fc;}
.response-box .nav{background-color: #f1f1f1;}
.response-box .tab-content .tab-response-pane{padding: 10px;}
#responseBodyJsonIframe{width: 100%;height: 300px;border: 0;}
/* S-模拟请求 */
#tabSimulationResult{padding: 0 10px 0 0;position: absolute; bottom: 0;top: 60px;overflow-y: auto; right: 0; left: 10px;}
/* E-模拟请求 */
/* 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展示的样式 */

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

View File

@@ -0,0 +1,405 @@
/**
* 一些公用方法
* @author 暮光:城中城
* @since 2017年5月7日
*/
function serialize(value) {
if (typeof value === 'string') {
return value;
}
return JSON.stringify(value);
}
function deserialize(value) {
if (typeof value !== 'string' || isEmpty(value)) {
return value;
}
try {
return JSON.parse(value);
} catch (e) {
try {
return eval('(' + value + ')');// 处理变态的单双引号共存字符串
} catch (e) {
return value || undefined;
}
}
}
function validateResult(result) {
if(result.errCode == 200) {
return true;
} else {
Toast.error(result.errMsg);
}
return false;
}
function getNowDate() {
var date = new Date();
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = date.getFullYear() + "-" + month + "-" + strDate;
return currentdate;
}
function getNowTime() {
var date = new Date();
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
if (hours >= 1 && hours <= 9) {
hours = "0" + hours;
}
if (minutes >= 0 && minutes <= 9) {
minutes = "0" + minutes;
}
if (seconds >= 0 && seconds <= 9) {
seconds = "0" + seconds;
}
var currentdate = hours + ":" + minutes + ":" + seconds;
return currentdate;
}
function getNowDateTime() {
var currentdate = getNowDate() + " " + getNowTime();
return currentdate;
}
/**
* 返回不为空的字符串为空返回def
*/
function getNotEmptyStr(str, def) {
if (isEmpty(str)) {
return isEmpty(def) ? "" : def;
}
return str;
}
/**
* 是否是空对象
* @param obj
* @returns
*/
function isEmptyObject(obj){
return isEmpty(obj) || $.isEmptyObject(obj);
}
/**
* 是否是空字符串
* @param str
* @returns
*/
function isEmpty(str){
return (str == "" || str == null || str == undefined);
}
/**
* 是否不是空字符串
* @param str
* @returns
*/
function isNotEmpty(str){
return !isEmpty(str);
}
/**
* 数组转字符串,使用空格分隔
* @param array
* @returns
*/
function arrToString(array){
var temStr = "";
if(isEmpty(array)){
return temStr;
}
array.forEach(function(e){
if(isNotEmpty(temStr)) {
temStr += " ";
}
temStr += e;
});
return temStr;
}
/**
* 数组array中是否包含str字符串
* @param array
* @param str
* @returns
*/
function haveString(array, str){
if(isEmpty(array)) {
return false;
}
for (var i = 0; i < array.length; i++) {
if(array[i] == str) {
return true;
}
}
return false;
}
/**
* 直接返回对象的第一个属性
* @param data
* @returns
*/
function getObjectFirstAttribute(data) {
for ( var key in data) {
return data[key];
}
}
/**
* 如果对象只有一个属性则返回第一个属性否则返回null
* @param data
* @returns
*/
function getObjectFirstAttributeIfOnly(data) {
var len = 0, value = "";
for ( var key in data) {
if (++len > 1) {
return null;
}
value = data[key];
}
return value;
}
/**
* ajax处理事件模板
*
* @url 后台处理的url即action
* @dataSentType 数据发送的方式有postget方式
* @dataReceiveType 数据接收格式有html json text等
* @paramsStr 传入后台的参数
* @successFunction ajax成功后执行的函数名 ajaxTemp("", "GET", "html", {}, function(){},
* function(){}, "");
*/
function ajaxTemp(url, dataSentType, dataReceiveType, paramsStr, successFunction, errorFunction, completeFunction, id) {
$.ajax({
url : url, // 后台处理程序
sync : false,
type : dataSentType, // 数据发送方式
dataType : dataReceiveType, // 接受数据格式
data : eval(paramsStr),
contentType : "application/x-www-form-urlencoded; charset=UTF-8",
success : function(msg) {
if(typeof successFunction == "function") {
successFunction(msg,id);
}
},
beforeSend : function() {
},
complete : function(msg) {
if(typeof completeFunction == "function") {
completeFunction(msg,id);
}
},
error : function(msg) {
if(typeof errorFunction == "function") {
errorFunction(msg,id);
}
}
});
}
function postWithFile(url, paramsStr, successFunction, errorFunction, completeFunction, id) {
$.ajax({
url: url, // 后台处理程序
sync: false,
type: "POST", // 数据发送方式
dataType: "JSON", // 接受数据格式
data: eval(paramsStr),
processData: false,
contentType: false,
success: function (msg) {
if (typeof successFunction == "function") {
successFunction(msg, id);
}
},
beforeSend: function () {
},
complete: function (msg) {
if (typeof completeFunction == "function") {
completeFunction(msg, id);
}
},
error: function (msg) {
if (typeof errorFunction == "function") {
errorFunction(msg, id);
}
}
});
}
/**
* 获取cookie
* @param name
* @returns
*/
function getCookie(name) {
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg)){
return unescape(arr[2]);
}
return null;
}
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
/**
* 字符串格式化
*/
String.prototype.format = function(args) {
if (arguments.length > 0) {
var result = this;
if (arguments.length == 1 && typeof (args) == "object") {
for ( var key in args) {
var reg = new RegExp("({" + key + "})", "g");
result = result.replace(reg, args[key]);
}
} else {
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] == undefined) {
return "";
} else {
var reg = new RegExp("({[" + i + "]})", "g");
result = result.replace(reg, arguments[i]);
}
}
}
return result;
} else {
return this;
}
};
String.prototype.endWith = function(str) {
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
return false;
}
return (this.substring(this.length - str.length) == str);
};
String.prototype.startWith = function(str) {
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
return false;
}
return (this.substr(0, str.length) == str);
};
/**
* 获取数据,异步的操作
*/
function getStorageLike(key, success, fail) {
var start = (typeof urlBase === 'string') ? urlBase : '';
ajaxTemp(start + "swagger-mg-ui/storage/like", "post", "json", {key: key}, function(json){
if(json.errCode == 200) {
if(typeof success == "function") {
var result = deserialize(json.data);
success(result);
}
} else {
if(typeof fail == "function") {
fail();
}
}
}, function(msg){
if(typeof fail == "function") {
fail();
}
});
}
/**
* 获取数据,异步的操作
*/
function getStorage(key, success, fail) {
var start = (typeof urlBase === 'string') ? urlBase : '';
ajaxTemp(start + "swagger-mg-ui/storage/data", "get", "json", {key: key}, function(json){
if(json.errCode == 200) {
if(typeof success == "function") {
var result = deserialize(json.data);
success(result);
}
} else {
if(typeof fail == "function") {
fail();
}
}
}, function(msg){
if(typeof fail == "function") {
fail();
}
});
}
/**
* 存储数据,异步的操作
*/
function setStorage(key, value, success, fail) {
value = $.zui.store.serialize(value);
var start = (typeof urlBase === 'string') ? urlBase : '';
ajaxTemp(start + "swagger-mg-ui/storage/data", "post", "json", {key: key, value: value}, function(json){
if(json.errCode == 200) {
if(typeof success == "function") {
success();
}
} else {
if(typeof fail == "function") {
fail(getNotEmptyStr(json.errMsg));
}
}
}, function(msg){
if(typeof fail == "function") {
fail("");
}
console.log("存储数据到服务器失败,请检查");
});
}
/**
* 删除数据
*/
function deleteStorage(key, success, fail) {
var start = (typeof urlBase === 'string') ? urlBase : '';
ajaxTemp(start + "swagger-mg-ui/storage/delete", "post", "json", {key: key}, function(json){
if(json.errCode == 200) {
if(typeof success == "function") {
success();
}
} else {
if(typeof fail == "function") {
fail(getNotEmptyStr(json.errMsg));
}
}
}, function(msg){
if(typeof fail == "function") {
fail("");
}
console.log("存储数据到服务器失败,请检查");
});
}
/**
* 获取父窗口的exports
* @returns
*/
function getExport(){
return window.parent.window.exports;
}

View File

@@ -0,0 +1,125 @@
/**
* 将对象处理成json格式化和着色的html
* @author 暮光:城中城
* @since 2017年5月7日
*/
var Formatjson = {
// 需要在对象或列表后面添加注释的对象,例:{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) {
var 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) {
var html = "";
var comma = (addComma) ? "<span class='comma'>,</span> " : "";
var type = typeof obj;
if (this.isArray(obj)) {
if (obj.length == 0) {
html += this.getRow(indent, "<span class='array-brace'>[ ]</span>" + comma, isPropertyContent);
} else {
var clpsHtml = '<span><img class="option-img" src="webjars/mg-ui/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
var annotation = '';
if(showAnnotation && isNotEmpty(keyName) && isNotEmpty(this.annotationObject[keyName])) {
annotation = '<span class="annotation">// '+this.annotationObject[keyName]+'</span>';
}
html += this.getRow(indent, "<span class='array-brace'>[</span>"+clpsHtml+annotation, isPropertyContent);
for (var 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') {
var numProps = 0;
for ( var prop in obj) {
numProps++;
}
if (numProps == 0) {
html += this.getRow(indent, "<span class='object-brace'>{ }</span>" + comma, isPropertyContent);
} else {
var clpsHtml = '<span><img class="option-img" src="webjars/mg-ui/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
var annotation = '';
if(showAnnotation && isNotEmpty(keyName) && isNotEmpty(this.annotationObject[keyName])) {
annotation = '<span class="annotation">// '+this.annotationObject[keyName]+'</span>';
}
html += this.getRow(indent, "<span class='object-brace'>{</span>"+clpsHtml+annotation, isPropertyContent);
var j = 0;
for ( var prop in obj) {
var 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){
var container = img.parentNode.nextSibling;
if(!container) return;
var disp = "none";
var 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("&lt;").split(">").join("&gt;");
}
var str = "<span class='" + style + "'>" + quote + literal + quote + comma + "</span>";
if (isArray) {
str = this.getRow(indent, str);
}
return str;
},
formatFunction: function(indent, obj) {
var tabs = "";
for (var i = 0; i < indent; i++) {
tabs += this.tabStr;
}
var funcStrArray = obj.toString().split("\n");
var str = "";
for (var i = 0; i < funcStrArray.length; i++) {
str += ((i == 0) ? "" : tabs) + funcStrArray[i] + "\n";
}
return str;
},
getRow: function(indent, data, isPropertyContent) {
var tabs = "";
for (var 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;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
/**
* 页面中所有使用到的缓存key必须定义在这里
*/
var cacheKeys = {
userSettings: 'userSettings',
swaggerResourcesList: 'swagger-resources-list',
swaggerLocationList: 'swagger-location-list',
globalParamList: 'zyplayer-doc-global-param-list',
pRequestObjStart: 'p-request-obj-',
pSimulationResponse: 'p-simulation-response',
}

View File

@@ -0,0 +1,633 @@
/**
* 在线调试页面js
* @author 暮光:城中城
* @since 2018年7月20日
*/
$(document).ready(function(){
$("#debugRequstType .dropdown-menu li").click(function(){
var text = $(this).find("a").text();
$("#debugRequstType .options").text(text);
});
/**
* 保存参数模板
* @returns
*/
$(".save-request-template").click(function(){
Toast.notOpen();
});
/**
* 发送请求
* @returns
*/
$(".send-request").click(function(){
// 多行编辑状态下转成表单,下面读取表单内容
if ($("#bulkEditFormCheck").prop('checked')) {
var bulkEdit = $("#bulkEditForm").val();
bulkEditToTable("#tabParamTypeForm", bulkEdit);
}
if ($("#bulkEditHeaderCheck").prop('checked')) {
var bulkEdit = $("#bulkEditHeader").val();
bulkEditToTable("#tabParamHeader", bulkEdit);
}
$("#tabResponseHeader table tbody").empty();
$("#tabResponseCookie table tbody").empty();
$("#responseBodyTextArea").val("");
$("#responseBodyJsonDiv").html("暂无数据");
var storeRequestParam = {};
var docUrl = $("#docUrl").text();
var options = $("#debugRequstType .btn .options").text();
var postUrl = $("#postUrlInput").val();
var requestHeaderForm = $("#requestHeaderForm").serializeArray();
var requestParamForm = $("#requestParamForm").serializeArray();
var paramHeaderSend = {};
var paramFormSend = {};
var paramBodySend = $("[name=paramBody]").val();
var formToUrl = $("[name=formToUrl]").prop('checked') ? 1 : 0;
// 组装空的表单对象
var formDataToServer = new FormData();
requestHeaderForm = serializeArrayToObj(requestHeaderForm);
requestParamForm = serializeArrayToObj(requestParamForm);
storeRequestParam.formToUrl = formToUrl;
formDataToServer.append("formToUrl", formToUrl);
if (isNotEmpty(paramBodySend)) {
try {
paramBodySend = JSON.stringify(JSON.parse(paramBodySend));
} catch (e) {}
storeRequestParam.body = paramBodySend;
formDataToServer.append("body", paramBodySend);
// 替换path参数
Object.keys(requestParamForm).forEach(function (key) {
postUrl = postUrl.replace("{" + key + "}", requestParamForm[key]);
});
}
var reqParamStr = "";
Object.keys(requestParamForm).forEach(function (key) {
var value = requestParamForm[key];
if (isNotEmpty(key) && isNotEmpty(value)) {
if (isNotEmpty(reqParamStr)) {
reqParamStr += "&";
}
reqParamStr += key + "=" + value;
paramFormSend[key] = value;
// 替换path参数
postUrl = postUrl.replace("{" + key + "}", value);
}
});
storeRequestParam.form = paramFormSend;
// 显示加载中图标
$(".send-request .icon").removeClass("hide");
// 获取header
Object.keys(requestHeaderForm).forEach(function(key){
var value = requestHeaderForm[key];
if(isNotEmpty(key) && isNotEmpty(value)) {
paramHeaderSend[key] = value;
}
});
storeRequestParam.header = paramHeaderSend;
//console.log(paramBodySend);
var beforeSendTime = new Date().getTime();
// 拼装文件
var fileInput = $('#requestParamForm').find(".file-input");
for (var i = 0; i < fileInput.length; i++) {
var fileName = $(fileInput[i]).parents("tr").find("[name=paramName]").val();
for (var j = 0; j < fileInput[i].files.length; j++) {
formDataToServer.append('files', fileInput[i].files[j]);
formDataToServer.append('fileNames', fileName);
}
paramFormSend[fileName] = "-";
}
formDataToServer.append("header", JSON.stringify(paramHeaderSend));
formDataToServer.append("url", postUrl);
formDataToServer.append("method", options);
// 表单参数是否拼在url上
if(formToUrl == 1) {
postUrl += "?" + reqParamStr;
paramFormSend = "";
} else {
formDataToServer.append("form", JSON.stringify(paramFormSend));
}
// debugger;
// 模拟请求开始
postWithFile("swagger-mg-ui/http/request", formDataToServer, function(result){
var afterSendTime = new Date().getTime();
//console.log(result);
var requestObj = result.data;
// open-doc去掉存储
$("#httpRequestStatus").text(requestObj.status);
$("#httpRequestTime").text((afterSendTime - beforeSendTime) + "ms");
try {
var htmlStr = Formatjson.processObjectToHtmlPre(JSON.parse(requestObj.data), 0, false, false, false, false);
$("#responseBodyJsonDiv").html(htmlStr);
} catch (e) {
// 转json失败应该是个页面输出到iframe里不能影响当前页面
$("#responseBodyJsonDiv").html("<iframe id='responseBodyJsonIframe'></iframe>");
setTimeout(function () {
$("#responseBodyJsonIframe").contents().find("body").html(requestObj.data);
}, 300);
}
$("#tabResponseHeader table tbody").empty();
$("#tabResponseCookie table tbody").empty();
var headers = requestObj.header || [];
for (var i = 0; i < headers.length; i++) {
var name = getNotEmptyStr(headers[i].name);
var value = getNotEmptyStr(headers[i].value);
$("#tabResponseHeader table tbody").append(
'<tr>' + '<td>' + name + '</td>' + '<td>' + value + '</td>' + '</tr>'
);
}
var cookies = requestObj.cookie || [];
for (var i = 0; i < cookies.length; i++) {
var name = getNotEmptyStr(cookies[i].name);
var value = getNotEmptyStr(cookies[i].value);
$("#tabResponseCookie table tbody").append(
'<tr>' + '<td>' + name + '</td>' + '<td>' + value + '</td>' + '</tr>'
);
}
}, function () {
Toast.error("请求失败!");
}, function () {
$(".send-request .icon").addClass("hide");
});
});
/**
* 输入框输入之后,如果是最后一行则在增加一行
* @returns
*/
$(".param-table").on("keyup", "input[name=paramName]", function(){
var nextTr = $(this).parents("tr").next();
if(nextTr.length <= 0) {
$(this).parents(".param-table").append(getParamTableTr());
}
});
/**
* 参数删除一行
* @returns
*/
$(".param-table").on("click", ".icon-times", function(){
$(this).parents("tr").remove();
});
/**
* 在线调试管理
*/
$("#onlineDebugLi").click(function(){
$(".tab-page,.tab-zpages").hide();
$(".tab-online-debug-page").show();
createOnlineDebugParamTable();
});
/**
* 在线调试管理-刷新
*/
$(".tab-online-debug-page .refresh").click(function(){
createOnlineDebugParamTable();
});
/**
* 在线调试管理-展开所有
*/
$(".tab-online-debug-page .expand-all").click(function(){
$("#onlineDebugParamTable .option-img").attr("src", "webjars/mg-ui/img/expanded.png");
$("#onlineDebugParamTable .option-img").parent().next().show();
});
/**
* 在线调试管理-收起所有
*/
$(".tab-online-debug-page .collapse-all").click(function(){
$("#onlineDebugParamTable .option-img").attr("src", "webjars/mg-ui/img/collapsed.png");
$("#onlineDebugParamTable .option-img").parent().next().hide();
});
/**
* 在线调试-删除所有参数
*/
$(".tab-online-debug-page").on("click", ".del-all-param", function(){
$.zui.store.forEach(function(key, value) {// 遍历所有本地存储的条目
if(!key.startWith(cacheKeys.pRequestObjStart)) {
return;
}
$.zui.store.remove(key);
});
createOnlineDebugParamTable();
});
/**
* 在线调试-删除参数
*/
$(".tab-online-debug-page").on("click", ".del-param", function(){
var key = $(this).attr("key");
if(isNotEmpty(key)) {
$.zui.store.remove(key);
$(this).parents("tr").remove();
}
});
/**
* 提交模拟返回值
*/
$("#simulationResultSubmit").click(function(){
// open-doc去掉存储
});
/**
* 获取模拟返回值
*/
$("#simulationResultGet").click(function(){
// open-doc去掉获取存储
});
});
/**
* 生成在线调试管理页面
* @returns
*/
function createOnlineDebugParamTable() {
$("#onlineDebugParamTable tbody").empty();
$.zui.store.forEach(function(key, value) {// 遍历所有本地存储的条目
if(!key.startWith(cacheKeys.pRequestObjStart)) {
return;
}
var newKey = key.substring(14, key.length);
var htmlStr = Formatjson.processObjectToHtmlPre(value, 0, false, false, false, false);
$("#onlineDebugParamTable tbody").append(
'<tr>'
+'<td>'+newKey+'</td>'
+'<td>'+htmlStr+'</td>'
+'<td><button class="btn btn-danger del-param" type="button" key="'+key+'">删除</button></td>'
+'</tr>'
);
});
}
/**
* 生成在线调试相关数据
* @param requestParamObj
* @returns
*/
function createOnlineDebugRequestParam(requestParamObj, url) {
// open-doc去掉获取存储
createOnlineDebugRequestParamFun({}, requestParamObj, url);
}
/**
* 生成在线调试相关数据
* @param oldRequestObj 之前的调试参数
* @param requestParamObj 参数列表的参数
* @param url 请求url
* @returns
*/
function createOnlineDebugRequestParamFun(oldRequestObj, requestParamObj, url) {
if(isEmptyObject(oldRequestObj)) {
oldRequestObj = {};
}
// 清空参数列表
$("#tabParamHeader table tbody .new").remove();
$("#tabParamTypeForm table tbody .new").remove();
$("#tabResponseHeader table tbody").empty();
$("#tabResponseCookie table tbody").empty();
$("#tabParamHeader .form-control").val("");
$("#tabParamTypeForm .form-control").val("");
$("#responseBodyTextArea").val("");
$("#responseBodyJsonDiv").html("暂无数据");
$("#bulkEditHeaderCheck").prop("checked", false);
$("#bulkEditFormCheck").prop("checked", false);
$("#bulkEditHeader,#bulkEditForm").hide();
$("#tabParamTypeForm table").show();
$("#requestHeaderForm table").show();
$("#tabParamTypeForm table tbody .base input[name=paramValue]")
.attr("type", "text").removeClass("file-input")
.removeAttr("multiple").attr("placeholder", "").val("");
var options = $("#debugRequstType .btn .options").text();
var formToUrl = oldRequestObj.formToUrl || 0;
var formToUrlChecked = (options != "GET" && formToUrl == 1);
$("input[name='formToUrl']").prop("checked", formToUrlChecked);
var onlyUseLastParam = (userSettings.onlyUseLastParam == 1);
var onlyUseLastHeader = onlyUseLastParam && !isEmptyObject(oldRequestObj.header);
var onlyUseLastForm = onlyUseLastParam && !isEmptyObject(oldRequestObj.form);
var onlyUseLastBody = onlyUseLastParam && !isEmptyObject(oldRequestObj.body);
var headerValueCount = 0, formValueCount = 0;
if(typeof oldRequestObj != 'object') {
oldRequestObj = {};
}
if(typeof oldRequestObj.header != 'object') {
oldRequestObj.header = {};
}
if(typeof oldRequestObj.form != 'object') {
oldRequestObj.form = {};
}
for (var i = 0; i < debugGlobalParam.length; i++) {
var item = debugGlobalParam[i];
if (item.paramIn == 'header') {
oldRequestObj.header[item.key] = item.value;
} else if (item.paramIn == 'form') {
oldRequestObj.form[item.key] = item.value;
}
}
Object.keys(requestParamObj).forEach(function(key){
var tempParam = requestParamObj[key];
if (key == "p-body-obj") {
//console.log(tempParam);
var paramObj = onlyUseLastBody ? {} : getParamBodyTransObj(tempParam);
var bodyObj = oldRequestObj.body;
try {
bodyObj = JSON.parse(bodyObj);
if(!isEmptyObject(bodyObj)) {
paramObj = $.extend(true, paramObj, bodyObj);
}
$("#tabParamTypeBody textarea").val(JSON.stringify(paramObj, null, 4));
} catch (e) {
var tempText = isEmptyObject(bodyObj) ? JSON.stringify(paramObj, null, 4) : bodyObj;
$("#tabParamTypeBody textarea").val(tempText);
}
$("#tabParamBody .nav li").eq(1).find("a").click();
} else {
if (tempParam.paramIn == "header" && !onlyUseLastHeader) {
//console.log(tempParam);
var headerVal = getNotEmptyStr(tempParam.value);
var headerObj = oldRequestObj.header;
if(!isEmptyObject(headerObj) && isNotEmpty(headerObj[key])) {
headerVal = headerObj[key];
headerObj[key] = "";// 赋值为空,后面不再使用
}
if(isEmpty(headerVal)) {
headerVal = getAutoFillValue(tempParam.paramType, key);
}
if(headerValueCount > 0) {
$("#tabParamHeader table tbody").append(getParamTableTr(key, headerVal, "", tempParam.paramDesc));
} else {
$("#tabParamHeader table tbody .base input[name=paramName]").val(key);
$("#tabParamHeader table tbody .base input[name=paramValue]").val(headerVal);
$("#tabParamHeader table tbody .base input[name=paramValue]").attr("placeholder", getNotEmptyStr(tempParam.paramDesc));
}
headerValueCount++;
} else {
// 只有这几种类型,列出来后面看单独处理不
var paramInForm = (tempParam.paramIn == "query")
|| (tempParam.paramIn == "path")
|| (tempParam.paramIn == "body")
|| (tempParam.paramIn == "form")
|| (tempParam.paramIn == "formData")
|| isNotEmpty(tempParam.paramIn);
paramInForm = paramInForm && !onlyUseLastForm;
var formObj = oldRequestObj.form;
if (onlyUseLastForm && !isEmptyObject(formObj) && isNotEmpty(formObj[key])) {
paramInForm = onlyUseLastForm || true;
}
if (paramInForm) {
//console.log(tempParam);
var formVal = getNotEmptyStr(tempParam.value);
if(!isEmptyObject(formObj) && isNotEmpty(formObj[key])) {
formVal = formObj[key];
formObj[key] = "";// 赋值为空,后面不再使用
}
if(isEmpty(formVal)) {
formVal = getAutoFillValue(tempParam.paramType, key);
}
if(formValueCount > 0) {
$("#tabParamTypeForm table tbody").append(getParamTableTr(key, formVal, "", tempParam.paramDesc, tempParam.paramType));
} else {
// 文件的input特殊处理
if(tempParam.paramType == 'file'){
$("#tabParamTypeForm table tbody .base input[name=paramValue]")
.attr("type", "file").attr("multiple", "multiple")
.addClass("file-input");
} else {
$("#tabParamTypeForm table tbody .base input[name=paramValue]").val(formVal);
}
$("#tabParamTypeForm table tbody .base input[name=paramName]").val(key);
$("#tabParamTypeForm table tbody .base input[name=paramValue]").attr("placeholder", getNotEmptyStr(tempParam.paramDesc));
}
$("#tabParamBody .nav li").eq(0).find("a").click();
formValueCount++;
}
}
}
});
// 处理参数外的header
var headerObj = oldRequestObj.header;
if(!isEmptyObject(headerObj)) {
Object.keys(headerObj).forEach(function(key){
if(isNotEmpty(headerObj[key])) {
if(headerValueCount > 0) {
$("#tabParamHeader table tbody").append(getParamTableTr(key, headerObj[key], "", ""));
} else {
$("#tabParamHeader table tbody .base input[name=paramName]").val(key);
$("#tabParamHeader table tbody .base input[name=paramValue]").val(headerObj[key]);
}
headerValueCount++;
}
});
}
// 处理参数外的form
var formObj = oldRequestObj.form;
if(!isEmptyObject(formObj)) {
Object.keys(formObj).forEach(function(key){
if(isNotEmpty(formObj[key])) {
if(formValueCount > 0) {
$("#tabParamTypeForm table tbody").append(getParamTableTr(key, formObj[key], "", ""));
} else {
$("#tabParamTypeForm table tbody .base input[name=paramName]").val(key);
$("#tabParamTypeForm table tbody .base input[name=paramValue]").val(formObj[key]);
}
formValueCount++;
}
});
}
if(headerValueCount > 0) {
$("#tabParamHeader table tbody").append(getParamTableTr("", "", "", ""));
}
if(formValueCount > 0) {
$("#tabParamTypeForm table tbody").append(getParamTableTr("", "", "", ""));
}
}
/**
* 获取测试的对象
*/
function getParamBodyTransObj(paramObj) {
var newObject = $.extend(true, {}, paramObj);
Object.keys(newObject).forEach(function(key){
var subObj = newObject[key];
if(typeof subObj == 'object') {
if (subObj.hasOwnProperty("isParamObj")) {
var value = getNotEmptyStr(subObj.value);
if(isEmpty(value) && isNotEmpty(subObj.paramType)) {
value = getAutoFillValue(subObj.paramType, key);
}
newObject[key] = value;
} else if(subObj instanceof Array) {
subObj[0] = getParamBodyTransObj(subObj[0]);
} else {
newObject[key] = getParamBodyTransObj(subObj);
}
}
});
return newObject;
}
function serializeArrayToBulkEdit(formArr) {
var formObj = serializeArrayToObj(formArr);
var formStr = "";
Object.keys(formObj).forEach(function(key){
formStr += key + ":" + formObj[key] + "\n";
});
return formStr;
}
function serializeArrayToObj(formArr) {
var paramObj = {};
for (var i = 0; i < formArr.length; i++) {
if (formArr[i].name == "paramName" && i < formArr.length) {
var key = formArr[i].value;
var value = formArr[i + 1].value;
if (isNotEmpty(key) && formArr[i + 1].name != "paramName") {
paramObj[key] = value;
}
}
}
return paramObj;
}
function bulkEditToTable(tableId, bulkEdit) {
$(tableId + " table tbody .new").remove();
var valueCount = 0;
var headerArr = bulkEdit.split("\n");
for (var i = 0; i < headerArr.length; i++) {
var index = headerArr[i].indexOf(":");
if(index < 0) {
continue;
}
var key = headerArr[i].substring(0, index);
var value = headerArr[i].substring(index+1, headerArr[i].length);
if(valueCount > 0) {
$(tableId + " table tbody").append(getParamTableTr(key, value, "", ""));
} else {
$(tableId + " table tbody .base input[name=paramName]").val(key);
$(tableId + " table tbody .base input[name=paramValue]").val(value);
}
valueCount++;
}
if(valueCount > 0) {
$(tableId + " table tbody").append(getParamTableTr("", "", "", ""));
}
}
/**
* 获取参数的tr
* @param name
* @param value
* @param namePl
* @param valuePl
* @returns
*/
function getParamTableTr(name, value, namePl, valuePl, paramType) {
name = getNotEmptyStr(name);
namePl = getNotEmptyStr(namePl);
value = getNotEmptyStr(value);
valuePl = getNotEmptyStr(valuePl);
var regExp = new RegExp("\"", "gm");
name = (typeof name === 'string') ? name.replace(regExp, "&quot;") : name;
namePl = (typeof namePl === 'string') ? namePl.replace(regExp, "&quot;") : namePl;
value = (typeof value === 'string') ? value.replace(regExp, "&quot;") : value;
valuePl = (typeof valuePl === 'string') ? valuePl.replace(regExp, "&quot;") : valuePl;
var resultStr =
'<tr class="new">'
+'<td><input type="text" class="form-control" name="paramName" value="'+name+'" placeholder="'+namePl+'"></td>';
// 文件的input特殊处理
if(paramType == 'file') {
resultStr += '<td><input type="file" multiple class="form-control file-input" name="paramValue" placeholder="'+valuePl+'"></td>';
} else {
resultStr += '<td><input type="text" class="form-control" name="paramValue" value="'+value+'" placeholder="'+valuePl+'"></td>'
}
resultStr += '<td><i class="icon-times"></i></td>'
+'</tr>';
return resultStr;
}
/**
* 获取自动填充的值
* @param paramType
* @returns
*/
function getAutoFillValue(paramType, paramName) {
if(userSettings.autoFillParam == 0 || isEmpty(paramType)) {
return "";
}
paramName = getNotEmptyStr(paramName).toLowerCase();
var isTimeColumn = (paramType.indexOf("date-time") >= 0
|| paramName.endWith("date") || paramName.endWith("time"));
var isTypeColumn = (paramName.endWith("type") || paramName.endWith("status")
|| paramName.endWith("level") || paramName.endWith("num"));
var isPriceColumn = (paramName.endWith("money") || paramName.endWith("price")
|| paramName.endWith("cash") || paramName.endWith("coin"));
var isBooleanColumn = (paramName.startWith("is"));
var resultValue = "";
if(paramType.indexOf("int") >= 0){
if(isTypeColumn) {
resultValue = Math.ceil(Math.random() * 5);
} else if(paramName.endWith("age")) {
resultValue = Math.ceil(Math.random() * 100);
} else {
resultValue = Math.ceil(Math.random() * 100);
}
} else if(paramType.indexOf("double") >= 0){
resultValue = Math.ceil(Math.random() * 1000);
} else if(paramType.indexOf("float") >= 0){
resultValue = parseFloat(Math.random() * 1000).toFixed(2);
} else if(paramType.indexOf("byte") >= 0){
if(isTypeColumn) {
resultValue = Math.ceil(Math.random() * 5);
} else {
resultValue = Math.ceil(Math.random() * 127);
}
} else if(paramType.indexOf("boolean") >= 0){
resultValue = Math.random() > 0.5;
} else if(isTimeColumn){
resultValue = getNowDateTime();
} else {
if(paramName.endWith("id")) {
resultValue = Math.ceil(Math.random() * 1000);
} else if(paramName.endWith("age")) {
resultValue = Math.ceil(Math.random() * 100);
} else if(isPriceColumn){
resultValue = parseFloat(Math.random() * 1000).toFixed(2);
} else if(isTypeColumn){
resultValue = Math.ceil(Math.random() * 5);
} else if(isBooleanColumn){
resultValue = (Math.random() > 0.5) ? 0 : 1;
} else if(paramName.endWith("phone") || paramName.endWith("mobile")){
var arr = ["15226645814", "15226645815", "15226645816", "15226645817", "15226645818"];
resultValue = arr[Math.ceil(Math.random() * 5) - 1];
} else if(paramName.endWith("ids")){
var counts = Math.ceil(Math.random() * 5);
for (var i = 0; i < counts; i++) {
if(isNotEmpty(resultValue)){resultValue += ",";}
resultValue += Math.ceil(Math.random() * 1000);
}
} else if(paramName.endWith("types")){
var counts = Math.ceil(Math.random() * 3);
for (var i = 0; i < counts; i++) {
if(isNotEmpty(resultValue)){resultValue += ",";}
resultValue += Math.ceil(Math.random() * 5);
}
} else if(paramName.endWith("md5")){
resultValue = "5082079d92a8ef985f59e001d445ff20";
} else if(paramName.endWith("photo")){
resultValue = "http://www.zyplayer.com/freeplay/img/headIcon/myhead.jpg";
} else if(paramName.endWith("url") || paramName.endWith("uri")){
var arr = ["http://www.zyplayer.com", "http://www.kongjianzhou.com"];
resultValue = arr[Math.ceil(Math.random() * 2) - 1];
} else if(paramName.endWith("username")){
var arr = ["张三", "李四", "王二", "暮光:城中城", "海贼王"];
resultValue = arr[Math.ceil(Math.random() * 5) - 1];
} else if(userSettings.autoFillParam == 2){
//var arr = ["您好!","请!","对不起。","谢谢!","再见!","您早!","晚安!","请问您贵姓?","请原谅!","不用谢!","没关系!","欢迎您光临!","请坐!","请喝茶!","请多关照!","请多指教!","谢谢您的合作!","对不起,让您久等了。","没关系,我刚到。","给您添麻烦了。","我能为您做什么?","您好,请问您需要帮助吗?","您走好。","请慢走!"];
//resultValue = arr[Math.ceil(Math.random() * 24) - 1];
resultValue = "我是默认字符串";
}
//console.log(paramType);
}
return resultValue;
}

View File

@@ -0,0 +1,26 @@
/**
* 所有需要iframe页面调用的接口必须定义在这里
* 通过getExport()来吊起父页面的这些接口
*/
var exports = {
regeneratePathTree: function(){
// 定义在mg-ui.js用于重新生成文档树目录
regeneratePathTree();
},
updateTreeShowType: function(){
// 定义在mg-ui.js用于修改树形菜单展示类型
updateTreeShowType();
},
updateUserSettings: function(setting){
// 定义在mg-ui.js用于更新用户设置
updateUserSettings(setting);
},
exportDocument: function(){
// 定义在mg-ui.js用于打开导出文档框
exportDocument();
},
updateGlobalParam: function(param){
// 更新调试的全局参数变量
debugGlobalParam = param;
}
};

View File

@@ -0,0 +1,130 @@
/**
* 以每个Tag方式生成并展示
* 核心信息控制器
* /api/data/getDataList
* /api/data/getDataDetail
* 跟进控制器
* /api/track/getTrackList
* /api/track/getTrackDetail
*
* 先把树形的写完了再写这个,,
*
* @author 暮光:城中城
* @since 2018年5月26日
*/
function createTreeViewByTag(json, keywords) {
var pathIndex = {};
var paths = json.paths;
var domain = json.domainUrl;// 服务器代理会返回此属性
var rewriteDomainUrl = json.rewriteDomainUrl;// 服务器代理会返回此属性
if(isEmpty(domain)) {
domain = "http://" + json.host + json.basePath;
}
if(domain.endWith("/")) {
domain = domain.substring(0, domain.length - 1);
}
if (isEmptyObject(paths)) {
return;
}
//console.log(paths);
Object.keys(paths).forEach(function(key){
//console.log(key, paths[key]);
if(!findInPathsValue(key, paths[key], keywords)) {
return;
}
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "get");
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "head");
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "post");
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "put");
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "patch");
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "delete");
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "options");
setRequestMethodForTag(rewriteDomainUrl, domain, paths[key], pathIndex, key, "trace");
});
//console.log(pathIndex);
var htmlStr = '<li>';
htmlStr += '<a href="#">'+json.info.title+'</a>';
htmlStr += '<ul>';
htmlStr += getTreeHtmlForTag(pathIndex, projectTreeIdIndex);
htmlStr += '</ul>';
htmlStr += '</li>';
$('#apiPathTree .projects').append(htmlStr);
projectTreeIdIndex++;
}
/**
* 设置对象的各种请求方式,存在则复制
* @param source 资源原始json的paths的指定对象
* @param pathObj 当前的待赋值对象
* @param url url绝对路径
* @param method 请求方式post、get...
* @returns
*/
function setRequestMethodForTag(rewriteDomainUrl, domain, source, pathObj, url, method) {
if (isEmpty(source[method])) {
return;
}
source[method].tags.forEach(function(val, index) {
var tempObj = pathObj[val];
if(isEmpty(tempObj)) {
tempObj = pathObj[val] = {};
}
var tempUrlObj = tempObj[url];
if(isEmpty(tempUrlObj)) {
tempUrlObj = tempObj[url] = {};
}
var tempPath = projectTreeIdIndex + 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.set(tempPath, source[method]);
});
}
/**
* 将对象列表递归的方式转换成文档格式html字符串
* @param pathData 处理后的对象列表
* @returns 生成的html字符串
*/
function getTreeHtmlForTag(pathData, treeIdStr) {
var tempStr = "";
var indexNow = 1;
// get, head, post, put, patch, delete, options, trace
var actionArrays = ["get", "head", "post", "put", "patch", "delete", "options", "trace"];
Object.keys(pathData).forEach(function(key){
var tempNode = pathData[key];
var tempTreeId = treeIdStr + "_" + indexNow;
// 只有一个子元素而且有method元素说明是只有一个节点
var nodeSub = getObjectFirstAttributeIfOnly(tempNode);
if(nodeSub != null && isNotEmpty(nodeSub.method)) {
var summary = isEmpty(nodeSub.summary) ? "" : "(" + nodeSub.summary + ")";
if(summary.length > 10){
summary = summary.substring(0, 10)+"...)";// 防止被撑得太长只显示10个字
}
nodeSub.treeId = tempTreeId;
tempStr += '<li m-id="'+tempTreeId+'"><a href="#" class="show-doc" path="'+nodeSub.path+'">'+key+'<span>'+summary+'</span></a></li>';
} else if(haveString(actionArrays, key)) {
//console.log(tempTreeId);
tempNode.treeId = tempTreeId;
var summary = isEmpty(tempNode.summary) ? "" : "("+tempNode.summary+")";
if(summary.length > 10){
summary = summary.substring(0, 10)+"...)";// 防止被撑得太长只显示10个字
}
tempStr += '<li m-id="'+tempTreeId+'"><a href="#" class="show-doc" path="'+tempNode.path+'">'+key+'<span>'+summary+'</span></a></li>';
} else {
tempStr += '<li>';
tempStr += '<a href="#">'+key+'</a>';
tempStr += '<ul>';
tempStr += getTreeHtmlForTag(tempNode, tempTreeId);
tempStr += '</ul>';
tempStr += '</li>';
}
indexNow++;
});
return tempStr;
}

View File

@@ -0,0 +1,143 @@
/**
* 以树形方式生成并展示:
* /api
* /data
* /getDateList
* post
* get
* @author 暮光:城中城
* @since 2018年5月26日
*/
/**
* 把原始的json字符串转换成对象列表的方式方便后续使用
* @param json swagger的原始对象
* @returns
*/
function createTreeViewByTree(json, keywords) {
var pathIndex = {};
var paths = json.paths;
var domain = json.domainUrl;// 服务器代理会返回此属性
var rewriteDomainUrl = json.rewriteDomainUrl;// 服务器代理会返回此属性
if(isEmpty(domain)) {
domain = "http://" + json.host + json.basePath;
}
if(domain.endWith("/")) {
domain = domain.substring(0, domain.length - 1);
}
if (isEmptyObject(paths)) {
return;
}
//console.log(paths);
Object.keys(paths).forEach(function(key){
//console.log(key, paths[key]);
if(!findInPathsValue(key, paths[key], keywords)) {
return;
}
var keyArr = key.split("/");
var nowPathObj = null;
keyArr.forEach(function(val, index) {
//console.log(val, index);
if(isEmpty(val) && index == 0) {
return;
}
var nowPath = "/" + val;
if(nowPathObj == null) {
nowPathObj = {};
nowPathObj[nowPath] = pathIndex[nowPath];
if(nowPathObj[nowPath] == null) {
nowPathObj[nowPath] = {};
pathIndex[nowPath] = nowPathObj[nowPath];
}
}
var tempPathObj = nowPathObj[nowPath];
if(isEmpty(tempPathObj)) {
tempPathObj = nowPathObj[nowPath] = {};
}
nowPathObj = tempPathObj;
if(index == keyArr.length - 1) {
//get, head, post, put, patch, delete, options, trace
setRequestMethodForTree(rewriteDomainUrl, domain, paths[key], tempPathObj, key, "get");
setRequestMethodForTree(rewriteDomainUrl, domain, paths[key], tempPathObj, key, "head");
setRequestMethodForTree(rewriteDomainUrl, domain, paths[key], tempPathObj, key, "post");
setRequestMethodForTree(rewriteDomainUrl, domain, paths[key], tempPathObj, key, "put");
setRequestMethodForTree(rewriteDomainUrl, domain, paths[key], tempPathObj, key, "patch");
setRequestMethodForTree(rewriteDomainUrl, domain, paths[key], tempPathObj, key, "delete");
setRequestMethodForTree(rewriteDomainUrl, domain, paths[key], tempPathObj, key, "options");
setRequestMethodForTree(rewriteDomainUrl, domain, paths[key], tempPathObj, key, "trace");
}
});
});
var htmlStr = '<li>';
htmlStr += '<a href="#">'+json.info.title+'</a>';
htmlStr += '<ul>';
htmlStr += getTreeHtmlForTree(pathIndex, projectTreeIdIndex);
htmlStr += '</ul>';
htmlStr += '</li>';
$('#apiPathTree .projects').append(htmlStr);
projectTreeIdIndex++;
}
/**
* 设置对象的各种请求方式,存在则复制
* @param source 资源原始json的paths的指定对象
* @param pathObj 当前的待赋值对象
* @param url url绝对路径
* @param method 请求方式post、get...
* @returns
*/
function setRequestMethodForTree(rewriteDomainUrl, domain, source, pathObj, url, method) {
if (isEmpty(source[method])) {
return;
}
var tempPath = projectTreeIdIndex + url + "." + method;
pathObj[method] = source[method];
pathObj[method].path = tempPath;
pathObj[method].url = url;
pathObj[method].method = method;
pathObj[method].domain = domain;
pathObj[method].rewriteDomainUrl = rewriteDomainUrl;
treePathDataMap.set(tempPath, source[method]);
}
/**
* 将对象列表递归的方式转换成文档格式html字符串
* @param pathData 处理后的对象列表
* @returns 生成的html字符串
*/
function getTreeHtmlForTree(pathData, treeIdStr) {
var tempStr = "";
var indexNow = 1;
Object.keys(pathData).forEach(function(key){
var tempNode = pathData[key];
var tempTreeId = treeIdStr + "_" + indexNow;
var nodeSub = getObjectFirstAttributeIfOnly(tempNode);
if(nodeSub != null && isNotEmpty(nodeSub.method)) {
//console.log(nodeSub);
nodeSub.treeId = tempTreeId;
var summary = isEmpty(nodeSub.summary) ? "" : "("+nodeSub.summary+")";
if(summary.length > 10){
summary = summary.substring(0, 10)+"...)";// 防止被撑得太长只显示10个字
}
tempStr += '<li m-id="'+tempTreeId+'"><a href="#" class="show-doc" path="'+nodeSub.path+'">'+key+'<span>'+summary+'</span></a></li>';
} else if(key.indexOf("/") < 0) {
//console.log(tempTreeId);
tempNode.treeId = tempTreeId;
var summary = isEmpty(tempNode.summary) ? "" : "("+tempNode.summary+")";
if(summary.length > 10){
summary = summary.substring(0, 10)+"...)";// 防止被撑得太长只显示10个字
}
tempStr += '<li m-id="'+tempTreeId+'"><a href="#" class="show-doc" path="'+tempNode.path+'">'+key+'<span>'+summary+'</span></a></li>';
} else {
tempStr += '<li>';
tempStr += '<a href="#">'+key+'</a>';
tempStr += '<ul>';
tempStr += getTreeHtmlForTree(tempNode, tempTreeId);
tempStr += '</ul>';
tempStr += '</li>';
}
indexNow++;
});
return tempStr;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,106 @@
/**
* 两个元素上下、左右拖动动态改变大小
* @author 暮光:城中城
* @since 2017年5月7日
*/
(function($){
$.fn.mgResizableHeight = function(options) {
var defaults = {prev:this,next:this, prevHtMin:0, prevHtMax:999, nextHtMin:0, nextHtMax:999};
var opts = $.extend(defaults, options);
var disY = 0, prevH = 0, nextH = 0, isStart = false;
var prev, next, thisObj = this;
$(document).mousemove(function(ev){
if(!isStart){return;}
var ev = ev || window.event;
var H = ev.clientY - disY;
var prevHNow = prevH+H, nextHNow = nextH-H;
if(opts.prevHtMin >= prevHNow) {
prevHNow = opts.prevHtMin;
nextHNow = next.outerHeight();
}
if(opts.nextHtMin >= nextHNow) {
nextHNow = opts.nextHtMin;
prevHNow = prev.outerHeight();
}
if(opts.prevHtMax <= prevHNow) {
prevHNow = opts.prevHtMax;
nextHNow = next.outerHeight();
}
if(opts.nextHtMax <= nextHNow) {
nextHNow = opts.nextHtMax;
prevHNow = prev.outerHeight();
}
//prev.css("height", prevHNow + 'px');
//next.css("height", nextHNow + 'px');
if(typeof opts.onresize == 'function') {
opts.onresize(prevHNow, nextHNow);
}
}).mouseup(function(ev){
isStart = false;
});
$(this).mousedown(function(ev){
var ev = ev || window.event;
disY = ev.clientY;
prev = (opts.prev == thisObj)?$(opts.prev).prev():$(opts.prev);
next = (opts.next == thisObj)?$(opts.next).next():$(opts.next);
prevH = prev.outerHeight();
nextH = next.outerHeight();
isStart = true;
});
}
/**
* 改变宽度的功能,只是实现各种消息的通知,实际改变大小需要在回调里面自己操作
*/
$.fn.mgResizableWidth = function(options) {
var defaults = {prev:this,next:this, prevWtMin:0, prevWtMax:999, nextWtMin:0, nextWtMax:999};
var opts = $.extend(defaults, options);
var disX = 0, prevW = 0, nextW = 0, isStart = false;
var prev, next, thisObj = this;
$(document).mousemove(function(ev){
if(!isStart){return;}
var ev = ev || window.event;
var W = ev.clientX - disX;
var prevWNow = prevW+W, nextWNow = nextW-W;
if(opts.prevWtMin >= prevWNow) {
prevWNow = opts.prevWtMin;
nextWNow = next.outerWidth();
}
if(opts.nextWtMin >= nextWNow) {
nextWNow = opts.nextWtMin;
prevWNow = prev.outerWidth();
}
if(opts.prevWtMax <= prevWNow) {
prevWNow = opts.prevWtMax;
nextWNow = next.outerWidth();
}
if(opts.nextWtMax <= nextWNow) {
nextWNow = opts.nextWtMax;
prevWNow = prev.outerWidth();
}
//prev.css("width", prevWNow + 'px');
//next.css("width", nextWNow + 'px');
if(typeof opts.onresize == 'function') {
opts.onresize(prevWNow, nextWNow);
}
}).mouseup(function(ev){
if(!isStart){return;}
isStart = false;
if(typeof opts.onfinish == 'function') {
opts.onfinish();
}
});
$(this).mousedown(function(ev){
var ev = ev || window.event;
disX = ev.clientX;
prev = (opts.prev == thisObj)?$(opts.prev).prev():$(opts.prev);
next = (opts.next == thisObj)?$(opts.next).next():$(opts.next);
prevW = prev.outerWidth();
nextW = next.outerWidth();
isStart = true;
if(typeof opts.onstart == 'function') {
opts.onstart();
}
});
}
})(jQuery);

View File

@@ -0,0 +1,40 @@
/**
* 提示工具类
* @author 暮光:城中城
* @since 2017年5月7日
*/
var Toast = {
notOpen: function () {
var data = {
message: "该功能暂未开放,敬请期待!",
icon: 'exclamation-sign', type: "warning",
};
this.show(data);
},
success: function (msg, time) {
var data = {
message: msg, time: time,
icon: 'check-circle-o', type: 'success',
};
this.show(data);
},
warn: function (msg, time) {
var data = {
message: msg, time: time,
icon: 'exclamation-sign', type: 'warning',
};
this.show(data);
},
error: function (msg, time) {
var data = {
message: msg, time: time,
icon: 'exclamation-sign', type: 'danger',
};
this.show(data);
},
show: function (data) {
data.time = isEmpty(data.time) ? 2000 : data.time;
data.placement = isEmpty(data.placement) ? 'top' : data.placement;
new $.zui.Messager(data.message, data).show();
}
}

View File

@@ -0,0 +1,204 @@
<!doctype html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>详细地址管理</title>
<link rel="stylesheet" type="text/css" href="../zui/css/zui.min.css">
</head>
<body>
<div id="app">
<table class="table table-bordered setting-table">
<thead>
<tr>
<td style="width: 50px;">序号</td>
<td>地址</td>
<td>唯一文档地址</td>
<td>重写域名地址</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in swaggerLocationList" :key="item.id" :data-id="item.id" :data-index="index" >
<td>{{index+1}}</td>
<td>{{item.location}}</td>
<td><a :href="'../../open-doc.html?doc='+item.uuid" target="_blank">{{item.uuid}}</a></td>
<td>{{item.rewriteDomainUrl}}</td>
<td>
<button class="btn btn-danger" type="button" v-on:click="deleteDocUrl($event)">删除</button>
<button class="btn btn-info" type="button" v-on:click="editDocUrl($event)">编辑</button>
<!--<button class="btn btn-danger" type="button" v-on:click="syncDocData($event)">持久化</button>-->
</td>
</tr>
<tr>
<td colspan="5" align="center">
<button class="btn" type="button" v-on:click="btnRefreshList"> 刷新 </button>
<button class="btn btn-info" type="button" v-on:click="exportDocument">导出文档</button>
<button class="btn btn-primary" type="button" v-on:click="addNewDocument">增加文档</button>
</td>
</tr>
</tbody>
</table>
<!-- 增加文档弹出框 -->
<div class="modal fade" id="addNewDocumentModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span><span class="sr-only">关闭</span>
</button>
<h4 class="modal-title">输入文档地址</h4>
</div>
<div class="modal-body">
<div class="input-line">
地址:
<input v-model="addNewDocumentInput" type="text" class="form-control" placeholder="例http://192.168.0.172/swagger-resources 或 http://192.168.0.172/v2/api-docs">
</div>
<div class="input-line">
重写域名地址:
<input v-model="rewriteDomainUrl" type="text" name="rewriteDomainUrl" class="form-control" placeholder="文档展示配置页 勾选“重写域名”重写的地址">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" v-on:click="addNewDocumentBtn">保存</button>
</div>
</div>
</div>
</div>
</div>
</body>
<script src="../mg-ui/js/jquery-3.1.0.min.js"></script>
<script src="../zui/js/zui.min.js"></script>
<script src="../mg-ui/js/common.js"></script>
<script src="../mg-ui/js/mg-ui-cache-keys.js"></script>
<script src="../vue/vue.js"></script>
<script src="../mg-ui/js/toast.js"></script>
<script>
var urlBase = "../../";
var app = new Vue({
el: '#app',
data: {
swaggerLocationList: [],
addNewDocumentInput: '',
rewriteDomainUrl: '',
oldLocation: ''
},
methods: {
btnRefreshList: function(){
this.refreshList();
Toast.success("刷新成功!");
},
refreshList: function () {
getStorage(cacheKeys.swaggerLocationList, function (data) {
//console.log(data);
var swaggerLocationList = data;
for (var i = 0; i < swaggerLocationList.length; i++) {
swaggerLocationList[i].location = decodeURI(swaggerLocationList[i].location);
}
app.swaggerLocationList = swaggerLocationList;
});
},
editDocUrl: function (event) {
var tr = $(event.currentTarget).parents("tr");
var index = tr.data("index");
var item = app.swaggerLocationList[index];
app.oldLocation = item.location;
app.addNewDocumentInput = item.location;
app.rewriteDomainUrl = item.rewriteDomainUrl;
$('#addNewDocumentModal').modal({moveable: true});
},
addNewDocument: function(){
app.oldLocation = '';
app.addNewDocumentInput = '';
$('#addNewDocumentModal').modal({moveable:true});
},
addNewDocumentBtn: function(){
var addNewDocumentInput = app.addNewDocumentInput;
if(isEmpty(addNewDocumentInput)) {
Toast.error("地址不可以为空");return;
}
var param = {
resourcesUrl: addNewDocumentInput,
rewriteDomainUrl: app.rewriteDomainUrl,
oldUrl: app.oldLocation
};
ajaxTemp(urlBase + "swagger-mg-ui/document/addSwaggerResources", "post", "json", param, function(json){
if(validateResult(json)) {
//window.parent.document.location.reload();
//app.swaggerLocationList.push(addNewDocumentInput);
app.refreshList();
$('#addNewDocumentModal').modal('hide');
Toast.success("保存成功,刷新后生效!");
}
});
},
exportDocument: function () {
getExport().exportDocument();
},
deleteDocUrl: function (event) {
if (!confirm("确定要删除吗?")) {
return;
}
var tr = $(event.currentTarget).parents("tr");
var index = tr.data("index");
var newDocList = [];
for (var i = 0; i < app.swaggerLocationList.length; i++) {
if (i !== index) {
newDocList.push(app.swaggerLocationList[i]);
}
}
setStorage(cacheKeys.swaggerLocationList, newDocList, function () {
app.swaggerLocationList = newDocList;
});
},
syncDocData: function (event) {
var tr = $(event.currentTarget).parents("tr");
var index = tr.data("index");
var newDocUrl = app.swaggerLocationList[index].location;
ajaxTemp(urlBase + "swagger-mg-ui/document/syncDocData", "post", "json", {resourcesUrl: newDocUrl}, function (json) {
if (validateResult(json)) {
app.refreshList();
Toast.success("持久化成功!");
}
});
},
encodeUrlParam: function(resourcesUrl) {
var indexOf = resourcesUrl.indexOf("?");
if (indexOf < 0) {
return resourcesUrl;
}
var baseUrl = resourcesUrl.substring(0, indexOf + 1);
var paramArr = resourcesUrl.substring(indexOf + 1).split("&");
for (var i = 0; i < paramArr.length; i++) {
var param = paramArr[i];
var split = param.split("=");
if (i > 0) {
baseUrl.append("&");
}
if (split.length === 2) {
baseUrl += split[0] + "=" + encodeURI(split[1]);
} else {
baseUrl += param;
}
}
return baseUrl.toString();
}
},
mounted: function(){
this.refreshList();
},
watch: {
}
});
</script>
<style>
#app{padding-top: 10px;}
.input-line{margin-bottom: 15px;}
</style>
</html>