dubbo文档优化
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
||||
*.iml
|
||||
tmlog*.lck
|
||||
tmlog*.log
|
||||
dependency-reduced-pom.xml
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<dependency>
|
||||
<groupId>com.zyplayer</groupId>
|
||||
<artifactId>zyplayer-doc-annotation</artifactId>
|
||||
<version>1.0.6</version>
|
||||
<version>${zyplayer.doc.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
|
||||
@@ -1,44 +1,32 @@
|
||||
package com.zyplayer.doc.dubbo.controller;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.zyplayer.doc.core.annotation.AuthMan;
|
||||
import com.zyplayer.doc.core.json.DocResponseJson;
|
||||
import com.zyplayer.doc.dubbo.controller.param.DubboRequestParam;
|
||||
import com.zyplayer.doc.dubbo.controller.vo.DubboInfoVo;
|
||||
import com.zyplayer.doc.dubbo.controller.vo.NacosServiceInfoVo;
|
||||
import com.zyplayer.doc.dubbo.controller.vo.NacosServiceListVo;
|
||||
import com.zyplayer.doc.dubbo.framework.bean.DubboDocInfo;
|
||||
import com.zyplayer.doc.dubbo.framework.bean.DubboInfo;
|
||||
import com.zyplayer.doc.dubbo.framework.bean.NacosDubboInfo;
|
||||
import com.zyplayer.doc.dubbo.framework.bean.ReferenceConfigHolder;
|
||||
import com.zyplayer.doc.dubbo.framework.constant.DubboDocConst;
|
||||
import com.zyplayer.doc.dubbo.framework.constant.StorageKeys;
|
||||
import com.zyplayer.doc.dubbo.framework.service.ClassLoadService;
|
||||
import com.zyplayer.doc.dubbo.framework.service.MgDubboStorageService;
|
||||
import com.zyplayer.doc.dubbo.framework.service.NacosDocService;
|
||||
import com.zyplayer.doc.dubbo.framework.service.ZookeeperDocService;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.apache.curator.RetryPolicy;
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.CuratorFrameworkFactory;
|
||||
import org.apache.curator.retry.ExponentialBackoffRetry;
|
||||
import org.apache.dubbo.common.Constants;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.utils.UrlUtils;
|
||||
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
|
||||
import org.apache.dubbo.metadata.definition.model.MethodDefinition;
|
||||
import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URLDecoder;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -56,53 +44,17 @@ import java.util.stream.Collectors;
|
||||
public class DubboController {
|
||||
private static Logger logger = LoggerFactory.getLogger(DubboController.class);
|
||||
|
||||
private final static String DEFAULT_ROOT = "dubbo";
|
||||
private final static String METADATA_NODE_NAME = "service.data";
|
||||
private String root;
|
||||
@Value("${zyplayer.doc.dubbo.doc-lib-path}")
|
||||
private String zyplayerDocDubboLibPath;
|
||||
|
||||
@Value("${zyplayer.doc.dubbo.zookeeper.url:}")
|
||||
private String serviceZookeeperUrl;
|
||||
@Value("${zyplayer.doc.dubbo.zookeeper.metadata-url:}")
|
||||
private String metadataZookeeperUrl;
|
||||
@Value("${zyplayer.doc.dubbo.nacos.url:}")
|
||||
private String nacosUrl;
|
||||
// @Value("${zyplayer.doc.dubbo.nacos.service:}")
|
||||
// private String nacosService;
|
||||
@Resource
|
||||
private MgDubboStorageService mgDubboStorageService;
|
||||
|
||||
private CuratorFramework serverClient;
|
||||
private CuratorFramework metadataClient;
|
||||
|
||||
private void initServerClient() {
|
||||
if (serverClient == null && StringUtils.isNotBlank(serviceZookeeperUrl)) {
|
||||
synchronized (DEFAULT_ROOT) {
|
||||
if (serverClient == null) {
|
||||
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
|
||||
serverClient = CuratorFrameworkFactory.newClient(serviceZookeeperUrl, retryPolicy);
|
||||
serverClient.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initMetadataClient() {
|
||||
if (metadataClient == null && StringUtils.isNotBlank(metadataZookeeperUrl)) {
|
||||
synchronized (DEFAULT_ROOT) {
|
||||
if (metadataClient == null) {
|
||||
URL url = UrlUtils.parseURL(metadataZookeeperUrl, Collections.emptyMap());
|
||||
String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
|
||||
if (!group.startsWith(Constants.PATH_SEPARATOR)) {
|
||||
group = Constants.PATH_SEPARATOR + group;
|
||||
}
|
||||
this.root = group;
|
||||
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
|
||||
metadataClient = CuratorFrameworkFactory.newClient(metadataZookeeperUrl, retryPolicy);
|
||||
metadataClient.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Resource
|
||||
private ZookeeperDocService zookeeperDocService;
|
||||
@Resource
|
||||
private NacosDocService nacosDocService;
|
||||
@Resource
|
||||
ClassLoadService classLoadService;
|
||||
|
||||
/**
|
||||
* 重新获取所有的服务列表
|
||||
@@ -111,17 +63,17 @@ public class DubboController {
|
||||
* @since 2019年2月10日
|
||||
**/
|
||||
@PostMapping(value = "/reloadService")
|
||||
public DocResponseJson loadService() throws Exception {
|
||||
public DocResponseJson loadService() {
|
||||
List<DubboInfo> providerList;
|
||||
try {
|
||||
if (StringUtils.isBlank(serviceZookeeperUrl)) {
|
||||
if (StringUtils.isBlank(nacosUrl)) {// || StringUtils.isBlank(nacosService)) {
|
||||
if (!zookeeperDocService.isEnable()) {
|
||||
if (!nacosDocService.isEnable()) {
|
||||
return DocResponseJson.warn("zyplayer.doc.dubbo.zookeeper.url、zyplayer.doc.dubbo.nacos.url 参数均未配置");
|
||||
}
|
||||
logger.info("zookeeper参数未配置,使用nacos配置");
|
||||
providerList = this.getDubboInfoByNacos();
|
||||
providerList = nacosDocService.getDubboInfoByNacos();
|
||||
} else {
|
||||
providerList = this.getDubboInfoByZookeeper();
|
||||
providerList = zookeeperDocService.getDubboInfoByZookeeper();
|
||||
}
|
||||
mgDubboStorageService.put(StorageKeys.DUBBO_SERVICE_LIST, JSON.toJSONString(providerList));
|
||||
} catch (Exception e) {
|
||||
@@ -143,6 +95,8 @@ public class DubboController {
|
||||
dubboNodeInfo.setIp(param.getIp());
|
||||
dubboNodeInfo.setPort(param.getPort());
|
||||
dubboNodeInfo.setInterfaceX(param.getService());
|
||||
dubboNodeInfo.setVersion(param.getVersion());
|
||||
dubboNodeInfo.setGroup(param.getGroup());
|
||||
String paramTypeStr = Optional.ofNullable(param.getParamTypes()).orElse("");
|
||||
String paramsStr = Optional.ofNullable(param.getParams()).orElse("");
|
||||
List<String> typeList = JSON.parseArray(paramTypeStr, String.class);
|
||||
@@ -155,7 +109,7 @@ public class DubboController {
|
||||
try {
|
||||
if (typeStr.endsWith("[]")) {
|
||||
String type = typeStr.substring(0, typeStr.length() - 2);
|
||||
Class<?> aClass = Class.forName(type);
|
||||
Class<?> aClass = classLoadService.loadClass(type);
|
||||
List<?> objects = JSON.parseArray(paramStr, aClass);
|
||||
queryTypeList.add(typeStr);
|
||||
queryParamList.add(objects);
|
||||
@@ -164,13 +118,13 @@ public class DubboController {
|
||||
Matcher matcher = pattern.matcher(typeStr);
|
||||
if (matcher.find()) {
|
||||
String group = matcher.group(1);
|
||||
Class<?> aClass = Class.forName(group);
|
||||
Class<?> aClass = classLoadService.loadClass(group);
|
||||
List<?> objects = JSON.parseArray(paramStr, aClass);
|
||||
queryParamList.add(objects);
|
||||
queryTypeList.add("java.util.List");
|
||||
}
|
||||
} else {
|
||||
Class<?> aClass = Class.forName(typeStr);
|
||||
Class<?> aClass = classLoadService.loadClass(typeStr);
|
||||
Object object = JSON.parseObject(paramStr, aClass);
|
||||
queryParamList.add(object);
|
||||
queryTypeList.add(typeStr);
|
||||
@@ -182,13 +136,16 @@ public class DubboController {
|
||||
queryTypeList.add(typeStr);
|
||||
}
|
||||
}
|
||||
GenericService bean = ReferenceConfigHolder.getBean(dubboNodeInfo);
|
||||
try {
|
||||
GenericService bean = ReferenceConfigHolder.getBean(dubboNodeInfo);
|
||||
if (bean == null) {
|
||||
return DocResponseJson.warn("操作失败,获取dubbo服务失败");
|
||||
}
|
||||
Object result = bean.$invoke(param.getMethod(), queryTypeList.toArray(new String[]{}), queryParamList.toArray());
|
||||
return DocResponseJson.ok(result);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return DocResponseJson.warn("请求失败:" + e.getMessage());
|
||||
return DocResponseJson.warn("操作失败," + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,9 +181,9 @@ public class DubboController {
|
||||
**/
|
||||
@PostMapping(value = "/findDocInfo")
|
||||
public DocResponseJson findDocInfo(DubboRequestParam param) {
|
||||
DubboDocInfo definition = this.getDefinitionByJar(param);
|
||||
DubboDocInfo definition = zookeeperDocService.getDefinitionByJar(param);
|
||||
if (definition == null) {
|
||||
definition = this.getDefinitionByMetadata(param);
|
||||
definition = zookeeperDocService.getDefinitionByMetadata(param);
|
||||
}
|
||||
if (definition == null) {
|
||||
return DocResponseJson.warn("未找到指定类,请引入相关包或开启metadata,类名:" + param.getService());
|
||||
@@ -298,173 +255,36 @@ public class DubboController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过nacos方式获取所有服务
|
||||
* 上传文档jar
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年2月10日
|
||||
* @since 2020年10月08日
|
||||
**/
|
||||
private List<DubboInfo> getDubboInfoByNacos() {
|
||||
List<DubboInfo> providerList = new LinkedList<>();
|
||||
// 获取所有的服务列表
|
||||
String serviceListStr = HttpUtil.get(nacosUrl + "/v1/ns/catalog/services?withInstances=false&pageNo=1&pageSize=100000");
|
||||
NacosServiceInfoVo nacosServiceInfoVo = JSON.parseObject(serviceListStr, NacosServiceInfoVo.class);
|
||||
if (nacosServiceInfoVo == null || nacosServiceInfoVo.getServiceList().isEmpty()) {
|
||||
return providerList;
|
||||
@PostMapping(value = "/uploadDocJar")
|
||||
public DocResponseJson uploadDocJar(@RequestParam("file") MultipartFile file) {
|
||||
File newFileDir = new File(zyplayerDocDubboLibPath);
|
||||
if (!newFileDir.exists() && !newFileDir.mkdirs()) {
|
||||
return DocResponseJson.warn("创建文件夹失败");
|
||||
}
|
||||
for (NacosServiceListVo service : nacosServiceInfoVo.getServiceList()) {
|
||||
String serviceName = service.getName();
|
||||
String resultStr = HttpUtil.get(nacosUrl + "/v1/ns/instance/list?serviceName=" + serviceName);
|
||||
NacosDubboInfo dubboInstance = JSON.parseObject(resultStr, NacosDubboInfo.class);
|
||||
List<NacosDubboInfo.HostsBean> hosts = dubboInstance.getHosts();
|
||||
DubboInfo dubboInfo = new DubboInfo();
|
||||
List<DubboInfo.DubboNodeInfo> nodeList = new LinkedList<>();
|
||||
for (NacosDubboInfo.HostsBean host : hosts) {
|
||||
DubboInfo.DubboNodeInfo dubboNodeInfo = new DubboInfo.DubboNodeInfo();
|
||||
dubboNodeInfo.setIp(host.getIp());
|
||||
dubboNodeInfo.setPort(host.getPort());
|
||||
dubboNodeInfo.setInterfaceX(host.getMetadata().getInterfaceX());
|
||||
dubboNodeInfo.setMethods(host.getMetadata().getMethods().split(","));
|
||||
dubboNodeInfo.setApplication(host.getMetadata().getApplication());
|
||||
nodeList.add(dubboNodeInfo);
|
||||
}
|
||||
if (serviceName.contains(":")) {
|
||||
serviceName = serviceName.substring(serviceName.indexOf(":") + 1);
|
||||
}
|
||||
dubboInfo.setInterfaceX(serviceName);
|
||||
dubboInfo.setNodeList(nodeList);
|
||||
providerList.add(dubboInfo);
|
||||
String fileSuffix = null;
|
||||
String fileName = file.getOriginalFilename();
|
||||
if (fileName != null) {
|
||||
fileSuffix = fileName.substring(fileName.lastIndexOf("."));
|
||||
}
|
||||
return providerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过Zookeeper方式获取所有服务
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年2月10日
|
||||
**/
|
||||
private List<DubboInfo> getDubboInfoByZookeeper() throws Exception {
|
||||
this.initServerClient();
|
||||
List<String> dubboList = serverClient.getChildren().forPath("/dubbo");
|
||||
if (dubboList == null || dubboList.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
if (!Objects.equals(".jar", fileSuffix)) {
|
||||
return DocResponseJson.warn("仅支持jar后缀的文件格式上传");
|
||||
}
|
||||
List<DubboInfo> providerList = new LinkedList<>();
|
||||
for (String dubboStr : dubboList) {
|
||||
String path = "/dubbo/" + dubboStr + "/providers";
|
||||
if (serverClient.checkExists().forPath(path) == null) {
|
||||
continue;
|
||||
}
|
||||
List<String> providers = serverClient.getChildren().forPath(path);
|
||||
List<DubboInfo.DubboNodeInfo> nodeList = providers.stream().map(val -> {
|
||||
String tempStr = val;
|
||||
try {
|
||||
tempStr = URLDecoder.decode(val, "utf-8");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// IP和端口
|
||||
String ipPort = tempStr.substring(tempStr.indexOf("://") + 3);
|
||||
ipPort = ipPort.substring(0, ipPort.indexOf("/"));
|
||||
String[] ipPortArr = ipPort.split(":");
|
||||
// 参数
|
||||
Map<String, String> paramMap = new HashMap<>();
|
||||
String params = tempStr.substring(tempStr.indexOf("?"));
|
||||
String[] paramsArr = params.split("&");
|
||||
for (String param : paramsArr) {
|
||||
String[] split = param.split("=");
|
||||
paramMap.put(split[0], split[1]);
|
||||
}
|
||||
DubboInfo.DubboNodeInfo dubboNodeInfo = new DubboInfo.DubboNodeInfo();
|
||||
dubboNodeInfo.setIp(ipPortArr[0]);
|
||||
dubboNodeInfo.setPort(NumberUtils.toInt(ipPortArr[1]));
|
||||
dubboNodeInfo.setInterfaceX(paramMap.get("interface"));
|
||||
dubboNodeInfo.setMethods(paramMap.get("methods").split(","));
|
||||
dubboNodeInfo.setApplication(paramMap.get("application"));
|
||||
return dubboNodeInfo;
|
||||
}).collect(Collectors.toList());
|
||||
DubboInfo dubboInfo = new DubboInfo();
|
||||
dubboInfo.setInterfaceX(dubboStr);
|
||||
dubboInfo.setNodeList(nodeList);
|
||||
providerList.add(dubboInfo);
|
||||
}
|
||||
return providerList;
|
||||
}
|
||||
|
||||
private DubboDocInfo getDefinitionByMetadata(DubboRequestParam param) {
|
||||
try {
|
||||
this.initMetadataClient();
|
||||
String path = getNodePath(param.getService(), null, null, param.getApplication());
|
||||
if (metadataClient.checkExists().forPath(path) == null) {
|
||||
return null;
|
||||
}
|
||||
String resultType = null;
|
||||
String metadata = new String(metadataClient.getData().forPath(path));
|
||||
FullServiceDefinition definition = JSON.parseObject(metadata, FullServiceDefinition.class);
|
||||
List<DubboDocInfo.DubboDocParam> paramList = new LinkedList<>();
|
||||
for (MethodDefinition method : definition.getMethods()) {
|
||||
if (Objects.equals(method.getName(), param.getMethod())) {
|
||||
String[] parameterTypes = method.getParameterTypes();
|
||||
resultType = method.getReturnType();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
DubboDocInfo.DubboDocParam docParam = new DubboDocInfo.DubboDocParam();
|
||||
docParam.setParamType(parameterTypes[i]);
|
||||
docParam.setParamName("arg" + i);
|
||||
paramList.add(docParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
DubboDocInfo dubboDocInfo = new DubboDocInfo();
|
||||
dubboDocInfo.setParams(paramList);
|
||||
dubboDocInfo.setResultType(resultType);
|
||||
return dubboDocInfo;
|
||||
classLoadService.closeClassLoad(() -> {
|
||||
File docJarFile = new File(zyplayerDocDubboLibPath + "/" + DubboDocConst.DUBBO_DOC_LIB_NAME);
|
||||
file.transferTo(docJarFile);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return DocResponseJson.warn("保存文件失败:" + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
return DocResponseJson.ok();
|
||||
}
|
||||
|
||||
private DubboDocInfo getDefinitionByJar(DubboRequestParam param) {
|
||||
String resultType = null;
|
||||
List<DubboDocInfo.DubboDocParam> paramList = new LinkedList<>();
|
||||
try {
|
||||
Class clazz = Class.forName(param.getService());
|
||||
Method[] methods = clazz.getMethods();
|
||||
for (Method method : methods) {
|
||||
String methodName = method.getName();
|
||||
if (methodName.equals(param.getMethod())) {
|
||||
resultType = method.getGenericReturnType().getTypeName();
|
||||
Type[] parameterTypes = method.getGenericParameterTypes();
|
||||
Parameter[] parameters = method.getParameters();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
DubboDocInfo.DubboDocParam docParam = new DubboDocInfo.DubboDocParam();
|
||||
docParam.setParamName(parameters[i].getName());
|
||||
docParam.setParamType(parameterTypes[i].getTypeName());
|
||||
paramList.add(docParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
DubboDocInfo dubboDocInfo = new DubboDocInfo();
|
||||
dubboDocInfo.setParams(paramList);
|
||||
dubboDocInfo.setResultType(resultType);
|
||||
return dubboDocInfo;
|
||||
}
|
||||
|
||||
String toRootDir() {
|
||||
if (root.equals(Constants.PATH_SEPARATOR)) {
|
||||
return root;
|
||||
}
|
||||
return root + Constants.PATH_SEPARATOR;
|
||||
}
|
||||
|
||||
String getNodePath(String serviceInterface, String version, String group, String application) {
|
||||
MetadataIdentifier metadataIdentifier = new MetadataIdentifier(serviceInterface, version, group, Constants.PROVIDER_SIDE, application);
|
||||
return toRootDir() + metadataIdentifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.PATH) + Constants.PATH_SEPARATOR + METADATA_NODE_NAME;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ public class DubboRequestParam {
|
||||
private String method;
|
||||
private String ip;
|
||||
private Integer port;
|
||||
private String version;
|
||||
private String group;
|
||||
private String paramTypes;
|
||||
private String params;
|
||||
|
||||
@@ -70,4 +72,20 @@ public class DubboRequestParam {
|
||||
public void setApplication(String application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
this.group = group;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ public class DubboDocInfo {
|
||||
private String paramDesc;
|
||||
private Object paramValue;
|
||||
private Integer required;
|
||||
private List<DubboDocParam> params;
|
||||
|
||||
public String getParamName() {
|
||||
return paramName;
|
||||
@@ -65,14 +64,6 @@ public class DubboDocInfo {
|
||||
public void setRequired(Integer required) {
|
||||
this.required = required;
|
||||
}
|
||||
|
||||
public List<DubboDocParam> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(List<DubboDocParam> params) {
|
||||
this.params = params;
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getVersion() {
|
||||
|
||||
@@ -20,6 +20,8 @@ public class DubboInfo {
|
||||
private String interfaceX;
|
||||
private String[] methods;
|
||||
private String application;
|
||||
private String version;
|
||||
private String group;
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
@@ -60,6 +62,22 @@ public class DubboInfo {
|
||||
public void setApplication(String application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
this.group = group;
|
||||
}
|
||||
}
|
||||
|
||||
public List<DubboNodeInfo> getNodeList() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.zyplayer.doc.dubbo.framework.bean;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.config.ReferenceConfig;
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
@@ -15,24 +16,29 @@ public class ReferenceConfigHolder {
|
||||
private static Map<String, ReferenceConfig> referenceConfigMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static GenericService getBean(DubboInfo.DubboNodeInfo dubboNodeInfo) {
|
||||
String name = dubboNodeInfo.getInterfaceX();
|
||||
String url = "dubbo://" + dubboNodeInfo.getIp() + ":" + dubboNodeInfo.getPort() + "/" + dubboNodeInfo.getInterfaceX();
|
||||
ReferenceConfig referenceConfig = referenceConfigMap.get(url);
|
||||
String url = "dubbo://" + dubboNodeInfo.getIp() + ":" + dubboNodeInfo.getPort();
|
||||
String referenceKey = url + "_" + StringUtils.defaultIfBlank(dubboNodeInfo.getVersion(), "0") + "_" + StringUtils.defaultIfBlank(dubboNodeInfo.getGroup(), "0");
|
||||
ReferenceConfig referenceConfig = referenceConfigMap.get(referenceKey);
|
||||
if (referenceConfig == null) {
|
||||
ApplicationConfig application = new ApplicationConfig();
|
||||
application.setName("zyplayer-doc-consume");
|
||||
// 参考:http://dubbo.apache.org/zh-cn/docs/user/configuration/api.html
|
||||
// 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
|
||||
referenceConfig = new ReferenceConfig<>();
|
||||
// 如果点对点直连,可以用reference.setUrl()指定目标地址,设置url后将绕过注册中心,
|
||||
// 其中,协议对应provider.setProtocol()的值,端口对应provider.setPort()的值,
|
||||
// 路径对应service.setPath()的值,如果未设置path,缺省path为接口名
|
||||
referenceConfig.setUrl(url);
|
||||
referenceConfig.setInterface(name.substring(name.lastIndexOf(".") + 1));
|
||||
referenceConfig.setGeneric(true);
|
||||
referenceConfig.setApplication(application);
|
||||
referenceConfig.setTimeout(5000);
|
||||
referenceConfigMap.put(url, referenceConfig);
|
||||
synchronized (ReferenceConfigHolder.class) {
|
||||
ApplicationConfig application = new ApplicationConfig();
|
||||
application.setName("zyplayer-doc-consume");
|
||||
// 参考:http://dubbo.apache.org/zh-cn/docs/user/configuration/api.html
|
||||
// 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
|
||||
referenceConfig = new ReferenceConfig<>();
|
||||
// 如果点对点直连,可以用reference.setUrl()指定目标地址,设置url后将绕过注册中心,
|
||||
// 其中,协议对应provider.setProtocol()的值,端口对应provider.setPort()的值,
|
||||
// 路径对应service.setPath()的值,如果未设置path,缺省path为接口名
|
||||
referenceConfig.setUrl(url);
|
||||
String groupAppend = StringUtils.isNotBlank(dubboNodeInfo.getGroup()) ? dubboNodeInfo.getGroup() + "/" : "";
|
||||
referenceConfig.setInterface(groupAppend + dubboNodeInfo.getInterfaceX());
|
||||
referenceConfig.setGeneric(true);
|
||||
referenceConfig.setApplication(application);
|
||||
referenceConfig.setTimeout(5000);
|
||||
referenceConfig.setVersion(dubboNodeInfo.getVersion());
|
||||
referenceConfig.setGroup(dubboNodeInfo.getGroup());
|
||||
referenceConfigMap.put(referenceKey, referenceConfig);
|
||||
}
|
||||
}
|
||||
// 本项目没有dubbo里面申明的类,快放弃时看源码发现可以设置generic返回一个GenericService对象,通过$invoke去操作具体方法,感觉又打开了一扇大门
|
||||
// 本项目选择的不入侵的方式管理文档,所以文档里面就必须手动加参数,写文档那些了
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.zyplayer.doc.dubbo.framework.constant;
|
||||
|
||||
/**
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
public class DubboDocConst {
|
||||
/**上传的文档jar文件名*/
|
||||
public static final String DUBBO_DOC_LIB_NAME = "zyplayer-doc-dubbo-libs.jar";
|
||||
|
||||
}
|
||||
@@ -1,14 +1,19 @@
|
||||
package com.zyplayer.doc.dubbo.framework.service;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.zyplayer.doc.annotation.DocMethod;
|
||||
import com.zyplayer.doc.annotation.DocParam;
|
||||
import com.zyplayer.doc.core.exception.ConfirmException;
|
||||
import com.zyplayer.doc.dubbo.framework.bean.DubboResponseInfo;
|
||||
import com.zyplayer.doc.dubbo.framework.bean.InterfaceType;
|
||||
import com.zyplayer.doc.dubbo.framework.constant.BaseType;
|
||||
import com.zyplayer.doc.dubbo.framework.constant.DubboDocConst;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.net.JarURLConnection;
|
||||
@@ -18,39 +23,111 @@ import java.util.*;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* 类加载服务
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
@Service
|
||||
public class ClassLoadService {
|
||||
private static Logger logger = LoggerFactory.getLogger(ClassLoadService.class);
|
||||
|
||||
@Value("${zyplayer.doc.dubbo.doc-lib-path}")
|
||||
private String zyplayerDocDubboLibPath;
|
||||
|
||||
private URLClassLoader docClassLoader;
|
||||
|
||||
/**
|
||||
* 获取文档jar类加载器
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
private URLClassLoader getDocClassLoader() throws Exception {
|
||||
if (docClassLoader != null) {
|
||||
return docClassLoader;
|
||||
}
|
||||
if (!FileUtil.isFile(zyplayerDocDubboLibPath + "/" + DubboDocConst.DUBBO_DOC_LIB_NAME)) {
|
||||
throw new ConfirmException("请先上传文档JAR");
|
||||
}
|
||||
synchronized (ClassLoadService.class) {
|
||||
// file:D:/maven/repository/com/zyplayer/dubbo-api/1.0/dubbo-api-1.0.jar
|
||||
URL fileUrl = new URL("file:/" + zyplayerDocDubboLibPath + "/" + DubboDocConst.DUBBO_DOC_LIB_NAME);
|
||||
docClassLoader = new URLClassLoader(new URL[]{fileUrl}, Thread.currentThread().getContextClassLoader());
|
||||
}
|
||||
return docClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭类加载器,callback中可对文件进行覆盖上传
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
public void closeClassLoad(ClassLoaderCallback callback) throws Exception {
|
||||
synchronized (ClassLoadService.class) {
|
||||
try {
|
||||
if (docClassLoader != null) {
|
||||
docClassLoader.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("关闭类加载器失败", e);
|
||||
}
|
||||
docClassLoader = null;
|
||||
if (callback != null) {
|
||||
// callback方式,防止刚close,马上又被别人new出来了
|
||||
callback.callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载类
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
public Class<?> loadClass(String serverName) throws Exception {
|
||||
try {
|
||||
return this.getDocClassLoader().loadClass(serverName);
|
||||
} catch (Exception e) {
|
||||
// 失败之后先关闭再去加载一次
|
||||
this.closeClassLoad(null);
|
||||
return this.getDocClassLoader().loadClass(serverName);
|
||||
}
|
||||
}
|
||||
|
||||
// public static void main(String[] args) throws Exception {
|
||||
// String serviceName = "com.zyplayer.dubbo.service.AnnotateService";
|
||||
// String jarGroup = "com.zyplayer";
|
||||
// String jarArtifact = "dubbo-api";
|
||||
// String jarVersion = "1.0";
|
||||
// String basePath = "file:D:/maven/repository";
|
||||
//// String basePath = "http://nexus.dmall.com:8081/nexus/content/groups/public";
|
||||
//// String basePath = "http://nexus.zyplayer.com:8081/nexus/content/groups/public";
|
||||
// new ClassLoadService().loadServerMethod(serviceName, basePath, jarGroup, jarArtifact, jarVersion);
|
||||
// }
|
||||
|
||||
// public static void main(String[] args) throws Exception {
|
||||
// String serviceName = "com.zyplayer.data.service.dubbo.DataIndicatorsService";
|
||||
// String jarGroup = "com.zyplayer.data";
|
||||
// String jarArtifact = "data-api-client";
|
||||
// String jarVersion = "1.0.9.SNAPSHOTS";
|
||||
// String basePath = "http://nexus.zyplayer.com:8081/nexus/content/groups/public";
|
||||
// new ClassLoadService().loadServerMethod(serviceName, basePath, jarGroup, jarArtifact, jarVersion);
|
||||
// }
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String serviceName = "com.dmall.data.service.dubbo.DataIndicatorsService";
|
||||
String jarGroup = "com.dmall.data";
|
||||
String jarArtifact = "data-api-client";
|
||||
String jarVersion = "1.0.9.SNAPSHOTS";
|
||||
String basePath = "http://nexus.dmall.com:8081/nexus/content/groups/public";
|
||||
new ClassLoadService().loadServerMethod(serviceName, basePath, jarGroup, jarArtifact, jarVersion);
|
||||
}
|
||||
|
||||
public void loadServerMethod(String serverName, String basePath, String jarGroup, String jarArtifact, String jarVersion) throws Exception {
|
||||
public void loadServerMethod(String serverName) throws Exception {
|
||||
// jar:file:D:/maven/repository/com/zyplayer/dubbo-api/1.0/dubbo-api-1.0.jar!/
|
||||
String jarPath = jarGroup.replaceAll("\\.", "/") + "/" + jarArtifact + "/" + jarVersion + "/" + jarArtifact + "-" + jarVersion + ".jar";
|
||||
URL jarUrl = new URL("jar:" + basePath + "/" + jarPath + "!/");
|
||||
String docJarFileUrl = "file:/" + zyplayerDocDubboLibPath + "/" + DubboDocConst.DUBBO_DOC_LIB_NAME;
|
||||
URL jarUrl = new URL("jar:" + docJarFileUrl + "!/");
|
||||
JarFile jar = ((JarURLConnection) jarUrl.openConnection()).getJarFile();
|
||||
JarEntry jarEntry = jar.getJarEntry(serverName.replaceAll("\\.", "/") + ".class");
|
||||
if (jarEntry == null) {
|
||||
logger.info("未找到类");
|
||||
return;
|
||||
}
|
||||
URL fileUrl = new URL(basePath + "/" + jarPath);
|
||||
URL fileUrl = new URL(docJarFileUrl);
|
||||
URLClassLoader classLoader = new URLClassLoader(new URL[]{fileUrl}, Thread.currentThread().getContextClassLoader());
|
||||
Class<?> clazz = classLoader.loadClass(serverName);
|
||||
Method[] methods = clazz.getMethods();
|
||||
@@ -220,8 +297,8 @@ public class ClassLoadService {
|
||||
List<DubboResponseInfo> paramList = new LinkedList<>();
|
||||
Field[] fieldArr = clazz.getDeclaredFields();
|
||||
for (Field field : fieldArr) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
paramList.add(this.getInfoByField(classLoader, field, recursion));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.zyplayer.doc.dubbo.framework.service;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2018年8月19日
|
||||
*/
|
||||
public interface ClassLoaderCallback {
|
||||
|
||||
/**
|
||||
* 回调
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年10月08日
|
||||
*/
|
||||
void callback() throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.zyplayer.doc.dubbo.framework.service;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.zyplayer.doc.dubbo.controller.vo.NacosServiceInfoVo;
|
||||
import com.zyplayer.doc.dubbo.controller.vo.NacosServiceListVo;
|
||||
import com.zyplayer.doc.dubbo.framework.bean.DubboInfo;
|
||||
import com.zyplayer.doc.dubbo.framework.bean.NacosDubboInfo;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* nacos方式加载文档服务
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
@Service
|
||||
public class NacosDocService {
|
||||
|
||||
@Value("${zyplayer.doc.dubbo.nacos.url:}")
|
||||
private String nacosUrl;
|
||||
// @Value("${zyplayer.doc.dubbo.nacos.service:}")
|
||||
// private String nacosService;
|
||||
|
||||
/**
|
||||
* 是否开启nacos文档
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
public boolean isEnable() {
|
||||
return StringUtils.isNotBlank(nacosUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过nacos方式获取所有服务
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年2月10日
|
||||
**/
|
||||
public List<DubboInfo> getDubboInfoByNacos() {
|
||||
List<DubboInfo> providerList = new LinkedList<>();
|
||||
// 获取所有的服务列表
|
||||
String serviceListStr = HttpUtil.get(nacosUrl + "/v1/ns/catalog/services?withInstances=false&pageNo=1&pageSize=100000");
|
||||
NacosServiceInfoVo nacosServiceInfoVo = JSON.parseObject(serviceListStr, NacosServiceInfoVo.class);
|
||||
if (nacosServiceInfoVo == null || nacosServiceInfoVo.getServiceList().isEmpty()) {
|
||||
return providerList;
|
||||
}
|
||||
for (NacosServiceListVo service : nacosServiceInfoVo.getServiceList()) {
|
||||
String serviceName = service.getName();
|
||||
String resultStr = HttpUtil.get(nacosUrl + "/v1/ns/instance/list?serviceName=" + serviceName);
|
||||
NacosDubboInfo dubboInstance = JSON.parseObject(resultStr, NacosDubboInfo.class);
|
||||
List<NacosDubboInfo.HostsBean> hosts = dubboInstance.getHosts();
|
||||
DubboInfo dubboInfo = new DubboInfo();
|
||||
List<DubboInfo.DubboNodeInfo> nodeList = new LinkedList<>();
|
||||
for (NacosDubboInfo.HostsBean host : hosts) {
|
||||
DubboInfo.DubboNodeInfo dubboNodeInfo = new DubboInfo.DubboNodeInfo();
|
||||
dubboNodeInfo.setIp(host.getIp());
|
||||
dubboNodeInfo.setPort(host.getPort());
|
||||
dubboNodeInfo.setInterfaceX(host.getMetadata().getInterfaceX());
|
||||
dubboNodeInfo.setMethods(host.getMetadata().getMethods().split(","));
|
||||
dubboNodeInfo.setApplication(host.getMetadata().getApplication());
|
||||
nodeList.add(dubboNodeInfo);
|
||||
}
|
||||
if (serviceName.contains(":")) {
|
||||
serviceName = serviceName.substring(serviceName.indexOf(":") + 1);
|
||||
}
|
||||
dubboInfo.setInterfaceX(serviceName);
|
||||
dubboInfo.setNodeList(nodeList);
|
||||
providerList.add(dubboInfo);
|
||||
}
|
||||
return providerList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package com.zyplayer.doc.dubbo.framework.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.zyplayer.doc.dubbo.controller.param.DubboRequestParam;
|
||||
import com.zyplayer.doc.dubbo.framework.bean.DubboDocInfo;
|
||||
import com.zyplayer.doc.dubbo.framework.bean.DubboInfo;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.apache.curator.RetryPolicy;
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.CuratorFrameworkFactory;
|
||||
import org.apache.curator.retry.ExponentialBackoffRetry;
|
||||
import org.apache.dubbo.common.Constants;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.utils.UrlUtils;
|
||||
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
|
||||
import org.apache.dubbo.metadata.definition.model.MethodDefinition;
|
||||
import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* zookeeper方式加载文档服务
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
@Service
|
||||
public class ZookeeperDocService {
|
||||
|
||||
@Value("${zyplayer.doc.dubbo.zookeeper.url:}")
|
||||
private String serviceZookeeperUrl;
|
||||
@Value("${zyplayer.doc.dubbo.zookeeper.metadata-url:}")
|
||||
private String metadataZookeeperUrl;
|
||||
|
||||
@Resource
|
||||
ClassLoadService classLoadService;
|
||||
|
||||
private CuratorFramework serverClient;
|
||||
private CuratorFramework metadataClient;
|
||||
|
||||
private final static String DEFAULT_ROOT = "dubbo";
|
||||
private final static String METADATA_NODE_NAME = "service.data";
|
||||
private String root;
|
||||
|
||||
/**
|
||||
* zookeeper初始化
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
// 初始化zk注册中心连接
|
||||
if (StringUtils.isNotBlank(serviceZookeeperUrl)) {
|
||||
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
|
||||
serverClient = CuratorFrameworkFactory.newClient(serviceZookeeperUrl, retryPolicy);
|
||||
serverClient.start();
|
||||
}
|
||||
// 初始化zk注册中心元数据信息
|
||||
if (StringUtils.isNotBlank(metadataZookeeperUrl)) {
|
||||
URL url = UrlUtils.parseURL(metadataZookeeperUrl, Collections.emptyMap());
|
||||
String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
|
||||
if (!group.startsWith(Constants.PATH_SEPARATOR)) {
|
||||
group = Constants.PATH_SEPARATOR + group;
|
||||
}
|
||||
this.root = group;
|
||||
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
|
||||
metadataClient = CuratorFrameworkFactory.newClient(metadataZookeeperUrl, retryPolicy);
|
||||
metadataClient.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否启用了zk文档
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
public boolean isEnable() {
|
||||
return StringUtils.isNotBlank(serviceZookeeperUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过Zookeeper方式获取所有服务
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年2月10日
|
||||
**/
|
||||
public List<DubboInfo> getDubboInfoByZookeeper() throws Exception {
|
||||
if (serverClient == null) {
|
||||
return null;
|
||||
}
|
||||
List<String> dubboList = serverClient.getChildren().forPath("/dubbo");
|
||||
if (dubboList == null || dubboList.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<DubboInfo> providerList = new LinkedList<>();
|
||||
for (String dubboStr : dubboList) {
|
||||
String path = "/dubbo/" + dubboStr + "/providers";
|
||||
if (serverClient.checkExists().forPath(path) == null) {
|
||||
continue;
|
||||
}
|
||||
List<String> providers = serverClient.getChildren().forPath(path);
|
||||
List<DubboInfo.DubboNodeInfo> nodeList = providers.stream().map(val -> {
|
||||
String tempStr = val;
|
||||
try {
|
||||
tempStr = URLDecoder.decode(val, "utf-8");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// IP和端口
|
||||
String ipPort = tempStr.substring(tempStr.indexOf("://") + 3);
|
||||
ipPort = ipPort.substring(0, ipPort.indexOf("/"));
|
||||
String[] ipPortArr = ipPort.split(":");
|
||||
// 参数
|
||||
Map<String, String> paramMap = new HashMap<>();
|
||||
String params = tempStr.substring(tempStr.indexOf("?") + 1);
|
||||
String[] paramsArr = params.split("&");
|
||||
for (String param : paramsArr) {
|
||||
String[] split = param.split("=");
|
||||
paramMap.put(split[0], split[1]);
|
||||
}
|
||||
DubboInfo.DubboNodeInfo dubboNodeInfo = new DubboInfo.DubboNodeInfo();
|
||||
dubboNodeInfo.setIp(ipPortArr[0]);
|
||||
dubboNodeInfo.setPort(NumberUtils.toInt(ipPortArr[1]));
|
||||
dubboNodeInfo.setInterfaceX(paramMap.get("interface"));
|
||||
dubboNodeInfo.setMethods(paramMap.get("methods").split(","));
|
||||
dubboNodeInfo.setApplication(paramMap.get("application"));
|
||||
dubboNodeInfo.setVersion(paramMap.get("version"));
|
||||
dubboNodeInfo.setGroup(paramMap.get("group"));
|
||||
return dubboNodeInfo;
|
||||
}).collect(Collectors.toList());
|
||||
DubboInfo dubboInfo = new DubboInfo();
|
||||
dubboInfo.setInterfaceX(dubboStr);
|
||||
dubboInfo.setNodeList(nodeList);
|
||||
providerList.add(dubboInfo);
|
||||
}
|
||||
return providerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过zk中的meta信息获取文档
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
public DubboDocInfo getDefinitionByMetadata(DubboRequestParam param) {
|
||||
if (metadataClient == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String path = getNodePath(param.getService(), null, null, param.getApplication());
|
||||
if (metadataClient.checkExists().forPath(path) == null) {
|
||||
return null;
|
||||
}
|
||||
String resultType = null;
|
||||
String metadata = new String(metadataClient.getData().forPath(path));
|
||||
FullServiceDefinition definition = JSON.parseObject(metadata, FullServiceDefinition.class);
|
||||
List<DubboDocInfo.DubboDocParam> paramList = new LinkedList<>();
|
||||
for (MethodDefinition method : definition.getMethods()) {
|
||||
if (Objects.equals(method.getName(), param.getMethod())) {
|
||||
String[] parameterTypes = method.getParameterTypes();
|
||||
resultType = method.getReturnType();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
DubboDocInfo.DubboDocParam docParam = new DubboDocInfo.DubboDocParam();
|
||||
docParam.setParamType(parameterTypes[i]);
|
||||
docParam.setParamName("arg" + i);
|
||||
paramList.add(docParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
DubboDocInfo dubboDocInfo = new DubboDocInfo();
|
||||
dubboDocInfo.setParams(paramList);
|
||||
dubboDocInfo.setResultType(resultType);
|
||||
return dubboDocInfo;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过jar方式获取文档
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2020年11月08日
|
||||
*/
|
||||
public DubboDocInfo getDefinitionByJar(DubboRequestParam param) {
|
||||
String resultType = null;
|
||||
List<DubboDocInfo.DubboDocParam> paramList = new LinkedList<>();
|
||||
try {
|
||||
Class clazz = classLoadService.loadClass(param.getService());
|
||||
Method[] methods = clazz.getMethods();
|
||||
for (Method method : methods) {
|
||||
String methodName = method.getName();
|
||||
if (methodName.equals(param.getMethod())) {
|
||||
resultType = method.getGenericReturnType().getTypeName();
|
||||
Type[] parameterTypes = method.getGenericParameterTypes();
|
||||
Parameter[] parameters = method.getParameters();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
DubboDocInfo.DubboDocParam docParam = new DubboDocInfo.DubboDocParam();
|
||||
docParam.setParamName(parameters[i].getName());
|
||||
docParam.setParamType(parameterTypes[i].getTypeName());
|
||||
paramList.add(docParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
DubboDocInfo dubboDocInfo = new DubboDocInfo();
|
||||
dubboDocInfo.setParams(paramList);
|
||||
dubboDocInfo.setResultType(resultType);
|
||||
return dubboDocInfo;
|
||||
}
|
||||
|
||||
private String toRootDir() {
|
||||
if (Objects.isNull(root)) {
|
||||
return Constants.PATH_SEPARATOR;
|
||||
}
|
||||
if (Objects.equals(Constants.PATH_SEPARATOR, root)) {
|
||||
return root;
|
||||
}
|
||||
return root + Constants.PATH_SEPARATOR;
|
||||
}
|
||||
|
||||
private String getNodePath(String serviceInterface, String version, String group, String application) {
|
||||
MetadataIdentifier metadataIdentifier = new MetadataIdentifier(serviceInterface, version, group, Constants.PROVIDER_SIDE, application);
|
||||
return toRootDir() + metadataIdentifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.PATH) + Constants.PATH_SEPARATOR + METADATA_NODE_NAME;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.header-right-user-name{color:#fff;padding-right:5px}.el-menu-vertical{border-right:0}.el-menu-vertical,.el-menu-vertical .el-menu{background:#fafafa}.el-header{background-color:#409eff;color:#333;line-height:40px;text-align:right;height:40px!important}body,html{margin:0;padding:0}#app,.el-container,.el-menu,body,html{height:100%}.el-menu{-webkit-box-sizing:border-box;box-sizing:border-box;border-right:0}.el-menu,.el-tree{margin-right:3px}.el-tree-node__content{padding-right:20px}.el-header{background-color:#1d4e89!important}.el-button-group>.el-button:first-child{padding:0!important;border:0}.login-container{border-radius:5px;-moz-border-radius:5px;background-clip:padding-box;margin:0 auto;width:350px;padding:35px 35px 15px 35px;background:#fff;border:1px solid #eaeaea;-webkit-box-shadow:0 0 25px #cac6c6;box-shadow:0 0 25px #cac6c6}.title{margin:0 auto 40px auto;text-align:center;color:#505458}.remember{margin:0 0 35px 0}.my-info-vue .box-card{margin:10px}.dubbo-doc-view{padding:0 10px}.dubbo-doc-view .el-tabs--border-card>.el-tabs__content{height:calc(100vh - 180px);overflow-y:auto}.dubbo-doc-view .request-result pre{margin:0}
|
||||
File diff suppressed because one or more lines are too long
513
zyplayer-doc-dubbo/src/main/resources/doc-dubbo-old.html
Normal file
513
zyplayer-doc-dubbo/src/main/resources/doc-dubbo-old.html
Normal file
@@ -0,0 +1,513 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<!--无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢-->
|
||||
<meta name="author" content="开发者列表:暮光:城中城,项目地址:https://gitee.com/zyplayer/zyplayer-doc" />
|
||||
<title>dubbo文档管理系统</title>
|
||||
<link rel="shortcut icon" href="webjars/doc-dubbo/img/dubbo.ico"/>
|
||||
<link rel="stylesheet" href="webjars/doc-dubbo/css/element-ui.css">
|
||||
<link rel="stylesheet" href="webjars/doc-dubbo/css/doc-dubbo.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<el-container style="height: 100%;">
|
||||
<el-aside width="auto" style="height: 100%;">
|
||||
<div class="logo" @click="aboutDialogVisible = true">zyplayer-doc-dubbo</div>
|
||||
<div style="padding: 10px;">
|
||||
<div align="center">
|
||||
<el-dropdown split-button type="primary" @command="dropdownCommand">
|
||||
<el-upload class="upload-page-file" action="zyplayer-doc-dubbo/doc-dubbo/uploadDocJar"
|
||||
:on-success="uploadFileSuccess" :on-error="uploadFileError"
|
||||
name="file" :show-file-list="false" :limit="999">
|
||||
<el-button type="primary" icon="el-icon-upload">上传文档JAR</el-button>
|
||||
</el-upload>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="reload" icon="el-icon-refresh">重新加载服务列表</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<!--<el-row><el-switch v-model="isCollapse"></el-switch></el-row>-->
|
||||
<el-input v-model="searchKeywords" placeholder="搜索文档" style="margin: 10px 0;">
|
||||
<el-button slot="append" icon="el-icon-search" v-on:click="searchByKeywords"></el-button>
|
||||
</el-input>
|
||||
<!--<el-menu default-active="" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose" :collapse="isCollapse">-->
|
||||
<!--<el-submenu index="1">-->
|
||||
<!--<template slot="title">-->
|
||||
<!--<i class="el-icon-setting"></i>-->
|
||||
<!--<span slot="title">文档管理</span>-->
|
||||
<!--</template>-->
|
||||
<!--<el-menu-item index="1-1">管理服务列表</el-menu-item>-->
|
||||
<!--</el-submenu>-->
|
||||
<!--</el-menu>-->
|
||||
<el-tree :data="pathIndex" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
|
||||
</div>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-tabs type="border-card" style="width: 100%;">
|
||||
<el-tab-pane label="接口说明">
|
||||
<div v-if="!dubboInfo.interface">
|
||||
请先选择服务
|
||||
</div>
|
||||
<el-form v-else label-width="80px">
|
||||
<el-form-item label="服务:">
|
||||
{{dubboInfo.interface}}
|
||||
</el-form-item>
|
||||
<el-form-item label="方法:">
|
||||
{{dubboInfo.method}}
|
||||
</el-form-item>
|
||||
<el-form-item label="说明:">
|
||||
<div v-if="dubboInfoExplainShow">
|
||||
<pre>{{dubboInfo.docInfo.explain}}<el-button @click.prevent="dubboInfoExplainShow = false;" style="float: right;">编辑</el-button></pre>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-input type="textarea" :rows="4" placeholder="维护人员、使用说明、便于搜索的信息" v-model="docInfoExplainInput"></el-input>
|
||||
<el-button @click.prevent="dubboInfoExplainShow = true;" style="float: right;margin: 5px;">取消</el-button>
|
||||
<el-button type="primary" @click.prevent="saveDocInfoExplain" style="float: right;margin: 5px;">保存</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="节点:">
|
||||
<el-table :data="dubboInfo.nodeList" border style="width: 100%">
|
||||
<el-table-column prop="application" label="应用"></el-table-column>
|
||||
<el-table-column prop="ip" label="IP"></el-table-column>
|
||||
<el-table-column prop="port" label="端口"></el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
<el-form-item label="参数:">
|
||||
<!--<div slot="label">-->
|
||||
<!--<el-tooltip placement="top">-->
|
||||
<!--<div slot="content">1. 顺序必须和参数的顺序一致<br/>2. 参数名意义不大,可不填</div>-->
|
||||
<!--<i class="el-icon-info" style="color: #aaa;"></i>-->
|
||||
<!--</el-tooltip>-->
|
||||
<!--参数:-->
|
||||
<!--</div>-->
|
||||
<el-table :data="docParamList" border style="width: 100%; margin-bottom: 5px;">
|
||||
<el-table-column label="顺序" width="100">
|
||||
<template slot-scope="scope">{{scope.$index}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参数名" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.paramName"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" width="300">
|
||||
<template slot-scope="scope">{{scope.row.paramType}}</template>
|
||||
<!--<template slot-scope="scope">-->
|
||||
<!--<el-select v-model="scope.row.paramType" filterable allow-create clearable placeholder="请选择" style="width: 100%;">-->
|
||||
<!--<el-option v-for="item in paramTypeOptions" :key="item.value" :label="item.value" :value="item.value"></el-option>-->
|
||||
<!--</el-select>-->
|
||||
<!--</template>-->
|
||||
</el-table-column>
|
||||
<el-table-column label="说明">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.paramDesc"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-button @click.prevent="saveDocInfoParam" type="primary" style="float: right;margin: 5px;">保存</el-button>
|
||||
<!--<el-button @click.prevent="addDocParam" style="float: right;margin: 5px;">添加</el-button>-->
|
||||
</el-form-item>
|
||||
<el-form-item label="返回值:">
|
||||
{{dubboInfo.docInfo.resultType}}
|
||||
</el-form-item>
|
||||
<el-form-item label="结果:">
|
||||
<div v-if="dubboInfoResultShow">
|
||||
<pre>{{dubboInfo.docInfo.result}}<el-button @click.prevent="dubboInfoResultShow = false;" style="float: right;">编辑</el-button></pre>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-input type="textarea" :rows="4" placeholder="结果集说明等" v-model="docInfoResultInput"></el-input>
|
||||
<el-button @click.prevent="dubboInfoResultShow = true;" style="float: right;margin: 5px;">取消</el-button>
|
||||
<el-button type="primary" @click.prevent="saveDocInfoResult" style="float: right;margin: 5px;">保存</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="在线调试">
|
||||
<div v-if="!dubboInfo.interface">
|
||||
请先选择服务
|
||||
</div>
|
||||
<div v-loading="onlineDebugLoading" v-else>
|
||||
<el-input placeholder="请输入内容" v-model="dubboInfo.function" class="input-with-select">
|
||||
<el-select v-model="requestHostValue" slot="prepend" placeholder="请选择" style="width: 200px;">
|
||||
<el-option v-for="item in requestHostOptions" :key="item.value" :label="item.value" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
<el-button slot="append" @click.prevent="requestExecute">执行</el-button>
|
||||
</el-input>
|
||||
<el-form label-width="100px" label-position="top">
|
||||
<el-form-item label="请求参数:">
|
||||
<el-table :data="docParamRequestList" border style="width: 100%; margin: 10px 0;">
|
||||
<el-table-column label="顺序" width="100">
|
||||
<template slot-scope="scope">{{scope.$index}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参数名">
|
||||
<template slot-scope="scope">{{scope.row.paramName}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型">
|
||||
<template slot-scope="scope">{{scope.row.paramType}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参数值">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.paramValue"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="说明">
|
||||
<template slot-scope="scope">{{scope.row.paramDesc}}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求结果:">
|
||||
<div v-html="requestResult"></div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-container>
|
||||
</el-container>
|
||||
<el-dialog title="关于zyplayer-doc-dubbo" :visible.sync="aboutDialogVisible" width="600px">
|
||||
<el-form>
|
||||
<el-form-item label="项目地址:">
|
||||
<a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc">zyplayer-doc</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="开发人员:">
|
||||
<a target="_blank" href="http://zyplayer.com">暮光:城中城</a>
|
||||
</el-form-item>
|
||||
<template v-if="upgradeInfo.lastVersion">
|
||||
<el-form-item label="当前版本:">{{upgradeInfo.nowVersion}}</el-form-item>
|
||||
<el-form-item label="最新版本:">{{upgradeInfo.lastVersion}}</el-form-item>
|
||||
<el-form-item label="升级地址:">
|
||||
<a target="_blank" :href="upgradeInfo.upgradeUrl">{{upgradeInfo.upgradeUrl}}</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="升级内容:">{{upgradeInfo.upgradeContent}}</el-form-item>
|
||||
</template>
|
||||
<el-form-item label="">
|
||||
欢迎加群讨论,QQ群号:466363173,欢迎提交需求,欢迎使用和加入开发!
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/vue/vue.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/element-ui.js"></script>
|
||||
<!-- ajax 用到了jquery -->
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/jquery-3.1.0.min.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/common.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/toast.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/formatjson.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/doc-dubbo-tree.js"></script>
|
||||
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
isCollapse: false,
|
||||
aboutDialogVisible: false,
|
||||
onlineDebugLoading: false,
|
||||
pathIndex: [],
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
},
|
||||
// 展示的信息
|
||||
dubboInfo: {},
|
||||
dubboInfoExplainShow: true,
|
||||
docInfoExplainInput: "",
|
||||
dubboInfoResultShow: true,
|
||||
docInfoResultInput: "",
|
||||
// 请求的IP端口下拉选项
|
||||
requestHostOptions: [],
|
||||
requestHostValue: "",
|
||||
requestResult: "",
|
||||
// 依据目录树存储的map全局对象
|
||||
treePathDataMap: new Map(),
|
||||
// dubbo列表
|
||||
dubboDocList: [],
|
||||
dubboDocMap: [],
|
||||
// 搜索的输入内容
|
||||
searchKeywords: "",
|
||||
docParamList: [],
|
||||
docParamRequestList: [],
|
||||
// 参数类型选项
|
||||
paramTypeOptions: [{
|
||||
value: 'java.lang.String'
|
||||
}, {
|
||||
value: 'java.lang.Long'
|
||||
}, {
|
||||
value: 'java.lang.Integer'
|
||||
}],
|
||||
paramTypeValue: "java.lang.String",
|
||||
// 升级信息
|
||||
upgradeInfo: {},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
mounted: function () {
|
||||
// 无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢
|
||||
console.log("%c项目信息:\n开发者列表:暮光:城中城\n项目地址:https://gitee.com/zyplayer/zyplayer-doc", "color:red");
|
||||
this.doGetServiceList();
|
||||
this.checkSystemUpgrade();
|
||||
},
|
||||
methods: {
|
||||
handleOpen(key, keyPath) {
|
||||
console.log(key, keyPath);
|
||||
},
|
||||
handleClose(key, keyPath) {
|
||||
console.log(key, keyPath);
|
||||
},
|
||||
handleNodeClick(data) {
|
||||
if (data.children == null) {
|
||||
console.log(data);
|
||||
var path = data.interface;
|
||||
var application = data.application;
|
||||
var docInfo = app.dubboDocMap[path];
|
||||
if (!!docInfo) {
|
||||
this.createDocInfo(path, data.method);
|
||||
} else {
|
||||
var service = path.substring(0, path.lastIndexOf("."));
|
||||
var method = path.substring(path.lastIndexOf(".") + 1, path.length);
|
||||
var param = {service: service, method: method, application: application};
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/findDocInfo", "post", "json", param, function (json) {
|
||||
if (validateResult(json)) {
|
||||
if (!!json.data) {
|
||||
app.dubboDocMap[json.data.function] = json.data;
|
||||
}
|
||||
app.createDocInfo(path, method);
|
||||
}
|
||||
});
|
||||
}
|
||||
//console.log(app.dubboInfo);
|
||||
}
|
||||
},
|
||||
createDocInfo(path, method) {
|
||||
var docInfo = app.dubboDocMap[path];
|
||||
var dubboInfo = app.treePathDataMap.get(path);
|
||||
dubboInfo.method = method;
|
||||
dubboInfo.function = path;
|
||||
dubboInfo.docInfo = docInfo || {};
|
||||
// 清空再赋值才会重新渲染
|
||||
app.dubboInfo = {};
|
||||
app.dubboInfo = dubboInfo;
|
||||
app.docInfoExplainInput = dubboInfo.docInfo.explain;
|
||||
app.docParamList = [];
|
||||
app.docParamList = dubboInfo.docInfo.params || [];
|
||||
this.createDocParamRequestList();
|
||||
// 请求相关
|
||||
app.requestResult = "";
|
||||
app.requestHostValue = "";
|
||||
app.requestHostOptions = [];
|
||||
for (var i = 0; i < dubboInfo.nodeList.length; i++) {
|
||||
var item = dubboInfo.nodeList[i];
|
||||
let option = item.ip + ":" + item.port;
|
||||
if (!!item.version) option += " V" + item.version;
|
||||
if (!!item.group) option += " G" + item.group;
|
||||
app.requestHostOptions.push({value: option});
|
||||
}
|
||||
if (app.requestHostOptions.length > 0) {
|
||||
app.requestHostValue = app.requestHostOptions[0].value;
|
||||
}
|
||||
},
|
||||
uploadFileError(err) {
|
||||
app.$message({message: "上传失败," + err, type: 'error'});
|
||||
},
|
||||
uploadFileSuccess(response) {
|
||||
if (validateResult(response)) {
|
||||
app.$message({message: "上传成功!", type: 'success'});
|
||||
}
|
||||
},
|
||||
reloadService() {
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/reloadService", "post", "json", {}, function (json) {
|
||||
if (validateResult(json)) {
|
||||
app.$message({message: '加载成功!', type: 'success'});
|
||||
app.doGetServiceList();
|
||||
}
|
||||
});
|
||||
},
|
||||
dropdownCommand(command) {
|
||||
if(command == 'reload') {
|
||||
this.reloadService();
|
||||
}
|
||||
},
|
||||
searchByKeywords() {
|
||||
app.pathIndex = createTreeViewByTreeWithMerge(app.dubboDocList, app.searchKeywords);
|
||||
},
|
||||
doGetServiceList() {
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/getDocList", "post", "json", {}, function (json) {
|
||||
if (validateResult(json)) {
|
||||
app.dubboDocList = json.data.serverList || [];
|
||||
app.dubboDocMap = json.data.docMap || {};
|
||||
app.pathIndex = createTreeViewByTreeWithMerge(app.dubboDocList);
|
||||
}
|
||||
});
|
||||
},
|
||||
saveDocInfoExplain(){
|
||||
this.doSaveDocInfo(app.docInfoExplainInput, null, null, true);
|
||||
},
|
||||
saveDocInfoResult(){
|
||||
this.doSaveDocInfo(null, null, app.docInfoResultInput, true);
|
||||
},
|
||||
saveDocInfoParam() {
|
||||
var docParamList = [];
|
||||
for (var i = 0; i < app.docParamList.length; i++) {
|
||||
var item = app.docParamList[i];
|
||||
if (isNotEmpty(item.paramType)) {
|
||||
docParamList.push(item);
|
||||
}
|
||||
}
|
||||
var paramsJson = JSON.stringify(docParamList);
|
||||
this.doSaveDocInfo(null, paramsJson, null, true);
|
||||
},
|
||||
createDocParamRequestList() {
|
||||
var docParamList = [];
|
||||
for (var i = 0; i < app.docParamList.length; i++) {
|
||||
var item = app.docParamList[i];
|
||||
if (isNotEmpty(item.paramType) || isNotEmpty(item.paramDesc)) {
|
||||
docParamList.push(item);
|
||||
}
|
||||
}
|
||||
app.docParamRequestList = docParamList;
|
||||
},
|
||||
doSaveDocInfo(explain, params, result, showSuccess){
|
||||
var param = {
|
||||
service: app.dubboInfo.interface,
|
||||
method: app.dubboInfo.method,
|
||||
resultType: app.dubboInfo.resultType,
|
||||
paramValue: app.dubboInfo.paramValue,
|
||||
version: app.dubboInfo.docInfo.version || 0,
|
||||
explain: explain,
|
||||
result: result,
|
||||
paramsJson: params,
|
||||
};
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/saveDoc", "post", "json", param, function (json) {
|
||||
if (validateResult(json)) {
|
||||
app.dubboDocMap[json.data.function] = json.data;
|
||||
app.dubboInfo.docInfo = json.data;
|
||||
app.dubboInfoExplainShow = true;
|
||||
app.dubboInfoResultShow = true;
|
||||
app.docParamList = json.data.params || [];
|
||||
app.createDocParamRequestList();
|
||||
if (showSuccess) {
|
||||
Toast.success("保存成功!");
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
addDocParam() {
|
||||
var leadAdd = app.docParamList.length <= 0;
|
||||
if (!leadAdd) {
|
||||
var last = app.docParamList[app.docParamList.length - 1];
|
||||
if (isNotEmpty(last.paramType) || isNotEmpty(last.paramDesc)) {
|
||||
leadAdd = true;
|
||||
}
|
||||
}
|
||||
if (leadAdd) {
|
||||
app.docParamList.push({
|
||||
paramName: '',
|
||||
paramType: '',
|
||||
paramDesc: '',
|
||||
paramValue: '',
|
||||
});
|
||||
}
|
||||
},
|
||||
requestExecute() {
|
||||
var fuc = app.dubboInfo.function;
|
||||
var hostValue = app.requestHostValue;
|
||||
var service = fuc.substring(0, fuc.lastIndexOf("."));
|
||||
var method = fuc.substring(fuc.lastIndexOf(".") + 1, fuc.length);
|
||||
var paramArr = hostValue.split(" ");
|
||||
var ipPortArr = paramArr[0].split(":");
|
||||
var version = '', group = '';
|
||||
paramArr.forEach(item => {
|
||||
if (item.startsWith("V")) version = item.substring(1, item.length);
|
||||
if (item.startsWith("G")) group = item.substring(1, item.length);
|
||||
});
|
||||
var paramTypes = [];
|
||||
var params = [];
|
||||
for (var i = 0; i < app.docParamList.length; i++) {
|
||||
var item = app.docParamList[i];
|
||||
paramTypes.push(item.paramType);
|
||||
params.push(item.paramValue || '');
|
||||
}
|
||||
var param = {
|
||||
service: service,
|
||||
method: method,
|
||||
ip: ipPortArr[0],
|
||||
port: ipPortArr[1],
|
||||
version: version,
|
||||
group: group,
|
||||
paramTypes: JSON.stringify(paramTypes),
|
||||
params: JSON.stringify(params),
|
||||
};
|
||||
app.requestResult = "";
|
||||
app.onlineDebugLoading = true;
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/request", "post", "json", param, function (json) {
|
||||
app.onlineDebugLoading = false;
|
||||
if (json.errCode == 200) {
|
||||
try {
|
||||
app.requestResult = Formatjson.processObjectToHtmlPre(JSON.parse(json.data), 0, false, false, false, false);
|
||||
} catch (e) {
|
||||
try {
|
||||
app.requestResult = Formatjson.processObjectToHtmlPre(json.data, 0, false, false, false, false);
|
||||
} catch (e) {
|
||||
app.requestResult = json.data;
|
||||
}
|
||||
}
|
||||
var paramsJson = JSON.stringify(app.docParamRequestList);
|
||||
app.doSaveDocInfo(null, paramsJson, null, false);
|
||||
} else {
|
||||
app.requestResult = json.errMsg;
|
||||
}
|
||||
}, function (err) {
|
||||
app.onlineDebugLoading = false;
|
||||
app.requestResult = err.responseJSON.message;
|
||||
});
|
||||
},
|
||||
checkSystemUpgrade() {
|
||||
ajaxTemp("system/info/upgrade", "post", "json", {}, function (json) {
|
||||
if (json.errCode == 200 && !!json.data) {
|
||||
app.upgradeInfo = json.data;
|
||||
console.log("zyplayer-doc发现新版本:"
|
||||
+ "\n升级地址:" + json.data.upgradeUrl
|
||||
+ "\n当前版本:" + json.data.nowVersion
|
||||
+ "\n最新版本:" + json.data.lastVersion
|
||||
+ "\n升级内容:" + json.data.upgradeContent
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
html,body,#app {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
pre{margin: 0;}
|
||||
.el-menu {
|
||||
box-sizing: border-box;
|
||||
border-right: 0;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.el-tree{
|
||||
margin-right: 3px;
|
||||
}
|
||||
.el-tree-node__content{
|
||||
padding-right: 20px;
|
||||
}
|
||||
.el-tabs--border-card>.el-tabs__content{
|
||||
height: calc(100vh - 100px);overflow-y: auto;
|
||||
}
|
||||
.logo{
|
||||
background: linear-gradient(-90deg, #03DDE4 0%, #30AFED 51%, #8755FF 100%); cursor: pointer;
|
||||
width: 100%; height:60px;line-height:60px;font-size: 25px;color: #fff;text-align: center;
|
||||
}
|
||||
.el-button-group>.el-button:first-child{padding: 0!important;border: 0;}
|
||||
</style>
|
||||
</html>
|
||||
|
||||
@@ -1,482 +1 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<!--无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢-->
|
||||
<meta name="author" content="开发者列表:暮光:城中城,项目地址:https://gitee.com/zyplayer/zyplayer-doc" />
|
||||
<title>dubbo文档管理系统</title>
|
||||
<link rel="shortcut icon" href="webjars/doc-dubbo/img/dubbo.ico"/>
|
||||
<link rel="stylesheet" href="webjars/doc-dubbo/css/element-ui.css">
|
||||
<link rel="stylesheet" href="webjars/doc-dubbo/css/doc-dubbo.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<el-container style="height: 100%;">
|
||||
<el-aside width="auto" style="height: 100%;">
|
||||
<div class="logo" @click="aboutDialogVisible = true">zyplayer-doc-dubbo</div>
|
||||
<div style="padding: 10px;">
|
||||
<div align="center"><el-button type="primary" v-on:click="reloadService" icon="el-icon-refresh" style="width: 100%;">重新加载服务列表</el-button></div>
|
||||
<!--<el-row><el-switch v-model="isCollapse"></el-switch></el-row>-->
|
||||
<el-input v-model="searchKeywords" placeholder="搜索文档" style="margin: 10px 0;">
|
||||
<el-button slot="append" icon="el-icon-search" v-on:click="searchByKeywords"></el-button>
|
||||
</el-input>
|
||||
<!--<el-menu default-active="" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose" :collapse="isCollapse">-->
|
||||
<!--<el-submenu index="1">-->
|
||||
<!--<template slot="title">-->
|
||||
<!--<i class="el-icon-setting"></i>-->
|
||||
<!--<span slot="title">文档管理</span>-->
|
||||
<!--</template>-->
|
||||
<!--<el-menu-item index="1-1">管理服务列表</el-menu-item>-->
|
||||
<!--</el-submenu>-->
|
||||
<!--</el-menu>-->
|
||||
<el-tree :data="pathIndex" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
|
||||
</div>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-tabs type="border-card" style="width: 100%;">
|
||||
<el-tab-pane label="接口说明">
|
||||
<div v-if="!dubboInfo.interface">
|
||||
请先选择服务
|
||||
</div>
|
||||
<el-form v-else label-width="80px">
|
||||
<el-form-item label="服务:">
|
||||
{{dubboInfo.interface}}
|
||||
</el-form-item>
|
||||
<el-form-item label="方法:">
|
||||
{{dubboInfo.method}}
|
||||
</el-form-item>
|
||||
<el-form-item label="说明:">
|
||||
<div v-if="dubboInfoExplainShow">
|
||||
<pre>{{dubboInfo.docInfo.explain}}<el-button @click.prevent="dubboInfoExplainShow = false;" style="float: right;">编辑</el-button></pre>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-input type="textarea" :rows="4" placeholder="维护人员、使用说明、便于搜索的信息" v-model="docInfoExplainInput"></el-input>
|
||||
<el-button @click.prevent="dubboInfoExplainShow = true;" style="float: right;margin: 5px;">取消</el-button>
|
||||
<el-button type="primary" @click.prevent="saveDocInfoExplain" style="float: right;margin: 5px;">保存</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="节点:">
|
||||
<el-table :data="dubboInfo.nodeList" border style="width: 100%">
|
||||
<el-table-column prop="application" label="应用"></el-table-column>
|
||||
<el-table-column prop="ip" label="IP"></el-table-column>
|
||||
<el-table-column prop="port" label="端口"></el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
<el-form-item label="参数:">
|
||||
<!--<div slot="label">-->
|
||||
<!--<el-tooltip placement="top">-->
|
||||
<!--<div slot="content">1. 顺序必须和参数的顺序一致<br/>2. 参数名意义不大,可不填</div>-->
|
||||
<!--<i class="el-icon-info" style="color: #aaa;"></i>-->
|
||||
<!--</el-tooltip>-->
|
||||
<!--参数:-->
|
||||
<!--</div>-->
|
||||
<el-table :data="docParamList" border style="width: 100%; margin-bottom: 5px;">
|
||||
<el-table-column label="顺序" width="100">
|
||||
<template slot-scope="scope">{{scope.$index}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参数名" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.paramName"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" width="300">
|
||||
<template slot-scope="scope">{{scope.row.paramType}}</template>
|
||||
<!--<template slot-scope="scope">-->
|
||||
<!--<el-select v-model="scope.row.paramType" filterable allow-create clearable placeholder="请选择" style="width: 100%;">-->
|
||||
<!--<el-option v-for="item in paramTypeOptions" :key="item.value" :label="item.value" :value="item.value"></el-option>-->
|
||||
<!--</el-select>-->
|
||||
<!--</template>-->
|
||||
</el-table-column>
|
||||
<el-table-column label="说明">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.paramDesc"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-button @click.prevent="saveDocInfoParam" type="primary" style="float: right;margin: 5px;">保存</el-button>
|
||||
<!--<el-button @click.prevent="addDocParam" style="float: right;margin: 5px;">添加</el-button>-->
|
||||
</el-form-item>
|
||||
<el-form-item label="返回值:">
|
||||
{{dubboInfo.docInfo.resultType}}
|
||||
</el-form-item>
|
||||
<el-form-item label="结果:">
|
||||
<div v-if="dubboInfoResultShow">
|
||||
<pre>{{dubboInfo.docInfo.result}}<el-button @click.prevent="dubboInfoResultShow = false;" style="float: right;">编辑</el-button></pre>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-input type="textarea" :rows="4" placeholder="结果集说明等" v-model="docInfoResultInput"></el-input>
|
||||
<el-button @click.prevent="dubboInfoResultShow = true;" style="float: right;margin: 5px;">取消</el-button>
|
||||
<el-button type="primary" @click.prevent="saveDocInfoResult" style="float: right;margin: 5px;">保存</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="在线调试">
|
||||
<div v-if="!dubboInfo.interface">
|
||||
请先选择服务
|
||||
</div>
|
||||
<div v-loading="onlineDebugLoading" v-else>
|
||||
<el-input placeholder="请输入内容" v-model="dubboInfo.function" class="input-with-select">
|
||||
<el-select v-model="requestHostValue" slot="prepend" placeholder="请选择" style="width: 200px;">
|
||||
<el-option v-for="item in requestHostOptions" :key="item.value" :label="item.value" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
<el-button slot="append" @click.prevent="requestExecute">执行</el-button>
|
||||
</el-input>
|
||||
<el-form label-width="100px" label-position="top">
|
||||
<el-form-item label="请求参数:">
|
||||
<el-table :data="docParamRequestList" border style="width: 100%; margin: 10px 0;">
|
||||
<el-table-column label="顺序" width="100">
|
||||
<template slot-scope="scope">{{scope.$index}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参数名">
|
||||
<template slot-scope="scope">{{scope.row.paramName}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型">
|
||||
<template slot-scope="scope">{{scope.row.paramType}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参数值">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.paramValue"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="说明">
|
||||
<template slot-scope="scope">{{scope.row.paramDesc}}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求结果:">
|
||||
<div v-html="requestResult"></div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-container>
|
||||
</el-container>
|
||||
<el-dialog title="关于zyplayer-doc-dubbo" :visible.sync="aboutDialogVisible" width="600px">
|
||||
<el-form>
|
||||
<el-form-item label="项目地址:">
|
||||
<a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc">zyplayer-doc</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="开发人员:">
|
||||
<a target="_blank" href="http://zyplayer.com">暮光:城中城</a>
|
||||
</el-form-item>
|
||||
<template v-if="upgradeInfo.lastVersion">
|
||||
<el-form-item label="当前版本:">{{upgradeInfo.nowVersion}}</el-form-item>
|
||||
<el-form-item label="最新版本:">{{upgradeInfo.lastVersion}}</el-form-item>
|
||||
<el-form-item label="升级地址:">
|
||||
<a target="_blank" :href="upgradeInfo.upgradeUrl">{{upgradeInfo.upgradeUrl}}</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="升级内容:">{{upgradeInfo.upgradeContent}}</el-form-item>
|
||||
</template>
|
||||
<el-form-item label="">
|
||||
欢迎加群讨论,QQ群号:466363173,欢迎提交需求,欢迎使用和加入开发!
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/vue/vue.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/element-ui.js"></script>
|
||||
<!-- ajax 用到了jquery -->
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/jquery-3.1.0.min.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/common.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/toast.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/formatjson.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-dubbo/js/doc-dubbo-tree.js"></script>
|
||||
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
isCollapse: false,
|
||||
aboutDialogVisible: false,
|
||||
onlineDebugLoading: false,
|
||||
pathIndex: [],
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
},
|
||||
// 展示的信息
|
||||
dubboInfo: {},
|
||||
dubboInfoExplainShow: true,
|
||||
docInfoExplainInput: "",
|
||||
dubboInfoResultShow: true,
|
||||
docInfoResultInput: "",
|
||||
// 请求的IP端口下拉选项
|
||||
requestHostOptions: [],
|
||||
requestHostValue: "",
|
||||
requestResult: "",
|
||||
// 依据目录树存储的map全局对象
|
||||
treePathDataMap: new Map(),
|
||||
// dubbo列表
|
||||
dubboDocList: [],
|
||||
dubboDocMap: [],
|
||||
// 搜索的输入内容
|
||||
searchKeywords: "",
|
||||
docParamList: [],
|
||||
docParamRequestList: [],
|
||||
// 参数类型选项
|
||||
paramTypeOptions: [{
|
||||
value: 'java.lang.String'
|
||||
}, {
|
||||
value: 'java.lang.Long'
|
||||
}, {
|
||||
value: 'java.lang.Integer'
|
||||
}],
|
||||
paramTypeValue: "java.lang.String",
|
||||
// 升级信息
|
||||
upgradeInfo: {},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
mounted: function () {
|
||||
// 无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢
|
||||
console.log("%c项目信息:\n开发者列表:暮光:城中城\n项目地址:https://gitee.com/zyplayer/zyplayer-doc", "color:red");
|
||||
this.doGetServiceList();
|
||||
this.checkSystemUpgrade();
|
||||
},
|
||||
methods: {
|
||||
handleOpen(key, keyPath) {
|
||||
console.log(key, keyPath);
|
||||
},
|
||||
handleClose(key, keyPath) {
|
||||
console.log(key, keyPath);
|
||||
},
|
||||
handleNodeClick(data) {
|
||||
if (data.children == null) {
|
||||
console.log(data);
|
||||
var path = data.interface;
|
||||
var application = data.application;
|
||||
var docInfo = app.dubboDocMap[path];
|
||||
if (!!docInfo) {
|
||||
this.createDocInfo(path, data.method);
|
||||
} else {
|
||||
var service = path.substring(0, path.lastIndexOf("."));
|
||||
var method = path.substring(path.lastIndexOf(".") + 1, path.length);
|
||||
var param = {service: service, method: method, application: application};
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/findDocInfo", "post", "json", param, function (json) {
|
||||
if (validateResult(json)) {
|
||||
if (!!json.data) {
|
||||
app.dubboDocMap[json.data.function] = json.data;
|
||||
}
|
||||
app.createDocInfo(path, method);
|
||||
}
|
||||
});
|
||||
}
|
||||
//console.log(app.dubboInfo);
|
||||
}
|
||||
},
|
||||
createDocInfo(path, method) {
|
||||
var docInfo = app.dubboDocMap[path];
|
||||
var dubboInfo = app.treePathDataMap.get(path);
|
||||
dubboInfo.method = method;
|
||||
dubboInfo.function = path;
|
||||
dubboInfo.docInfo = docInfo || {};
|
||||
// 清空再赋值才会重新渲染
|
||||
app.dubboInfo = {};
|
||||
app.dubboInfo = dubboInfo;
|
||||
app.docInfoExplainInput = dubboInfo.docInfo.explain;
|
||||
app.docParamList = [];
|
||||
app.docParamList = dubboInfo.docInfo.params || [];
|
||||
this.createDocParamRequestList();
|
||||
// 请求相关
|
||||
app.requestResult = "";
|
||||
app.requestHostValue = "";
|
||||
app.requestHostOptions = [];
|
||||
for (var i = 0; i < dubboInfo.nodeList.length; i++) {
|
||||
var item = dubboInfo.nodeList[i];
|
||||
app.requestHostOptions.push({
|
||||
value: item.ip + ":" + item.port
|
||||
});
|
||||
}
|
||||
if (app.requestHostOptions.length > 0) {
|
||||
app.requestHostValue = app.requestHostOptions[0].value;
|
||||
}
|
||||
},
|
||||
reloadService(){
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/reloadService", "post", "json", {}, function (json) {
|
||||
if (validateResult(json)) {
|
||||
app.$message({
|
||||
message: '加载成功!',
|
||||
type: 'success'
|
||||
});
|
||||
app.doGetServiceList();
|
||||
}
|
||||
});
|
||||
},
|
||||
searchByKeywords() {
|
||||
app.pathIndex = createTreeViewByTreeWithMerge(app.dubboDocList, app.searchKeywords);
|
||||
},
|
||||
doGetServiceList() {
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/getDocList", "post", "json", {}, function (json) {
|
||||
if (validateResult(json)) {
|
||||
app.dubboDocList = json.data.serverList || [];
|
||||
app.dubboDocMap = json.data.docMap || {};
|
||||
app.pathIndex = createTreeViewByTreeWithMerge(app.dubboDocList);
|
||||
}
|
||||
});
|
||||
},
|
||||
saveDocInfoExplain(){
|
||||
this.doSaveDocInfo(app.docInfoExplainInput, null, null, true);
|
||||
},
|
||||
saveDocInfoResult(){
|
||||
this.doSaveDocInfo(null, null, app.docInfoResultInput, true);
|
||||
},
|
||||
saveDocInfoParam() {
|
||||
var docParamList = [];
|
||||
for (var i = 0; i < app.docParamList.length; i++) {
|
||||
var item = app.docParamList[i];
|
||||
if (isNotEmpty(item.paramType)) {
|
||||
docParamList.push(item);
|
||||
}
|
||||
}
|
||||
var paramsJson = JSON.stringify(docParamList);
|
||||
this.doSaveDocInfo(null, paramsJson, null, true);
|
||||
},
|
||||
createDocParamRequestList() {
|
||||
var docParamList = [];
|
||||
for (var i = 0; i < app.docParamList.length; i++) {
|
||||
var item = app.docParamList[i];
|
||||
if (isNotEmpty(item.paramType) || isNotEmpty(item.paramDesc)) {
|
||||
docParamList.push(item);
|
||||
}
|
||||
}
|
||||
app.docParamRequestList = docParamList;
|
||||
},
|
||||
doSaveDocInfo(explain, params, result, showSuccess){
|
||||
var param = {
|
||||
service: app.dubboInfo.interface,
|
||||
method: app.dubboInfo.method,
|
||||
resultType: app.dubboInfo.resultType,
|
||||
paramValue: app.dubboInfo.paramValue,
|
||||
version: app.dubboInfo.docInfo.version || 0,
|
||||
explain: explain,
|
||||
result: result,
|
||||
paramsJson: params,
|
||||
};
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/saveDoc", "post", "json", param, function (json) {
|
||||
if (validateResult(json)) {
|
||||
app.dubboDocMap[json.data.function] = json.data;
|
||||
app.dubboInfo.docInfo = json.data;
|
||||
app.dubboInfoExplainShow = true;
|
||||
app.dubboInfoResultShow = true;
|
||||
app.docParamList = json.data.params || [];
|
||||
app.createDocParamRequestList();
|
||||
if (showSuccess) {
|
||||
Toast.success("保存成功!");
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
addDocParam() {
|
||||
var leadAdd = app.docParamList.length <= 0;
|
||||
if (!leadAdd) {
|
||||
var last = app.docParamList[app.docParamList.length - 1];
|
||||
if (isNotEmpty(last.paramType) || isNotEmpty(last.paramDesc)) {
|
||||
leadAdd = true;
|
||||
}
|
||||
}
|
||||
if (leadAdd) {
|
||||
app.docParamList.push({
|
||||
paramName: '',
|
||||
paramType: '',
|
||||
paramDesc: '',
|
||||
paramValue: '',
|
||||
});
|
||||
}
|
||||
},
|
||||
requestExecute() {
|
||||
var fuc = app.dubboInfo.function;
|
||||
var hostValue = app.requestHostValue;
|
||||
var service = fuc.substring(0, fuc.lastIndexOf("."));
|
||||
var method = fuc.substring(fuc.lastIndexOf(".") + 1, fuc.length);
|
||||
var ip = hostValue.substring(0, hostValue.lastIndexOf(":"));
|
||||
var port = hostValue.substring(hostValue.lastIndexOf(":") + 1, hostValue.length);
|
||||
var paramTypes = [];
|
||||
var params = [];
|
||||
for (var i = 0; i < app.docParamList.length; i++) {
|
||||
var item = app.docParamList[i];
|
||||
if (isNotEmpty(item.paramType) && isNotEmpty(item.paramValue)) {
|
||||
paramTypes.push(item.paramType);
|
||||
params.push(item.paramValue);
|
||||
}
|
||||
}
|
||||
var param = {
|
||||
service: service,
|
||||
method: method,
|
||||
ip: ip,
|
||||
port: port,
|
||||
paramTypes: JSON.stringify(paramTypes),
|
||||
params: JSON.stringify(params),
|
||||
};
|
||||
app.requestResult = "";
|
||||
app.onlineDebugLoading = true;
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/request", "post", "json", param, function (json) {
|
||||
app.onlineDebugLoading = false;
|
||||
if (json.errCode == 200) {
|
||||
try {
|
||||
app.requestResult = Formatjson.processObjectToHtmlPre(JSON.parse(json.data), 0, false, false, false, false);
|
||||
} catch (e) {
|
||||
try {
|
||||
app.requestResult = Formatjson.processObjectToHtmlPre(json.data, 0, false, false, false, false);
|
||||
} catch (e) {
|
||||
app.requestResult = json.data;
|
||||
}
|
||||
}
|
||||
var paramsJson = JSON.stringify(app.docParamRequestList);
|
||||
app.doSaveDocInfo(null, paramsJson, null, false);
|
||||
} else {
|
||||
app.requestResult = json.errMsg;
|
||||
}
|
||||
});
|
||||
},
|
||||
checkSystemUpgrade() {
|
||||
ajaxTemp("system/info/upgrade", "post", "json", {}, function (json) {
|
||||
if (json.errCode == 200 && !!json.data) {
|
||||
app.upgradeInfo = json.data;
|
||||
console.log("zyplayer-doc发现新版本:"
|
||||
+ "\n升级地址:" + json.data.upgradeUrl
|
||||
+ "\n当前版本:" + json.data.nowVersion
|
||||
+ "\n最新版本:" + json.data.lastVersion
|
||||
+ "\n升级内容:" + json.data.upgradeContent
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
html,body,#app {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
pre{margin: 0;}
|
||||
.el-menu {
|
||||
box-sizing: border-box;
|
||||
border-right: 0;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.el-tree{
|
||||
margin-right: 3px;
|
||||
}
|
||||
.el-tree-node__content{
|
||||
padding-right: 20px;
|
||||
}
|
||||
.el-tabs--border-card>.el-tabs__content{
|
||||
height: calc(100vh - 100px);overflow-y: auto;
|
||||
}
|
||||
.logo{
|
||||
background: linear-gradient(-90deg, #03DDE4 0%, #30AFED 51%, #8755FF 100%); cursor: pointer;
|
||||
width: 100%; height:60px;line-height:60px;font-size: 25px;color: #fff;text-align: center;
|
||||
}
|
||||
</style>
|
||||
</html>
|
||||
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon-dubbo.png><title>DUBBO文档管理</title><link href=css/app.b311b071.css rel=preload as=style><link href=css/chunk-vendors.7998ce0c.css rel=preload as=style><link href=js/app.393d2924.js rel=preload as=script><link href=js/chunk-vendors.3d65a5e1.js rel=preload as=script><link href=css/chunk-vendors.7998ce0c.css rel=stylesheet><link href=css/app.b311b071.css rel=stylesheet></head><body><noscript><strong>We're sorry but zyplayer-dubbo-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.3d65a5e1.js></script><script src=js/app.393d2924.js></script></body></html>
|
||||
BIN
zyplayer-doc-dubbo/src/main/resources/favicon-dubbo.png
Normal file
BIN
zyplayer-doc-dubbo/src/main/resources/favicon-dubbo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
Binary file not shown.
1
zyplayer-doc-dubbo/src/main/resources/js/app.393d2924.js
Normal file
1
zyplayer-doc-dubbo/src/main/resources/js/app.393d2924.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -62,6 +62,8 @@ zyplayer:
|
||||
white-domain: .+
|
||||
# ------dubbo相关配置------
|
||||
dubbo:
|
||||
# 存放dubbo文档jar上传后存放的目录
|
||||
doc-lib-path: D:/zyplayerDoc/dubbo
|
||||
# 优先使用zookeeper,未配置时找nacos的配置
|
||||
zookeeper:
|
||||
url: 127.0.0.1:2181
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<modules>
|
||||
<module>zyplayer-doc-test</module>
|
||||
<module>zyplayer-doc-annotation</module>
|
||||
<module>zyplayer-doc-dubbo-libs</module>
|
||||
</modules>
|
||||
|
||||
|
||||
</project>
|
||||
|
||||
108
zyplayer-doc-other/zyplayer-doc-dubbo-libs/pom.xml
Normal file
108
zyplayer-doc-other/zyplayer-doc-dubbo-libs/pom.xml
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.zyplayer</groupId>
|
||||
<artifactId>zyplayer-doc-dubbo-libs</artifactId>
|
||||
<version>1.0.6</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>zyplayer-doc-dubbo-libs</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!--所有业务包放这里,打包之后在文档页面上传此jar-->
|
||||
<!--
|
||||
尝试过很多方式:
|
||||
比如在dubbo文档项目内,这样每次依赖的jar升级都需要重新发版
|
||||
比如自动下载远程仓库或读取本地仓库的jar来获取类,这样如果jar包里依赖了另外的jar则不可行了,需要解析整个maven依赖树,复杂度高
|
||||
当前找到的最合适的方式就是一个模块依赖所有需要的jar,然后打包后传上去,这样所有的依赖都在此包里了,也不需要重新发版
|
||||
如果你有更好的建议欢迎提出来探讨,非常乐意接受更加方便的建议!
|
||||
-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.zyplayer</groupId>-->
|
||||
<!-- <artifactId>dubbo-api</artifactId>-->
|
||||
<!-- <version>1.1</version>-->
|
||||
<!-- </dependency>-->
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-resources</id>
|
||||
<!-- 在default生命周期的 validate阶段就执行resources插件的copy-resources目标 -->
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<!-- 指定resources插件处理资源文件到哪个目录下 -->
|
||||
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
|
||||
<!-- 也可以用这样的方式<outputDirectory>target/classes</outputDirectory> -->
|
||||
<!-- 待处理的资源定义 -->
|
||||
<resources>
|
||||
<resource>
|
||||
<!-- 指定resources插件处理哪个目录下的资源文件 -->
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/spring.handlers</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/spring.schemas</resource>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -2,8 +2,8 @@
|
||||
ENV = 'development'
|
||||
|
||||
# base api
|
||||
VUE_APP_BASE_API = 'http://local.zyplayer.com:8083/zyplayer-doc-manage'
|
||||
# VUE_APP_BASE_API = 'http://doc.zyplayer.com/zyplayer-doc-manage'
|
||||
# VUE_APP_BASE_API = 'http://local.zyplayer.com:8083/zyplayer-doc-manage'
|
||||
VUE_APP_BASE_API = 'http://doc.zyplayer.com/zyplayer-doc-manage'
|
||||
|
||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
ENV = 'development'
|
||||
|
||||
# base api
|
||||
# VUE_APP_BASE_API = 'http://local.zyplayer.com:8083/zyplayer-doc-manage'
|
||||
VUE_APP_BASE_API = 'http://doc.zyplayer.com/zyplayer-doc-manage'
|
||||
VUE_APP_BASE_API = 'http://local.zyplayer.com:8083/zyplayer-doc-manage'
|
||||
# VUE_APP_BASE_API = 'http://doc.zyplayer.com/zyplayer-doc-manage'
|
||||
|
||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
||||
|
||||
|
||||
38
zyplayer-doc-ui/dubbo-ui/package-lock.json
generated
38
zyplayer-doc-ui/dubbo-ui/package-lock.json
generated
@@ -1971,6 +1971,14 @@
|
||||
"integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=",
|
||||
"dev": true
|
||||
},
|
||||
"async-validator": {
|
||||
"version": "1.8.5",
|
||||
"resolved": "https://registry.npm.taobao.org/async-validator/download/async-validator-1.8.5.tgz",
|
||||
"integrity": "sha1-3D4I7B/Q3dtn5ghC8CwM0c7G1/A=",
|
||||
"requires": {
|
||||
"babel-runtime": "6.x"
|
||||
}
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "http://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz",
|
||||
@@ -2057,7 +2065,7 @@
|
||||
},
|
||||
"babel-helper-vue-jsx-merge-props": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "http://registry.npm.taobao.org/babel-helper-vue-jsx-merge-props/download/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/babel-helper-vue-jsx-merge-props/download/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
|
||||
"integrity": "sha1-Iq69OzOQIyjlEyk6jkmSs4T58bY="
|
||||
},
|
||||
"babel-loader": {
|
||||
@@ -2096,7 +2104,7 @@
|
||||
},
|
||||
"babel-runtime": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "http://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz",
|
||||
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||
"requires": {
|
||||
"core-js": "^2.4.0",
|
||||
@@ -2104,13 +2112,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.6.10",
|
||||
"resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.10.tgz?cache=0&sync_timestamp=1573985371469&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.10.tgz",
|
||||
"integrity": "sha1-iluDkfjMcBPacDQRzltYVwYwDX8="
|
||||
"version": "2.6.11",
|
||||
"resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.11.tgz?cache=0&sync_timestamp=1604675508568&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.11.tgz",
|
||||
"integrity": "sha1-OIMUafmSK97Y7iHJ3EaYXgOZMIw="
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz?cache=0&sync_timestamp=1595456105304&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk="
|
||||
}
|
||||
}
|
||||
@@ -4110,9 +4118,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"element-ui": {
|
||||
"version": "2.13.1",
|
||||
"resolved": "https://registry.npm.taobao.org/element-ui/download/element-ui-2.13.1.tgz?cache=0&sync_timestamp=1586761028754&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felement-ui%2Fdownload%2Felement-ui-2.13.1.tgz",
|
||||
"integrity": "sha1-DLGkXPJ6phxgHe++GSdArFy533w=",
|
||||
"version": "2.14.1",
|
||||
"resolved": "https://registry.npm.taobao.org/element-ui/download/element-ui-2.14.1.tgz?cache=0&sync_timestamp=1605089928506&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felement-ui%2Fdownload%2Felement-ui-2.14.1.tgz",
|
||||
"integrity": "sha1-i1dFxzZsHBpgO7bAIShupxh+KqI=",
|
||||
"requires": {
|
||||
"async-validator": "~1.8.1",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.0",
|
||||
@@ -4120,16 +4128,6 @@
|
||||
"normalize-wheel": "^1.0.1",
|
||||
"resize-observer-polyfill": "^1.5.0",
|
||||
"throttle-debounce": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"async-validator": {
|
||||
"version": "1.8.5",
|
||||
"resolved": "https://registry.npm.taobao.org/async-validator/download/async-validator-1.8.5.tgz",
|
||||
"integrity": "sha1-3D4I7B/Q3dtn5ghC8CwM0c7G1/A=",
|
||||
"requires": {
|
||||
"babel-runtime": "6.x"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"elliptic": {
|
||||
@@ -7497,7 +7495,7 @@
|
||||
},
|
||||
"normalize-wheel": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/normalize-wheel/download/normalize-wheel-1.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnormalize-wheel%2Fdownload%2Fnormalize-wheel-1.0.1.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/normalize-wheel/download/normalize-wheel-1.0.1.tgz",
|
||||
"integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
|
||||
},
|
||||
"npm-run-path": {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"vue-hljs": "^1.1.2",
|
||||
"vue-router": "^3.1.3",
|
||||
"vuex": "^3.1.2",
|
||||
"element-ui": "^2.10.0",
|
||||
"element-ui": "^2.14.0",
|
||||
"sql-formatter": "^2.3.3",
|
||||
"wangeditor": "^3.1.1"
|
||||
},
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon-db.png">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon-dubbo.png">
|
||||
<title>DUBBO文档管理</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but zyplayer-db-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
<strong>We're sorry but zyplayer-dubbo-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
|
||||
@@ -4,116 +4,68 @@
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
<el-container v-else>
|
||||
<el-aside style="background: #fafafa;">
|
||||
<el-aside style="background: #fff;">
|
||||
<div style="padding: 10px;height: 100%;box-sizing: border-box;">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<el-select v-model="choiceDatasourceGroup" @change="sourceGroupChangeEvents" size="small" filterable placeholder="请先选择分组" style="width: 100%;">
|
||||
<el-option value="" label="全部分组"></el-option>
|
||||
<el-option v-for="item in datasourceGroupList" :key="item" :value="item"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="choiceDatasourceId" @change="datasourceChangeEvents" size="small" filterable placeholder="请先选择数据源" style="width: 100%;margin-top: 10px;">
|
||||
<el-option v-for="item in datasourceOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<el-menu :router="true" class="el-menu-vertical" style="height: auto;">
|
||||
<el-menu-item index="/data/datasourceManage"><i class="el-icon-coin"></i>数据源管理</el-menu-item>
|
||||
<el-menu-item index="/data/executor"><i class="el-icon-video-play"></i>SQL执行器</el-menu-item>
|
||||
<el-submenu index="1">
|
||||
<template slot="title">
|
||||
<i class="el-icon-s-platform"></i>
|
||||
<span slot="title">管理工具</span>
|
||||
</template>
|
||||
<el-menu-item index="/data/export"><i class="el-icon-finished"></i>数据库表导出</el-menu-item>
|
||||
<el-menu-item index="/data/transferData"><i class="el-icon-document-copy"></i>数据互导工具</el-menu-item>
|
||||
</el-submenu>
|
||||
</el-menu>
|
||||
<div align="center">
|
||||
<el-dropdown split-button type="primary" @command="dropdownCommand" style="width: 280px;">
|
||||
<el-upload class="upload-page-file" action="zyplayer-doc-dubbo/doc-dubbo/uploadDocJar"
|
||||
:on-success="uploadFileSuccess" :on-error="uploadFileError"
|
||||
name="file" :show-file-list="false" :limit="999">
|
||||
<el-button type="primary" icon="el-icon-upload" style="width: 250px;">上传文档JAR</el-button>
|
||||
</el-upload>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="reload" icon="el-icon-refresh">重新加载服务列表</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<el-input v-model="searchKeywords" placeholder="搜索文档" style="margin: 10px 0;">
|
||||
<el-button slot="append" icon="el-icon-search" v-on:click="searchByKeywords"></el-button>
|
||||
</el-input>
|
||||
<!-- <el-menu :router="true" class="el-menu-vertical" style="height: auto;">-->
|
||||
<!-- <el-menu-item index="/doc/dubboDocView"><i class="el-icon-coin"></i>系统管理</el-menu-item>-->
|
||||
<!-- </el-menu>-->
|
||||
<div style="overflow: auto;padding-bottom: 30px;">
|
||||
<el-tree :props="defaultProps" :data="databaseList" @node-click="handleNodeClick"
|
||||
ref="databaseTree" highlight-current empty-text=""
|
||||
:default-expanded-keys="databaseExpandedKeys"
|
||||
node-key="id" @node-expand="handleNodeExpand"
|
||||
class="database-list-tree">
|
||||
<span slot-scope="{node, data}">
|
||||
<span v-if="data.needLoad"><i class="el-icon-loading"></i></span>
|
||||
<span v-else>
|
||||
{{node.label}}
|
||||
<el-tooltip v-if="!!data.comment" effect="dark" :content="data.comment" placement="top-start" :open-delay="600">
|
||||
<span style="color: #aaa;">-{{data.comment}}</span>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</span>
|
||||
</el-tree>
|
||||
<el-tree :data="pathIndex" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
|
||||
</div>
|
||||
</div>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-header>
|
||||
<span class="header-right-user-name">{{userSelfInfo.userName}}</span>
|
||||
<el-dropdown @command="userSettingDropdown" trigger="click">
|
||||
<i class="el-icon-setting" style="margin-right: 15px; font-size: 16px;cursor: pointer;color: #fff;"> </i>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="console">控制台</el-dropdown-item>
|
||||
<el-dropdown-item command="aboutDoc" divided>关于</el-dropdown-item>
|
||||
<el-dropdown-item command="myInfo">我的资料</el-dropdown-item>
|
||||
<el-dropdown-item command="userSignOut">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<header-right></header-right>
|
||||
</el-header>
|
||||
<el-main style="padding: 0;">
|
||||
<router-view @initLoadDataList="initLoadDataList"
|
||||
@loadDatasourceList="loadDatasourceList">
|
||||
</router-view>
|
||||
<el-main style="padding: 0;box-shadow: rgba(0, 0, 0, 0.1) 0 0 8px;">
|
||||
<router-view :dubboDocMap="dubboDocMap" :treePathDataMap="treePathDataMap"></router-view>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
<!--关于弹窗-->
|
||||
<el-dialog title="关于zyplayer-doc" :visible.sync="aboutDialogVisible" width="600px">
|
||||
<el-form>
|
||||
<el-form-item label="项目地址:">
|
||||
<a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc">zyplayer-doc</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="开发人员:">
|
||||
<a target="_blank" href="http://zyplayer.com">暮光:城中城</a>
|
||||
</el-form-item>
|
||||
<template v-if="upgradeInfo.lastVersion">
|
||||
<el-form-item label="当前版本:">{{upgradeInfo.nowVersion}}</el-form-item>
|
||||
<el-form-item label="最新版本:">{{upgradeInfo.lastVersion}}</el-form-item>
|
||||
<el-form-item label="升级地址:">
|
||||
<a target="_blank" :href="upgradeInfo.upgradeUrl">{{upgradeInfo.upgradeUrl}}</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="升级内容:">{{upgradeInfo.upgradeContent}}</el-form-item>
|
||||
</template>
|
||||
<el-form-item label="">
|
||||
欢迎加群讨论,QQ群号:466363173,欢迎提交需求,欢迎使用和加入开发!
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import userApi from './common/api/user'
|
||||
import datasourceApi from './common/api/datasource'
|
||||
import dubboApi from './common/api/dubbo'
|
||||
import docTree from './common/js/doc-dubbo-tree'
|
||||
import headerRight from './views/user/HeaderRight'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
'header-right': headerRight
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isCollapse: false,
|
||||
aboutDialogVisible: false,
|
||||
userSelfInfo: {},
|
||||
// 数据源相关
|
||||
datasourceOptions: [],
|
||||
datasourceList: [],
|
||||
datasourceGroupList: [],
|
||||
choiceDatasourceId: "",
|
||||
choiceDatasourceGroup: "",
|
||||
defaultProps: {children: 'children', label: 'name'},
|
||||
// 页面展示相关
|
||||
nowDatasourceShow: {},
|
||||
databaseList: [],
|
||||
databaseExpandedKeys: [],
|
||||
// 升级信息
|
||||
upgradeInfo: {},
|
||||
pathIndex: [],
|
||||
defaultProps: {children: 'children', label: 'label'},
|
||||
// 展示的信息
|
||||
dubboInfo: {},
|
||||
// 请求的IP端口下拉选项
|
||||
requestHostOptions: [],
|
||||
// 依据目录树存储的map全局对象
|
||||
treePathDataMap: new Map(),
|
||||
// dubbo列表
|
||||
dubboDocList: [],
|
||||
dubboDocMap: [],
|
||||
// 搜索的输入内容
|
||||
searchKeywords: "",
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -122,154 +74,50 @@
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.getSelfUserInfo();
|
||||
this.checkSystemUpgrade();
|
||||
this.loadDatasourceList();
|
||||
this.doGetServiceList();
|
||||
},
|
||||
methods: {
|
||||
userSettingDropdown(command) {
|
||||
console.log("command:" + command);
|
||||
if (command == 'userSignOut') {
|
||||
this.userSignOut();
|
||||
} else if (command == 'aboutDoc') {
|
||||
this.aboutDialogVisible = true;
|
||||
} else if (command == 'myInfo') {
|
||||
this.$router.push({path: '/user/myInfo'});
|
||||
} else if (command == 'console') {
|
||||
window.location = process.env.VUE_APP_BASE_API;
|
||||
} else {
|
||||
this.$message.warning("功能暂未开放");
|
||||
}
|
||||
},
|
||||
userSignOut() {
|
||||
userApi.userLogout().then(() => {
|
||||
location.reload();
|
||||
});
|
||||
},
|
||||
getSelfUserInfo() {
|
||||
userApi.getSelfUserInfo().then(json=>{
|
||||
this.userSelfInfo = json.data;
|
||||
});
|
||||
},
|
||||
sourceGroupChangeEvents() {
|
||||
let datasourceOptions = [];
|
||||
for (let i = 0; i < this.datasourceList.length; i++) {
|
||||
let item = this.datasourceList[i];
|
||||
if (!this.choiceDatasourceGroup || this.choiceDatasourceGroup == item.groupName) {
|
||||
datasourceOptions.push({label: item.name, value: item.id});
|
||||
}
|
||||
}
|
||||
this.datasourceOptions = datasourceOptions;
|
||||
},
|
||||
datasourceChangeEvents() {
|
||||
this.nowDatasourceShow = this.choiceDatasourceId;
|
||||
var host = "";
|
||||
for (var i = 0; i < this.datasourceList.length; i++) {
|
||||
if (this.datasourceList[i].id == this.choiceDatasourceId) {
|
||||
host = this.datasourceList[i].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.loadDatabaseList(this.choiceDatasourceId, host);
|
||||
},
|
||||
handleNodeClick(node) {
|
||||
console.log("点击节点:", node);
|
||||
// 执行器里面点击库表不跳转页面
|
||||
// if (this.$router.currentRoute.path == "/data/executor") {
|
||||
// return;
|
||||
// }
|
||||
if (node.type == 1) {
|
||||
this.nowClickPath = {sourceId: this.choiceDatasourceId, host: node.host, dbName: node.dbName, tableName: node.tableName};
|
||||
this.$router.push({path: '/table/database', query: this.nowClickPath});
|
||||
} else if (node.type == 2) {
|
||||
this.nowClickPath = {sourceId: this.choiceDatasourceId, host: node.host, dbName: node.dbName, tableName: node.tableName};
|
||||
this.$router.push({path: '/table/info', query: this.nowClickPath});
|
||||
}
|
||||
},
|
||||
handleNodeExpand(node) {
|
||||
if (node.children.length > 0 && node.children[0].needLoad) {
|
||||
console.log("加载节点:", node);
|
||||
if (node.type == 1) {
|
||||
this.loadGetTableList(node);
|
||||
}
|
||||
}
|
||||
},
|
||||
loadGetTableList(node, callback) {
|
||||
datasourceApi.tableList({sourceId: this.choiceDatasourceId, dbName: node.dbName}).then(json => {
|
||||
let pathIndex = [];
|
||||
let result = json.data || [];
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
let item = {
|
||||
id: node.host + "_" + node.dbName + "_" + result[i].tableName, host: node.host,
|
||||
dbName: node.dbName, tableName: result[i].tableName, name: result[i].tableName, type: 2,
|
||||
comment: result[i].tableComment
|
||||
};
|
||||
// item.children = [{label: '', needLoad: true}];// 初始化一个对象,点击展开时重新查询加载
|
||||
pathIndex.push(item);
|
||||
}
|
||||
node.children = pathIndex;
|
||||
if (typeof callback == 'function') {
|
||||
callback(pathIndex);
|
||||
}
|
||||
});
|
||||
},
|
||||
loadDatasourceList() {
|
||||
datasourceApi.datasourceList({}).then(json => {
|
||||
this.datasourceList = json.data || [];
|
||||
let datasourceOptions = [];
|
||||
for (let i = 0; i < this.datasourceList.length; i++) {
|
||||
let item = this.datasourceList[i];
|
||||
datasourceOptions.push({label: item.name, value: item.id});
|
||||
}
|
||||
this.datasourceOptions = datasourceOptions;
|
||||
let datasourceGroupList = [];
|
||||
this.datasourceList.filter(item => !!item.groupName).forEach(item => datasourceGroupList.push(item.groupName || ''));
|
||||
this.datasourceGroupList = Array.from(new Set(datasourceGroupList));
|
||||
});
|
||||
},
|
||||
loadDatabaseList(sourceId, host) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.databaseList = [];
|
||||
datasourceApi.databaseList({sourceId: sourceId}).then(json => {
|
||||
let result = json.data || [];
|
||||
let pathIndex = [];
|
||||
let children = [];
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
let item = {
|
||||
id: host + "_" + result[i].dbName, host: host, dbName: result[i].dbName,
|
||||
name: result[i].dbName, type: 1
|
||||
};
|
||||
item.children = [{label: '', needLoad: true}];// 初始化一个对象,点击展开时重新查询加载
|
||||
children.push(item);
|
||||
}
|
||||
pathIndex.push({id: host, host: host, name: host, children: children});
|
||||
this.databaseList = pathIndex;
|
||||
resolve();
|
||||
handleNodeClick(data) {
|
||||
if (data.children == null) {
|
||||
// console.log(data);
|
||||
//console.log(this.dubboInfo);
|
||||
this.$router.push({
|
||||
path: '/doc/dubboDocView',
|
||||
query: {path: data.interface, method: data.method, application: data.application}
|
||||
});
|
||||
}
|
||||
},
|
||||
uploadFileError(err) {
|
||||
this.$message({message: "上传失败," + err, type: 'error'});
|
||||
},
|
||||
uploadFileSuccess(response) {
|
||||
if (response.errCode == 200) {
|
||||
this.$message({message: "上传成功!", type: 'success'});
|
||||
} else {
|
||||
this.$message({message: "上传失败," + response.errMsg, type: 'error'});
|
||||
}
|
||||
},
|
||||
reloadService() {
|
||||
dubboApi.reloadService().then(json => {
|
||||
this.$message({message: '加载成功!', type: 'success'});
|
||||
this.doGetServiceList();
|
||||
});
|
||||
},
|
||||
initLoadDataList(param) {
|
||||
if (this.databaseList.length > 0) {
|
||||
return;
|
||||
}
|
||||
this.choiceDatasourceId = parseInt(param.sourceId);
|
||||
this.loadDatabaseList(param.sourceId, param.host).then(() => {
|
||||
this.databaseExpandedKeys = [param.host];
|
||||
},
|
||||
dropdownCommand(command) {
|
||||
if(command == 'reload') {
|
||||
this.reloadService();
|
||||
}
|
||||
},
|
||||
searchByKeywords() {
|
||||
this.pathIndex = docTree.createTreeViewByTreeWithMerge(this.treePathDataMap, this.dubboDocList, this.searchKeywords);
|
||||
},
|
||||
doGetServiceList() {
|
||||
dubboApi.getDocList({}).then(json => {
|
||||
this.dubboDocList = json.data.serverList || [];
|
||||
this.dubboDocMap = json.data.docMap || {};
|
||||
this.pathIndex = docTree.createTreeViewByTreeWithMerge(this.treePathDataMap, this.dubboDocList);
|
||||
});
|
||||
},
|
||||
checkSystemUpgrade() {
|
||||
datasourceApi.systemUpgradeInfo({}).then(json => {
|
||||
if (!!json.data) {
|
||||
this.upgradeInfo = json.data;
|
||||
console.log("zyplayer-doc发现新版本:"
|
||||
+ "\n升级地址:" + json.data.upgradeUrl
|
||||
+ "\n当前版本:" + json.data.nowVersion
|
||||
+ "\n最新版本:" + json.data.lastVersion
|
||||
+ "\n升级内容:" + json.data.upgradeContent
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -283,15 +131,19 @@
|
||||
#app, .el-container, .el-menu {
|
||||
height: 100%;
|
||||
}
|
||||
.el-menu {
|
||||
box-sizing: border-box;
|
||||
border-right: 0;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.el-tree{
|
||||
margin-right: 3px;
|
||||
}
|
||||
.el-tree-node__content{
|
||||
padding-right: 20px;
|
||||
}
|
||||
.el-header {
|
||||
background-color: #1D4E89 !important;
|
||||
}
|
||||
.database-list-tree{background-color: #fafafa;}
|
||||
.database-list-tree .el-tree-node>.el-tree-node__children {
|
||||
overflow: unset;
|
||||
}
|
||||
.header-right-user-name{color: #fff;padding-right: 5px;}
|
||||
.el-menu-vertical{border-right: 0;background: #fafafa;}
|
||||
.el-menu-vertical .el-menu{background: #fafafa;}
|
||||
.el-header {background-color: #409EFF; color: #333; line-height: 40px; text-align: right;height: 40px !important;}
|
||||
.el-button-group>.el-button:first-child{padding: 0!important;border: 0;}
|
||||
</style>
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
import Qs from 'qs'
|
||||
import request from './request'
|
||||
|
||||
export default {
|
||||
queryTestDatasource: data => {
|
||||
return request({url: '/zyplayer-doc-db/datasource/test', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
queryTableDdl: data => {
|
||||
return request({url: '/zyplayer-doc-db/doc-db/getTableDdl', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
getEditorData: data => {
|
||||
return request({url: '/zyplayer-doc-db/doc-db/getEditorData', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
datasourceList: data => {
|
||||
return request({url: '/zyplayer-doc-db/doc-db/getDataSourceList', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
databaseList: data => {
|
||||
return request({url: '/zyplayer-doc-db/doc-db/getDatabaseList', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
tableList: data => {
|
||||
return request({url: '/zyplayer-doc-db/doc-db/getTableList', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
tableColumnList: data => {
|
||||
return request({url: '/zyplayer-doc-db/doc-db/getTableColumnList', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
tableStatus: data => {
|
||||
return request({url: '/zyplayer-doc-db/doc-db/getTableStatus', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
tableAndColumnBySearch: data => {
|
||||
return request({url: '/zyplayer-doc-db/doc-db/getTableAndColumnBySearch', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
updateTableDesc: data => {
|
||||
return request({url: '/zyplayer-doc-db/doc-db/updateTableDesc', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
updateTableColumnDesc: data => {
|
||||
return request({url: '/zyplayer-doc-db/doc-db/updateTableColumnDesc', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
manageDatasourceList: data => {
|
||||
return request({url: '/zyplayer-doc-db/datasource/list', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
manageUpdateDatasource: data => {
|
||||
return request({url: '/zyplayer-doc-db/datasource/update', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
queryExecuteSql: data => {
|
||||
return request({url: '/zyplayer-doc-db/executor/execute', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
executeSqlCancel: data => {
|
||||
return request({url: '/zyplayer-doc-db/executor/cancel', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
updateFavorite: data => {
|
||||
return request({url: '/zyplayer-doc-db/executor/favorite/add', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
favoriteList: data => {
|
||||
return request({url: '/zyplayer-doc-db/executor/favorite/list', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
historyList: data => {
|
||||
return request({url: '/zyplayer-doc-db/executor/history/list', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
transferStart: data => {
|
||||
return request({url: '/zyplayer-doc-db/transfer/start', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
transferCancel: data => {
|
||||
return request({url: '/zyplayer-doc-db/transfer/cancel', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
transferList: data => {
|
||||
return request({url: '/zyplayer-doc-db/transfer/list', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
transferDetail: data => {
|
||||
return request({url: '/zyplayer-doc-db/transfer/detail', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
transferUpdate: data => {
|
||||
return request({url: '/zyplayer-doc-db/transfer/update', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
transferSqlColumns: data => {
|
||||
return request({url: '/zyplayer-doc-db/transfer/sqlColumns', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
assignDbUserAuth: data => {
|
||||
return request({url: '/zyplayer-doc-db/auth/assign', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
dbUserAuthList: data => {
|
||||
return request({url: '/zyplayer-doc-db/auth/list', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
systemUpgradeInfo: data => {
|
||||
return request({url: '/system/info/upgrade', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
};
|
||||
23
zyplayer-doc-ui/dubbo-ui/src/common/api/dubbo.js
Normal file
23
zyplayer-doc-ui/dubbo-ui/src/common/api/dubbo.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import Qs from 'qs'
|
||||
import request from './request'
|
||||
|
||||
export default {
|
||||
findDocInfo: data => {
|
||||
return request({url: '/zyplayer-doc-dubbo/doc-dubbo/findDocInfo', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
reloadService: data => {
|
||||
return request({url: '/zyplayer-doc-dubbo/doc-dubbo/reloadService', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
getDocList: data => {
|
||||
return request({url: '/zyplayer-doc-dubbo/doc-dubbo/getDocList', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
saveDoc: data => {
|
||||
return request({url: '/zyplayer-doc-dubbo/doc-dubbo/saveDoc', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
request: data => {
|
||||
return request({url: '/zyplayer-doc-dubbo/doc-dubbo/request', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
systemUpgradeInfo: data => {
|
||||
return request({url: '/system/info/upgrade', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
};
|
||||
@@ -9,8 +9,7 @@ const service = axios.create({
|
||||
});
|
||||
// 增加不需要验证结果的标记
|
||||
const noValidate = {
|
||||
"/zyplayer-doc-db/executor/execute": true,
|
||||
"/zyplayer-doc-db/datasource/test": true,
|
||||
"/zyplayer-doc-dubbo/doc-dubbo/request": true,
|
||||
};
|
||||
|
||||
service.interceptors.request.use(
|
||||
@@ -32,17 +31,18 @@ service.interceptors.response.use(
|
||||
response => {
|
||||
if (!!response.message) {
|
||||
vue.$message.error('请求错误:' + response.message);
|
||||
}else {
|
||||
} else {
|
||||
if (!response.config.needValidateResult || response.data.errCode == 200) {
|
||||
return response.data;
|
||||
} else if (response.data.errCode == 400) {
|
||||
vue.$message.error('请先登录');
|
||||
var href = encodeURIComponent(window.location.href);
|
||||
let href = encodeURIComponent(window.location.href);
|
||||
window.location = process.env.VUE_APP_BASE_API + "#/user/login?redirect=" + href;
|
||||
} else if (response.data.errCode == 402) {
|
||||
vue.$router.push("/common/noAuth");
|
||||
} else if (response.data.errCode !== 200) {
|
||||
vue.$message.error(response.data.errMsg || "未知错误");
|
||||
return Promise.reject(response.data.errMsg || "未知错误");
|
||||
}
|
||||
}
|
||||
return Promise.reject('请求错误');
|
||||
|
||||
154
zyplayer-doc-ui/dubbo-ui/src/common/js/doc-dubbo-tree.js
Normal file
154
zyplayer-doc-ui/dubbo-ui/src/common/js/doc-dubbo-tree.js
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* 以树形方式生成并展示:
|
||||
* /api
|
||||
* /data
|
||||
* /getDateList
|
||||
* post
|
||||
* get
|
||||
* @author 暮光:城中城
|
||||
* @since 2018年5月26日
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* 把原始的json字符串转换成对象列表的方式,方便后续使用
|
||||
* @param json swagger的原始对象
|
||||
* @returns
|
||||
*/
|
||||
createTreeViewByTree(treePathDataMap, json, keywords) {
|
||||
let pathIndex = [];
|
||||
if (!json) return;
|
||||
//console.log(paths);
|
||||
let lastId = "";
|
||||
for (let i = 0; i < json.length; i++) {
|
||||
let interfaceX = json[i].interface;
|
||||
//console.log(key, paths[key]);
|
||||
if (!this.findInPathsValue(json[i], keywords)) {
|
||||
continue;
|
||||
}
|
||||
if (json[i].nodeList.length <= 0) {
|
||||
continue;
|
||||
}
|
||||
let methods = json[i].nodeList[0].methods;
|
||||
let application = json[i].nodeList[0].application;
|
||||
for (let j = 0; j < methods.length; j++) {
|
||||
let interfaceTemp = interfaceX + "." + methods[j];
|
||||
let keyArr = interfaceTemp.split(".");
|
||||
let nowPathObj = null;
|
||||
keyArr.forEach((val, index) => {
|
||||
//console.log(val, index);
|
||||
if (!val && index == 0) {
|
||||
return;
|
||||
}
|
||||
let nowPath = val;
|
||||
if (nowPathObj == null) {
|
||||
nowPathObj = this.findNode(pathIndex, nowPath);
|
||||
if (nowPathObj == null) {
|
||||
nowPathObj = {
|
||||
id: pathIndex.length,
|
||||
label: nowPath, children: []
|
||||
};
|
||||
pathIndex.push(nowPathObj);
|
||||
}
|
||||
lastId = nowPathObj.id;
|
||||
nowPathObj = nowPathObj.children;
|
||||
} else {
|
||||
let tempPathObj = this.findNode(nowPathObj, nowPath);
|
||||
if (tempPathObj == null) {
|
||||
tempPathObj = {
|
||||
id: lastId + "." + nowPathObj.length,
|
||||
label: nowPath, children: []
|
||||
};
|
||||
nowPathObj.push(tempPathObj);
|
||||
}
|
||||
lastId = tempPathObj.id;
|
||||
nowPathObj = tempPathObj.children;
|
||||
if (index == keyArr.length - 1) {
|
||||
let tempPath = interfaceTemp;
|
||||
tempPathObj.children = null;
|
||||
tempPathObj.method = methods[j];
|
||||
tempPathObj.interface = tempPath;
|
||||
tempPathObj.application = application;
|
||||
treePathDataMap.set(tempPath, json[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// console.log(pathIndex);
|
||||
return pathIndex;
|
||||
},
|
||||
createTreeViewByTreeWithMerge(treePathDataMap, json, keywords) {
|
||||
let pathIndex = this.createTreeViewByTree(treePathDataMap, json, keywords);
|
||||
this.mergeNode(pathIndex);
|
||||
return pathIndex;
|
||||
},
|
||||
/**
|
||||
* 查找node节点
|
||||
*/
|
||||
findNode(arr, service) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (arr[i].label == service) {
|
||||
return arr[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* 多层级合并
|
||||
*/
|
||||
mergeNode(node) {
|
||||
for (let i = 0; i < node.length; i++) {
|
||||
let tempNode = node[i];
|
||||
if (tempNode.children == null
|
||||
|| tempNode.children[0].children == null
|
||||
|| tempNode.children[0].children[0].children == null) {
|
||||
continue;
|
||||
}
|
||||
if (tempNode.children.length == 1) {
|
||||
tempNode.label = tempNode.label + "." + tempNode.children[0].label;
|
||||
tempNode.children = tempNode.children[0].children;
|
||||
i--;
|
||||
}
|
||||
this.mergeNode(tempNode.children);
|
||||
}
|
||||
},
|
||||
findInPathsValue(pathsValue, keywords) {
|
||||
if (!keywords) {
|
||||
return true;
|
||||
}
|
||||
keywords = keywords.toLowerCase();
|
||||
// 找路径和说明里面包含关键字的
|
||||
let interfaceX = pathsValue.interface;
|
||||
if (!!interfaceX && interfaceX.toLowerCase().indexOf(keywords) >= 0) {
|
||||
return true;
|
||||
}
|
||||
if (pathsValue.nodeList.length > 0) {
|
||||
for (let i = 0; i < pathsValue.nodeList.length; i++) {
|
||||
let node = pathsValue.nodeList[i];
|
||||
if (!!node.application && node.application.toLowerCase().indexOf(keywords) >= 0) {
|
||||
return true;
|
||||
}
|
||||
if (!!node.methods && node.methods.length > 0) {
|
||||
for (let j = 0; j < node.methods.length; j++) {
|
||||
let method = node.methods[j];
|
||||
if (method.toLowerCase().indexOf(keywords) >= 0) {
|
||||
return true;
|
||||
}
|
||||
let path = interfaceX + "." + method;
|
||||
let docInfo = app.dubboDocMap[path];
|
||||
if (!!docInfo) {
|
||||
if (!!docInfo.explain && docInfo.explain.toLowerCase().indexOf(keywords) >= 0) {
|
||||
return true;
|
||||
}
|
||||
if (!!docInfo.explain && docInfo.explain.toLowerCase().indexOf(keywords) >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
125
zyplayer-doc-ui/dubbo-ui/src/common/js/format-json.js
Normal file
125
zyplayer-doc-ui/dubbo-ui/src/common/js/format-json.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 将对象处理成json格式化和着色的html
|
||||
* @author 暮光:城中城
|
||||
* @since 2017年5月7日
|
||||
*/
|
||||
let 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/doc-dubbo/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
|
||||
var annotation = '';
|
||||
if (showAnnotation && !!keyName && !!this.annotationObject[keyName]) {
|
||||
annotation = '<span class="annotation">// ' + this.annotationObject[keyName] + '</span>';
|
||||
}
|
||||
html += this.getRow(indent, "<span class='array-brace'>[</span>" + clpsHtml + annotation, isPropertyContent);
|
||||
for (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/doc-dubbo/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
|
||||
var annotation = '';
|
||||
if (showAnnotation && !!keyName && !!this.annotationObject[keyName]) {
|
||||
annotation = '<span class="annotation">// ' + this.annotationObject[keyName] + '</span>';
|
||||
}
|
||||
html += this.getRow(indent, "<span class='object-brace'>{</span>" + clpsHtml + annotation, isPropertyContent);
|
||||
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/doc-dubbo/img/collapsed.png";
|
||||
if (container.style.display == "none") {
|
||||
disp = "inline";
|
||||
src = "webjars/doc-dubbo/img/expanded.png";
|
||||
}
|
||||
container.style.display = disp;
|
||||
img.src = src;
|
||||
},
|
||||
formatLiteral: function (literal, quote, comma, indent, isArray, style) {
|
||||
if (typeof literal == 'string') {
|
||||
literal = literal.split("<").join("<").split(">").join(">");
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
window.Formatjson = Formatjson;
|
||||
export default Formatjson;
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
<el-tab-pane :label="pageTabNameMap[item.fullPath]||item.name" :name="item.fullPath" v-for="item in pageList"/>
|
||||
</el-tabs>
|
||||
<keep-alive>
|
||||
<router-view :key="$route.fullPath" @initLoadDataList="initLoadDataList" @loadDatasourceList="loadDatasourceList"/>
|
||||
<router-view :key="$route.fullPath" :dubboDocMap="dubboDocMap" :treePathDataMap="treePathDataMap"></router-view>
|
||||
</keep-alive>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["dubboDocMap", "treePathDataMap"],
|
||||
name: 'PageTableView',
|
||||
components: {},
|
||||
data() {
|
||||
@@ -44,12 +45,6 @@
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
initLoadDataList(param) {
|
||||
this.$emit('initLoadDataList', param);
|
||||
},
|
||||
loadDatasourceList() {
|
||||
this.$emit('loadDatasourceList');
|
||||
},
|
||||
changePage(key) {
|
||||
this.activePage = key.name;
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ import Home from './views/home/Home.vue'
|
||||
|
||||
import UserLogin from './views/user/Login.vue'
|
||||
import UserMyInfo from './views/user/MyInfo.vue'
|
||||
import DubboDocView from './views/doc/DubboDocView.vue'
|
||||
import UserRouterView from './views/user/RouterView.vue'
|
||||
|
||||
import PageTableView from './components/layouts/PageTableView'
|
||||
@@ -22,10 +23,11 @@ let routes = [
|
||||
}, {
|
||||
path: '/',
|
||||
name: 'Tab标签页',
|
||||
component: PageTableView,
|
||||
children: [
|
||||
{path: '/user/myInfo', name: '我的信息',component: UserMyInfo},
|
||||
]
|
||||
component: PageTableView,
|
||||
children: [
|
||||
{path: '/doc/dubboDocView', name: '文档信息', component: DubboDocView},
|
||||
{path: '/user/myInfo', name: '我的信息', component: UserMyInfo},
|
||||
]
|
||||
}, {
|
||||
path: '/user',
|
||||
name: '用户管理',
|
||||
|
||||
322
zyplayer-doc-ui/dubbo-ui/src/views/doc/DubboDocView.vue
Normal file
322
zyplayer-doc-ui/dubbo-ui/src/views/doc/DubboDocView.vue
Normal file
@@ -0,0 +1,322 @@
|
||||
<template>
|
||||
<div class="dubbo-doc-view">
|
||||
<el-tabs type="border-card" style="width: 100%;box-shadow: none;">
|
||||
<el-tab-pane label="接口说明">
|
||||
<div v-if="!dubboInfo.interface">请先选择服务</div>
|
||||
<el-form v-else label-width="100px">
|
||||
<el-form-item label="服务:">
|
||||
{{dubboInfo.interface}}
|
||||
</el-form-item>
|
||||
<el-form-item label="方法:">
|
||||
{{dubboInfo.method}}
|
||||
</el-form-item>
|
||||
<el-form-item label="说明:">
|
||||
<div v-if="dubboInfoExplainShow">
|
||||
<pre style="margin: 0;">{{dubboInfo.docInfo.explain}}<el-button @click="editDocInfoExplain" style="float: right;">编辑</el-button></pre>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-input type="textarea" :rows="4" placeholder="维护人员、使用说明、便于搜索的信息" v-model="docInfoExplainInput"></el-input>
|
||||
<el-button @click.prevent="dubboInfoExplainShow = true" style="float: right;margin: 5px;">取消</el-button>
|
||||
<el-button type="primary" @click.prevent="saveDocInfoExplain" style="float: right;margin: 5px;">保存</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="节点:">
|
||||
<el-table :data="dubboInfo.nodeList" border style="width: 100%">
|
||||
<el-table-column prop="application" label="应用"></el-table-column>
|
||||
<el-table-column prop="ip" label="IP"></el-table-column>
|
||||
<el-table-column prop="port" label="端口"></el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
<el-form-item label="参数:">
|
||||
<el-table :data="docParamList" border style="width: 100%; margin-bottom: 5px;">
|
||||
<el-table-column label="顺序" width="100">
|
||||
<template slot-scope="scope">{{scope.$index}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参数名" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.paramName"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" width="300">
|
||||
<template slot-scope="scope">{{scope.row.paramType}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="说明">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.paramDesc"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-button @click.prevent="saveDocInfoParam" type="primary" style="float: right;margin: 5px;">保存</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="返回值:">
|
||||
{{dubboInfo.docInfo.resultType}}
|
||||
</el-form-item>
|
||||
<el-form-item label="结果说明:">
|
||||
<div v-if="dubboInfoResultShow">
|
||||
<pre style="margin: 0;">{{dubboInfo.docInfo.result}}<el-button @click="editDocInfoResult" style="float: right;">编辑</el-button></pre>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-input type="textarea" :rows="4" placeholder="结果集说明等" v-model="docInfoResultInput"></el-input>
|
||||
<el-button @click.prevent="dubboInfoResultShow = true" style="float: right;margin: 5px;">取消</el-button>
|
||||
<el-button type="primary" @click.prevent="saveDocInfoResult" style="float: right;margin: 5px;">保存</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="在线调试">
|
||||
<div v-if="!dubboInfo.interface">请先选择服务</div>
|
||||
<div v-loading="onlineDebugLoading" v-else>
|
||||
<el-input placeholder="请输入内容" v-model="dubboInfo.function" class="input-with-select">
|
||||
<el-select v-model="requestHostValue" slot="prepend" placeholder="请选择" style="width: 200px;">
|
||||
<el-option v-for="item in requestHostOptions" :key="item.value" :label="item.value" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
<el-button slot="append" @click.prevent="requestExecute">执行</el-button>
|
||||
</el-input>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="请求参数:">
|
||||
<el-table :data="docParamRequestList" border style="width: 100%; margin: 10px 0;">
|
||||
<el-table-column label="顺序" width="100">
|
||||
<template slot-scope="scope">{{scope.$index}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参数名">
|
||||
<template slot-scope="scope">{{scope.row.paramName}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型">
|
||||
<template slot-scope="scope">{{scope.row.paramType}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参数值">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.paramValue"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="说明">
|
||||
<template slot-scope="scope">{{scope.row.paramDesc}}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求结果:">
|
||||
<div class="request-result" v-html="requestResult"></div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dubboApi from '../../common/api/dubbo'
|
||||
import formatJson from '../../common/js/format-json'
|
||||
|
||||
export default {
|
||||
props: ["dubboDocMap", "treePathDataMap"],
|
||||
data() {
|
||||
return {
|
||||
vueQueryParam: {},
|
||||
dubboInfo: {},
|
||||
requestHostOptions: [],
|
||||
onlineDebugLoading: false,
|
||||
// 展示的信息
|
||||
dubboInfoExplainShow: true,
|
||||
docInfoExplainInput: "",
|
||||
dubboInfoResultShow: true,
|
||||
docInfoResultInput: "",
|
||||
requestHostValue: "",
|
||||
requestResult: "",
|
||||
docParamList: [],
|
||||
docParamRequestList: [],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
activated() {
|
||||
this.initQueryParam(this.$route);
|
||||
},
|
||||
methods: {
|
||||
initQueryParam(to) {
|
||||
this.vueQueryParam = to.query;
|
||||
let newName = {key: this.$route.fullPath, val: this.vueQueryParam.method};
|
||||
this.$store.commit('global/addTableName', newName);
|
||||
let path = this.vueQueryParam.path;
|
||||
let method = this.vueQueryParam.method;
|
||||
let application = this.vueQueryParam.application;
|
||||
let docInfo = this.dubboDocMap[path];
|
||||
if (!!docInfo) {
|
||||
this.createDocInfo(path, method);
|
||||
} else {
|
||||
let service = path.substring(0, path.lastIndexOf("."));
|
||||
let method = path.substring(path.lastIndexOf(".") + 1, path.length);
|
||||
let param = {service: service, method: method, application: application};
|
||||
dubboApi.findDocInfo(param).then(json => {
|
||||
if (!!json.data) {
|
||||
this.dubboDocMap[json.data.function] = json.data;
|
||||
}
|
||||
this.createDocInfo(path, method);
|
||||
});
|
||||
}
|
||||
},
|
||||
createDocInfo(path, method, isRetry) {
|
||||
let docInfo = this.dubboDocMap[path];
|
||||
let dubboInfo = this.treePathDataMap.get(path);
|
||||
if (!docInfo || !dubboInfo) {
|
||||
if (!isRetry) {
|
||||
// 打开一个方法后,刷新页面后等待数据加载完成再初始化一次
|
||||
setTimeout(() => this.createDocInfo(path, method, true), 1500);
|
||||
}
|
||||
return;
|
||||
}
|
||||
dubboInfo.method = method;
|
||||
dubboInfo.function = path;
|
||||
dubboInfo.docInfo = docInfo || {};
|
||||
// 清空再赋值才会重新渲染
|
||||
this.dubboInfo = {};
|
||||
this.dubboInfo = dubboInfo;
|
||||
// 请求相关
|
||||
this.requestHostOptions = [];
|
||||
let optionSet = {};
|
||||
for (let i = 0; i < dubboInfo.nodeList.length; i++) {
|
||||
let item = dubboInfo.nodeList[i];
|
||||
let option = item.ip + ":" + item.port;
|
||||
if (!!item.version) option += " V" + item.version;
|
||||
if (!!item.group) option += " G" + item.group;
|
||||
if (!optionSet[option]) {
|
||||
optionSet[option] = 1;
|
||||
this.requestHostOptions.push({value: option});
|
||||
}
|
||||
}
|
||||
this.requestHostValue = "";
|
||||
this.docInfoExplainInput = this.dubboInfo.docInfo.explain;
|
||||
if (this.requestHostOptions.length > 0) {
|
||||
this.requestHostValue = this.requestHostOptions[0].value;
|
||||
}
|
||||
this.docParamList = [];
|
||||
this.docParamList = this.dubboInfo.docInfo.params || [];
|
||||
this.createDocParamRequestList();
|
||||
},
|
||||
saveDocInfoExplain(){
|
||||
this.doSaveDocInfo(this.docInfoExplainInput, null, null, true);
|
||||
},
|
||||
saveDocInfoResult(){
|
||||
this.doSaveDocInfo(null, null, this.docInfoResultInput, true);
|
||||
},
|
||||
editDocInfoResult() {
|
||||
this.dubboInfoResultShow = false;
|
||||
this.docInfoResultInput = this.dubboInfo.docInfo.result || '';
|
||||
},
|
||||
editDocInfoExplain() {
|
||||
this.dubboInfoExplainShow = false;
|
||||
this.docInfoExplainInput = this.dubboInfo.docInfo.explain || '';
|
||||
},
|
||||
saveDocInfoParam() {
|
||||
var docParamList = [];
|
||||
for (var i = 0; i < this.docParamList.length; i++) {
|
||||
var item = this.docParamList[i];
|
||||
if (!!item.paramType) {
|
||||
docParamList.push(item);
|
||||
}
|
||||
}
|
||||
var paramsJson = JSON.stringify(docParamList);
|
||||
this.doSaveDocInfo(null, paramsJson, null, true);
|
||||
},
|
||||
createDocParamRequestList() {
|
||||
var docParamList = [];
|
||||
for (var i = 0; i < this.docParamList.length; i++) {
|
||||
var item = this.docParamList[i];
|
||||
if (!!item.paramType || !!item.paramDesc) {
|
||||
docParamList.push(item);
|
||||
}
|
||||
}
|
||||
this.docParamRequestList = docParamList;
|
||||
},
|
||||
doSaveDocInfo(explain, params, result, showSuccess){
|
||||
var param = {
|
||||
service: this.dubboInfo.interface,
|
||||
method: this.dubboInfo.method,
|
||||
resultType: this.dubboInfo.resultType,
|
||||
paramValue: this.dubboInfo.paramValue,
|
||||
version: this.dubboInfo.docInfo.version || 0,
|
||||
explain: explain,
|
||||
result: result,
|
||||
paramsJson: params,
|
||||
};
|
||||
dubboApi.saveDoc(param).then(json => {
|
||||
this.dubboDocMap[json.data.function] = json.data;
|
||||
this.dubboInfo.docInfo = json.data;
|
||||
this.dubboInfoExplainShow = true;
|
||||
this.dubboInfoResultShow = true;
|
||||
this.docParamList = json.data.params || [];
|
||||
this.createDocParamRequestList();
|
||||
if (showSuccess) {
|
||||
this.$message({message: '保存成功!', type: 'success'});
|
||||
}
|
||||
});
|
||||
},
|
||||
requestExecute() {
|
||||
var fuc = this.dubboInfo.function;
|
||||
var hostValue = this.requestHostValue;
|
||||
var service = fuc.substring(0, fuc.lastIndexOf("."));
|
||||
var method = fuc.substring(fuc.lastIndexOf(".") + 1, fuc.length);
|
||||
var paramArr = hostValue.split(" ");
|
||||
var ipPortArr = paramArr[0].split(":");
|
||||
var version = '', group = '';
|
||||
paramArr.forEach(item => {
|
||||
if (item.startsWith("V")) version = item.substring(1, item.length);
|
||||
if (item.startsWith("G")) group = item.substring(1, item.length);
|
||||
});
|
||||
var paramTypes = [];
|
||||
var params = [];
|
||||
for (var i = 0; i < this.docParamList.length; i++) {
|
||||
var item = this.docParamList[i];
|
||||
paramTypes.push(item.paramType);
|
||||
params.push(item.paramValue || '');
|
||||
}
|
||||
var param = {
|
||||
service: service,
|
||||
method: method,
|
||||
ip: ipPortArr[0],
|
||||
port: ipPortArr[1],
|
||||
version: version,
|
||||
group: group,
|
||||
paramTypes: JSON.stringify(paramTypes),
|
||||
params: JSON.stringify(params),
|
||||
};
|
||||
this.requestResult = "";
|
||||
this.onlineDebugLoading = true;
|
||||
dubboApi.request(param).then(json => {
|
||||
this.onlineDebugLoading = false;
|
||||
if (json.errCode == 200) {
|
||||
try {
|
||||
this.requestResult = formatJson.processObjectToHtmlPre(JSON.parse(json.data), 0, false, false, false, false);
|
||||
} catch (e) {
|
||||
try {
|
||||
this.requestResult = formatJson.processObjectToHtmlPre(json.data, 0, false, false, false, false);
|
||||
} catch (e) {
|
||||
this.requestResult = json.data;
|
||||
}
|
||||
}
|
||||
var paramsJson = JSON.stringify(this.docParamRequestList);
|
||||
this.doSaveDocInfo(null, paramsJson, null, false);
|
||||
} else {
|
||||
this.requestResult = json.errMsg;
|
||||
}
|
||||
}, err => {
|
||||
this.onlineDebugLoading = false;
|
||||
this.requestResult = err || '';
|
||||
if (!!err.responseJSON && err.responseJSON.message) {
|
||||
this.requestResult = err.responseJSON.message;
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.dubbo-doc-view{padding: 0 10px;}
|
||||
.dubbo-doc-view .el-tabs--border-card>.el-tabs__content{
|
||||
height: calc(100vh - 180px);overflow-y: auto;
|
||||
}
|
||||
.dubbo-doc-view .request-result pre{
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div style="padding: 10px;">
|
||||
<div style="max-width: 1200px;margin: 20px auto;">
|
||||
<div style="text-align: center;">欢迎使用ヾ(๑╹◡╹)ノ" - 在左上角选择一个数据源吧~</div>
|
||||
<div style="text-align: center;">欢迎使用ヾ(๑╹◡╹)ノ"</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
103
zyplayer-doc-ui/dubbo-ui/src/views/user/HeaderRight.vue
Normal file
103
zyplayer-doc-ui/dubbo-ui/src/views/user/HeaderRight.vue
Normal file
@@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<div class="header-right">
|
||||
<span class="header-right-user-name">{{userSelfInfo.userName}}</span>
|
||||
<el-dropdown @command="userSettingDropdown" trigger="click">
|
||||
<i class="el-icon-setting" style="margin-right: 15px; font-size: 16px;cursor: pointer;color: #fff;"> </i>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="console">控制台</el-dropdown-item>
|
||||
<el-dropdown-item command="aboutDoc" divided>关于</el-dropdown-item>
|
||||
<el-dropdown-item command="myInfo">我的资料</el-dropdown-item>
|
||||
<el-dropdown-item command="userSignOut">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<!--关于弹窗-->
|
||||
<el-dialog title="关于zyplayer-doc-dubbo" :visible.sync="aboutDialogVisible" width="600px" style="text-align: left;">
|
||||
<el-form>
|
||||
<el-form-item label="开源地址:">
|
||||
<a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc">zyplayer-doc</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="开发人员:">
|
||||
<a target="_blank" href="http://zyplayer.com">暮光:城中城</a>
|
||||
</el-form-item>
|
||||
<template v-if="upgradeInfo.lastVersion">
|
||||
<el-form-item label="当前版本:">{{upgradeInfo.nowVersion}}</el-form-item>
|
||||
<el-form-item label="最新版本:">{{upgradeInfo.lastVersion}}</el-form-item>
|
||||
<el-form-item label="升级地址:">
|
||||
<a target="_blank" :href="upgradeInfo.upgradeUrl">{{upgradeInfo.upgradeUrl}}</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="升级内容:">{{upgradeInfo.upgradeContent}}</el-form-item>
|
||||
</template>
|
||||
<el-form-item label="">
|
||||
欢迎加群讨论,QQ群号:466363173,欢迎提交需求,欢迎使用和加入开发!
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dubboApi from '../../common/api/dubbo'
|
||||
import userApi from '../../common/api/user'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
userSelfInfo: {},
|
||||
aboutDialogVisible: false,
|
||||
// 升级信息
|
||||
upgradeInfo: {},
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
this.getSelfUserInfo();
|
||||
this.checkSystemUpgrade();
|
||||
},
|
||||
methods: {
|
||||
userSignOut() {
|
||||
userApi.userLogout().then(() => {
|
||||
location.reload();
|
||||
});
|
||||
},
|
||||
getSelfUserInfo() {
|
||||
userApi.getSelfUserInfo().then(json => {
|
||||
this.userSelfInfo = json.data;
|
||||
});
|
||||
},
|
||||
userSettingDropdown(command) {
|
||||
console.log("command:" + command);
|
||||
if (command == 'userSignOut') {
|
||||
this.userSignOut();
|
||||
} else if (command == 'aboutDoc') {
|
||||
this.aboutDialogVisible = true;
|
||||
} else if (command == 'myInfo') {
|
||||
this.$router.push({path: '/user/myInfo'});
|
||||
} else if (command == 'console') {
|
||||
window.location = process.env.VUE_APP_BASE_API;
|
||||
} else {
|
||||
this.$message.warning("功能暂未开放");
|
||||
}
|
||||
},
|
||||
checkSystemUpgrade() {
|
||||
dubboApi.systemUpgradeInfo({}).then(json => {
|
||||
if (!!json.data) {
|
||||
this.upgradeInfo = json.data;
|
||||
console.log("zyplayer-doc发现新版本:"
|
||||
+ "\n升级地址:" + json.data.upgradeUrl
|
||||
+ "\n当前版本:" + json.data.nowVersion
|
||||
+ "\n最新版本:" + json.data.lastVersion
|
||||
+ "\n升级内容:" + json.data.upgradeContent
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.header-right-user-name{color: #fff;padding-right: 5px;}
|
||||
.el-menu-vertical{border-right: 0;background: #fafafa;}
|
||||
.el-menu-vertical .el-menu{background: #fafafa;}
|
||||
.el-header {background-color: #409EFF; color: #333; line-height: 40px; text-align: right;height: 40px !important;}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user