From 3ee105a0922921a1579dfc6aabd38f1af552bb8e Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 14 Jun 2019 17:26:42 +0800 Subject: [PATCH 01/40] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/docs/_sidebar.md | 53 +++++++++++++++-------------- doc/docs/files/10086_自定义路由.md | 23 +++++++++++++ doc/docs/files/10095_SDK开发.md | 2 ++ doc/docs/files/90100_常见问题.md | 20 ++++++++++- doc/docs/files/images/10086_1.png | Bin 0 -> 68234 bytes doc/docs/files/images/10086_2.png | Bin 0 -> 31310 bytes 6 files changed, 71 insertions(+), 27 deletions(-) create mode 100644 doc/docs/files/10086_自定义路由.md create mode 100644 doc/docs/files/images/10086_1.png create mode 100644 doc/docs/files/images/10086_2.png diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index bfce503d..6ba62b4e 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,28 +1,29 @@ -* [首页](/?t=1559803778913) +* [首页](/?t=1560480225362) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1559803778920) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1559803778940) - * [新增接口](files/10020_新增接口.md?t=1559803778940) - * [业务参数校验](files/10030_业务参数校验.md?t=1559803778940) - * [错误处理](files/10040_错误处理.md?t=1559803778940) - * [编写文档](files/10041_编写文档.md?t=1559803778941) - * [接口交互详解](files/10050_接口交互详解.md?t=1559803778941) - * [easyopen支持](files/10070_easyopen支持.md?t=1559803778941) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1559803778941) - * [ISV管理](files/10085_ISV管理.md?t=1559803778941) - * [路由授权](files/10090_路由授权.md?t=1559803778941) - * [接口限流](files/10092_接口限流.md?t=1559803778941) - * [监控日志](files/10093_监控日志.md?t=1559803778941) - * [SDK开发](files/10095_SDK开发.md?t=1559803778941) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1559803778942) - * [应用授权](files/10097_应用授权.md?t=1559803778942) - * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1559803778942) - * [对接前端](files/10100_对接前端.md?t=1559803778942) - * [自定义过滤器](files/10102_自定义过滤器.md?t=1559803778942) - * [文件上传](files/10104_文件上传.md?t=1559803778942) + * [快速体验](files/10010_快速体验.md?t=1560480225362) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1560480225379) + * [新增接口](files/10020_新增接口.md?t=1560480225379) + * [业务参数校验](files/10030_业务参数校验.md?t=1560480225380) + * [错误处理](files/10040_错误处理.md?t=1560480225380) + * [编写文档](files/10041_编写文档.md?t=1560480225380) + * [接口交互详解](files/10050_接口交互详解.md?t=1560480225380) + * [easyopen支持](files/10070_easyopen支持.md?t=1560480225380) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1560480225380) + * [ISV管理](files/10085_ISV管理.md?t=1560480225380) + * [自定义路由](files/10086_自定义路由.md?t=1560480225381) + * [路由授权](files/10090_路由授权.md?t=1560480225381) + * [接口限流](files/10092_接口限流.md?t=1560480225381) + * [监控日志](files/10093_监控日志.md?t=1560480225381) + * [SDK开发](files/10095_SDK开发.md?t=1560480225381) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1560480225382) + * [应用授权](files/10097_应用授权.md?t=1560480225382) + * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1560480225382) + * [对接前端](files/10100_对接前端.md?t=1560480225382) + * [自定义过滤器](files/10102_自定义过滤器.md?t=1560480225382) + * [文件上传](files/10104_文件上传.md?t=1560480225382) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1559803778942) - * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1559803778942) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1559803778942) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1559803778942) - * [常见问题](files/90100_常见问题.md?t=1559803778942) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1560480225382) + * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1560480225382) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1560480225383) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1560480225383) + * [常见问题](files/90100_常见问题.md?t=1560480225383) diff --git a/doc/docs/files/10086_自定义路由.md b/doc/docs/files/10086_自定义路由.md new file mode 100644 index 00000000..48f4ebd4 --- /dev/null +++ b/doc/docs/files/10086_自定义路由.md @@ -0,0 +1,23 @@ +# 自定义路由 + +假设有一个非java开发的接口,比如php开发的接口,然后需要接入到SOP,使用接口名版本号进行路由跳转。 + +操作方式如下: + +- 登录sop-admin,服务管理--路由管理 +- 新建一个自定义服务:`php-service` + +![新建一个自定义服务](images/10086_1.png "10086_1.png") + +- 选中php-service,新建一个路由,输入接口名、版本号、uri + +![新建一个路由](images/10086_2.png "10086_2.png") + +- 请求网关 + +`http://localhost:8081/api?method=php.goods.list&version=1.0`会跳转到`http://www.xxx.com/api/listGoods.php` + +注意: + +- php接口返回数据必须是json格式,返回其它内容可能会调用失败 +- 只有自定义服务、路由可以删除 diff --git a/doc/docs/files/10095_SDK开发.md b/doc/docs/files/10095_SDK开发.md index 740d6b6e..82427627 100644 --- a/doc/docs/files/10095_SDK开发.md +++ b/doc/docs/files/10095_SDK开发.md @@ -86,6 +86,8 @@ protected RequestMethod getRequestMethod() { } ``` +**建议读请求用GET,写请求用POST**, + ### 使用方式 ```java diff --git a/doc/docs/files/90100_常见问题.md b/doc/docs/files/90100_常见问题.md index ae293ecd..e40a39c5 100644 --- a/doc/docs/files/90100_常见问题.md +++ b/doc/docs/files/90100_常见问题.md @@ -28,4 +28,22 @@ public class ZuulConfig extends AlipayZuulConfiguration { } } -``` \ No newline at end of file +``` + +## 注册到eureka显示hostname,非ip + +```yaml +eureka: + instance: + prefer-ip-address: true + instance-id: ${spring.cloud.client.ip-address}:${server.port} +``` + +```xml + + org.springframework.cloud + spring-cloud-commons + +``` + +参考:https://www.jianshu.com/p/5ad8317961b7 diff --git a/doc/docs/files/images/10086_1.png b/doc/docs/files/images/10086_1.png new file mode 100644 index 0000000000000000000000000000000000000000..d5da23b6cdf47689c3115bfb64f5464215526749 GIT binary patch literal 68234 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 Q2>6q^qi{R_PXnL-4~z<}qyPW_ literal 0 HcmV?d00001 diff --git a/doc/docs/files/images/10086_2.png b/doc/docs/files/images/10086_2.png new file mode 100644 index 0000000000000000000000000000000000000000..de61367b9cca671bbab4e3bc88383b092858f743 GIT binary patch literal 31310 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 z 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 literal 0 HcmV?d00001 From b21a02c4a56e566481044522aa67fe9caad3dfce Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 14 Jun 2019 17:28:18 +0800 Subject: [PATCH 02/40] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E8=B7=AF?= =?UTF-8?q?=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gitee/sop/adminserver/api/isv/IsvApi.java | 12 +- .../sop/adminserver/api/service/LimitApi.java | 4 +- .../adminserver/api/service/LimitNewApi.java | 6 +- .../sop/adminserver/api/service/LogApi.java | 12 +- .../sop/adminserver/api/service/RouteApi.java | 101 +++-- .../adminserver/api/service/ServiceApi.java | 56 ++- .../api/service/param/LimitNewAddParam.java | 2 + .../service/param/LimitNewUpdateParam.java | 2 + .../api/service/param/RouteAddParam.java | 76 ++++ .../api/service/param/RouteDeleteParam.java | 22 ++ ...{RouteParam.java => RouteUpdateParam.java} | 31 +- .../api/service/param/ServiceAddParam.java | 21 + .../api/service/result/ServiceInfo.java | 4 + .../bean/GatewayRouteDefinition.java | 15 +- .../adminserver/bean/ServiceRouteInfo.java | 3 + .../adminserver/bean/ZookeeperContext.java | 136 +++++-- .../sop/adminserver/common/BizException.java | 33 ++ .../common/ZookeeperOperationException.java | 26 ++ .../common/ZookeeperPathExistException.java | 10 + .../ZookeeperPathNotExistException.java | 10 + .../service/RouteConfigService.java | 2 +- .../sop/adminserver/service/RouteService.java | 4 +- .../src/main/resources/public/index.html | 2 +- .../static/css/chunk-29b24c82.857979fb.css | 1 - .../static/css/chunk-2a9bc230.2dae711a.css | 1 + ...3114f3.css => chunk-37401378.a43114f3.css} | 0 .../static/css/chunk-6a68a33e.3b12267b.css | 1 + .../js/{app.36a3cb86.js => app.3225a72c.js} | 2 +- .../static/js/chunk-29b24c82.2b3ac7ca.js | 1 - .../static/js/chunk-2a9bc230.6f8c0d92.js | 1 + .../static/js/chunk-2d0aa95b.447435b3.js | 1 - ...3ec98327.js => chunk-37401378.4e39ec9b.js} | 2 +- .../static/js/chunk-6a68a33e.8b63492e.js | 1 + sop-admin/sop-admin-vue/src/utils/global.js | 10 +- .../src/views/service/limit/index2.vue | 12 +- .../src/views/service/route/index.vue | 371 ++++++++++++++---- 36 files changed, 800 insertions(+), 194 deletions(-) create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteAddParam.java create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteDeleteParam.java rename sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/{RouteParam.java => RouteUpdateParam.java} (54%) create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/ServiceAddParam.java create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/BizException.java create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperOperationException.java create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperPathExistException.java create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperPathNotExistException.java delete mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-29b24c82.857979fb.css create mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-2a9bc230.2dae711a.css rename sop-admin/sop-admin-server/src/main/resources/public/static/css/{chunk-19100986.a43114f3.css => chunk-37401378.a43114f3.css} (100%) create mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-6a68a33e.3b12267b.css rename sop-admin/sop-admin-server/src/main/resources/public/static/js/{app.36a3cb86.js => app.3225a72c.js} (64%) delete mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-29b24c82.2b3ac7ca.js create mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2a9bc230.6f8c0d92.js delete mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d0aa95b.447435b3.js rename sop-admin/sop-admin-server/src/main/resources/public/static/js/{chunk-19100986.3ec98327.js => chunk-37401378.4e39ec9b.js} (89%) create mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-6a68a33e.8b63492e.js diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java index 64e6ca4f..9ddb5cc8 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java @@ -7,7 +7,6 @@ import com.gitee.easyopen.doc.DataType; import com.gitee.easyopen.doc.annotation.ApiDoc; import com.gitee.easyopen.doc.annotation.ApiDocField; import com.gitee.easyopen.doc.annotation.ApiDocMethod; -import com.gitee.easyopen.exception.ApiException; import com.gitee.easyopen.util.CopyUtil; import com.gitee.easyopen.util.KeyStore; import com.gitee.easyopen.util.RSAUtil; @@ -24,7 +23,10 @@ import com.gitee.sop.adminserver.api.isv.result.IsvVO; import com.gitee.sop.adminserver.api.isv.result.RoleVO; import com.gitee.sop.adminserver.bean.ChannelMsg; import com.gitee.sop.adminserver.bean.ZookeeperContext; +import com.gitee.sop.adminserver.common.BizException; import com.gitee.sop.adminserver.common.IdGen; +import com.gitee.sop.adminserver.common.ZookeeperOperationException; +import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException; import com.gitee.sop.adminserver.entity.IsvInfo; import com.gitee.sop.adminserver.entity.PermIsvRole; import com.gitee.sop.adminserver.entity.PermRole; @@ -133,7 +135,7 @@ public class IsvApi { @Transactional(rollbackFor = Exception.class) public void addIsv(IsvInfoFormAdd param) throws Exception { if (isvInfoMapper.getByColumn("app_key", param.getAppKey()) != null) { - throw new ApiException("appKey已存在"); + throw new BizException("appKey已存在"); } formatForm(param); IsvInfo rec = new IsvInfo(); @@ -175,9 +177,9 @@ public class IsvApi { try { log.info("消息推送--ISV信息(update), path:{}, data:{}", path, data); ZookeeperContext.updatePathData(path, data); - } catch (Exception e) { + } catch (ZookeeperPathNotExistException e) { log.error("发送isvChannelMsg失败, path:{}, msg:{}", path, data, e); - throw new ApiException("保存失败,请查看日志"); + throw new BizException("路径不存在"); } } @@ -222,7 +224,7 @@ public class IsvApi { routePermissionService.sendIsvRolePermissionToZookeeper(isvInfo.getAppKey(), roleCodeList); } catch (Exception e) { log.error("保存到zookeeper中失败,isvInfo:{}, roleCodeList:{}", isvInfo, roleCodeList); - throw new ApiException("保存失败,请查看日志"); + throw new BizException("保存失败,请查看日志"); } } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java index 5d5d524c..e6ddb5cd 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitApi.java @@ -4,7 +4,6 @@ import com.gitee.easyopen.annotation.Api; import com.gitee.easyopen.annotation.ApiService; import com.gitee.easyopen.doc.annotation.ApiDoc; import com.gitee.easyopen.doc.annotation.ApiDocMethod; -import com.gitee.easyopen.exception.ApiException; import com.gitee.easyopen.util.CopyUtil; import com.gitee.fastmybatis.core.query.Query; import com.gitee.sop.adminserver.api.service.param.LimitParam; @@ -12,6 +11,7 @@ import com.gitee.sop.adminserver.api.service.param.RouteSearchParam; import com.gitee.sop.adminserver.api.service.result.LimitVO; import com.gitee.sop.adminserver.bean.GatewayRouteDefinition; import com.gitee.sop.adminserver.bean.RouteConfigDto; +import com.gitee.sop.adminserver.common.BizException; import com.gitee.sop.adminserver.common.LimitEnum; import com.gitee.sop.adminserver.entity.ConfigRouteLimit; import com.gitee.sop.adminserver.mapper.ConfigRouteLimitMapper; @@ -118,7 +118,7 @@ public class LimitApi { routeConfigService.sendRouteConfigMsg(routeConfigDto); } catch (Exception e) { log.error("推送限流消息错误, param:{}", param, e); - throw new ApiException("修改失败,请查看日志"); + throw new BizException("修改失败,请查看日志"); } } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitNewApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitNewApi.java index e31fe409..d67ee856 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitNewApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LimitNewApi.java @@ -4,7 +4,6 @@ import com.gitee.easyopen.annotation.Api; import com.gitee.easyopen.annotation.ApiService; import com.gitee.easyopen.doc.annotation.ApiDoc; import com.gitee.easyopen.doc.annotation.ApiDocMethod; -import com.gitee.easyopen.exception.ApiException; import com.gitee.easyopen.util.CopyUtil; import com.gitee.fastmybatis.core.PageInfo; import com.gitee.fastmybatis.core.query.Query; @@ -15,6 +14,7 @@ import com.gitee.sop.adminserver.api.service.param.LimitNewParam; import com.gitee.sop.adminserver.api.service.param.LimitNewUpdateParam; import com.gitee.sop.adminserver.api.service.result.LimitNewVO; import com.gitee.sop.adminserver.bean.ConfigLimitDto; +import com.gitee.sop.adminserver.common.BizException; import com.gitee.sop.adminserver.entity.ConfigLimit; import com.gitee.sop.adminserver.mapper.ConfigLimitMapper; import com.gitee.sop.adminserver.service.RouteConfigService; @@ -65,7 +65,7 @@ public class LimitNewApi { routeConfigService.sendLimitConfigMsg(configLimitDto); } catch (Exception e) { log.error("推送限流消息错误, param:{}", param, e); - throw new ApiException("新增失败,请查看日志"); + throw new BizException("新增失败,请查看日志"); } } @@ -87,7 +87,7 @@ public class LimitNewApi { routeConfigService.sendLimitConfigMsg(configLimitDto); } catch (Exception e) { log.error("推送限流消息错误, param:{}", param, e); - throw new ApiException("修改失败,请查看日志"); + throw new BizException("修改失败,请查看日志"); } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java index ad037c42..a72a29d0 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java @@ -6,11 +6,11 @@ import com.gitee.easyopen.annotation.Api; import com.gitee.easyopen.annotation.ApiService; import com.gitee.easyopen.doc.annotation.ApiDoc; import com.gitee.easyopen.doc.annotation.ApiDocMethod; -import com.gitee.easyopen.exception.ApiException; import com.gitee.easyopen.verify.DefaultMd5Verifier; import com.gitee.fastmybatis.core.query.Query; import com.gitee.sop.adminserver.api.service.param.LogMonitorInstanceAddParam; import com.gitee.sop.adminserver.api.service.result.LogMonitorInstanceVO; +import com.gitee.sop.adminserver.common.BizException; import com.gitee.sop.adminserver.common.QueryUtil; import com.gitee.sop.adminserver.entity.ConfigCommon; import com.gitee.sop.adminserver.mapper.ConfigCommonMapper; @@ -80,7 +80,7 @@ public class LogApi { } } catch (Exception e) { log.error("获取日志信息出错", e); - throw new ApiException("获取日志信息出错"); + throw new BizException("获取日志信息出错"); } } Collections.sort(ret, Comparator.comparing(LogMonitorInstanceVO::getCount)); @@ -98,7 +98,7 @@ public class LogApi { String ipPort = configCommon.getConfigKey(); this.requestLogServer(ipPort, "clearErrors"); } catch (Exception e) { - throw new ApiException("清除失败"); + throw new BizException("清除失败"); } } @@ -122,7 +122,7 @@ public class LogApi { .eq("config_key", ipPort); ConfigCommon rec = configCommonMapper.getByQuery(query); if (rec != null) { - throw new ApiException("该实例已添加"); + throw new BizException("该实例已添加"); } ConfigCommon configCommon = new ConfigCommon(); configCommon.setConfigGroup(LOG_MONITOR_INSTANCE); @@ -137,11 +137,11 @@ public class LogApi { JSONObject jsonObject = JSON.parseObject(json); if (!CODE_SUCCESS.equals(jsonObject.getString("code"))) { log.error("请求结果:{}", json); - throw new ApiException("添加失败"); + throw new BizException("添加失败"); } } catch (Exception e) { log.error("添加失败", e); - throw new ApiException("添加失败"); + throw new BizException("添加失败"); } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java index 433a0b00..526ebba6 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java @@ -5,18 +5,21 @@ import com.gitee.easyopen.annotation.Api; import com.gitee.easyopen.annotation.ApiService; import com.gitee.easyopen.doc.annotation.ApiDoc; import com.gitee.easyopen.doc.annotation.ApiDocMethod; -import com.gitee.easyopen.exception.ApiException; import com.gitee.easyopen.util.CopyUtil; import com.gitee.fastmybatis.core.query.Query; import com.gitee.sop.adminserver.api.isv.result.RoleVO; -import com.gitee.sop.adminserver.api.service.param.RouteParam; +import com.gitee.sop.adminserver.api.service.param.RouteAddParam; +import com.gitee.sop.adminserver.api.service.param.RouteDeleteParam; import com.gitee.sop.adminserver.api.service.param.RoutePermissionParam; import com.gitee.sop.adminserver.api.service.param.RouteSearchParam; +import com.gitee.sop.adminserver.api.service.param.RouteUpdateParam; import com.gitee.sop.adminserver.api.service.result.RouteVO; -import com.gitee.sop.adminserver.api.service.result.ServiceInfo; import com.gitee.sop.adminserver.bean.GatewayRouteDefinition; import com.gitee.sop.adminserver.bean.RouteConfigDto; import com.gitee.sop.adminserver.bean.ZookeeperContext; +import com.gitee.sop.adminserver.common.BizException; +import com.gitee.sop.adminserver.common.ZookeeperPathExistException; +import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException; import com.gitee.sop.adminserver.entity.ConfigRouteBase; import com.gitee.sop.adminserver.entity.PermRole; import com.gitee.sop.adminserver.entity.PermRolePermission; @@ -28,14 +31,13 @@ import com.gitee.sop.adminserver.service.RoutePermissionService; import com.gitee.sop.adminserver.service.RouteService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; -import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Date; import java.util.List; import java.util.stream.Collectors; @@ -96,67 +98,84 @@ public class RouteApi { return routeDefinitionList; } + @Api(name = "route.add") + @ApiDocMethod(description = "新增路由") + void addRoute(RouteAddParam param) { + String id = param.getName() + param.getVersion(); + String routePath = ZookeeperContext.buildRoutePath(param.getServiceId(), id); + GatewayRouteDefinition routeDefinition = new GatewayRouteDefinition(); + CopyUtil.copyPropertiesIgnoreNull(param, routeDefinition); + routeDefinition.setId(id); + routeDefinition.setCustom(1); + try { + ZookeeperContext.addPath(routePath, JSON.toJSONString(routeDefinition)); + } catch (ZookeeperPathExistException e) { + throw new BizException("路由已存在"); + } + this.updateRouteConfig(routeDefinition); + } + @Api(name = "route.update") @ApiDocMethod(description = "修改路由") - void updateRoute(RouteParam param) throws Exception { - String serviceIdPath = ZookeeperContext.getSopRouteRootPath() + "/" + param.getServiceId(); - String zookeeperRoutePath = serviceIdPath + "/" + param.getId(); - String data = ZookeeperContext.getData(zookeeperRoutePath); - GatewayRouteDefinition routeDefinition = JSON.parseObject(data, GatewayRouteDefinition.class); + void updateRoute(RouteUpdateParam param) { + String routePath = ZookeeperContext.buildRoutePath(param.getServiceId(), param.getId()); + GatewayRouteDefinition routeDefinition = this.getGatewayRouteDefinition(routePath); CopyUtil.copyPropertiesIgnoreNull(param, routeDefinition); - ZookeeperContext.updatePathData(zookeeperRoutePath, JSON.toJSONString(routeDefinition)); + try { + ZookeeperContext.updatePathData(routePath, JSON.toJSONString(routeDefinition)); + } catch (ZookeeperPathNotExistException e) { + throw new BizException("路由不存在"); + } + this.updateRouteConfig(routeDefinition); + } - this.updateRouteConfig(param); + @Api(name = "route.del") + @ApiDocMethod(description = "删除路由") + void delRoute(RouteDeleteParam param) { + String routePath = ZookeeperContext.buildRoutePath(param.getServiceId(), param.getId()); + GatewayRouteDefinition routeDefinition = this.getGatewayRouteDefinition(routePath); + if (!BooleanUtils.toBoolean(routeDefinition.getCustom())) { + throw new BizException("非自定义路由,无法删除"); + } + ZookeeperContext.deletePathDeep(routePath); } - @Api(name = "route.add") - @ApiDocMethod(description = "新增路由") - void addRoute(RouteParam param) throws Exception { - String serviceIdPath = ZookeeperContext.getSopRouteRootPath() + "/" + param.getServiceId(); - String zookeeperRoutePath = serviceIdPath + "/" + param.getId(); - if (ZookeeperContext.isPathExist(zookeeperRoutePath)) { - throw new ApiException("id已存在"); + private GatewayRouteDefinition getGatewayRouteDefinition(String zookeeperRoutePath) { + String data = null; + try { + data = ZookeeperContext.getData(zookeeperRoutePath); + } catch (ZookeeperPathNotExistException e) { + throw new BizException("路由不存在"); } - GatewayRouteDefinition routeDefinition = new GatewayRouteDefinition(); - CopyUtil.copyPropertiesIgnoreNull(param, routeDefinition); - ZookeeperContext.createNewData(zookeeperRoutePath, JSON.toJSONString(routeDefinition)); - ServiceInfo serviceInfo = new ServiceInfo(); - serviceInfo.setServiceId(param.getServiceId()); - serviceInfo.setDescription(param.getServiceId()); - String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); - serviceInfo.setCreateTime(now); - serviceInfo.setUpdateTime(now); - ZookeeperContext.updatePathData(serviceIdPath, JSON.toJSONString(serviceInfo)); - - this.updateRouteConfig(param); + return JSON.parseObject(data, GatewayRouteDefinition.class); } - private void updateRouteConfig(RouteParam param) { + private void updateRouteConfig(GatewayRouteDefinition routeDefinition) { try { - String routeId = param.getId(); + String routeId = routeDefinition.getId(); ConfigRouteBase configRouteBase = configRouteBaseMapper.getByColumn("route_id", routeId); boolean doSave = configRouteBase == null; if (doSave) { configRouteBase = new ConfigRouteBase(); - configRouteBase.setRouteId(param.getId()); + configRouteBase.setRouteId(routeId); } - configRouteBase.setStatus(param.getStatus().byteValue()); + configRouteBase.setStatus((byte) routeDefinition.getStatus()); int i = doSave ? configRouteBaseMapper.save(configRouteBase) : configRouteBaseMapper.update(configRouteBase); if (i > 0) { - this.sendMsg(param); + this.sendMsg(routeDefinition); } } catch (Exception e) { log.error("发送msg失败", e); } } - private void sendMsg(RouteParam param) throws Exception { + private void sendMsg(GatewayRouteDefinition routeDefinition) { RouteConfigDto routeConfigDto = new RouteConfigDto(); - routeConfigDto.setRouteId(param.getId()); - routeConfigDto.setStatus(param.getStatus()); + routeConfigDto.setRouteId(routeDefinition.getId()); + routeConfigDto.setStatus(routeDefinition.getStatus()); routeConfigService.sendRouteConfigMsg(routeConfigDto); } @@ -164,7 +183,7 @@ public class RouteApi { @ApiDocMethod(description = "获取路由对应的角色", elementClass = RoleVO.class) List getRouteRole(RouteSearchParam param) { if (StringUtils.isBlank(param.getId())) { - throw new ApiException("id不能为空"); + throw new BizException("id不能为空"); } return this.getRouteRole(param.getId()); } @@ -209,7 +228,7 @@ public class RouteApi { routePermissionService.sendRoutePermissionReloadMsg(); } catch (Exception e) { log.info("消息推送--路由权限(reload)失败", e); - throw new ApiException("修改失败,请查看日志"); + throw new BizException("修改失败,请查看日志"); } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java index 93653a3b..3d2c972e 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java @@ -5,7 +5,7 @@ import com.gitee.easyopen.annotation.Api; import com.gitee.easyopen.annotation.ApiService; import com.gitee.easyopen.doc.annotation.ApiDoc; import com.gitee.easyopen.doc.annotation.ApiDocMethod; -import com.gitee.easyopen.exception.ApiException; +import com.gitee.sop.adminserver.api.service.param.ServiceAddParam; import com.gitee.sop.adminserver.api.service.param.ServiceInstanceParam; import com.gitee.sop.adminserver.api.service.param.ServiceSearchParam; import com.gitee.sop.adminserver.api.service.result.ServiceInfo; @@ -14,11 +14,16 @@ import com.gitee.sop.adminserver.bean.EurekaApplication; import com.gitee.sop.adminserver.bean.EurekaApps; import com.gitee.sop.adminserver.bean.EurekaInstance; import com.gitee.sop.adminserver.bean.EurekaUri; +import com.gitee.sop.adminserver.bean.ServiceRouteInfo; import com.gitee.sop.adminserver.bean.ZookeeperContext; +import com.gitee.sop.adminserver.common.BizException; +import com.gitee.sop.adminserver.common.ZookeeperPathExistException; +import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException; import lombok.extern.slf4j.Slf4j; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.apache.curator.framework.recipes.cache.ChildData; import org.springframework.beans.BeanUtils; @@ -28,6 +33,7 @@ import org.springframework.core.env.Environment; import javax.annotation.PostConstruct; import java.io.IOException; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -48,8 +54,6 @@ public class ServiceApi { private String eurekaUrl; - // eureka.client.serviceUrl.defaultZone - @Api(name = "service.list") @ApiDocMethod(description = "服务列表(旧)", elementClass = ServiceInfo.class) List listServiceInfo(ServiceSearchParam param) throws Exception { @@ -74,6 +78,48 @@ public class ServiceApi { return serviceInfoList; } + @Api(name = "service.custom.add") + @ApiDocMethod(description = "添加服务") + void addService(ServiceAddParam param) { + String serviceId = param.getServiceId(); + String servicePath = ZookeeperContext.buildServiceIdPath(serviceId); + ServiceRouteInfo serviceRouteInfo = new ServiceRouteInfo(); + Date now = new Date(); + serviceRouteInfo.setServiceId(serviceId); + serviceRouteInfo.setDescription("自定义服务"); + serviceRouteInfo.setCreateTime(now); + serviceRouteInfo.setUpdateTime(now); + serviceRouteInfo.setCustom(BooleanUtils.toInteger(true)); + String serviceData = JSON.toJSONString(serviceRouteInfo); + try { + ZookeeperContext.addPath(servicePath, serviceData); + } catch (ZookeeperPathExistException e) { + throw new BizException("服务已存在"); + } + } + + @Api(name = "service.custom.del") + @ApiDocMethod(description = "删除自定义服务") + void delService(ServiceSearchParam param) { + String serviceId = param.getServiceId(); + String servicePath = ZookeeperContext.buildServiceIdPath(serviceId); + String data = null; + try { + data = ZookeeperContext.getData(servicePath); + } catch (ZookeeperPathNotExistException e) { + throw new BizException("服务不存在"); + } + if (StringUtils.isBlank(data)) { + throw new BizException("非自定义服务,无法删除"); + } + ServiceRouteInfo serviceRouteInfo = JSON.parseObject(data, ServiceRouteInfo.class); + int custom = serviceRouteInfo.getCustom(); + if (!BooleanUtils.toBoolean(custom)) { + throw new BizException("非自定义服务,无法删除"); + } + ZookeeperContext.deletePathDeep(servicePath); + } + @Api(name = "service.instance.list") @ApiDocMethod(description = "服务列表", elementClass = ServiceInfoVo.class) List listService(ServiceSearchParam param) throws Exception { @@ -133,7 +179,7 @@ public class ServiceApi { return response.body().string(); } else { log.error("操作失败,url:{}, msg:{}, code:{}", eurekaUri.getUri(args), response.message(), response.code()); - throw new ApiException("操作失败", String.valueOf(response.code())); + throw new BizException("操作失败", String.valueOf(response.code())); } } @@ -141,7 +187,7 @@ public class ServiceApi { protected void after() { String eurekaUrls = environment.getProperty("eureka.client.serviceUrl.defaultZone"); if (StringUtils.isBlank(eurekaUrls)) { - throw new ApiException("未指定eureka.client.serviceUrl.defaultZone参数"); + throw new BizException("未指定eureka.client.serviceUrl.defaultZone参数"); } String url = eurekaUrls.split("\\,")[0]; if (url.endsWith("/")) { diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitNewAddParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitNewAddParam.java index 0936c270..e7da2c63 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitNewAddParam.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitNewAddParam.java @@ -41,10 +41,12 @@ public class LimitNewAddParam { /** 返回的错误码, 数据库字段:limit_code */ @ApiDocField(description = "返回的错误码") + @Length(max = 64, message = "limitCode长度不能超过64") private String limitCode; /** 返回的错误信息, 数据库字段:limit_msg */ @ApiDocField(description = "返回的错误信息") + @Length(max = 100, message = "limitMsg长度不能超过100") private String limitMsg; /** 令牌桶容量, 数据库字段:token_bucket_count */ diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitNewUpdateParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitNewUpdateParam.java index d04630e6..aebadc77 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitNewUpdateParam.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LimitNewUpdateParam.java @@ -46,10 +46,12 @@ public class LimitNewUpdateParam { /** 返回的错误码, 数据库字段:limit_code */ @ApiDocField(description = "返回的错误码") + @Length(max = 64, message = "limitCode长度不能超过64") private String limitCode; /** 返回的错误信息, 数据库字段:limit_msg */ @ApiDocField(description = "返回的错误信息") + @Length(max = 100, message = "limitMsg长度不能超过100") private String limitMsg; /** 令牌桶容量, 数据库字段:token_bucket_count */ diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteAddParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteAddParam.java new file mode 100644 index 00000000..f72a274e --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteAddParam.java @@ -0,0 +1,76 @@ +package com.gitee.sop.adminserver.api.service.param; + +import com.gitee.easyopen.doc.annotation.ApiDocField; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author tanghc + */ +@Getter +@Setter +public class RouteAddParam { + + @NotBlank(message = "serviceId不能为空") + @Length(max = 100, message = "serviceId长度不能超过100") + @ApiDocField(description = "serviceId") + private String serviceId; + + /** + * 接口名 + */ + @NotBlank(message = "接口名不能为空") + @Length(max = 100, message = "name长度不能超过100") + @ApiDocField(description = "接口名") + private String name; + + /** + * 版本号 + */ + @NotBlank(message = "版本号不能为空") + @Length(max = 100, message = "version长度不能超过100") + @ApiDocField(description = "版本号") + private String version; + + /** + * 路由规则转发的目标uri + */ + @NotBlank(message = "uri不能为空") + @Length(max = 100, message = "uri长度不能超过100") + @ApiDocField(description = "路由uri") + private String uri; + + /** + * uri后面跟的path + */ + @ApiDocField(description = "路由path") + @Length(max = 100, message = "path长度不能超过100") + private String path; + + /** + * 是否忽略验证,业务参数验证除外 + */ + @ApiDocField(description = "是否忽略验证,业务参数验证除外,1:忽略,0:不忽略") + private Integer ignoreValidate; + + /** + * 合并结果,统一格式输出 + */ + @ApiDocField(description = "合并结果,统一格式输出,1:合并,2:不合并") + private Integer mergeResult; + + /** + * 状态 + */ + @NotNull + @ApiDocField(description = "状态,0:审核,1:启用,2:禁用") + private Integer status; + + @ApiDocField(description = "是否是自定义路由,1:是,0:否") + private Integer custom; + +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteDeleteParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteDeleteParam.java new file mode 100644 index 00000000..8ab52da5 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteDeleteParam.java @@ -0,0 +1,22 @@ +package com.gitee.sop.adminserver.api.service.param; + +import com.gitee.easyopen.doc.annotation.ApiDocField; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotBlank; + +/** + * @author tanghc + */ +@Getter +@Setter +public class RouteDeleteParam { + @ApiDocField(description = "服务名serviceId") + @NotBlank(message = "serviceId不能为空") + private String serviceId; + + @ApiDocField(description = "路由id") + @NotBlank(message = "id不能为空") + private String id; +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteUpdateParam.java similarity index 54% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteParam.java rename to sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteUpdateParam.java index 3ea6bbd4..be0ccf1c 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteParam.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/RouteUpdateParam.java @@ -3,6 +3,7 @@ package com.gitee.sop.adminserver.api.service.param; import com.gitee.easyopen.doc.annotation.ApiDocField; import lombok.Getter; import lombok.Setter; +import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -12,23 +13,25 @@ import javax.validation.constraints.NotNull; */ @Getter @Setter -public class RouteParam { - - @NotBlank(message = "serviceId不能为空") - @ApiDocField(description = "serviceId") - private String serviceId; +public class RouteUpdateParam { /** * 路由的Id */ @NotBlank(message = "id不能为空") @ApiDocField(description = "路由id") - private String id = ""; + private String id; + + @NotBlank(message = "serviceId不能为空") + @Length(max = 100, message = "serviceId长度不能超过100") + @ApiDocField(description = "serviceId") + private String serviceId; /** * 路由规则转发的目标uri */ @NotBlank(message = "uri不能为空") + @Length(max = 100, message = "uri长度不能超过100") @ApiDocField(description = "路由uri") private String uri; @@ -36,8 +39,21 @@ public class RouteParam { * uri后面跟的path */ @ApiDocField(description = "路由path") + @Length(max = 100, message = "path长度不能超过100") private String path; + /** + * 是否忽略验证,业务参数验证除外 + */ + @ApiDocField(description = "是否忽略验证,业务参数验证除外,1:忽略,0:不忽略") + private Integer ignoreValidate; + + /** + * 合并结果,统一格式输出 + */ + @ApiDocField(description = "合并结果,统一格式输出,1:合并,2:不合并") + private Integer mergeResult; + /** * 状态 */ @@ -45,4 +61,7 @@ public class RouteParam { @ApiDocField(description = "状态,0:审核,1:启用,2:禁用") private Integer status; + @ApiDocField(description = "是否是自定义路由,1:是,0:否") + private Integer custom; + } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/ServiceAddParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/ServiceAddParam.java new file mode 100644 index 00000000..e9dedcbc --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/ServiceAddParam.java @@ -0,0 +1,21 @@ +package com.gitee.sop.adminserver.api.service.param; + +import com.gitee.easyopen.doc.annotation.ApiDocField; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; + +/** + * @author tanghc + */ +@Getter +@Setter +public class ServiceAddParam { + + @ApiDocField(description = "服务名serviceId") + @Length(max = 100, message = "长度不能超过100") + @NotBlank(message = "serviceId不能为空") + private String serviceId; +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInfo.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInfo.java index 85d561fb..b44a4e29 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInfo.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInfo.java @@ -19,4 +19,8 @@ public class ServiceInfo { @ApiDocField(description = "描述") private String description; + + /** 是否是自定义服务,1:是,0:否 */ + @ApiDocField(description = "是否是自定义服务,1:是,0:否") + private Integer custom; } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/GatewayRouteDefinition.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/GatewayRouteDefinition.java index 8ad92c47..9dd60585 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/GatewayRouteDefinition.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/GatewayRouteDefinition.java @@ -1,5 +1,6 @@ package com.gitee.sop.adminserver.bean; +import com.alibaba.fastjson.annotation.JSONField; import com.gitee.easyopen.doc.annotation.ApiDocField; import lombok.Data; @@ -30,11 +31,13 @@ public class GatewayRouteDefinition { /** * 路由断言集合配置 */ + @JSONField(serialize = false) private List predicates = new ArrayList<>(); /** * 路由过滤器集合配置 */ + @JSONField(serialize = false) private List filters = new ArrayList<>(); /** @@ -67,14 +70,20 @@ public class GatewayRouteDefinition { private int status = 1; /** - * 合并结果 + * 合并结果,统一格式输出 */ - @ApiDocField(description = "合并结果,1:合并,2:不合并") + @ApiDocField(description = "合并结果,统一格式输出,1:合并,0:不合并") private int mergeResult = 1; /** * 是否需要授权才能访问 */ - @ApiDocField(description = "是否需要授权才能访问,1:是,2:否") + @ApiDocField(description = "是否需要授权才能访问,1:是,0:否") private int permission; + + /** + * 是否是自定义路由 + */ + @ApiDocField(description = "是否是自定义路由,1:是,0:否") + private int custom; } \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceRouteInfo.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceRouteInfo.java index 25317cf2..9a3d1034 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceRouteInfo.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceRouteInfo.java @@ -24,4 +24,7 @@ public class ServiceRouteInfo { @JSONField(serialize = false) private List routeDefinitionList; + + /** 是否是自定义服务,1:是,0:否 */ + private int custom; } \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java index 8f8d8487..2f2ae540 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java @@ -1,6 +1,9 @@ package com.gitee.sop.adminserver.bean; -import com.gitee.easyopen.exception.ApiException; +import com.gitee.sop.adminserver.common.ZookeeperOperationException; +import com.gitee.sop.adminserver.common.ZookeeperPathExistException; +import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.curator.framework.CuratorFramework; @@ -23,6 +26,7 @@ import static com.gitee.sop.adminserver.bean.SopAdminConstants.SOP_ROUTE_PERMISS * @author tanghc */ @Configuration +@Slf4j public class ZookeeperContext { private static CuratorFramework client; @@ -55,6 +59,24 @@ public class ZookeeperContext { return SopAdminConstants.SOP_SERVICE_ROUTE_PATH; } + public static String buildServiceIdPath(String serviceId) { + if (StringUtils.isBlank(serviceId)) { + throw new NullPointerException("serviceId不能为空"); + } + return getSopRouteRootPath() + "/" + serviceId; + } + + public static String buildRoutePath(String serviceId, String routeId) { + if (StringUtils.isBlank(serviceId)) { + throw new NullPointerException("serviceId不能为空"); + } + if (StringUtils.isBlank(routeId)) { + throw new NullPointerException("routeId不能为空"); + } + String serviceIdPath = getSopRouteRootPath() + "/" + serviceId; + return serviceIdPath + "/" + routeId; + } + public static String getRoutePermissionPath() { return SOP_ROUTE_PERMISSION_PATH; } @@ -95,30 +117,72 @@ public class ZookeeperContext { * 对已存在的path赋值。如果path不存在抛异常 * * @param path 已存在的 - * @param data + * @param data 数据 * @return - * @throws Exception + * @throws ZookeeperPathNotExistException */ - public static Stat updatePathData(String path, String data) throws Exception { + public static Stat updatePathData(String path, String data) throws ZookeeperPathNotExistException { if (!isPathExist(path)) { - throw new ApiException("path " + path + " 不存在"); + throw new ZookeeperPathNotExistException("path " + path + " 不存在"); + } + try { + return getClient().setData().forPath(path, data.getBytes()); + } catch (Exception e) { + throw new ZookeeperOperationException("updatePathData error, path=" + path, e); } - return getClient().setData().forPath(path, data.getBytes()); } /** * 创建新的path,并赋值。如果path已存在抛异常 * @param path 待创建的path * @param data 值 + * @throws ZookeeperPathExistException */ - public static String createNewData(String path, String data) throws Exception { + public static String addPath(String path, String data) throws ZookeeperPathExistException { if (isPathExist(path)) { - throw new ApiException("path " + path + " 已存在"); + throw new ZookeeperPathExistException("path " + path + " 已存在"); + } + try { + return getClient().create() + // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点 + .creatingParentContainersIfNeeded() + .forPath(path, data.getBytes()); + } catch (Exception e) { + throw new ZookeeperOperationException("addPath error path=" + path, e); + } + } + + /** + * 删除节点及子节点 + * @param path + */ + public static void deletePathDeep(String path) { + try { + getClient().delete() + .deletingChildrenIfNeeded() + .forPath(path); + } catch (Exception e) { + throw new ZookeeperOperationException("deletePathDeep error path=" + path, e); + } + } + + /** + * 创建新的path,并赋值。如果path已存在则不创建 + * @param path 待创建的path + * @param data 值 + */ + public static String addPathQuietly(String path, String data) { + if (isPathExist(path)) { + return path; + } + try { + return getClient().create() + // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点 + .creatingParentContainersIfNeeded() + .forPath(path, data.getBytes()); + } catch (Exception e) { + throw new ZookeeperOperationException("addPathQuietly error path=" + path, e); } - return getClient().create() - // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点 - .creatingParentContainersIfNeeded() - .forPath(path, data.getBytes()); } /** @@ -126,23 +190,36 @@ public class ZookeeperContext { * @param path * @param data * @return - * @throws Exception */ - public static String createOrUpdateData(String path, String data) throws Exception { - return getClient().create() - // 如果节点存在则Curator将会使用给出的数据设置这个节点的值 - .orSetData() - // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点 - .creatingParentContainersIfNeeded() - .forPath(path, data.getBytes()); + public static String createOrUpdateData(String path, String data) { + try { + return getClient().create() + // 如果节点存在则Curator将会使用给出的数据设置这个节点的值 + .orSetData() + // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点 + .creatingParentContainersIfNeeded() + .forPath(path, data.getBytes()); + } catch (Exception e) { + throw new ZookeeperOperationException("createOrUpdateData error path=" + path, e); + } } - public static String getData(String path) throws Exception { + /** + * 获取节点内容 + * @param path + * @return + * @throws ZookeeperPathNotExistException + */ + public static String getData(String path) throws ZookeeperPathNotExistException { if (!isPathExist(path)) { - return null; + throw new ZookeeperPathNotExistException("path 不存在, path=" + path); + } + try { + byte[] data = getClient().getData().forPath(path); + return new String(data); + } catch (Exception e) { + throw new ZookeeperOperationException("getData error path=" + path, e); } - byte[] data = getClient().getData().forPath(path); - return new String(data); } /** @@ -150,9 +227,8 @@ public class ZookeeperContext { * * @param parentPath 父节点 * @return - * @throws Exception */ - public static List getChildrenData(String parentPath) throws Exception { + public static List getChildrenData(String parentPath) { PathChildrenCache pathChildrenCache = buildPathChildrenCache(parentPath); if (pathChildrenCache == null) { return Collections.emptyList(); @@ -160,7 +236,7 @@ public class ZookeeperContext { return pathChildrenCache.getCurrentData(); } - public static PathChildrenCache buildPathChildrenCache(String path) throws Exception { + public static PathChildrenCache buildPathChildrenCache(String path) { if (!isPathExist(path)) { return null; } @@ -168,7 +244,11 @@ public class ZookeeperContext { // 且第三个参数要设置为true,不然ChildData对象中的getData返回null PathChildrenCache childrenCache = new PathChildrenCache(client, path, true); // 列出子节点数据列表,需要使用BUILD_INITIAL_CACHE同步初始化模式才能获得,异步是获取不到的 - childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE); + try { + childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE); + } catch (Exception e) { + throw new ZookeeperOperationException("buildPathChildrenCache error path=" + path, e); + } return childrenCache; } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/BizException.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/BizException.java new file mode 100644 index 00000000..0c7c46ce --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/BizException.java @@ -0,0 +1,33 @@ +package com.gitee.sop.adminserver.common; + +import com.gitee.easyopen.exception.ApiException; +import com.gitee.easyopen.message.Error; + +/** + * @author tanghc + */ +public class BizException extends ApiException { + public BizException(String msg) { + super(msg, "4000"); + } + + public BizException(Exception e) { + super(e); + } + + public BizException(Error error) { + super(error); + } + + public BizException(String msg, String code) { + super(msg, code); + } + + public BizException(String msg, String code, Object data) { + super(msg, code, data); + } + + public BizException(Error error, Object data) { + super(error, data); + } +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperOperationException.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperOperationException.java new file mode 100644 index 00000000..d75f35df --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperOperationException.java @@ -0,0 +1,26 @@ +package com.gitee.sop.adminserver.common; + +/** + * @author tanghc + */ +public class ZookeeperOperationException extends RuntimeException { + + public ZookeeperOperationException() { + } + + public ZookeeperOperationException(String message) { + super(message); + } + + public ZookeeperOperationException(String message, Throwable cause) { + super(message, cause); + } + + public ZookeeperOperationException(Throwable cause) { + super(cause); + } + + public ZookeeperOperationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperPathExistException.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperPathExistException.java new file mode 100644 index 00000000..4ec2e104 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperPathExistException.java @@ -0,0 +1,10 @@ +package com.gitee.sop.adminserver.common; + +/** + * @author tanghc + */ +public class ZookeeperPathExistException extends Exception { + public ZookeeperPathExistException(String message) { + super(message); + } +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperPathNotExistException.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperPathNotExistException.java new file mode 100644 index 00000000..bf690146 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/common/ZookeeperPathNotExistException.java @@ -0,0 +1,10 @@ +package com.gitee.sop.adminserver.common; + +/** + * @author tanghc + */ +public class ZookeeperPathNotExistException extends Exception { + public ZookeeperPathNotExistException(String message) { + super(message); + } +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteConfigService.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteConfigService.java index ac02f8db..0b09a09b 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteConfigService.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteConfigService.java @@ -20,7 +20,7 @@ public class RouteConfigService { * @param routeConfigDto * @throws Exception */ - public void sendRouteConfigMsg(RouteConfigDto routeConfigDto) throws Exception { + public void sendRouteConfigMsg(RouteConfigDto routeConfigDto) { String configData = JSON.toJSONString(routeConfigDto); ChannelMsg channelMsg = new ChannelMsg("update", configData); String jsonData = JSON.toJSONString(channelMsg); diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteService.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteService.java index 4b48c084..b3fe1670 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteService.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RouteService.java @@ -10,7 +10,6 @@ import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; -import java.util.stream.Stream; import static java.util.stream.Collectors.toList; @@ -44,8 +43,7 @@ public class RouteService { return isRoute && gatewayRouteDefinition.getId().contains(id); } }) - .collect(toList()) - ; + .collect(toList()); return routeDefinitionStream; } diff --git a/sop-admin/sop-admin-server/src/main/resources/public/index.html b/sop-admin/sop-admin-server/src/main/resources/public/index.html index 73897f95..ddd04955 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/index.html +++ b/sop-admin/sop-admin-server/src/main/resources/public/index.html @@ -1 +1 @@ -SOP Admin

\ No newline at end of file +SOP Admin
\ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-29b24c82.857979fb.css b/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-29b24c82.857979fb.css deleted file mode 100644 index 26ea8fa2..00000000 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-29b24c82.857979fb.css +++ /dev/null @@ -1 +0,0 @@ -.limit-tip[data-v-29df7fee]{cursor:pointer;margin-left:10px} \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-2a9bc230.2dae711a.css b/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-2a9bc230.2dae711a.css new file mode 100644 index 00000000..0852192c --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-2a9bc230.2dae711a.css @@ -0,0 +1 @@ +.limit-tip[data-v-31efca04]{cursor:pointer;margin-left:10px} \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-19100986.a43114f3.css b/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-37401378.a43114f3.css similarity index 100% rename from sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-19100986.a43114f3.css rename to sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-37401378.a43114f3.css diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-6a68a33e.3b12267b.css b/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-6a68a33e.3b12267b.css new file mode 100644 index 00000000..e41f7849 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-6a68a33e.3b12267b.css @@ -0,0 +1 @@ +.custom-tree-node{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:14px;padding-right:8px}.el-input.is-disabled .el-input__inner,.el-radio__input.is-disabled+span.el-radio__label{color:#909399} \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.36a3cb86.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.3225a72c.js similarity index 64% rename from sop-admin/sop-admin-server/src/main/resources/public/static/js/app.36a3cb86.js rename to sop-admin/sop-admin-server/src/main/resources/public/static/js/app.3225a72c.js index d0df45df..5612aac1 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.36a3cb86.js +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.3225a72c.js @@ -1 +1 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["app"],{0:function(e,t,n){e.exports=n("56d7")},"0cb8":function(e,t,n){},"186a":function(e,t,n){"use strict";var a=n("dc52"),i=n.n(a);i.a},"18f0":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-link",use:"icon-link-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"1f59":function(e,t,n){},2536:function(e,t,n){},2635:function(e,t,n){},"2a3d":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-password",use:"icon-password-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"30c3":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-example",use:"icon-example-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"34c8":function(e,t,n){"use strict";var a=n("5332"),i=n.n(a);i.a},"405a":function(e,t,n){"use strict";var a=n("1f59"),i=n.n(a);i.a},"47f1":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-table",use:"icon-table-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"4df5":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye",use:"icon-eye-usage",viewBox:"0 0 128 64",content:''});r.a.add(s);t["default"]=s},"50be":function(e,t,n){"use strict";var a=n("2536"),i=n.n(a);i.a},"51ff":function(e,t,n){var a={"./dashboard.svg":"f782","./example.svg":"30c3","./eye-open.svg":"d7ec","./eye.svg":"4df5","./form.svg":"eb1b","./link.svg":"18f0","./nested.svg":"dcf8","./password.svg":"2a3d","./table.svg":"47f1","./tree.svg":"93cd","./user.svg":"b3b5"};function i(e){var t=o(e);return n(t)}function o(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return t}i.keys=function(){return Object.keys(a)},i.resolve=o,e.exports=i,i.id="51ff"},5332:function(e,t,n){},"56d7":function(e,t,n){"use strict";n.r(t);n("cadf"),n("551c"),n("f751"),n("097d");var a=n("2b0e"),i=(n("f5df"),n("5c96")),o=n.n(i),r=(n("0fae"),n("f0d9")),s=n.n(r),c=(n("b20f"),function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"app"}},[n("router-view")],1)}),u=[],l={name:"App"},d=l,m=n("2877"),h=Object(m["a"])(d,c,u,!1,null,null,null),f=h.exports,p=n("2f62"),v=(n("7f7f"),{sidebar:function(e){return e.app.sidebar},device:function(e){return e.app.device},token:function(e){return e.user.token},avatar:function(e){return e.user.avatar},name:function(e){return e.user.name}}),b=v,g=n("a78e"),w=n.n(g),x={sidebar:{opened:!w.a.get("sidebarStatus")||!!+w.a.get("sidebarStatus"),withoutAnimation:!1},device:"desktop"},y={TOGGLE_SIDEBAR:function(e){e.sidebar.opened=!e.sidebar.opened,e.sidebar.withoutAnimation=!1,e.sidebar.opened?w.a.set("sidebarStatus",1):w.a.set("sidebarStatus",0)},CLOSE_SIDEBAR:function(e,t){w.a.set("sidebarStatus",0),e.sidebar.opened=!1,e.sidebar.withoutAnimation=t},TOGGLE_DEVICE:function(e,t){e.device=t}},_={toggleSideBar:function(e){var t=e.commit;t("TOGGLE_SIDEBAR")},closeSideBar:function(e,t){var n=e.commit,a=t.withoutAnimation;n("CLOSE_SIDEBAR",a)},toggleDevice:function(e,t){var n=e.commit;n("TOGGLE_DEVICE",t)}},C={namespaced:!0,state:x,mutations:y,actions:_},k=n("83d6"),O=n.n(k),S=O.a.showSettings,z=O.a.fixedHeader,B=O.a.sidebarLogo,H={showSettings:S,fixedHeader:z,sidebarLogo:B},M={CHANGE_SETTING:function(e,t){var n=t.key,a=t.value;e.hasOwnProperty(n)&&(e[n]=a)}},T={changeSetting:function(e,t){var n=e.commit;n("CHANGE_SETTING",t)}},E={namespaced:!0,state:H,mutations:M,actions:T},L=n("bc3a"),$=n.n(L),V=n("5f87"),A=$.a.create({baseURL:"/api",withCredentials:!0,timeout:5e3});A.interceptors.request.use(function(e){return bt.getters.token&&(e.headers["X-Token"]=Object(V["a"])()),e},function(e){return console.log(e),Promise.reject(e)}),A.interceptors.response.use(function(e){var t=e.data;return 2e4!==t.code?(Object(i["Message"])({message:t.message||"error",type:"error",duration:5e3}),50008!==t.code&&50012!==t.code&&50014!==t.code||i["MessageBox"].confirm("You have been logged out, you can cancel to stay on this page, or log in again","Confirm logout",{confirmButtonText:"Re-Login",cancelButtonText:"Cancel",type:"warning"}).then(function(){bt.dispatch("user/resetToken").then(function(){location.reload()})}),Promise.reject(t.message||"error")):t},function(e){return console.log("err"+e),Object(i["Message"])({message:e.message,type:"error",duration:5e3}),Promise.reject(e)});var j=A;function P(e){return j({url:"/user/login",method:"post",data:e})}function I(e){return j({url:"/user/info",method:"get",params:{token:e}})}function N(){return j({url:"/user/logout",method:"post"})}var D=n("8c4f"),q=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-wrapper",class:e.classObj},["mobile"===e.device&&e.sidebar.opened?n("div",{staticClass:"drawer-bg",on:{click:e.handleClickOutside}}):e._e(),e._v(" "),n("sidebar",{staticClass:"sidebar-container"}),e._v(" "),n("div",{staticClass:"main-container"},[n("div",{class:{"fixed-header":e.fixedHeader}},[n("navbar")],1),e._v(" "),n("app-main")],1)],1)},R=[],G=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"navbar"},[n("hamburger",{staticClass:"hamburger-container",attrs:{"is-active":e.sidebar.opened},on:{toggleClick:e.toggleSideBar}}),e._v(" "),n("breadcrumb",{staticClass:"breadcrumb-container"}),e._v(" "),n("div",{staticClass:"right-menu"},[n("el-button",{staticStyle:{"margin-right":"10px"},attrs:{type:"text"},on:{click:e.doLogout}},[e._v("退出")])],1)],1)},F=[],U=n("cebc"),K=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("el-breadcrumb",{staticClass:"app-breadcrumb",attrs:{separator:"/"}},[n("transition-group",{attrs:{name:"breadcrumb"}},e._l(e.levelList,function(t,a){return n("el-breadcrumb-item",{key:t.path},["noRedirect"===t.redirect||a==e.levelList.length-1?n("span",{staticClass:"no-redirect"},[e._v(e._s(t.meta.title))]):n("a",{on:{click:function(n){return n.preventDefault(),e.handleLink(t)}}},[e._v(e._s(t.meta.title))])])}),1)],1)},W=[],J=n("bd11"),X=n.n(J),Y={data:function(){return{levelList:null}},watch:{$route:function(){this.getBreadcrumb()}},created:function(){this.getBreadcrumb()},methods:{getBreadcrumb:function(){var e=this.$route.matched.filter(function(e){return e.meta&&e.meta.title}),t=e[0];this.isDashboard(t)||(e=[{path:"/dashboard",meta:{title:"Dashboard"}}].concat(e)),this.levelList=e.filter(function(e){return e.meta&&e.meta.title&&!1!==e.meta.breadcrumb})},isDashboard:function(e){var t=e&&e.name;return!!t&&t.trim().toLocaleLowerCase()==="Dashboard".toLocaleLowerCase()},pathCompile:function(e){var t=this.$route.params,n=X.a.compile(e);return n(t)},handleLink:function(e){var t=e.redirect,n=e.path;t?this.$router.push(t):this.$router.push(this.pathCompile(n))}}},Q=Y,Z=(n("34c8"),Object(m["a"])(Q,K,W,!1,null,"62cc9144",null)),ee=Z.exports,te=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticStyle:{padding:"0 15px"},on:{click:e.toggleClick}},[n("svg",{staticClass:"hamburger",class:{"is-active":e.isActive},attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"64",height:"64"}},[n("path",{attrs:{d:"M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"}})])])},ne=[],ae={name:"Hamburger",props:{isActive:{type:Boolean,default:!1}},methods:{toggleClick:function(){this.$emit("toggleClick")}}},ie=ae,oe=(n("186a"),Object(m["a"])(ie,te,ne,!1,null,"49e15297",null)),re=oe.exports,se={components:{Breadcrumb:ee,Hamburger:re},computed:Object(U["a"])({},Object(p["b"])(["sidebar","avatar"])),methods:{toggleSideBar:function(){this.$store.dispatch("app/toggleSideBar")},doLogout:function(){this.logout()}}},ce=se,ue=(n("405a"),Object(m["a"])(ce,G,F,!1,null,"1eff5c58",null)),le=ue.exports,de=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{class:{"has-logo":e.showLogo}},[e.showLogo?n("logo",{attrs:{collapse:e.isCollapse}}):e._e(),e._v(" "),n("el-scrollbar",{attrs:{"wrap-class":"scrollbar-wrapper"}},[n("el-menu",{attrs:{"default-active":e.activeMenu,collapse:e.isCollapse,"background-color":e.variables.menuBg,"text-color":e.variables.menuText,"unique-opened":!1,"active-text-color":e.variables.menuActiveText,"collapse-transition":!1,mode:"vertical"}},e._l(e.routes,function(e){return n("sidebar-item",{key:e.path,attrs:{item:e,"base-path":e.path}})}),1)],1)],1)},me=[],he=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"sidebar-logo-container",class:{collapse:e.collapse}},[n("transition",{attrs:{name:"sidebarLogoFade"}},[e.collapse?n("router-link",{key:"collapse",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])]):n("router-link",{key:"expand",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):e._e(),e._v(" "),n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])])],1)],1)},fe=[],pe={name:"SidebarLogo",props:{collapse:{type:Boolean,required:!0}},data:function(){return{title:"SOP Admin",logo:"https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png"}}},ve=pe,be=(n("7c27"),Object(m["a"])(ve,he,fe,!1,null,"b905289c",null)),ge=be.exports,we=function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.item.hidden?e._e():n("div",{staticClass:"menu-wrapper"},[!e.hasOneShowingChild(e.item.children,e.item)||e.onlyOneChild.children&&!e.onlyOneChild.noShowingChildren||e.item.alwaysShow?n("el-submenu",{ref:"subMenu",attrs:{index:e.resolvePath(e.item.path),"popper-append-to-body":""}},[n("template",{slot:"title"},[e.item.meta?n("item",{attrs:{icon:e.item.meta&&e.item.meta.icon,title:e.item.meta.title}}):e._e()],1),e._v(" "),e._l(e.item.children,function(t){return n("sidebar-item",{key:t.path,staticClass:"nest-menu",attrs:{"is-nest":!0,item:t,"base-path":e.resolvePath(t.path)}})})],2):[e.onlyOneChild.meta?n("app-link",{attrs:{to:e.resolvePath(e.onlyOneChild.path)}},[n("el-menu-item",{class:{"submenu-title-noDropdown":!e.isNest},attrs:{index:e.resolvePath(e.onlyOneChild.path)}},[n("item",{attrs:{icon:e.onlyOneChild.meta.icon||e.item.meta&&e.item.meta.icon,title:e.onlyOneChild.meta.title}})],1)],1):e._e()]],2)},xe=[],ye=n("df7c"),_e=n.n(ye);function Ce(e){return/^(https?:|mailto:|tel:)/.test(e)}var ke,Oe,Se={name:"MenuItem",functional:!0,props:{icon:{type:String,default:""},title:{type:String,default:""}},render:function(e,t){var n=t.props,a=n.icon,i=n.title,o=[];return a&&o.push(e("svg-icon",{attrs:{"icon-class":a}})),i&&o.push(e("span",{slot:"title"},[i])),o}},ze=Se,Be=Object(m["a"])(ze,ke,Oe,!1,null,null,null),He=Be.exports,Me=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("component",e._b({},"component",e.linkProps(e.to),!1),[e._t("default")],2)},Te=[],Ee={props:{to:{type:String,required:!0}},methods:{linkProps:function(e){return Ce(e)?{is:"a",href:e,target:"_blank",rel:"noopener"}:{is:"router-link",to:e}}}},Le=Ee,$e=Object(m["a"])(Le,Me,Te,!1,null,null,null),Ve=$e.exports,Ae={computed:{device:function(){return this.$store.state.app.device}},mounted:function(){this.fixBugIniOS()},methods:{fixBugIniOS:function(){var e=this,t=this.$refs.subMenu;if(t){var n=t.handleMouseleave;t.handleMouseleave=function(t){"mobile"!==e.device&&n(t)}}}}},je={name:"SidebarItem",components:{Item:He,AppLink:Ve},mixins:[Ae],props:{item:{type:Object,required:!0},isNest:{type:Boolean,default:!1},basePath:{type:String,default:""}},data:function(){return this.onlyOneChild=null,{}},methods:{hasOneShowingChild:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1?arguments[1]:void 0,a=t.filter(function(t){return!t.hidden&&(e.onlyOneChild=t,!0)});return 1===a.length||0===a.length&&(this.onlyOneChild=Object(U["a"])({},n,{path:"",noShowingChildren:!0}),!0)},resolvePath:function(e){return Ce(e)?e:Ce(this.basePath)?this.basePath:_e.a.resolve(this.basePath,e)}}},Pe=je,Ie=Object(m["a"])(Pe,we,xe,!1,null,null,null),Ne=Ie.exports,De=n("cf1e"),qe=n.n(De),Re={components:{SidebarItem:Ne,Logo:ge},computed:Object(U["a"])({},Object(p["b"])(["sidebar"]),{routes:function(){return this.$router.options.routes},activeMenu:function(){var e=this.$route,t=e.meta,n=e.path;return t.activeMenu?t.activeMenu:n},showLogo:function(){return this.$store.state.settings.sidebarLogo},variables:function(){return qe.a},isCollapse:function(){return!this.sidebar.opened}})},Ge=Re,Fe=Object(m["a"])(Ge,de,me,!1,null,null,null),Ue=Fe.exports,Ke=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("section",{staticClass:"app-main"},[n("transition",{attrs:{name:"fade-transform",mode:"out-in"}},[n("router-view",{key:e.key})],1)],1)},We=[],Je={name:"AppMain",computed:{key:function(){return this.$route.fullPath}}},Xe=Je,Ye=(n("50be"),Object(m["a"])(Xe,Ke,We,!1,null,"43c24f68",null)),Qe=Ye.exports,Ze=document,et=Ze.body,tt=992,nt={watch:{$route:function(e){"mobile"===this.device&&this.sidebar.opened&&bt.dispatch("app/closeSideBar",{withoutAnimation:!1})}},beforeMount:function(){window.addEventListener("resize",this.$_resizeHandler)},beforeDestroy:function(){window.removeEventListener("resize",this.$_resizeHandler)},mounted:function(){var e=this.$_isMobile();e&&(bt.dispatch("app/toggleDevice","mobile"),bt.dispatch("app/closeSideBar",{withoutAnimation:!0}))},methods:{$_isMobile:function(){var e=et.getBoundingClientRect();return e.width-1'});r.a.add(s);t["default"]=s},"9f2b":function(e,t,n){"use strict";var a=n("5bb9"),i=n.n(a);i.a},b20f:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},b3b5:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-user",use:"icon-user-usage",viewBox:"0 0 130 130",content:''});r.a.add(s);t["default"]=s},cf1e:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},d7ec:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye-open",use:"icon-eye-open-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(s);t["default"]=s},dc52:function(e,t,n){},dcf8:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-nested",use:"icon-nested-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},eb1b:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-form",use:"icon-form-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},f782:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-dashboard",use:"icon-dashboard-usage",viewBox:"0 0 128 100",content:''});r.a.add(s);t["default"]=s}},[[0,"runtime","chunk-elementUI","chunk-libs"]]]); \ No newline at end of file +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["app"],{0:function(e,t,n){e.exports=n("56d7")},"0cb8":function(e,t,n){},"186a":function(e,t,n){"use strict";var a=n("dc52"),i=n.n(a);i.a},"18f0":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-link",use:"icon-link-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"1f59":function(e,t,n){},2536:function(e,t,n){},2635:function(e,t,n){},"2a3d":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-password",use:"icon-password-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"30c3":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-example",use:"icon-example-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"34c8":function(e,t,n){"use strict";var a=n("5332"),i=n.n(a);i.a},"405a":function(e,t,n){"use strict";var a=n("1f59"),i=n.n(a);i.a},"47f1":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-table",use:"icon-table-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"4df5":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye",use:"icon-eye-usage",viewBox:"0 0 128 64",content:''});r.a.add(s);t["default"]=s},"50be":function(e,t,n){"use strict";var a=n("2536"),i=n.n(a);i.a},"51ff":function(e,t,n){var a={"./dashboard.svg":"f782","./example.svg":"30c3","./eye-open.svg":"d7ec","./eye.svg":"4df5","./form.svg":"eb1b","./link.svg":"18f0","./nested.svg":"dcf8","./password.svg":"2a3d","./table.svg":"47f1","./tree.svg":"93cd","./user.svg":"b3b5"};function i(e){var t=o(e);return n(t)}function o(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return t}i.keys=function(){return Object.keys(a)},i.resolve=o,e.exports=i,i.id="51ff"},5332:function(e,t,n){},"56d7":function(e,t,n){"use strict";n.r(t);n("cadf"),n("551c"),n("f751"),n("097d");var a=n("2b0e"),i=(n("f5df"),n("5c96")),o=n.n(i),r=(n("0fae"),n("f0d9")),s=n.n(r),c=(n("b20f"),function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"app"}},[n("router-view")],1)}),u=[],l={name:"App"},d=l,m=n("2877"),h=Object(m["a"])(d,c,u,!1,null,null,null),f=h.exports,p=n("2f62"),v=(n("7f7f"),{sidebar:function(e){return e.app.sidebar},device:function(e){return e.app.device},token:function(e){return e.user.token},avatar:function(e){return e.user.avatar},name:function(e){return e.user.name}}),b=v,g=n("a78e"),w=n.n(g),x={sidebar:{opened:!w.a.get("sidebarStatus")||!!+w.a.get("sidebarStatus"),withoutAnimation:!1},device:"desktop"},y={TOGGLE_SIDEBAR:function(e){e.sidebar.opened=!e.sidebar.opened,e.sidebar.withoutAnimation=!1,e.sidebar.opened?w.a.set("sidebarStatus",1):w.a.set("sidebarStatus",0)},CLOSE_SIDEBAR:function(e,t){w.a.set("sidebarStatus",0),e.sidebar.opened=!1,e.sidebar.withoutAnimation=t},TOGGLE_DEVICE:function(e,t){e.device=t}},_={toggleSideBar:function(e){var t=e.commit;t("TOGGLE_SIDEBAR")},closeSideBar:function(e,t){var n=e.commit,a=t.withoutAnimation;n("CLOSE_SIDEBAR",a)},toggleDevice:function(e,t){var n=e.commit;n("TOGGLE_DEVICE",t)}},C={namespaced:!0,state:x,mutations:y,actions:_},k=n("83d6"),O=n.n(k),S=O.a.showSettings,z=O.a.fixedHeader,B=O.a.sidebarLogo,H={showSettings:S,fixedHeader:z,sidebarLogo:B},M={CHANGE_SETTING:function(e,t){var n=t.key,a=t.value;e.hasOwnProperty(n)&&(e[n]=a)}},T={changeSetting:function(e,t){var n=e.commit;n("CHANGE_SETTING",t)}},E={namespaced:!0,state:H,mutations:M,actions:T},L=n("bc3a"),$=n.n(L),V=n("5f87"),A=$.a.create({baseURL:"/api",withCredentials:!0,timeout:5e3});A.interceptors.request.use(function(e){return bt.getters.token&&(e.headers["X-Token"]=Object(V["a"])()),e},function(e){return console.log(e),Promise.reject(e)}),A.interceptors.response.use(function(e){var t=e.data;return 2e4!==t.code?(Object(i["Message"])({message:t.message||"error",type:"error",duration:5e3}),50008!==t.code&&50012!==t.code&&50014!==t.code||i["MessageBox"].confirm("You have been logged out, you can cancel to stay on this page, or log in again","Confirm logout",{confirmButtonText:"Re-Login",cancelButtonText:"Cancel",type:"warning"}).then(function(){bt.dispatch("user/resetToken").then(function(){location.reload()})}),Promise.reject(t.message||"error")):t},function(e){return console.log("err"+e),Object(i["Message"])({message:e.message,type:"error",duration:5e3}),Promise.reject(e)});var j=A;function P(e){return j({url:"/user/login",method:"post",data:e})}function I(e){return j({url:"/user/info",method:"get",params:{token:e}})}function N(){return j({url:"/user/logout",method:"post"})}var D=n("8c4f"),q=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-wrapper",class:e.classObj},["mobile"===e.device&&e.sidebar.opened?n("div",{staticClass:"drawer-bg",on:{click:e.handleClickOutside}}):e._e(),e._v(" "),n("sidebar",{staticClass:"sidebar-container"}),e._v(" "),n("div",{staticClass:"main-container"},[n("div",{class:{"fixed-header":e.fixedHeader}},[n("navbar")],1),e._v(" "),n("app-main")],1)],1)},R=[],G=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"navbar"},[n("hamburger",{staticClass:"hamburger-container",attrs:{"is-active":e.sidebar.opened},on:{toggleClick:e.toggleSideBar}}),e._v(" "),n("breadcrumb",{staticClass:"breadcrumb-container"}),e._v(" "),n("div",{staticClass:"right-menu"},[n("el-button",{staticStyle:{"margin-right":"10px"},attrs:{type:"text"},on:{click:e.doLogout}},[e._v("退出")])],1)],1)},F=[],U=n("cebc"),K=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("el-breadcrumb",{staticClass:"app-breadcrumb",attrs:{separator:"/"}},[n("transition-group",{attrs:{name:"breadcrumb"}},e._l(e.levelList,function(t,a){return n("el-breadcrumb-item",{key:t.path},["noRedirect"===t.redirect||a==e.levelList.length-1?n("span",{staticClass:"no-redirect"},[e._v(e._s(t.meta.title))]):n("a",{on:{click:function(n){return n.preventDefault(),e.handleLink(t)}}},[e._v(e._s(t.meta.title))])])}),1)],1)},W=[],J=n("bd11"),X=n.n(J),Y={data:function(){return{levelList:null}},watch:{$route:function(){this.getBreadcrumb()}},created:function(){this.getBreadcrumb()},methods:{getBreadcrumb:function(){var e=this.$route.matched.filter(function(e){return e.meta&&e.meta.title}),t=e[0];this.isDashboard(t)||(e=[{path:"/dashboard",meta:{title:"Dashboard"}}].concat(e)),this.levelList=e.filter(function(e){return e.meta&&e.meta.title&&!1!==e.meta.breadcrumb})},isDashboard:function(e){var t=e&&e.name;return!!t&&t.trim().toLocaleLowerCase()==="Dashboard".toLocaleLowerCase()},pathCompile:function(e){var t=this.$route.params,n=X.a.compile(e);return n(t)},handleLink:function(e){var t=e.redirect,n=e.path;t?this.$router.push(t):this.$router.push(this.pathCompile(n))}}},Q=Y,Z=(n("34c8"),Object(m["a"])(Q,K,W,!1,null,"62cc9144",null)),ee=Z.exports,te=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticStyle:{padding:"0 15px"},on:{click:e.toggleClick}},[n("svg",{staticClass:"hamburger",class:{"is-active":e.isActive},attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"64",height:"64"}},[n("path",{attrs:{d:"M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"}})])])},ne=[],ae={name:"Hamburger",props:{isActive:{type:Boolean,default:!1}},methods:{toggleClick:function(){this.$emit("toggleClick")}}},ie=ae,oe=(n("186a"),Object(m["a"])(ie,te,ne,!1,null,"49e15297",null)),re=oe.exports,se={components:{Breadcrumb:ee,Hamburger:re},computed:Object(U["a"])({},Object(p["b"])(["sidebar","avatar"])),methods:{toggleSideBar:function(){this.$store.dispatch("app/toggleSideBar")},doLogout:function(){this.logout()}}},ce=se,ue=(n("405a"),Object(m["a"])(ce,G,F,!1,null,"1eff5c58",null)),le=ue.exports,de=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{class:{"has-logo":e.showLogo}},[e.showLogo?n("logo",{attrs:{collapse:e.isCollapse}}):e._e(),e._v(" "),n("el-scrollbar",{attrs:{"wrap-class":"scrollbar-wrapper"}},[n("el-menu",{attrs:{"default-active":e.activeMenu,collapse:e.isCollapse,"background-color":e.variables.menuBg,"text-color":e.variables.menuText,"unique-opened":!1,"active-text-color":e.variables.menuActiveText,"collapse-transition":!1,mode:"vertical"}},e._l(e.routes,function(e){return n("sidebar-item",{key:e.path,attrs:{item:e,"base-path":e.path}})}),1)],1)],1)},me=[],he=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"sidebar-logo-container",class:{collapse:e.collapse}},[n("transition",{attrs:{name:"sidebarLogoFade"}},[e.collapse?n("router-link",{key:"collapse",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])]):n("router-link",{key:"expand",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):e._e(),e._v(" "),n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])])],1)],1)},fe=[],pe={name:"SidebarLogo",props:{collapse:{type:Boolean,required:!0}},data:function(){return{title:"SOP Admin",logo:"https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png"}}},ve=pe,be=(n("7c27"),Object(m["a"])(ve,he,fe,!1,null,"b905289c",null)),ge=be.exports,we=function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.item.hidden?e._e():n("div",{staticClass:"menu-wrapper"},[!e.hasOneShowingChild(e.item.children,e.item)||e.onlyOneChild.children&&!e.onlyOneChild.noShowingChildren||e.item.alwaysShow?n("el-submenu",{ref:"subMenu",attrs:{index:e.resolvePath(e.item.path),"popper-append-to-body":""}},[n("template",{slot:"title"},[e.item.meta?n("item",{attrs:{icon:e.item.meta&&e.item.meta.icon,title:e.item.meta.title}}):e._e()],1),e._v(" "),e._l(e.item.children,function(t){return n("sidebar-item",{key:t.path,staticClass:"nest-menu",attrs:{"is-nest":!0,item:t,"base-path":e.resolvePath(t.path)}})})],2):[e.onlyOneChild.meta?n("app-link",{attrs:{to:e.resolvePath(e.onlyOneChild.path)}},[n("el-menu-item",{class:{"submenu-title-noDropdown":!e.isNest},attrs:{index:e.resolvePath(e.onlyOneChild.path)}},[n("item",{attrs:{icon:e.onlyOneChild.meta.icon||e.item.meta&&e.item.meta.icon,title:e.onlyOneChild.meta.title}})],1)],1):e._e()]],2)},xe=[],ye=n("df7c"),_e=n.n(ye);function Ce(e){return/^(https?:|mailto:|tel:)/.test(e)}var ke,Oe,Se={name:"MenuItem",functional:!0,props:{icon:{type:String,default:""},title:{type:String,default:""}},render:function(e,t){var n=t.props,a=n.icon,i=n.title,o=[];return a&&o.push(e("svg-icon",{attrs:{"icon-class":a}})),i&&o.push(e("span",{slot:"title"},[i])),o}},ze=Se,Be=Object(m["a"])(ze,ke,Oe,!1,null,null,null),He=Be.exports,Me=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("component",e._b({},"component",e.linkProps(e.to),!1),[e._t("default")],2)},Te=[],Ee={props:{to:{type:String,required:!0}},methods:{linkProps:function(e){return Ce(e)?{is:"a",href:e,target:"_blank",rel:"noopener"}:{is:"router-link",to:e}}}},Le=Ee,$e=Object(m["a"])(Le,Me,Te,!1,null,null,null),Ve=$e.exports,Ae={computed:{device:function(){return this.$store.state.app.device}},mounted:function(){this.fixBugIniOS()},methods:{fixBugIniOS:function(){var e=this,t=this.$refs.subMenu;if(t){var n=t.handleMouseleave;t.handleMouseleave=function(t){"mobile"!==e.device&&n(t)}}}}},je={name:"SidebarItem",components:{Item:He,AppLink:Ve},mixins:[Ae],props:{item:{type:Object,required:!0},isNest:{type:Boolean,default:!1},basePath:{type:String,default:""}},data:function(){return this.onlyOneChild=null,{}},methods:{hasOneShowingChild:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1?arguments[1]:void 0,a=t.filter(function(t){return!t.hidden&&(e.onlyOneChild=t,!0)});return 1===a.length||0===a.length&&(this.onlyOneChild=Object(U["a"])({},n,{path:"",noShowingChildren:!0}),!0)},resolvePath:function(e){return Ce(e)?e:Ce(this.basePath)?this.basePath:_e.a.resolve(this.basePath,e)}}},Pe=je,Ie=Object(m["a"])(Pe,we,xe,!1,null,null,null),Ne=Ie.exports,De=n("cf1e"),qe=n.n(De),Re={components:{SidebarItem:Ne,Logo:ge},computed:Object(U["a"])({},Object(p["b"])(["sidebar"]),{routes:function(){return this.$router.options.routes},activeMenu:function(){var e=this.$route,t=e.meta,n=e.path;return t.activeMenu?t.activeMenu:n},showLogo:function(){return this.$store.state.settings.sidebarLogo},variables:function(){return qe.a},isCollapse:function(){return!this.sidebar.opened}})},Ge=Re,Fe=Object(m["a"])(Ge,de,me,!1,null,null,null),Ue=Fe.exports,Ke=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("section",{staticClass:"app-main"},[n("transition",{attrs:{name:"fade-transform",mode:"out-in"}},[n("router-view",{key:e.key})],1)],1)},We=[],Je={name:"AppMain",computed:{key:function(){return this.$route.fullPath}}},Xe=Je,Ye=(n("50be"),Object(m["a"])(Xe,Ke,We,!1,null,"43c24f68",null)),Qe=Ye.exports,Ze=document,et=Ze.body,tt=992,nt={watch:{$route:function(e){"mobile"===this.device&&this.sidebar.opened&&bt.dispatch("app/closeSideBar",{withoutAnimation:!1})}},beforeMount:function(){window.addEventListener("resize",this.$_resizeHandler)},beforeDestroy:function(){window.removeEventListener("resize",this.$_resizeHandler)},mounted:function(){var e=this.$_isMobile();e&&(bt.dispatch("app/toggleDevice","mobile"),bt.dispatch("app/closeSideBar",{withoutAnimation:!0}))},methods:{$_isMobile:function(){var e=et.getBoundingClientRect();return e.width-1'});r.a.add(s);t["default"]=s},"9f2b":function(e,t,n){"use strict";var a=n("5bb9"),i=n.n(a);i.a},b20f:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},b3b5:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-user",use:"icon-user-usage",viewBox:"0 0 130 130",content:''});r.a.add(s);t["default"]=s},cf1e:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},d7ec:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye-open",use:"icon-eye-open-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(s);t["default"]=s},dc52:function(e,t,n){},dcf8:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-nested",use:"icon-nested-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},eb1b:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-form",use:"icon-form-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},f782:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-dashboard",use:"icon-dashboard-usage",viewBox:"0 0 128 100",content:''});r.a.add(s);t["default"]=s}},[[0,"runtime","chunk-elementUI","chunk-libs"]]]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-29b24c82.2b3ac7ca.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-29b24c82.2b3ac7ca.js deleted file mode 100644 index 55d5be10..00000000 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-29b24c82.2b3ac7ca.js +++ /dev/null @@ -1 +0,0 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-29b24c82"],{"0a49":function(e,t,i){var a=i("9b43"),l=i("626a"),o=i("4bf8"),r=i("9def"),s=i("cd1c");e.exports=function(e,t){var i=1==e,n=2==e,m=3==e,c=4==e,p=6==e,u=5==e||p,d=t||s;return function(t,s,g){for(var f,h,D=o(t),y=l(D),v=a(s,g,3),b=r(y.length),k=0,x=i?d(t,b):n?d(t,0):void 0;b>k;k++)if((u||k in y)&&(f=y[k],h=v(f,k,D),e))if(i)x[k]=h;else if(h)switch(e){case 3:return!0;case 5:return f;case 6:return k;case 2:x.push(f)}else if(c)return!1;return p?-1:m||c?c:x}}},1169:function(e,t,i){var a=i("2d95");e.exports=Array.isArray||function(e){return"Array"==a(e)}},1510:function(e,t,i){"use strict";i.r(t);var a=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"app-container"},[i("el-container",[i("el-aside",{staticStyle:{"min-height":"300px",width:"200px"}},[i("el-input",{staticStyle:{"margin-bottom":"20px"},attrs:{"prefix-icon":"el-icon-search",placeholder:"搜索服务...",size:"mini",clearable:""},model:{value:e.filterText,callback:function(t){e.filterText=t},expression:"filterText"}}),e._v(" "),i("el-tree",{ref:"tree2",staticClass:"filter-tree",attrs:{data:e.treeData,props:e.defaultProps,"filter-node-method":e.filterNode,"highlight-current":!0,"expand-on-click-node":!1,"empty-text":"无数据","node-key":"id","default-expand-all":""},on:{"node-click":e.onNodeClick},scopedSlots:e._u([{key:"default",fn:function(t){t.node;var a=t.data;return i("span",{staticClass:"custom-tree-node"},[a.label.length<15?i("span",[e._v(e._s(a.label))]):i("span",[i("el-tooltip",{staticClass:"item",attrs:{content:a.label,effect:"light",placement:"right"}},[i("span",[e._v(e._s(a.label.substring(0,15)+"..."))])])],1)])}}])})],1),e._v(" "),i("el-main",{staticStyle:{"padding-top":"0"}},[i("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:e.searchFormData,size:"mini"}},[i("el-form-item",{attrs:{label:"路由ID"}},[i("el-input",{attrs:{placeholder:"接口名,支持模糊查询",clearable:""},model:{value:e.searchFormData.routeId,callback:function(t){e.$set(e.searchFormData,"routeId",t)},expression:"searchFormData.routeId"}})],1),e._v(" "),i("el-form-item",{attrs:{label:"AppKey"}},[i("el-input",{attrs:{placeholder:"AppKey,支持模糊查询",clearable:""},model:{value:e.searchFormData.appKey,callback:function(t){e.$set(e.searchFormData,"appKey",t)},expression:"searchFormData.appKey"}})],1),e._v(" "),i("el-form-item",{attrs:{label:"IP"}},[i("el-input",{attrs:{placeholder:"ip,支持模糊查询",clearable:""},model:{value:e.searchFormData.limitIp,callback:function(t){e.$set(e.searchFormData,"limitIp",t)},expression:"searchFormData.limitIp"}})],1),e._v(" "),i("el-form-item",[i("el-button",{attrs:{type:"primary",icon:"el-icon-search",size:"mini"},on:{click:e.onSearchTable}},[e._v("查询")])],1)],1),e._v(" "),i("el-button",{staticStyle:{"margin-bottom":"10px"},attrs:{type:"primary",size:"mini",icon:"el-icon-plus"},on:{click:e.onAdd}},[e._v("新增限流")]),e._v(" "),i("el-table",{attrs:{data:e.pageInfo.list,border:""}},[i("el-table-column",{attrs:{prop:"limitKey",label:"限流维度",width:"400"},scopedSlots:e._u([{key:"default",fn:function(t){return[i("div",{domProps:{innerHTML:e._s(e.limitRender(t.row))}})]}}])}),e._v(" "),i("el-table-column",{attrs:{prop:"limitType",label:"限流策略",width:"120"},scopedSlots:e._u([{key:"default",fn:function(t){return[1===t.row.limitType?i("span",[e._v("窗口策略")]):e._e(),e._v(" "),2===t.row.limitType?i("span",[e._v("令牌桶策略")]):e._e()]}}])},[i("template",{slot:"header"},[e._v("\n 限流策略 "),i("i",{staticClass:"el-icon-question",staticStyle:{cursor:"pointer"},on:{click:e.onLimitTypeTipClick}})])],2),e._v(" "),i("el-table-column",{attrs:{prop:"info",label:"限流信息",width:"250"},scopedSlots:e._u([{key:"default",fn:function(t){return[i("span",{domProps:{innerHTML:e._s(e.infoRender(t.row))}})]}}])}),e._v(" "),i("el-table-column",{attrs:{prop:"limitStatus",label:"状态",width:"80"},scopedSlots:e._u([{key:"default",fn:function(t){return[1===t.row.limitStatus?i("span",{staticStyle:{color:"#67C23A"}},[e._v("已开启")]):e._e(),e._v(" "),0===t.row.limitStatus?i("span",{staticStyle:{color:"#909399"}},[e._v("已关闭")]):e._e()]}}])}),e._v(" "),i("el-table-column",{attrs:{prop:"orderIndex",label:"排序",width:"80"}}),e._v(" "),i("el-table-column",{attrs:{prop:"remark",label:"备注",width:"150","show-overflow-tooltip":!0}}),e._v(" "),i("el-table-column",{attrs:{prop:"gmtCreate",label:"创建时间",width:"160"}}),e._v(" "),i("el-table-column",{attrs:{prop:"gmtModified",label:"修改时间",width:"160"}}),e._v(" "),i("el-table-column",{attrs:{label:"操作",fixed:"right",width:"80"},scopedSlots:e._u([{key:"default",fn:function(t){return[i("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(i){return e.onTableUpdate(t.row)}}},[e._v("修改")])]}}])})],1),e._v(" "),i("el-pagination",{staticStyle:{"margin-top":"5px"},attrs:{background:"","current-page":e.searchFormData.pageIndex,"page-size":e.searchFormData.pageSize,"page-sizes":[5,10,20,40],total:e.pageInfo.total,layout:"total, sizes, prev, pager, next"},on:{"size-change":e.onSizeChange,"current-change":e.onPageIndexChange}}),e._v(" "),i("el-dialog",{attrs:{title:e.dlgTitle,visible:e.limitDialogVisible,"close-on-click-modal":!1},on:{"update:visible":function(t){e.limitDialogVisible=t},close:e.onLimitDialogClose}},[i("el-form",{ref:"limitDialogForm",attrs:{model:e.limitDialogFormData,rules:e.rulesLimit,"label-width":"150px",size:"mini"}},[i("el-form-item",{attrs:{label:"限流维度",prop:"typeKey"}},[i("el-checkbox-group",{model:{value:e.limitDialogFormData.typeKey,callback:function(t){e.$set(e.limitDialogFormData,"typeKey",t)},expression:"limitDialogFormData.typeKey"}},[i("el-checkbox",{attrs:{label:1,name:"typeKey"},model:{value:e.limitDialogFormData.typeKey[0],callback:function(t){e.$set(e.limitDialogFormData.typeKey,0,t)},expression:"limitDialogFormData.typeKey[0]"}},[e._v("路由ID")]),e._v(" "),i("el-checkbox",{attrs:{label:2,name:"typeKey"},model:{value:e.limitDialogFormData.typeKey[1],callback:function(t){e.$set(e.limitDialogFormData.typeKey,1,t)},expression:"limitDialogFormData.typeKey[1]"}},[e._v("AppKey")]),e._v(" "),i("el-checkbox",{attrs:{label:3,name:"typeKey"},model:{value:e.limitDialogFormData.typeKey[2],callback:function(t){e.$set(e.limitDialogFormData.typeKey,2,t)},expression:"limitDialogFormData.typeKey[2]"}},[e._v("IP")])],1)],1),e._v(" "),i("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.checkTypeKey(1),expression:"checkTypeKey(1)"}],attrs:{prop:"routeId",label:"路由ID",rules:e.checkTypeKey(1)?e.rulesLimit.routeId:[]}},[i("el-select",{staticStyle:{width:"300px"},attrs:{filterable:"",placeholder:"可筛选"},model:{value:e.limitDialogFormData.routeId,callback:function(t){e.$set(e.limitDialogFormData,"routeId",t)},expression:"limitDialogFormData.routeId"}},e._l(e.routeList,function(t){return i("el-option",{key:t.id,attrs:{label:t.id,value:t.id}},[i("span",{staticStyle:{float:"left"}},[e._v(e._s(t.name))]),e._v(" "),i("span",{staticStyle:{float:"right",color:"#8492a6","font-size":"13px"}},[e._v(e._s(t.version))])])}),1)],1),e._v(" "),i("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.checkTypeKey(2),expression:"checkTypeKey(2)"}],attrs:{prop:"appKey",label:"AppKey",rules:e.checkTypeKey(2)?e.rulesLimit.appKey:[]}},[i("el-input",{attrs:{placeholder:"需要限流的appKey"},model:{value:e.limitDialogFormData.appKey,callback:function(t){e.$set(e.limitDialogFormData,"appKey",t)},expression:"limitDialogFormData.appKey"}})],1),e._v(" "),i("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.checkTypeKey(3),expression:"checkTypeKey(3)"}],attrs:{label:"限流IP",prop:"limitIp",rules:e.checkTypeKey(3)?e.rulesLimit.ip:[]}},[i("el-input",{attrs:{type:"textarea",rows:2,placeholder:"多个用英文逗号隔开"},model:{value:e.limitDialogFormData.limitIp,callback:function(t){e.$set(e.limitDialogFormData,"limitIp",t)},expression:"limitDialogFormData.limitIp"}})],1),e._v(" "),i("el-form-item",{attrs:{label:"限流策略"}},[i("el-radio-group",{model:{value:e.limitDialogFormData.limitType,callback:function(t){e.$set(e.limitDialogFormData,"limitType",t)},expression:"limitDialogFormData.limitType"}},[i("el-radio",{attrs:{label:1}},[e._v("窗口策略")]),e._v(" "),i("el-radio",{attrs:{label:2}},[e._v("令牌桶策略")])],1),e._v(" "),i("i",{staticClass:"el-icon-question limit-tip",on:{click:e.onLimitTypeTipClick}})],1),e._v(" "),i("el-form-item",{attrs:{label:"开启状态"}},[i("el-switch",{attrs:{"active-color":"#13ce66","inactive-color":"#ff4949","active-value":1,"inactive-value":0},model:{value:e.limitDialogFormData.limitStatus,callback:function(t){e.$set(e.limitDialogFormData,"limitStatus",t)},expression:"limitDialogFormData.limitStatus"}})],1),e._v(" "),i("el-form-item",{attrs:{label:"排序",prop:"orderIndex"}},[i("el-input-number",{attrs:{"controls-position":"right",min:0},model:{value:e.limitDialogFormData.orderIndex,callback:function(t){e.$set(e.limitDialogFormData,"orderIndex",t)},expression:"limitDialogFormData.orderIndex"}}),e._v(" "),i("el-tooltip",{staticClass:"item",attrs:{content:"值小优先执行",placement:"top"}},[i("i",{staticClass:"el-icon-question limit-tip"})])],1),e._v(" "),i("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.isWindowType(),expression:"isWindowType()"}],attrs:{label:"每秒可处理请求数",prop:"execCountPerSecond",rules:e.isWindowType()?e.rulesLimit.execCountPerSecond:[]}},[i("el-input-number",{attrs:{"controls-position":"right",min:1},model:{value:e.limitDialogFormData.execCountPerSecond,callback:function(t){e.$set(e.limitDialogFormData,"execCountPerSecond",t)},expression:"limitDialogFormData.execCountPerSecond"}})],1),e._v(" "),i("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.isWindowType(),expression:"isWindowType()"}],attrs:{label:"错误码",prop:"limitCode",rules:e.isWindowType()?e.rulesLimit.limitCode:[]}},[i("el-input",{model:{value:e.limitDialogFormData.limitCode,callback:function(t){e.$set(e.limitDialogFormData,"limitCode",t)},expression:"limitDialogFormData.limitCode"}})],1),e._v(" "),i("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.isWindowType(),expression:"isWindowType()"}],attrs:{label:"错误信息",prop:"limitMsg",rules:e.isWindowType()?e.rulesLimit.limitMsg:[]}},[i("el-input",{model:{value:e.limitDialogFormData.limitMsg,callback:function(t){e.$set(e.limitDialogFormData,"limitMsg",t)},expression:"limitDialogFormData.limitMsg"}})],1),e._v(" "),i("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.isTokenType(),expression:"isTokenType()"}],attrs:{label:"令牌桶容量",prop:"tokenBucketCount",rules:e.isTokenType()?e.rulesLimit.tokenBucketCount:[]}},[i("el-input-number",{attrs:{"controls-position":"right",min:1},model:{value:e.limitDialogFormData.tokenBucketCount,callback:function(t){e.$set(e.limitDialogFormData,"tokenBucketCount",t)},expression:"limitDialogFormData.tokenBucketCount"}})],1),e._v(" "),i("el-form-item",{attrs:{label:"备注",prop:"remark"}},[i("el-input",{attrs:{type:"textarea",rows:2},model:{value:e.limitDialogFormData.remark,callback:function(t){e.$set(e.limitDialogFormData,"remark",t)},expression:"limitDialogFormData.remark"}})],1)],1),e._v(" "),i("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[i("el-button",{on:{click:function(t){e.limitDialogVisible=!1}}},[e._v("取 消")]),e._v(" "),i("el-button",{attrs:{type:"primary"},on:{click:e.onLimitDialogSave}},[e._v("保 存")])],1)],1)],1)],1)],1)},l=[],o=(i("7514"),{data:function(){return{filterText:"",treeData:[],tableData:[],serviceId:"",searchFormData:{pageIndex:1,pageSize:5},pageInfo:{list:[],total:0},routeList:[],defaultProps:{children:"children",label:"label"},dlgTitle:"设置限流",limitDialogVisible:!1,limitDialogFormData:{id:0,routeId:"",appKey:"",limitIp:"",limitKey:"",execCountPerSecond:5,limitCode:"",limitMsg:"",tokenBucketCount:5,limitStatus:0,limitType:1,orderIndex:0,remark:"",typeKey:[]},rulesLimit:{typeKey:[{type:"array",required:!0,message:"请至少选择一个",trigger:"change"}],routeId:[{required:!0,message:"不能为空",trigger:"blur"},{min:1,max:100,message:"长度在 1 到 100 个字符",trigger:"blur"}],appKey:[{required:!0,message:"不能为空",trigger:"blur"},{min:1,max:100,message:"长度在 1 到 100 个字符",trigger:"blur"}],ip:[{required:!0,message:"不能为空",trigger:"blur"},{min:1,max:500,message:"长度在 1 到 500 个字符",trigger:"blur"}],execCountPerSecond:[{required:!0,message:"不能为空",trigger:"blur"}],limitCode:[{required:!0,message:"不能为空",trigger:"blur"},{min:1,max:64,message:"长度在 1 到 64 个字符",trigger:"blur"}],limitMsg:[{required:!0,message:"不能为空",trigger:"blur"},{min:1,max:100,message:"长度在 1 到 100 个字符",trigger:"blur"}],tokenBucketCount:[{required:!0,message:"不能为空",trigger:"blur"}],orderIndex:[{required:!0,message:"不能为空",trigger:"blur"}],remark:[{max:128,message:"长度不能超过128字符",trigger:"blur"}]}}},watch:{filterText:function(e){this.$refs.tree2.filter(e)}},created:function(){this.loadTree()},methods:{loadTree:function(){this.post("service.list",{},function(e){var t=e.data;this.treeData=this.convertToTreeData(t,0)})},filterNode:function(e,t){return!e||-1!==t.label.indexOf(e)},onNodeClick:function(e,t,i){e.parentId&&(this.serviceId=e.label,this.searchFormData.serviceId=this.serviceId,this.loadTable(),this.loadRouteList(this.serviceId))},convertToTreeData:function(e,t){for(var i=[],a={label:"服务列表",parentId:t},l=[],o=0;osubCode:"+e.limitCode),t.push("
subMsg:"+e.limitMsg)):2===e.limitType&&t.push("令牌桶容量:"+e.tokenBucketCount),t.join("")},onLimitDialogSave:function(){var e=this;this.$refs["limitDialogForm"].validate(function(t){if(t){e.cleanCheckboxData(),e.limitDialogFormData.serviceId=e.serviceId;var i=e.limitDialogFormData.id?"config.limit.update":"config.limit.add";e.post(i,e.limitDialogFormData,function(e){this.limitDialogVisible=!1,this.loadTable()})}})},cleanCheckboxData:function(){this.checkTypeKey(1)||(this.limitDialogFormData.routeId=""),this.checkTypeKey(2)||(this.limitDialogFormData.appKey=""),this.checkTypeKey(3)||(this.limitDialogFormData.limitIp="")},onLimitTypeTipClick:function(){var e="窗口策略:每秒处理固定数量的请求,超出请求数量返回错误信息。",t="令牌桶策略:每秒放置固定数量的令牌数,每个请求进来后先去拿令牌,拿到了令牌才能继续,拿不到则等候令牌重新生成了再拿。",i=e+"
"+t;this.$alert(i,"限流策略",{dangerouslyUseHTMLString:!0})},onSizeChange:function(e){this.searchFormData.pageSize=e,this.loadTable()},onPageIndexChange:function(e){this.searchFormData.pageIndex=e,this.loadTable()},checkTypeKey:function(e){return this.limitDialogFormData.typeKey.find(function(t,i,a){return t===e})},isWindowType:function(){return 1===this.limitDialogFormData.limitType},isTokenType:function(){return 2===this.limitDialogFormData.limitType},limitRender:function(e){var t=[],i=[];return e.routeId&&(i.push(e.routeId),t.push("路由ID")),e.appKey&&(i.push(e.appKey),t.push("AppKey")),e.limitIp&&(i.push(e.limitIp),t.push("IP")),i.join(" + ")+"
("+t.join(" + ")+")"}}}),r=o,s=(i("edd4"),i("2877")),n=Object(s["a"])(r,a,l,!1,null,"29df7fee",null);t["default"]=n.exports},"44f4":function(e,t,i){},7514:function(e,t,i){"use strict";var a=i("5ca1"),l=i("0a49")(5),o="find",r=!0;o in[]&&Array(1)[o](function(){r=!1}),a(a.P+a.F*r,"Array",{find:function(e){return l(this,e,arguments.length>1?arguments[1]:void 0)}}),i("9c6c")(o)},cd1c:function(e,t,i){var a=i("e853");e.exports=function(e,t){return new(a(e))(t)}},e853:function(e,t,i){var a=i("d3f4"),l=i("1169"),o=i("2b4c")("species");e.exports=function(e){var t;return l(e)&&(t=e.constructor,"function"!=typeof t||t!==Array&&!l(t.prototype)||(t=void 0),a(t)&&(t=t[o],null===t&&(t=void 0))),void 0===t?Array:t}},edd4:function(e,t,i){"use strict";var a=i("44f4"),l=i.n(a);l.a}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2a9bc230.6f8c0d92.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2a9bc230.6f8c0d92.js new file mode 100644 index 00000000..2bf23197 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2a9bc230.6f8c0d92.js @@ -0,0 +1 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2a9bc230"],{"0a49":function(e,t,i){var a=i("9b43"),l=i("626a"),o=i("4bf8"),r=i("9def"),s=i("cd1c");e.exports=function(e,t){var i=1==e,n=2==e,m=3==e,c=4==e,p=6==e,u=5==e||p,d=t||s;return function(t,s,g){for(var f,h,D=o(t),y=l(D),v=a(s,g,3),b=r(y.length),k=0,x=i?d(t,b):n?d(t,0):void 0;b>k;k++)if((u||k in y)&&(f=y[k],h=v(f,k,D),e))if(i)x[k]=h;else if(h)switch(e){case 3:return!0;case 5:return f;case 6:return k;case 2:x.push(f)}else if(c)return!1;return p?-1:m||c?c:x}}},1169:function(e,t,i){var a=i("2d95");e.exports=Array.isArray||function(e){return"Array"==a(e)}},1510:function(e,t,i){"use strict";i.r(t);var a=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"app-container"},[i("el-container",[i("el-aside",{staticStyle:{"min-height":"300px",width:"250px"}},[i("el-input",{staticStyle:{"margin-bottom":"20px"},attrs:{"prefix-icon":"el-icon-search",placeholder:"搜索服务...",size:"mini",clearable:""},model:{value:e.filterText,callback:function(t){e.filterText=t},expression:"filterText"}}),e._v(" "),i("el-tree",{ref:"tree2",staticClass:"filter-tree",attrs:{data:e.treeData,props:e.defaultProps,"filter-node-method":e.filterNode,"highlight-current":!0,"expand-on-click-node":!1,"empty-text":"无数据","node-key":"id","default-expand-all":""},on:{"node-click":e.onNodeClick},scopedSlots:e._u([{key:"default",fn:function(t){t.node;var a=t.data;return i("span",{staticClass:"custom-tree-node"},[a.label.lengthsubCode:"+e.limitCode),t.push("
subMsg:"+e.limitMsg)):2===e.limitType&&t.push("令牌桶容量:"+e.tokenBucketCount),t.join("")},onLimitDialogSave:function(){var e=this;this.$refs["limitDialogForm"].validate(function(t){if(t){e.cleanCheckboxData(),e.limitDialogFormData.serviceId=e.serviceId;var i=e.limitDialogFormData.id?"config.limit.update":"config.limit.add";e.post(i,e.limitDialogFormData,function(e){this.limitDialogVisible=!1,this.loadTable()})}})},cleanCheckboxData:function(){this.checkTypeKey(1)||(this.limitDialogFormData.routeId=""),this.checkTypeKey(2)||(this.limitDialogFormData.appKey=""),this.checkTypeKey(3)||(this.limitDialogFormData.limitIp="")},onLimitTypeTipClick:function(){var e="窗口策略:每秒处理固定数量的请求,超出请求数量返回错误信息。",t="令牌桶策略:每秒放置固定数量的令牌数,每个请求进来后先去拿令牌,拿到了令牌才能继续,拿不到则等候令牌重新生成了再拿。",i=e+"
"+t;this.$alert(i,"限流策略",{dangerouslyUseHTMLString:!0})},onSizeChange:function(e){this.searchFormData.pageSize=e,this.loadTable()},onPageIndexChange:function(e){this.searchFormData.pageIndex=e,this.loadTable()},checkTypeKey:function(e){return this.limitDialogFormData.typeKey.find(function(t,i,a){return t===e})},isWindowType:function(){return 1===this.limitDialogFormData.limitType},isTokenType:function(){return 2===this.limitDialogFormData.limitType},limitRender:function(e){var t=[],i=[];return e.routeId&&(i.push(e.routeId),t.push("路由ID")),e.appKey&&(i.push(e.appKey),t.push("AppKey")),e.limitIp&&(i.push(e.limitIp),t.push("IP")),i.join(" + ")+"
("+t.join(" + ")+")"}}}),r=o,s=(i("bcf9"),i("2877")),n=Object(s["a"])(r,a,l,!1,null,"31efca04",null);t["default"]=n.exports},7514:function(e,t,i){"use strict";var a=i("5ca1"),l=i("0a49")(5),o="find",r=!0;o in[]&&Array(1)[o](function(){r=!1}),a(a.P+a.F*r,"Array",{find:function(e){return l(this,e,arguments.length>1?arguments[1]:void 0)}}),i("9c6c")(o)},a945:function(e,t,i){},bcf9:function(e,t,i){"use strict";var a=i("a945"),l=i.n(a);l.a},cd1c:function(e,t,i){var a=i("e853");e.exports=function(e,t){return new(a(e))(t)}},e853:function(e,t,i){var a=i("d3f4"),l=i("1169"),o=i("2b4c")("species");e.exports=function(e){var t;return l(e)&&(t=e.constructor,"function"!=typeof t||t!==Array&&!l(t.prototype)||(t=void 0),a(t)&&(t=t[o],null===t&&(t=void 0))),void 0===t?Array:t}}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d0aa95b.447435b3.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d0aa95b.447435b3.js deleted file mode 100644 index da97f7e1..00000000 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d0aa95b.447435b3.js +++ /dev/null @@ -1 +0,0 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0aa95b"],{1248:function(t,e,a){"use strict";a.r(e);var o=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"app-container"},[a("el-container",[a("el-aside",{staticStyle:{"min-height":"300px",width:"200px"}},[a("el-input",{staticStyle:{"margin-bottom":"20px"},attrs:{"prefix-icon":"el-icon-search",placeholder:"搜索服务...",size:"mini",clearable:""},model:{value:t.filterText,callback:function(e){t.filterText=e},expression:"filterText"}}),t._v(" "),a("el-tree",{ref:"tree2",staticClass:"filter-tree",attrs:{data:t.treeData,props:t.defaultProps,"filter-node-method":t.filterNode,"highlight-current":!0,"expand-on-click-node":!1,"empty-text":"无数据","node-key":"id","default-expand-all":""},on:{"node-click":t.onNodeClick},scopedSlots:t._u([{key:"default",fn:function(e){e.node;var o=e.data;return a("span",{staticClass:"custom-tree-node"},[o.label.length<15?a("span",[t._v(t._s(o.label))]):a("span",[a("el-tooltip",{staticClass:"item",attrs:{content:o.label,effect:"light",placement:"right"}},[a("span",[t._v(t._s(o.label.substring(0,15)+"..."))])])],1)])}}])})],1),t._v(" "),a("el-main",{staticStyle:{"padding-top":"0"}},[a("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:t.searchFormData,size:"mini"}},[a("el-form-item",{attrs:{label:"路由名称"}},[a("el-input",{attrs:{placeholder:"输入接口名或版本号"},model:{value:t.searchFormData.id,callback:function(e){t.$set(t.searchFormData,"id",e)},expression:"searchFormData.id"}})],1),t._v(" "),a("el-form-item",[a("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:t.onSearchTable}},[t._v("查询")])],1)],1),t._v(" "),a("el-table",{attrs:{data:t.tableData,border:"","max-height":"500"}},[a("el-table-column",{attrs:{prop:"name",label:"接口名 (版本号)",width:"200"},scopedSlots:t._u([{key:"default",fn:function(e){return[t._v("\n "+t._s(e.row.name+(e.row.version?" ("+e.row.version+")":""))+"\n ")]}}])}),t._v(" "),a("el-table-column",{attrs:{prop:"uri",label:"LoadBalance",width:"350"},scopedSlots:t._u([{key:"default",fn:function(e){return[t._v("\n "+t._s(e.row.uri+e.row.path)+"\n ")]}}])}),t._v(" "),a("el-table-column",{attrs:{prop:"roles",label:"访问权限",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[a("span",{domProps:{innerHTML:t._s(t.roleRender(e.row))}})]}}])}),t._v(" "),a("el-table-column",{attrs:{prop:"ignoreValidate",label:"忽略验证",width:"80"},scopedSlots:t._u([{key:"default",fn:function(e){return[1===e.row.ignoreValidate?a("span",{staticStyle:{color:"#67C23A"}},[t._v("是")]):t._e(),t._v(" "),0===e.row.ignoreValidate?a("span",{staticStyle:{color:"#909399"}},[t._v("否")]):t._e()]}}])}),t._v(" "),a("el-table-column",{attrs:{prop:"mergeResult",label:"统一格式输出",width:"120"},scopedSlots:t._u([{key:"default",fn:function(e){return[1===e.row.mergeResult?a("span",{staticStyle:{color:"#67C23A"}},[t._v("是")]):t._e(),t._v(" "),0===e.row.mergeResult?a("span",{staticStyle:{color:"#E6A23C"}},[t._v("否")]):t._e()]}}])}),t._v(" "),a("el-table-column",{attrs:{prop:"status",label:"状态",width:"80"},scopedSlots:t._u([{key:"default",fn:function(e){return[0===e.row.status?a("span",{staticStyle:{color:"#909399"}},[t._v("待审核")]):t._e(),t._v(" "),1===e.row.status?a("span",{staticStyle:{color:"#67C23A"}},[t._v("已启用")]):t._e(),t._v(" "),2===e.row.status?a("span",{staticStyle:{color:"#F56C6C"}},[t._v("已禁用")]):t._e()]}}])}),t._v(" "),a("el-table-column",{attrs:{label:"操作",fixed:"right",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return t.onTableUpdate(e.row)}}},[t._v("修改")]),t._v(" "),e.row.permission?a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return t.onTableAuth(e.row)}}},[t._v("授权")]):t._e()]}}])})],1),t._v(" "),a("el-dialog",{attrs:{title:"修改路由",visible:t.routeDialogVisible,"close-on-click-modal":!1},on:{"update:visible":function(e){t.routeDialogVisible=e}}},[a("el-form",{attrs:{model:t.routeDialogFormData,"label-width":"120px",size:"mini"}},[a("el-form-item",{attrs:{label:"id"}},[a("el-input",{attrs:{readonly:"readonly"},model:{value:t.routeDialogFormData.id,callback:function(e){t.$set(t.routeDialogFormData,"id",e)},expression:"routeDialogFormData.id"}})],1),t._v(" "),a("el-form-item",{attrs:{label:"uri"}},[a("el-input",{model:{value:t.routeDialogFormData.uri,callback:function(e){t.$set(t.routeDialogFormData,"uri",e)},expression:"routeDialogFormData.uri"}})],1),t._v(" "),a("el-form-item",{attrs:{label:"path"}},[a("el-input",{model:{value:t.routeDialogFormData.path,callback:function(e){t.$set(t.routeDialogFormData,"path",e)},expression:"routeDialogFormData.path"}})],1),t._v(" "),a("el-form-item",{attrs:{label:"状态"}},[a("el-radio-group",{model:{value:t.routeDialogFormData.status,callback:function(e){t.$set(t.routeDialogFormData,"status",e)},expression:"routeDialogFormData.status"}},[a("el-radio",{attrs:{label:1,name:"status"}},[t._v("启用")]),t._v(" "),a("el-radio",{staticStyle:{color:"#F56C6C"},attrs:{label:2,name:"status"}},[t._v("禁用")])],1)],1)],1),t._v(" "),a("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(e){t.routeDialogVisible=!1}}},[t._v("取 消")]),t._v(" "),a("el-button",{attrs:{type:"primary"},on:{click:t.onRouteDialogSave}},[t._v("保 存")])],1)],1),t._v(" "),a("el-dialog",{attrs:{title:"路由授权",visible:t.authDialogVisible,"close-on-click-modal":!1},on:{"update:visible":function(e){t.authDialogVisible=e}}},[a("el-form",{attrs:{model:t.authDialogFormData,"label-width":"120px",size:"mini"}},[a("el-form-item",{attrs:{label:"id"}},[a("el-input",{attrs:{readonly:"readonly"},model:{value:t.authDialogFormData.routeId,callback:function(e){t.$set(t.authDialogFormData,"routeId",e)},expression:"authDialogFormData.routeId"}})],1),t._v(" "),a("el-form-item",{attrs:{label:"角色"}},[a("el-checkbox-group",{model:{value:t.authDialogFormData.roleCode,callback:function(e){t.$set(t.authDialogFormData,"roleCode",e)},expression:"authDialogFormData.roleCode"}},t._l(t.roles,function(e){return a("el-checkbox",{key:e.roleCode,attrs:{label:e.roleCode}},[t._v(t._s(e.description))])}),1)],1)],1),t._v(" "),a("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(e){t.authDialogVisible=!1}}},[t._v("取 消")]),t._v(" "),a("el-button",{attrs:{type:"primary"},on:{click:t.onAuthDialogSave}},[t._v("保 存")])],1)],1)],1)],1)],1)},l=[],i={data:function(){return{filterText:"",treeData:[],tableData:[],serviceId:"",searchFormData:{},defaultProps:{children:"children",label:"label"},routeDialogFormData:{status:1},routeDialogVisible:!1,roles:[],authDialogFormData:{routeId:"",roleCode:[]},authDialogVisible:!1}},watch:{filterText:function(t){this.$refs.tree2.filter(t)}},created:function(){this.loadTree(),this.loadRouteRole()},methods:{loadTree:function(){this.post("service.list",{},function(t){var e=t.data;this.treeData=this.convertToTreeData(e,0)})},filterNode:function(t,e){return!t||-1!==e.label.indexOf(t)},onNodeClick:function(t,e,a){t.parentId&&(this.serviceId=t.label,this.searchFormData.serviceId=this.serviceId,this.loadTable())},convertToTreeData:function(t,e){for(var a=[],o={label:"服务列表",parentId:e},l=[],i=0;i0?e.join(", "):'未授权'},onRouteDialogSave:function(){this.routeDialogFormData.serviceId=this.serviceId,this.post("route.update",this.routeDialogFormData,function(){this.routeDialogVisible=!1,this.loadTable()})},onAuthDialogSave:function(){this.post("route.role.update",this.authDialogFormData,function(){console.log(this.authDialogFormData),this.authDialogVisible=!1,this.loadTable()})}}},r=i,s=a("2877"),n=Object(s["a"])(r,o,l,!1,null,null,null);e["default"]=n.exports}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-19100986.3ec98327.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-37401378.4e39ec9b.js similarity index 89% rename from sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-19100986.3ec98327.js rename to sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-37401378.4e39ec9b.js index f55a61bb..3d8d7bb3 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-19100986.3ec98327.js +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-37401378.4e39ec9b.js @@ -1 +1 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-19100986"],{5040:function(t,n,a){"use strict";var e=a("a5a4"),s=a.n(e);s.a},9406:function(t,n,a){"use strict";a.r(n);var e=function(){var t=this,n=t.$createElement;t._self._c;return t._m(0)},s=[function(){var t=this,n=t.$createElement,a=t._self._c||n;return a("div",{staticClass:"dashboard-container"},[a("div",{staticClass:"dashboard-text"},[t._v("欢迎使用SOP Admin")])])}],i={created:function(){this.post("admin.userinfo.get",{},function(t){})}},c=i,r=(a("5040"),a("2877")),o=Object(r["a"])(c,e,s,!1,null,"b4bd5162",null);n["default"]=o.exports},a5a4:function(t,n,a){}}]); \ No newline at end of file +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-37401378"],{5040:function(t,n,a){"use strict";var e=a("a5a4"),s=a.n(e);s.a},9406:function(t,n,a){"use strict";a.r(n);var e=function(){var t=this,n=t.$createElement;t._self._c;return t._m(0)},s=[function(){var t=this,n=t.$createElement,a=t._self._c||n;return a("div",{staticClass:"dashboard-container"},[a("div",{staticClass:"dashboard-text"},[t._v("欢迎使用SOP Admin")])])}],i={created:function(){this.post("admin.userinfo.get",{},function(t){})}},c=i,r=(a("5040"),a("2877")),o=Object(r["a"])(c,e,s,!1,null,"b4bd5162",null);n["default"]=o.exports},a5a4:function(t,n,a){}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-6a68a33e.8b63492e.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-6a68a33e.8b63492e.js new file mode 100644 index 00000000..0131ea81 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-6a68a33e.8b63492e.js @@ -0,0 +1 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-6a68a33e"],{1248:function(e,t,o){"use strict";o.r(t);var a=function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("div",{staticClass:"app-container"},[o("el-container",[o("el-aside",{staticStyle:{"min-height":"300px",width:"250px"}},[o("el-button",{attrs:{type:"primary",plain:"",size:"mini",icon:"el-icon-plus"},on:{click:function(t){return t.stopPropagation(),e.addService(t)}}},[e._v("\n 新建服务\n ")]),e._v(" "),o("el-input",{staticStyle:{"margin-bottom":"10px","margin-top":"10px"},attrs:{"prefix-icon":"el-icon-search",placeholder:"搜索服务...",size:"mini",clearable:""},model:{value:e.filterText,callback:function(t){e.filterText=t},expression:"filterText"}}),e._v(" "),o("el-tree",{ref:"serviceTree",staticClass:"filter-tree",attrs:{data:e.treeData,props:e.defaultProps,"filter-node-method":e.filterNode,"highlight-current":!0,"expand-on-click-node":!1,"empty-text":"无数据","node-key":"serviceId","default-expand-all":""},on:{"node-click":e.onNodeClick},scopedSlots:e._u([{key:"default",fn:function(t){t.node;var a=t.data;return o("span",{staticClass:"custom-tree-node"},[o("div",[o("el-tooltip",{directives:[{name:"show",rawName:"v-show",value:a.custom,expression:"data.custom"}],staticClass:"item",attrs:{content:"自定义服务",effect:"light",placement:"top"}},[o("i",{staticClass:"el-icon-warning-outline"})]),e._v(" "),a.label.length0?t.join(", "):'未授权'},onRouteDialogSave:function(){var e=this;this.$refs.routeDialogFormRef.validate(function(t){if(t){var o=e.routeDialogFormData.id?"route.update":"route.add";e.routeDialogFormData.serviceId=e.serviceId,e.post(o,e.routeDialogFormData,function(){this.routeDialogVisible=!1,this.loadTable()})}})},onAuthDialogSave:function(){this.post("route.role.update",this.authDialogFormData,function(){this.authDialogVisible=!1,this.loadTable()})},addService:function(){this.addServiceDialogVisible=!0},closeAddServiceDlg:function(){this.$refs.addServiceForm.resetFields()},onAddService:function(){var e=this;this.$refs.addServiceForm.validate(function(t){t&&e.post("service.custom.add",e.addServiceForm,function(e){this.addServiceDialogVisible=!1,this.tip("添加成功"),this.loadTree()})})},onDelService:function(e){var t=e.serviceId;this.confirm("确认要删除服务"+t+"吗,【对应的路由配置会一起删除】",function(e){var o={serviceId:t};this.post("service.custom.del",o,function(){e(),this.tip("删除成功"),this.loadTree()})})}}},l=r,s=(o("55a2"),o("2877")),n=Object(s["a"])(l,a,i,!1,null,null,null);t["default"]=n.exports},"55a2":function(e,t,o){"use strict";var a=o("b294"),i=o.n(a);i.a},b294:function(e,t,o){}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-vue/src/utils/global.js b/sop-admin/sop-admin-vue/src/utils/global.js index 1d3b1bca..e8e7570f 100644 --- a/sop-admin/sop-admin-vue/src/utils/global.js +++ b/sop-admin/sop-admin-vue/src/utils/global.js @@ -8,7 +8,7 @@ import { getToken, removeToken } from './auth' // 创建axios实例 const client = axios.create({ baseURL: process.env.VUE_APP_BASE_API, // api 的 base_url - timeout: 5000 // 请求超时时间 + timeout: 10000 // 请求超时时间 }) Object.assign(Vue.prototype, { @@ -94,6 +94,14 @@ Object.assign(Vue.prototype, { } }).catch(function() {}) }, + /** + * 重置表单 + * @param formName 表单元素的ref + */ + resetForm(formName) { + const frm = this.$refs[formName] + frm && frm.resetFields() + }, logout: function() { removeToken() const fullPath = this.$route.fullPath diff --git a/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue b/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue index 96ef8bbb..b7065189 100644 --- a/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue +++ b/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue @@ -1,7 +1,7 @@ - + diff --git a/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue b/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue index 10e21e64..03ec06fe 100644 --- a/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue +++ b/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue @@ -231,7 +231,18 @@ - + \ No newline at end of file +SOP Admin
\ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.29365d11.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.3daff0c2.js similarity index 51% rename from sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.29365d11.js rename to sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.3daff0c2.js index f381b186..11df8607 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.29365d11.js +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.3daff0c2.js @@ -1 +1 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-25908fca"],{"021d":function(e,t,a){},"0bac":function(e,t,a){"use strict";var s=a("021d"),i=a.n(s);i.a},cb56:function(e,t,a){"use strict";a.r(t);var s=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"app-container"},[a("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:e.searchFormData,size:"mini"}},[a("el-form-item",{attrs:{label:"appKey"}},[a("el-input",{staticStyle:{width:"250px"},attrs:{clearable:!0,placeholder:"appKey"},model:{value:e.searchFormData.appKey,callback:function(t){e.$set(e.searchFormData,"appKey",t)},expression:"searchFormData.appKey"}})],1),e._v(" "),a("el-form-item",[a("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:e.onSearchTable}},[e._v("查询")])],1)],1),e._v(" "),a("el-button",{staticStyle:{"margin-bottom":"10px"},attrs:{type:"primary",size:"mini",icon:"el-icon-plus"},on:{click:e.onAdd}},[e._v("新增ISV")]),e._v(" "),a("el-table",{attrs:{data:e.pageInfo.list,border:"",fit:"","highlight-current-row":""}},[a("el-table-column",{attrs:{prop:"id",label:"ID",width:"80"}}),e._v(" "),a("el-table-column",{attrs:{prop:"appKey",label:"appKey",width:"250"}}),e._v(" "),a("el-table-column",{attrs:{prop:"",label:"秘钥",width:"80"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return e.onShowKeys(t.row)}}},[e._v("查看")])]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"roleList",label:"角色"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("div",{domProps:{innerHTML:e._s(e.roleRender(t.row))}})]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"status",label:"状态",width:"80"},scopedSlots:e._u([{key:"default",fn:function(t){return[1===t.row.status?a("span",{staticStyle:{color:"#67C23A"}},[e._v("已启用")]):e._e(),e._v(" "),2===t.row.status?a("span",{staticStyle:{color:"#F56C6C"}},[e._v("已禁用")]):e._e()]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"gmtCreate",label:"添加时间",width:"160"}}),e._v(" "),a("el-table-column",{attrs:{prop:"gmtModified",label:"修改时间",width:"160"}}),e._v(" "),a("el-table-column",{attrs:{label:"操作",width:"150"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return e.onTableUpdate(t.row)}}},[e._v("修改")]),e._v(" "),a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return e.onKeysUpdate(t.row)}}},[e._v("秘钥管理")])]}}])})],1),e._v(" "),a("el-pagination",{staticStyle:{"margin-top":"5px"},attrs:{background:"","current-page":e.searchFormData.pageIndex,"page-size":e.searchFormData.pageSize,"page-sizes":[5,10,20,40],total:e.pageInfo.total,layout:"total, sizes, prev, pager, next"},on:{"size-change":e.onSizeChange,"current-change":e.onPageIndexChange}}),e._v(" "),a("el-dialog",{attrs:{title:e.isvDialogTitle,visible:e.isvDialogVisible,"close-on-click-modal":!1},on:{"update:visible":function(t){e.isvDialogVisible=t},close:e.onIsvDialogClose}},[a("el-form",{ref:"isvForm",attrs:{rules:e.rulesIsvForm,model:e.isvDialogFormData,"label-width":"120px",size:"mini"}},[a("el-form-item",{attrs:{label:"appKey"}},[0===e.isvDialogFormData.id?a("span",{staticStyle:{color:"gray"}},[e._v("(系统自动生成)")]):a("span",[e._v(e._s(e.isvDialogFormData.appKey))])]),e._v(" "),a("el-form-item",{attrs:{label:"角色"}},[a("el-checkbox-group",{model:{value:e.isvDialogFormData.roleCode,callback:function(t){e.$set(e.isvDialogFormData,"roleCode",t)},expression:"isvDialogFormData.roleCode"}},e._l(e.roles,function(t){return a("el-checkbox",{key:t.roleCode,attrs:{label:t.roleCode}},[e._v(e._s(t.description))])}),1)],1),e._v(" "),a("el-form-item",{attrs:{label:"状态"}},[a("el-radio-group",{model:{value:e.isvDialogFormData.status,callback:function(t){e.$set(e.isvDialogFormData,"status",t)},expression:"isvDialogFormData.status"}},[a("el-radio",{attrs:{label:1,name:"status"}},[e._v("启用")]),e._v(" "),a("el-radio",{attrs:{label:2,name:"status"}},[e._v("禁用")])],1)],1)],1),e._v(" "),a("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(t){e.isvDialogVisible=!1}}},[e._v("取 消")]),e._v(" "),a("el-button",{attrs:{type:"primary"},on:{click:e.onIsvDialogSave}},[e._v("保 存")])],1)],1),e._v(" "),a("el-dialog",{attrs:{title:"秘钥信息",visible:e.isvKeysDialogVisible},on:{"update:visible":function(t){e.isvKeysDialogVisible=t},close:function(t){return e.resetForm("isvKeysFrom")}}},[a("el-form",{ref:"isvKeysFrom",staticClass:"key-view",attrs:{model:e.isvKeysFormData,"label-width":"160px",size:"mini"}},[a("el-form-item",{attrs:{label:""}},[a("el-alert",{attrs:{title:"带 ★ 的分配给开发者",type:"warning",closable:!1}})],1),e._v(" "),a("el-form-item",{attrs:{label:e.selfLabel("appKey")}},[a("span",[e._v(e._s(e.isvKeysFormData.appKey))])]),e._v(" "),a("el-form-item",{attrs:{label:"签名方式"}},[1===e.isvKeysFormData.signType?a("span",[e._v("RSA2")]):e._e(),e._v(" "),2===e.isvKeysFormData.signType?a("span",[e._v("MD5")]):e._e()]),e._v(" "),a("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}],attrs:{label:"秘钥格式"}},[1===e.isvKeysFormData.keyFormat?a("span",[e._v("PKCS8(JAVA适用)")]):e._e(),e._v(" "),2===e.isvKeysFormData.keyFormat?a("span",[e._v("PKCS1(非JAVA适用)")]):e._e()]),e._v(" "),a("el-form-item",{directives:[{name:"show",rawName:"v-show",value:2===e.isvKeysFormData.signType,expression:"isvKeysFormData.signType === 2"}],attrs:{label:e.selfLabel("secret")}},[a("span",[e._v(e._s(e.isvKeysFormData.secret))])]),e._v(" "),a("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[a("legend",[e._v("ISV公私钥")]),e._v(" "),a("el-form-item",{attrs:{label:"ISV公钥"}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.publicKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyIsv",t)},expression:"isvKeysFormData.publicKeyIsv"}})],1),e._v(" "),a("el-form-item",{attrs:{label:e.selfLabel("ISV私钥")}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.privateKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyIsv",t)},expression:"isvKeysFormData.privateKeyIsv"}})],1)],1),e._v(" "),a("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[a("legend",[e._v("平台公私钥")]),e._v(" "),a("el-form-item",{attrs:{label:e.selfLabel("平台公钥")}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.publicKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyPlatform",t)},expression:"isvKeysFormData.publicKeyPlatform"}})],1),e._v(" "),a("el-form-item",{attrs:{prop:"privateKeyPlatform",label:"平台私钥"}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.privateKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyPlatform",t)},expression:"isvKeysFormData.privateKeyPlatform"}})],1)],1)],1),e._v(" "),a("span",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(t){e.isvKeysDialogVisible=!1}}},[e._v("关 闭")])],1)],1)],1)},i=[],o={data:function(){return{searchFormData:{appKey:"",pageIndex:1,pageSize:10},pageInfo:{list:[],total:0},roles:[],isvDialogVisible:!1,isvDialogTitle:"新增ISV",isvDialogFormData:{id:0,status:1,roleCode:[]},rulesIsvForm:{appKey:[{required:!0,message:"不能为空",trigger:"blur"},{min:1,max:100,message:"长度在 1 到 100 个字符",trigger:"blur"}]},isvKeysDialogVisible:!1,isvKeysFormData:{appKey:"",secret:"",publicKeyIsv:"",privateKeyIsv:"",publicKeyPlatform:"",privateKeyPlatform:"",signType:""}}},created:function(){this.loadTable(),this.loadRouteRole()},methods:{loadTable:function(){this.post("isv.info.page",this.searchFormData,function(e){this.pageInfo=e.data})},loadRouteRole:function(){0===this.roles.length&&this.post("role.listall",{},function(e){this.roles=e.data})},onShowKeys:function(e){this.post("isv.keys.get",{appKey:e.appKey},function(e){var t=this;this.isvKeysDialogVisible=!0,this.$nextTick(function(){Object.assign(t.isvKeysFormData,e.data)})})},onSearchTable:function(){this.loadTable()},onTableUpdate:function(e){var t=this;this.isvDialogTitle="修改ISV",this.isvDialogVisible=!0,this.$nextTick(function(){t.post("isv.info.get",{id:e.id},function(e){for(var t=e.data,a=t.roleList,s=[],i=0;i200&&a(new Error("长度不能超过200"))),a()},s=function(t,s,a){1===e.isvKeysFormData.signType&&""===s&&a(new Error("不能为空")),a()};return{isvKeysFormData:{appKey:"",secret:"",keyFormat:1,publicKeyIsv:"",privateKeyIsv:"",publicKeyPlatform:"",privateKeyPlatform:"",signType:1},rulesIsvKeysForm:{secret:[{validator:t,trigger:"blur"}],publicKeyIsv:[{validator:s,trigger:"blur"}],privateKeyIsv:[{validator:s,trigger:"blur"}]}}},created:function(){var e=this.$route.query;this.isvKeysFormData.appKey=e.appKey,this.loadForm()},methods:{loadForm:function(){this.post("isv.keys.get",{appKey:this.isvKeysFormData.appKey},function(e){Object.assign(this.isvKeysFormData,e.data)})},selfLabel:function(e){return"★ "+e},onSubmit:function(){var e=this;this.$refs.isvKeysForm.validate(function(t){t&&e.post("isv.keys.update",e.isvKeysFormData,function(){this.tip("保存成功")})})},onBack:function(){this.$router.push({path:"list"})},onGenKeysPlatform:function(){this.post("isv.keys.gen",{},function(e){this.tip("生成公私钥成功");var t=e.data;this.isvKeysFormData.publicKeyPlatform=t.publicKey,this.isvKeysFormData.privateKeyPlatform=t.privateKey})},onGenKeysIsv:function(){this.post("isv.keys.gen",{keyFormat:this.isvKeysFormData.keyFormat},function(e){this.tip("生成公私钥成功");var t=e.data;this.isvKeysFormData.publicKeyIsv=t.publicKey,this.isvKeysFormData.privateKeyIsv=t.privateKey})},onGenSecret:function(){this.post("isv.secret.gen",{},function(e){this.isvKeysFormData.secret=e.data})},showKeys:function(){return 1===this.isvKeysFormData.signType}}},o=r,l=(s("8b91"),s("2877")),n=Object(l["a"])(o,a,i,!1,null,null,null);t["default"]=n.exports},"8b91":function(e,t,s){"use strict";var a=s("29fd"),i=s.n(a);i.a}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.37433095.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.37433095.js deleted file mode 100644 index 0aa3c382..00000000 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.37433095.js +++ /dev/null @@ -1 +0,0 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-73b2dcec"],{"29fd":function(e,t,s){},"3bf7":function(e,t,s){"use strict";s.r(t);var a=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"app-container"},[s("el-button",{staticClass:"el-icon-back",attrs:{type:"text"},on:{click:e.onBack}},[e._v("返回")]),e._v(" "),s("el-form",{ref:"isvKeysForm",staticStyle:{width:"700px"},attrs:{rules:e.rulesIsvKeysForm,model:e.isvKeysFormData,"label-width":"160px",size:"mini"}},[s("el-form-item",{attrs:{label:""}},[s("el-alert",{attrs:{title:"带 ★ 的分配给开发者",type:"warning",closable:!1}})],1),e._v(" "),s("el-form-item",{attrs:{label:e.selfLabel("appKey")}},[s("div",[e._v(e._s(e.isvKeysFormData.appKey))])]),e._v(" "),s("el-form-item",{attrs:{label:"签名方式"}},[s("el-radio-group",{model:{value:e.isvKeysFormData.signType,callback:function(t){e.$set(e.isvKeysFormData,"signType",t)},expression:"isvKeysFormData.signType"}},[s("el-radio",{attrs:{label:1,name:"status"}},[e._v("RSA2")]),e._v(" "),s("el-radio",{attrs:{label:2,name:"status"}},[e._v("MD5")])],1)],1),e._v(" "),s("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}],attrs:{label:"秘钥格式"}},[s("el-radio-group",{model:{value:e.isvKeysFormData.keyFormat,callback:function(t){e.$set(e.isvKeysFormData,"keyFormat",t)},expression:"isvKeysFormData.keyFormat"}},[s("el-radio",{attrs:{label:1,name:"keyFormat"}},[e._v("PKCS8(JAVA适用)")]),e._v(" "),s("el-radio",{attrs:{label:2,name:"keyFormat"}},[e._v("PKCS1(非JAVA适用)")])],1)],1),e._v(" "),s("el-form-item",{directives:[{name:"show",rawName:"v-show",value:2===e.isvKeysFormData.signType,expression:"isvKeysFormData.signType === 2"}],attrs:{prop:"secret",label:e.selfLabel("secret")}},[s("el-input",{model:{value:e.isvKeysFormData.secret,callback:function(t){e.$set(e.isvKeysFormData,"secret",t)},expression:"isvKeysFormData.secret"}}),e._v(" "),s("el-button",{attrs:{type:"text"},on:{click:e.onGenSecret}},[e._v("重新生成")])],1),e._v(" "),s("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[s("legend",[e._v("ISV公私钥")]),e._v(" "),s("el-form-item",{staticClass:"gen-key"},[s("el-button",{attrs:{type:"text"},on:{click:e.onGenKeysIsv}},[e._v("重新生成")])],1),e._v(" "),s("el-form-item",{attrs:{prop:"publicKeyIsv",label:"ISV公钥"}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.publicKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyIsv",t)},expression:"isvKeysFormData.publicKeyIsv"}})],1),e._v(" "),s("el-form-item",{attrs:{prop:"privateKeyIsv",label:e.selfLabel("ISV私钥")}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.privateKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyIsv",t)},expression:"isvKeysFormData.privateKeyIsv"}})],1)],1),e._v(" "),s("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[s("legend",[e._v("平台公私钥")]),e._v(" "),s("el-form-item",{staticClass:"gen-key"},[s("el-button",{attrs:{type:"text"},on:{click:e.onGenKeysPlatform}},[e._v("重新生成")])],1),e._v(" "),s("el-form-item",{attrs:{prop:"publicKeyPlatform",label:e.selfLabel("平台公钥")}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.publicKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyPlatform",t)},expression:"isvKeysFormData.publicKeyPlatform"}})],1),e._v(" "),s("el-form-item",{attrs:{prop:"privateKeyPlatform",label:"平台私钥"}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.privateKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyPlatform",t)},expression:"isvKeysFormData.privateKeyPlatform"}})],1)],1),e._v(" "),s("el-form-item",[s("el-button",{attrs:{type:"primary"},on:{click:e.onSubmit}},[e._v("保存")]),e._v(" "),s("el-button",{on:{click:e.onBack}},[e._v("取消")])],1)],1)],1)},i=[],r={data:function(){var e=this,t=function(t,s,a){2===e.isvKeysFormData.signType&&(""===s&&a(new Error("不能为空")),s.length>200&&a(new Error("长度不能超过200"))),a()},s=function(t,s,a){1===e.isvKeysFormData.signType&&""===s&&a(new Error("不能为空")),a()};return{isvKeysFormData:{appKey:"",secret:"",keyFormat:1,publicKeyIsv:"",privateKeyIsv:"",publicKeyPlatform:"",privateKeyPlatform:"",signType:1},rulesIsvKeysForm:{secret:[{validator:t,trigger:"blur"}],publicKeyIsv:[{validator:s,trigger:"blur"}],privateKeyIsv:[{validator:s,trigger:"blur"}]}}},created:function(){var e=this.$route.query;this.isvKeysFormData.appKey=e.appKey,this.loadForm()},methods:{loadForm:function(){this.post("isv.keys.get",{appKey:this.isvKeysFormData.appKey},function(e){Object.assign(this.isvKeysFormData,e.data)})},selfLabel:function(e){return"★ "+e},onSubmit:function(){var e=this;this.$refs.isvKeysForm.validate(function(t){t&&e.post("isv.keys.update",e.isvKeysFormData,function(){this.tip("保存成功")})})},onBack:function(){this.$router.push({path:"list"})},onGenKeysPlatform:function(){this.post("isv.keys.gen",{},function(e){this.tip("生成公私钥成功");var t=e.data;this.isvKeysFormData.publicKeyPlatform=t.publicKey,this.isvKeysFormData.privateKeyPlatform=t.privateKey})},onGenKeysIsv:function(){this.post("isv.keys.gen",{keyFormat:this.isvKeysFormData.keyFormat},function(e){this.tip("生成公私钥成功");var t=e.data;this.isvKeysFormData.publicKeyIsv=t.publicKey,this.isvKeysFormData.privateKeyIsv=t.privateKey})},onGenSecret:function(){this.post("isv.secret.gen",{},function(e){this.isvKeysFormData.secret=e.data})},showKeys:function(){return 1===this.isvKeysFormData.signType}}},o=r,l=(s("8b91"),s("2877")),n=Object(l["a"])(o,a,i,!1,null,null,null);t["default"]=n.exports},"8b91":function(e,t,s){"use strict";var a=s("29fd"),i=s.n(a);i.a}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-vue/src/views/isv/index.vue b/sop-admin/sop-admin-vue/src/views/isv/index.vue index d491a493..258b617f 100644 --- a/sop-admin/sop-admin-vue/src/views/isv/index.vue +++ b/sop-admin/sop-admin-vue/src/views/isv/index.vue @@ -142,7 +142,7 @@ {{ isvKeysFormData.appKey }} - RSA2 + RSA MD5 diff --git a/sop-admin/sop-admin-vue/src/views/isv/keys.vue b/sop-admin/sop-admin-vue/src/views/isv/keys.vue index a5a2ac03..812f5857 100644 --- a/sop-admin/sop-admin-vue/src/views/isv/keys.vue +++ b/sop-admin/sop-admin-vue/src/views/isv/keys.vue @@ -21,7 +21,7 @@ - RSA2 + RSA MD5 From 8945e066825ab61fbcd484838c9f392e8d6f79a5 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 28 Jun 2019 10:38:51 +0800 Subject: [PATCH 21/40] 1.11.0 --- doc/docs/files/10085_ISV管理.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/docs/files/10085_ISV管理.md b/doc/docs/files/10085_ISV管理.md index 159523bc..e6334502 100644 --- a/doc/docs/files/10085_ISV管理.md +++ b/doc/docs/files/10085_ISV管理.md @@ -17,7 +17,7 @@ ISV:独立软体开发商(independent software vendor),即接入方或 点击操作列的`秘钥管理`,可对ISV的秘钥进行设置。 -- 如果采用淘宝开放平台签名方式,签名方式选择`MD5`,如果采用支付宝开放平台签名方式,选择`RSA2` +- 如果采用淘宝开放平台签名方式,签名方式选择`MD5`,如果采用支付宝开放平台签名方式,选择`RSA` - 如果对接的开发者使用非Java语言,秘钥格式选择`PKCS1` - 带 ★ 的分配给开发者 From 952d41f143ef579c73145405747e6e9096d46923 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 28 Jun 2019 10:39:19 +0800 Subject: [PATCH 22/40] 1.11.0 --- doc/docs/_sidebar.md | 54 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index 1b3d03f0..c18e4b3a 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,29 +1,29 @@ -* [首页](/?t=1561630813787) +* [首页](/?t=1561689549009) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1561630813789) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561630813807) - * [新增接口](files/10020_新增接口.md?t=1561630813808) - * [业务参数校验](files/10030_业务参数校验.md?t=1561630813808) - * [错误处理](files/10040_错误处理.md?t=1561630813808) - * [编写文档](files/10041_编写文档.md?t=1561630813808) - * [接口交互详解](files/10050_接口交互详解.md?t=1561630813808) - * [easyopen支持](files/10070_easyopen支持.md?t=1561630813808) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561630813808) - * [ISV管理](files/10085_ISV管理.md?t=1561630813808) - * [自定义路由](files/10086_自定义路由.md?t=1561630813808) - * [路由授权](files/10090_路由授权.md?t=1561630813809) - * [接口限流](files/10092_接口限流.md?t=1561630813809) - * [监控日志](files/10093_监控日志.md?t=1561630813809) - * [SDK开发](files/10095_SDK开发.md?t=1561630813809) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561630813809) - * [应用授权](files/10097_应用授权.md?t=1561630813809) - * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561630813809) - * [对接前端](files/10100_对接前端.md?t=1561630813809) - * [自定义过滤器](files/10102_自定义过滤器.md?t=1561630813809) - * [文件上传](files/10104_文件上传.md?t=1561630813809) + * [快速体验](files/10010_快速体验.md?t=1561689549011) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561689549027) + * [新增接口](files/10020_新增接口.md?t=1561689549027) + * [业务参数校验](files/10030_业务参数校验.md?t=1561689549028) + * [错误处理](files/10040_错误处理.md?t=1561689549028) + * [编写文档](files/10041_编写文档.md?t=1561689549028) + * [接口交互详解](files/10050_接口交互详解.md?t=1561689549028) + * [easyopen支持](files/10070_easyopen支持.md?t=1561689549028) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561689549028) + * [ISV管理](files/10085_ISV管理.md?t=1561689549028) + * [自定义路由](files/10086_自定义路由.md?t=1561689549028) + * [路由授权](files/10090_路由授权.md?t=1561689549028) + * [接口限流](files/10092_接口限流.md?t=1561689549029) + * [监控日志](files/10093_监控日志.md?t=1561689549029) + * [SDK开发](files/10095_SDK开发.md?t=1561689549029) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561689549029) + * [应用授权](files/10097_应用授权.md?t=1561689549029) + * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561689549029) + * [对接前端](files/10100_对接前端.md?t=1561689549029) + * [自定义过滤器](files/10102_自定义过滤器.md?t=1561689549029) + * [文件上传](files/10104_文件上传.md?t=1561689549029) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561630813810) - * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561630813810) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561630813810) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561630813810) - * [常见问题](files/90100_常见问题.md?t=1561630813810) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561689549029) + * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561689549030) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561689549030) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561689549030) + * [常见问题](files/90100_常见问题.md?t=1561689549030) From 36133adf627d98ac6d4674cf3869a326c5ef1630 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 28 Jun 2019 15:09:11 +0800 Subject: [PATCH 23/40] =?UTF-8?q?=E6=96=B0=E5=A2=9EISV=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java | 3 +++ .../main/java/com/gitee/sop/adminserver/entity/IsvInfo.java | 2 ++ 2 files changed, 5 insertions(+) diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java index 2db914fd..27755aa8 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java @@ -10,6 +10,7 @@ import com.gitee.easyopen.doc.annotation.ApiDocMethod; import com.gitee.easyopen.util.CopyUtil; import com.gitee.fastmybatis.core.PageInfo; import com.gitee.fastmybatis.core.query.Query; +import com.gitee.fastmybatis.core.query.Sort; import com.gitee.fastmybatis.core.util.MapperUtil; import com.gitee.sop.adminserver.api.IdParam; import com.gitee.sop.adminserver.api.isv.param.IsvInfoFormAdd; @@ -82,6 +83,7 @@ public class IsvApi { }) PageInfo pageIsv(IsvPageParam param) { Query query = Query.build(param); + query.orderby("id", Sort.DESC); PageInfo pageInfo = MapperUtil.query(isvInfoMapper, query); List list = pageInfo.getList(); @@ -165,6 +167,7 @@ public class IsvApi { } IsvKeysGenVO isvKeysGenVO = this.createIsvKeys(); IsvKeys isvKeys = new IsvKeys(); + isvKeys.setAppKey(appKey); CopyUtil.copyPropertiesIgnoreNull(isvKeysGenVO, isvKeys); isvKeysMapper.saveIgnoreNull(isvKeys); diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/IsvInfo.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/IsvInfo.java index 873dacb3..4b749092 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/IsvInfo.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/IsvInfo.java @@ -28,6 +28,8 @@ public class IsvInfo { /** appKey, 数据库字段:app_key */ private String appKey; + private String secret = ""; + /** 1启用,2禁用, 数据库字段:status */ private Byte status; From 21792d39b1560c95a737c326678b8b1e8deb3373 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 28 Jun 2019 18:16:32 +0800 Subject: [PATCH 24/40] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sop/adminserver/api/isv/RoleApi.java | 46 ++++- .../adminserver/api/isv/param/RoleForm.java | 24 +++ .../api/isv/param/RolePageParam.java | 19 ++ .../adminserver/api/isv/result/RoleVO.java | 8 + .../gitee/sop/adminserver/entity/IsvInfo.java | 7 + .../src/main/resources/public/index.html | 2 +- .../js/{app.3cc1fa6b.js => app.61234abc.js} | 2 +- ...3daff0c2.js => chunk-25908fca.e7e4b6d5.js} | 2 +- .../static/js/chunk-2d2085ef.a63a74dc.js | 1 + sop-admin/sop-admin-vue/src/router/index.js | 8 +- .../sop-admin-vue/src/views/isv/index.vue | 2 +- .../sop-admin-vue/src/views/isv/role.vue | 179 ++++++++++++++++++ sop.sql | 2 +- 13 files changed, 295 insertions(+), 7 deletions(-) create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/RoleForm.java create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/RolePageParam.java rename sop-admin/sop-admin-server/src/main/resources/public/static/js/{app.3cc1fa6b.js => app.61234abc.js} (50%) rename sop-admin/sop-admin-server/src/main/resources/public/static/js/{chunk-25908fca.3daff0c2.js => chunk-25908fca.e7e4b6d5.js} (93%) create mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d2085ef.a63a74dc.js create mode 100644 sop-admin/sop-admin-vue/src/views/isv/role.vue diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/RoleApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/RoleApi.java index b659ed66..b8ae1c97 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/RoleApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/RoleApi.java @@ -3,14 +3,20 @@ package com.gitee.sop.adminserver.api.isv; import com.gitee.easyopen.annotation.Api; import com.gitee.easyopen.annotation.ApiService; import com.gitee.easyopen.doc.annotation.ApiDoc; +import com.gitee.easyopen.doc.annotation.ApiDocMethod; import com.gitee.easyopen.util.CopyUtil; -import com.gitee.fastmybatis.core.PageInfo; import com.gitee.fastmybatis.core.query.Query; import com.gitee.fastmybatis.core.query.Sort; import com.gitee.fastmybatis.core.support.PageEasyui; import com.gitee.fastmybatis.core.util.MapperUtil; +import com.gitee.sop.adminserver.api.isv.param.RoleForm; +import com.gitee.sop.adminserver.api.isv.param.RolePageParam; import com.gitee.sop.adminserver.api.isv.result.RoleVO; +import com.gitee.sop.adminserver.common.BizException; +import com.gitee.sop.adminserver.entity.PermRole; +import com.gitee.sop.adminserver.entity.PermRolePermission; import com.gitee.sop.adminserver.mapper.PermRoleMapper; +import com.gitee.sop.adminserver.mapper.PermRolePermissionMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +34,9 @@ public class RoleApi { @Autowired PermRoleMapper permRoleMapper; + @Autowired + PermRolePermissionMapper permRolePermissionMapper; + @Api(name = "role.listall") List roleListall() { Query query = new Query(); @@ -40,4 +49,39 @@ public class RoleApi { }) .collect(Collectors.toList()); } + + @ApiDocMethod(description = "获取角色,分页") + @Api(name = "role.page") + PageEasyui pageRole(RolePageParam rolePage) { + Query query = Query.build(rolePage); + return MapperUtil.queryForEasyuiDatagrid(permRoleMapper, query, RoleVO.class); + } + + @Api(name = "role.add") + void addRole(RoleForm roleForm) { + PermRole rec = permRoleMapper.getByColumn("role_code", roleForm.getRoleCode()); + if (rec != null) { + throw new BizException("角色码已存在"); + } + PermRole permRole = new PermRole(); + CopyUtil.copyPropertiesIgnoreNull(roleForm, permRole); + permRoleMapper.saveIgnoreNull(permRole); + } + + @Api(name = "role.update") + void updateRole(RoleForm roleForm) { + PermRole rec = permRoleMapper.getById(roleForm.getId()); + rec.setDescription(roleForm.getDescription()); + permRoleMapper.updateIgnoreNull(rec); + } + + @Api(name = "role.del") + void delRole(long id) { + PermRole rec = permRoleMapper.getById(id); + PermRolePermission rolePermission = permRolePermissionMapper.getByColumn("role_code", rec.getRoleCode()); + if (rolePermission != null) { + throw new BizException("该角色已使用,无法删除"); + } + permRoleMapper.deleteById(id); + } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/RoleForm.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/RoleForm.java new file mode 100644 index 00000000..7e056a73 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/RoleForm.java @@ -0,0 +1,24 @@ +package com.gitee.sop.adminserver.api.isv.param; + +import com.gitee.easyopen.doc.annotation.ApiDocField; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; + +/** + * @author tanghc + */ +@Data +public class RoleForm { + @ApiDocField(description = "id") + private Long id; + + @ApiDocField(description = "角色码") + @NotBlank(message = "roleCode不能为空") + @Length(max = 64) + private String roleCode; + + @ApiDocField(description = "描述") + private String description; +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/RolePageParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/RolePageParam.java new file mode 100644 index 00000000..34690881 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/RolePageParam.java @@ -0,0 +1,19 @@ +package com.gitee.sop.adminserver.api.isv.param; + +import com.gitee.easyopen.doc.annotation.ApiDocField; +import com.gitee.fastmybatis.core.query.Operator; +import com.gitee.fastmybatis.core.query.annotation.Condition; +import com.gitee.fastmybatis.core.query.param.PageParam; +import lombok.Getter; +import lombok.Setter; + +/** + * @author tanghc + */ +@Getter +@Setter +public class RolePageParam extends PageParam { + @ApiDocField(description = "角色码") + @Condition(operator = Operator.like) + private String roleCode; +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/RoleVO.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/RoleVO.java index 3665b427..70b3ab9f 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/RoleVO.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/result/RoleVO.java @@ -10,10 +10,18 @@ import java.util.Date; */ @Data public class RoleVO { + @ApiDocField(description = "id") private Long id; + @ApiDocField(description = "角色码") private String roleCode; + @ApiDocField(description = "描述") private String description; + + @ApiDocField(description = "创建时间") private Date gmtCreate; + + @ApiDocField(description = "修改时间") + private Date gmtModified; } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/IsvInfo.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/IsvInfo.java index 4b749092..44720207 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/IsvInfo.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/entity/IsvInfo.java @@ -28,8 +28,15 @@ public class IsvInfo { /** appKey, 数据库字段:app_key */ private String appKey; + // 不再使用,转移到isv_keys表 private String secret = ""; + /** 公钥,不再使用,转移到isv_keys表 数据库字段:pub_key */ + private String pubKey; + + /** 私钥,不再使用,转移到isv_keys表 数据库字段:pri_key */ + private String priKey; + /** 1启用,2禁用, 数据库字段:status */ private Byte status; diff --git a/sop-admin/sop-admin-server/src/main/resources/public/index.html b/sop-admin/sop-admin-server/src/main/resources/public/index.html index a3a7d31e..40190d95 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/index.html +++ b/sop-admin/sop-admin-server/src/main/resources/public/index.html @@ -1 +1 @@ -SOP Admin
\ No newline at end of file +SOP Admin
\ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.3cc1fa6b.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.61234abc.js similarity index 50% rename from sop-admin/sop-admin-server/src/main/resources/public/static/js/app.3cc1fa6b.js rename to sop-admin/sop-admin-server/src/main/resources/public/static/js/app.61234abc.js index 7079d411..94c16887 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.3cc1fa6b.js +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.61234abc.js @@ -1 +1 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["app"],{0:function(e,t,n){e.exports=n("56d7")},"0cb8":function(e,t,n){},"186a":function(e,t,n){"use strict";var a=n("dc52"),i=n.n(a);i.a},"18f0":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-link",use:"icon-link-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"1f59":function(e,t,n){},2536:function(e,t,n){},2635:function(e,t,n){},"2a3d":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-password",use:"icon-password-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"30c3":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-example",use:"icon-example-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"34c8":function(e,t,n){"use strict";var a=n("5332"),i=n.n(a);i.a},"405a":function(e,t,n){"use strict";var a=n("1f59"),i=n.n(a);i.a},"47f1":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-table",use:"icon-table-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"4df5":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye",use:"icon-eye-usage",viewBox:"0 0 128 64",content:''});r.a.add(s);t["default"]=s},"50be":function(e,t,n){"use strict";var a=n("2536"),i=n.n(a);i.a},"51ff":function(e,t,n){var a={"./dashboard.svg":"f782","./example.svg":"30c3","./eye-open.svg":"d7ec","./eye.svg":"4df5","./form.svg":"eb1b","./link.svg":"18f0","./nested.svg":"dcf8","./password.svg":"2a3d","./table.svg":"47f1","./tree.svg":"93cd","./user.svg":"b3b5"};function i(e){var t=o(e);return n(t)}function o(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return t}i.keys=function(){return Object.keys(a)},i.resolve=o,e.exports=i,i.id="51ff"},5332:function(e,t,n){},"56d7":function(e,t,n){"use strict";n.r(t);n("cadf"),n("551c"),n("f751"),n("097d");var a=n("2b0e"),i=(n("f5df"),n("5c96")),o=n.n(i),r=(n("0fae"),n("f0d9")),s=n.n(r),c=(n("b20f"),function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"app"}},[n("router-view")],1)}),u=[],l={name:"App"},d=l,h=n("2877"),m=Object(h["a"])(d,c,u,!1,null,null,null),f=m.exports,p=n("2f62"),v=(n("7f7f"),{sidebar:function(e){return e.app.sidebar},device:function(e){return e.app.device},token:function(e){return e.user.token},avatar:function(e){return e.user.avatar},name:function(e){return e.user.name}}),b=v,g=n("a78e"),w=n.n(g),x={sidebar:{opened:!w.a.get("sidebarStatus")||!!+w.a.get("sidebarStatus"),withoutAnimation:!1},device:"desktop"},y={TOGGLE_SIDEBAR:function(e){e.sidebar.opened=!e.sidebar.opened,e.sidebar.withoutAnimation=!1,e.sidebar.opened?w.a.set("sidebarStatus",1):w.a.set("sidebarStatus",0)},CLOSE_SIDEBAR:function(e,t){w.a.set("sidebarStatus",0),e.sidebar.opened=!1,e.sidebar.withoutAnimation=t},TOGGLE_DEVICE:function(e,t){e.device=t}},_={toggleSideBar:function(e){var t=e.commit;t("TOGGLE_SIDEBAR")},closeSideBar:function(e,t){var n=e.commit,a=t.withoutAnimation;n("CLOSE_SIDEBAR",a)},toggleDevice:function(e,t){var n=e.commit;n("TOGGLE_DEVICE",t)}},C={namespaced:!0,state:x,mutations:y,actions:_},k=n("83d6"),O=n.n(k),S=O.a.showSettings,z=O.a.fixedHeader,B=O.a.sidebarLogo,H={showSettings:S,fixedHeader:z,sidebarLogo:B},M={CHANGE_SETTING:function(e,t){var n=t.key,a=t.value;e.hasOwnProperty(n)&&(e[n]=a)}},T={changeSetting:function(e,t){var n=e.commit;n("CHANGE_SETTING",t)}},E={namespaced:!0,state:H,mutations:M,actions:T},L=n("bc3a"),$=n.n(L),V=n("5f87"),A=$.a.create({baseURL:"/api",withCredentials:!0,timeout:5e3});A.interceptors.request.use(function(e){return bt.getters.token&&(e.headers["X-Token"]=Object(V["a"])()),e},function(e){return console.log(e),Promise.reject(e)}),A.interceptors.response.use(function(e){var t=e.data;return 2e4!==t.code?(Object(i["Message"])({message:t.message||"error",type:"error",duration:5e3}),50008!==t.code&&50012!==t.code&&50014!==t.code||i["MessageBox"].confirm("You have been logged out, you can cancel to stay on this page, or log in again","Confirm logout",{confirmButtonText:"Re-Login",cancelButtonText:"Cancel",type:"warning"}).then(function(){bt.dispatch("user/resetToken").then(function(){location.reload()})}),Promise.reject(t.message||"error")):t},function(e){return console.log("err"+e),Object(i["Message"])({message:e.message,type:"error",duration:5e3}),Promise.reject(e)});var j=A;function P(e){return j({url:"/user/login",method:"post",data:e})}function I(e){return j({url:"/user/info",method:"get",params:{token:e}})}function N(){return j({url:"/user/logout",method:"post"})}var D=n("8c4f"),q=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-wrapper",class:e.classObj},["mobile"===e.device&&e.sidebar.opened?n("div",{staticClass:"drawer-bg",on:{click:e.handleClickOutside}}):e._e(),e._v(" "),n("sidebar",{staticClass:"sidebar-container"}),e._v(" "),n("div",{staticClass:"main-container"},[n("div",{class:{"fixed-header":e.fixedHeader}},[n("navbar")],1),e._v(" "),n("app-main")],1)],1)},R=[],G=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"navbar"},[n("hamburger",{staticClass:"hamburger-container",attrs:{"is-active":e.sidebar.opened},on:{toggleClick:e.toggleSideBar}}),e._v(" "),n("breadcrumb",{staticClass:"breadcrumb-container"}),e._v(" "),n("div",{staticClass:"right-menu"},[n("el-button",{staticStyle:{"margin-right":"10px"},attrs:{type:"text"},on:{click:e.doLogout}},[e._v("退出")])],1)],1)},F=[],U=n("cebc"),K=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("el-breadcrumb",{staticClass:"app-breadcrumb",attrs:{separator:"/"}},[n("transition-group",{attrs:{name:"breadcrumb"}},e._l(e.levelList,function(t,a){return n("el-breadcrumb-item",{key:t.path},["noRedirect"===t.redirect||a==e.levelList.length-1?n("span",{staticClass:"no-redirect"},[e._v(e._s(t.meta.title))]):n("a",{on:{click:function(n){return n.preventDefault(),e.handleLink(t)}}},[e._v(e._s(t.meta.title))])])}),1)],1)},W=[],J=n("bd11"),X=n.n(J),Y={data:function(){return{levelList:null}},watch:{$route:function(){this.getBreadcrumb()}},created:function(){this.getBreadcrumb()},methods:{getBreadcrumb:function(){var e=this.$route.matched.filter(function(e){return e.meta&&e.meta.title}),t=e[0];this.isDashboard(t)||(e=[{path:"/dashboard",meta:{title:"Dashboard"}}].concat(e)),this.levelList=e.filter(function(e){return e.meta&&e.meta.title&&!1!==e.meta.breadcrumb})},isDashboard:function(e){var t=e&&e.name;return!!t&&t.trim().toLocaleLowerCase()==="Dashboard".toLocaleLowerCase()},pathCompile:function(e){var t=this.$route.params,n=X.a.compile(e);return n(t)},handleLink:function(e){var t=e.redirect,n=e.path;t?this.$router.push(t):this.$router.push(this.pathCompile(n))}}},Q=Y,Z=(n("34c8"),Object(h["a"])(Q,K,W,!1,null,"62cc9144",null)),ee=Z.exports,te=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticStyle:{padding:"0 15px"},on:{click:e.toggleClick}},[n("svg",{staticClass:"hamburger",class:{"is-active":e.isActive},attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"64",height:"64"}},[n("path",{attrs:{d:"M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"}})])])},ne=[],ae={name:"Hamburger",props:{isActive:{type:Boolean,default:!1}},methods:{toggleClick:function(){this.$emit("toggleClick")}}},ie=ae,oe=(n("186a"),Object(h["a"])(ie,te,ne,!1,null,"49e15297",null)),re=oe.exports,se={components:{Breadcrumb:ee,Hamburger:re},computed:Object(U["a"])({},Object(p["b"])(["sidebar","avatar"])),methods:{toggleSideBar:function(){this.$store.dispatch("app/toggleSideBar")},doLogout:function(){this.logout()}}},ce=se,ue=(n("405a"),Object(h["a"])(ce,G,F,!1,null,"1eff5c58",null)),le=ue.exports,de=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{class:{"has-logo":e.showLogo}},[e.showLogo?n("logo",{attrs:{collapse:e.isCollapse}}):e._e(),e._v(" "),n("el-scrollbar",{attrs:{"wrap-class":"scrollbar-wrapper"}},[n("el-menu",{attrs:{"default-active":e.activeMenu,collapse:e.isCollapse,"background-color":e.variables.menuBg,"text-color":e.variables.menuText,"unique-opened":!1,"active-text-color":e.variables.menuActiveText,"collapse-transition":!1,mode:"vertical"}},e._l(e.routes,function(e){return n("sidebar-item",{key:e.path,attrs:{item:e,"base-path":e.path}})}),1)],1)],1)},he=[],me=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"sidebar-logo-container",class:{collapse:e.collapse}},[n("transition",{attrs:{name:"sidebarLogoFade"}},[e.collapse?n("router-link",{key:"collapse",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])]):n("router-link",{key:"expand",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):e._e(),e._v(" "),n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])])],1)],1)},fe=[],pe={name:"SidebarLogo",props:{collapse:{type:Boolean,required:!0}},data:function(){return{title:"SOP Admin",logo:"https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png"}}},ve=pe,be=(n("7c27"),Object(h["a"])(ve,me,fe,!1,null,"b905289c",null)),ge=be.exports,we=function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.item.hidden?e._e():n("div",{staticClass:"menu-wrapper"},[!e.hasOneShowingChild(e.item.children,e.item)||e.onlyOneChild.children&&!e.onlyOneChild.noShowingChildren||e.item.alwaysShow?n("el-submenu",{ref:"subMenu",attrs:{index:e.resolvePath(e.item.path),"popper-append-to-body":""}},[n("template",{slot:"title"},[e.item.meta?n("item",{attrs:{icon:e.item.meta&&e.item.meta.icon,title:e.item.meta.title}}):e._e()],1),e._v(" "),e._l(e.item.children,function(t){return n("sidebar-item",{key:t.path,staticClass:"nest-menu",attrs:{"is-nest":!0,item:t,"base-path":e.resolvePath(t.path)}})})],2):[e.onlyOneChild.meta?n("app-link",{attrs:{to:e.resolvePath(e.onlyOneChild.path)}},[n("el-menu-item",{class:{"submenu-title-noDropdown":!e.isNest},attrs:{index:e.resolvePath(e.onlyOneChild.path)}},[n("item",{attrs:{icon:e.onlyOneChild.meta.icon||e.item.meta&&e.item.meta.icon,title:e.onlyOneChild.meta.title}})],1)],1):e._e()]],2)},xe=[],ye=n("df7c"),_e=n.n(ye);function Ce(e){return/^(https?:|mailto:|tel:)/.test(e)}var ke,Oe,Se={name:"MenuItem",functional:!0,props:{icon:{type:String,default:""},title:{type:String,default:""}},render:function(e,t){var n=t.props,a=n.icon,i=n.title,o=[];return a&&o.push(e("svg-icon",{attrs:{"icon-class":a}})),i&&o.push(e("span",{slot:"title"},[i])),o}},ze=Se,Be=Object(h["a"])(ze,ke,Oe,!1,null,null,null),He=Be.exports,Me=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("component",e._b({},"component",e.linkProps(e.to),!1),[e._t("default")],2)},Te=[],Ee={props:{to:{type:String,required:!0}},methods:{linkProps:function(e){return Ce(e)?{is:"a",href:e,target:"_blank",rel:"noopener"}:{is:"router-link",to:e}}}},Le=Ee,$e=Object(h["a"])(Le,Me,Te,!1,null,null,null),Ve=$e.exports,Ae={computed:{device:function(){return this.$store.state.app.device}},mounted:function(){this.fixBugIniOS()},methods:{fixBugIniOS:function(){var e=this,t=this.$refs.subMenu;if(t){var n=t.handleMouseleave;t.handleMouseleave=function(t){"mobile"!==e.device&&n(t)}}}}},je={name:"SidebarItem",components:{Item:He,AppLink:Ve},mixins:[Ae],props:{item:{type:Object,required:!0},isNest:{type:Boolean,default:!1},basePath:{type:String,default:""}},data:function(){return this.onlyOneChild=null,{}},methods:{hasOneShowingChild:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1?arguments[1]:void 0,a=t.filter(function(t){return!t.hidden&&(e.onlyOneChild=t,!0)});return 1===a.length||0===a.length&&(this.onlyOneChild=Object(U["a"])({},n,{path:"",noShowingChildren:!0}),!0)},resolvePath:function(e){return Ce(e)?e:Ce(this.basePath)?this.basePath:_e.a.resolve(this.basePath,e)}}},Pe=je,Ie=Object(h["a"])(Pe,we,xe,!1,null,null,null),Ne=Ie.exports,De=n("cf1e"),qe=n.n(De),Re={components:{SidebarItem:Ne,Logo:ge},computed:Object(U["a"])({},Object(p["b"])(["sidebar"]),{routes:function(){return this.$router.options.routes},activeMenu:function(){var e=this.$route,t=e.meta,n=e.path;return t.activeMenu?t.activeMenu:n},showLogo:function(){return this.$store.state.settings.sidebarLogo},variables:function(){return qe.a},isCollapse:function(){return!this.sidebar.opened}})},Ge=Re,Fe=Object(h["a"])(Ge,de,he,!1,null,null,null),Ue=Fe.exports,Ke=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("section",{staticClass:"app-main"},[n("transition",{attrs:{name:"fade-transform",mode:"out-in"}},[n("router-view",{key:e.key})],1)],1)},We=[],Je={name:"AppMain",computed:{key:function(){return this.$route.fullPath}}},Xe=Je,Ye=(n("50be"),Object(h["a"])(Xe,Ke,We,!1,null,"43c24f68",null)),Qe=Ye.exports,Ze=document,et=Ze.body,tt=992,nt={watch:{$route:function(e){"mobile"===this.device&&this.sidebar.opened&&bt.dispatch("app/closeSideBar",{withoutAnimation:!1})}},beforeMount:function(){window.addEventListener("resize",this.$_resizeHandler)},beforeDestroy:function(){window.removeEventListener("resize",this.$_resizeHandler)},mounted:function(){var e=this.$_isMobile();e&&(bt.dispatch("app/toggleDevice","mobile"),bt.dispatch("app/closeSideBar",{withoutAnimation:!0}))},methods:{$_isMobile:function(){var e=et.getBoundingClientRect();return e.width-1'});r.a.add(s);t["default"]=s},"9f2b":function(e,t,n){"use strict";var a=n("5bb9"),i=n.n(a);i.a},b20f:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},b3b5:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-user",use:"icon-user-usage",viewBox:"0 0 130 130",content:''});r.a.add(s);t["default"]=s},cf1e:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},d7ec:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye-open",use:"icon-eye-open-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(s);t["default"]=s},dc52:function(e,t,n){},dcf8:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-nested",use:"icon-nested-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},eb1b:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-form",use:"icon-form-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},f782:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-dashboard",use:"icon-dashboard-usage",viewBox:"0 0 128 100",content:''});r.a.add(s);t["default"]=s}},[[0,"runtime","chunk-elementUI","chunk-libs"]]]); \ No newline at end of file +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["app"],{0:function(e,t,n){e.exports=n("56d7")},"0cb8":function(e,t,n){},"186a":function(e,t,n){"use strict";var a=n("dc52"),i=n.n(a);i.a},"18f0":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-link",use:"icon-link-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"1f59":function(e,t,n){},2536:function(e,t,n){},2635:function(e,t,n){},"2a3d":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-password",use:"icon-password-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"30c3":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-example",use:"icon-example-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"34c8":function(e,t,n){"use strict";var a=n("5332"),i=n.n(a);i.a},"405a":function(e,t,n){"use strict";var a=n("1f59"),i=n.n(a);i.a},"47f1":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-table",use:"icon-table-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"4df5":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye",use:"icon-eye-usage",viewBox:"0 0 128 64",content:''});r.a.add(s);t["default"]=s},"50be":function(e,t,n){"use strict";var a=n("2536"),i=n.n(a);i.a},"51ff":function(e,t,n){var a={"./dashboard.svg":"f782","./example.svg":"30c3","./eye-open.svg":"d7ec","./eye.svg":"4df5","./form.svg":"eb1b","./link.svg":"18f0","./nested.svg":"dcf8","./password.svg":"2a3d","./table.svg":"47f1","./tree.svg":"93cd","./user.svg":"b3b5"};function i(e){var t=o(e);return n(t)}function o(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return t}i.keys=function(){return Object.keys(a)},i.resolve=o,e.exports=i,i.id="51ff"},5332:function(e,t,n){},"56d7":function(e,t,n){"use strict";n.r(t);n("cadf"),n("551c"),n("f751"),n("097d");var a=n("2b0e"),i=(n("f5df"),n("5c96")),o=n.n(i),r=(n("0fae"),n("f0d9")),s=n.n(r),c=(n("b20f"),function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"app"}},[n("router-view")],1)}),u=[],l={name:"App"},d=l,m=n("2877"),h=Object(m["a"])(d,c,u,!1,null,null,null),f=h.exports,p=n("2f62"),v=(n("7f7f"),{sidebar:function(e){return e.app.sidebar},device:function(e){return e.app.device},token:function(e){return e.user.token},avatar:function(e){return e.user.avatar},name:function(e){return e.user.name}}),b=v,g=n("a78e"),w=n.n(g),x={sidebar:{opened:!w.a.get("sidebarStatus")||!!+w.a.get("sidebarStatus"),withoutAnimation:!1},device:"desktop"},y={TOGGLE_SIDEBAR:function(e){e.sidebar.opened=!e.sidebar.opened,e.sidebar.withoutAnimation=!1,e.sidebar.opened?w.a.set("sidebarStatus",1):w.a.set("sidebarStatus",0)},CLOSE_SIDEBAR:function(e,t){w.a.set("sidebarStatus",0),e.sidebar.opened=!1,e.sidebar.withoutAnimation=t},TOGGLE_DEVICE:function(e,t){e.device=t}},_={toggleSideBar:function(e){var t=e.commit;t("TOGGLE_SIDEBAR")},closeSideBar:function(e,t){var n=e.commit,a=t.withoutAnimation;n("CLOSE_SIDEBAR",a)},toggleDevice:function(e,t){var n=e.commit;n("TOGGLE_DEVICE",t)}},C={namespaced:!0,state:x,mutations:y,actions:_},k=n("83d6"),O=n.n(k),S=O.a.showSettings,z=O.a.fixedHeader,B=O.a.sidebarLogo,H={showSettings:S,fixedHeader:z,sidebarLogo:B},M={CHANGE_SETTING:function(e,t){var n=t.key,a=t.value;e.hasOwnProperty(n)&&(e[n]=a)}},T={changeSetting:function(e,t){var n=e.commit;n("CHANGE_SETTING",t)}},E={namespaced:!0,state:H,mutations:M,actions:T},L=n("bc3a"),$=n.n(L),V=n("5f87"),A=$.a.create({baseURL:"/api",withCredentials:!0,timeout:5e3});A.interceptors.request.use(function(e){return bt.getters.token&&(e.headers["X-Token"]=Object(V["a"])()),e},function(e){return console.log(e),Promise.reject(e)}),A.interceptors.response.use(function(e){var t=e.data;return 2e4!==t.code?(Object(i["Message"])({message:t.message||"error",type:"error",duration:5e3}),50008!==t.code&&50012!==t.code&&50014!==t.code||i["MessageBox"].confirm("You have been logged out, you can cancel to stay on this page, or log in again","Confirm logout",{confirmButtonText:"Re-Login",cancelButtonText:"Cancel",type:"warning"}).then(function(){bt.dispatch("user/resetToken").then(function(){location.reload()})}),Promise.reject(t.message||"error")):t},function(e){return console.log("err"+e),Object(i["Message"])({message:e.message,type:"error",duration:5e3}),Promise.reject(e)});var j=A;function I(e){return j({url:"/user/login",method:"post",data:e})}function P(e){return j({url:"/user/info",method:"get",params:{token:e}})}function N(){return j({url:"/user/logout",method:"post"})}var D=n("8c4f"),R=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-wrapper",class:e.classObj},["mobile"===e.device&&e.sidebar.opened?n("div",{staticClass:"drawer-bg",on:{click:e.handleClickOutside}}):e._e(),e._v(" "),n("sidebar",{staticClass:"sidebar-container"}),e._v(" "),n("div",{staticClass:"main-container"},[n("div",{class:{"fixed-header":e.fixedHeader}},[n("navbar")],1),e._v(" "),n("app-main")],1)],1)},q=[],G=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"navbar"},[n("hamburger",{staticClass:"hamburger-container",attrs:{"is-active":e.sidebar.opened},on:{toggleClick:e.toggleSideBar}}),e._v(" "),n("breadcrumb",{staticClass:"breadcrumb-container"}),e._v(" "),n("div",{staticClass:"right-menu"},[n("el-button",{staticStyle:{"margin-right":"10px"},attrs:{type:"text"},on:{click:e.doLogout}},[e._v("退出")])],1)],1)},F=[],U=n("cebc"),K=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("el-breadcrumb",{staticClass:"app-breadcrumb",attrs:{separator:"/"}},[n("transition-group",{attrs:{name:"breadcrumb"}},e._l(e.levelList,function(t,a){return n("el-breadcrumb-item",{key:t.path},["noRedirect"===t.redirect||a==e.levelList.length-1?n("span",{staticClass:"no-redirect"},[e._v(e._s(t.meta.title))]):n("a",{on:{click:function(n){return n.preventDefault(),e.handleLink(t)}}},[e._v(e._s(t.meta.title))])])}),1)],1)},W=[],J=n("bd11"),X=n.n(J),Y={data:function(){return{levelList:null}},watch:{$route:function(){this.getBreadcrumb()}},created:function(){this.getBreadcrumb()},methods:{getBreadcrumb:function(){var e=this.$route.matched.filter(function(e){return e.meta&&e.meta.title}),t=e[0];this.isDashboard(t)||(e=[{path:"/dashboard",meta:{title:"Dashboard"}}].concat(e)),this.levelList=e.filter(function(e){return e.meta&&e.meta.title&&!1!==e.meta.breadcrumb})},isDashboard:function(e){var t=e&&e.name;return!!t&&t.trim().toLocaleLowerCase()==="Dashboard".toLocaleLowerCase()},pathCompile:function(e){var t=this.$route.params,n=X.a.compile(e);return n(t)},handleLink:function(e){var t=e.redirect,n=e.path;t?this.$router.push(t):this.$router.push(this.pathCompile(n))}}},Q=Y,Z=(n("34c8"),Object(m["a"])(Q,K,W,!1,null,"62cc9144",null)),ee=Z.exports,te=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticStyle:{padding:"0 15px"},on:{click:e.toggleClick}},[n("svg",{staticClass:"hamburger",class:{"is-active":e.isActive},attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"64",height:"64"}},[n("path",{attrs:{d:"M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"}})])])},ne=[],ae={name:"Hamburger",props:{isActive:{type:Boolean,default:!1}},methods:{toggleClick:function(){this.$emit("toggleClick")}}},ie=ae,oe=(n("186a"),Object(m["a"])(ie,te,ne,!1,null,"49e15297",null)),re=oe.exports,se={components:{Breadcrumb:ee,Hamburger:re},computed:Object(U["a"])({},Object(p["b"])(["sidebar","avatar"])),methods:{toggleSideBar:function(){this.$store.dispatch("app/toggleSideBar")},doLogout:function(){this.logout()}}},ce=se,ue=(n("405a"),Object(m["a"])(ce,G,F,!1,null,"1eff5c58",null)),le=ue.exports,de=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{class:{"has-logo":e.showLogo}},[e.showLogo?n("logo",{attrs:{collapse:e.isCollapse}}):e._e(),e._v(" "),n("el-scrollbar",{attrs:{"wrap-class":"scrollbar-wrapper"}},[n("el-menu",{attrs:{"default-active":e.activeMenu,collapse:e.isCollapse,"background-color":e.variables.menuBg,"text-color":e.variables.menuText,"unique-opened":!1,"active-text-color":e.variables.menuActiveText,"collapse-transition":!1,mode:"vertical"}},e._l(e.routes,function(e){return n("sidebar-item",{key:e.path,attrs:{item:e,"base-path":e.path}})}),1)],1)],1)},me=[],he=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"sidebar-logo-container",class:{collapse:e.collapse}},[n("transition",{attrs:{name:"sidebarLogoFade"}},[e.collapse?n("router-link",{key:"collapse",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])]):n("router-link",{key:"expand",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):e._e(),e._v(" "),n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])])],1)],1)},fe=[],pe={name:"SidebarLogo",props:{collapse:{type:Boolean,required:!0}},data:function(){return{title:"SOP Admin",logo:"https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png"}}},ve=pe,be=(n("7c27"),Object(m["a"])(ve,he,fe,!1,null,"b905289c",null)),ge=be.exports,we=function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.item.hidden?e._e():n("div",{staticClass:"menu-wrapper"},[!e.hasOneShowingChild(e.item.children,e.item)||e.onlyOneChild.children&&!e.onlyOneChild.noShowingChildren||e.item.alwaysShow?n("el-submenu",{ref:"subMenu",attrs:{index:e.resolvePath(e.item.path),"popper-append-to-body":""}},[n("template",{slot:"title"},[e.item.meta?n("item",{attrs:{icon:e.item.meta&&e.item.meta.icon,title:e.item.meta.title}}):e._e()],1),e._v(" "),e._l(e.item.children,function(t){return n("sidebar-item",{key:t.path,staticClass:"nest-menu",attrs:{"is-nest":!0,item:t,"base-path":e.resolvePath(t.path)}})})],2):[e.onlyOneChild.meta?n("app-link",{attrs:{to:e.resolvePath(e.onlyOneChild.path)}},[n("el-menu-item",{class:{"submenu-title-noDropdown":!e.isNest},attrs:{index:e.resolvePath(e.onlyOneChild.path)}},[n("item",{attrs:{icon:e.onlyOneChild.meta.icon||e.item.meta&&e.item.meta.icon,title:e.onlyOneChild.meta.title}})],1)],1):e._e()]],2)},xe=[],ye=n("df7c"),_e=n.n(ye);function Ce(e){return/^(https?:|mailto:|tel:)/.test(e)}var ke,Oe,Se={name:"MenuItem",functional:!0,props:{icon:{type:String,default:""},title:{type:String,default:""}},render:function(e,t){var n=t.props,a=n.icon,i=n.title,o=[];return a&&o.push(e("svg-icon",{attrs:{"icon-class":a}})),i&&o.push(e("span",{slot:"title"},[i])),o}},ze=Se,Be=Object(m["a"])(ze,ke,Oe,!1,null,null,null),He=Be.exports,Me=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("component",e._b({},"component",e.linkProps(e.to),!1),[e._t("default")],2)},Te=[],Ee={props:{to:{type:String,required:!0}},methods:{linkProps:function(e){return Ce(e)?{is:"a",href:e,target:"_blank",rel:"noopener"}:{is:"router-link",to:e}}}},Le=Ee,$e=Object(m["a"])(Le,Me,Te,!1,null,null,null),Ve=$e.exports,Ae={computed:{device:function(){return this.$store.state.app.device}},mounted:function(){this.fixBugIniOS()},methods:{fixBugIniOS:function(){var e=this,t=this.$refs.subMenu;if(t){var n=t.handleMouseleave;t.handleMouseleave=function(t){"mobile"!==e.device&&n(t)}}}}},je={name:"SidebarItem",components:{Item:He,AppLink:Ve},mixins:[Ae],props:{item:{type:Object,required:!0},isNest:{type:Boolean,default:!1},basePath:{type:String,default:""}},data:function(){return this.onlyOneChild=null,{}},methods:{hasOneShowingChild:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1?arguments[1]:void 0,a=t.filter(function(t){return!t.hidden&&(e.onlyOneChild=t,!0)});return 1===a.length||0===a.length&&(this.onlyOneChild=Object(U["a"])({},n,{path:"",noShowingChildren:!0}),!0)},resolvePath:function(e){return Ce(e)?e:Ce(this.basePath)?this.basePath:_e.a.resolve(this.basePath,e)}}},Ie=je,Pe=Object(m["a"])(Ie,we,xe,!1,null,null,null),Ne=Pe.exports,De=n("cf1e"),Re=n.n(De),qe={components:{SidebarItem:Ne,Logo:ge},computed:Object(U["a"])({},Object(p["b"])(["sidebar"]),{routes:function(){return this.$router.options.routes},activeMenu:function(){var e=this.$route,t=e.meta,n=e.path;return t.activeMenu?t.activeMenu:n},showLogo:function(){return this.$store.state.settings.sidebarLogo},variables:function(){return Re.a},isCollapse:function(){return!this.sidebar.opened}})},Ge=qe,Fe=Object(m["a"])(Ge,de,me,!1,null,null,null),Ue=Fe.exports,Ke=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("section",{staticClass:"app-main"},[n("transition",{attrs:{name:"fade-transform",mode:"out-in"}},[n("router-view",{key:e.key})],1)],1)},We=[],Je={name:"AppMain",computed:{key:function(){return this.$route.fullPath}}},Xe=Je,Ye=(n("50be"),Object(m["a"])(Xe,Ke,We,!1,null,"43c24f68",null)),Qe=Ye.exports,Ze=document,et=Ze.body,tt=992,nt={watch:{$route:function(e){"mobile"===this.device&&this.sidebar.opened&&bt.dispatch("app/closeSideBar",{withoutAnimation:!1})}},beforeMount:function(){window.addEventListener("resize",this.$_resizeHandler)},beforeDestroy:function(){window.removeEventListener("resize",this.$_resizeHandler)},mounted:function(){var e=this.$_isMobile();e&&(bt.dispatch("app/toggleDevice","mobile"),bt.dispatch("app/closeSideBar",{withoutAnimation:!0}))},methods:{$_isMobile:function(){var e=et.getBoundingClientRect();return e.width-1'});r.a.add(s);t["default"]=s},"9f2b":function(e,t,n){"use strict";var a=n("5bb9"),i=n.n(a);i.a},b20f:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},b3b5:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-user",use:"icon-user-usage",viewBox:"0 0 130 130",content:''});r.a.add(s);t["default"]=s},cf1e:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},d7ec:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye-open",use:"icon-eye-open-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(s);t["default"]=s},dc52:function(e,t,n){},dcf8:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-nested",use:"icon-nested-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},eb1b:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-form",use:"icon-form-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},f782:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-dashboard",use:"icon-dashboard-usage",viewBox:"0 0 128 100",content:''});r.a.add(s);t["default"]=s}},[[0,"runtime","chunk-elementUI","chunk-libs"]]]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.3daff0c2.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.e7e4b6d5.js similarity index 93% rename from sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.3daff0c2.js rename to sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.e7e4b6d5.js index 11df8607..08f5eef6 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.3daff0c2.js +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.e7e4b6d5.js @@ -1 +1 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-25908fca"],{"021d":function(e,t,a){},"0bac":function(e,t,a){"use strict";var s=a("021d"),i=a.n(s);i.a},cb56:function(e,t,a){"use strict";a.r(t);var s=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"app-container"},[a("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:e.searchFormData,size:"mini"}},[a("el-form-item",{attrs:{label:"appKey"}},[a("el-input",{staticStyle:{width:"250px"},attrs:{clearable:!0,placeholder:"appKey"},model:{value:e.searchFormData.appKey,callback:function(t){e.$set(e.searchFormData,"appKey",t)},expression:"searchFormData.appKey"}})],1),e._v(" "),a("el-form-item",[a("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:e.onSearchTable}},[e._v("查询")])],1)],1),e._v(" "),a("el-button",{staticStyle:{"margin-bottom":"10px"},attrs:{type:"primary",size:"mini",icon:"el-icon-plus"},on:{click:e.onAdd}},[e._v("新增ISV")]),e._v(" "),a("el-table",{attrs:{data:e.pageInfo.list,border:"",fit:"","highlight-current-row":""}},[a("el-table-column",{attrs:{prop:"id",label:"ID",width:"80"}}),e._v(" "),a("el-table-column",{attrs:{prop:"appKey",label:"appKey",width:"250"}}),e._v(" "),a("el-table-column",{attrs:{prop:"",label:"秘钥",width:"80"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return e.onShowKeys(t.row)}}},[e._v("查看")])]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"roleList",label:"角色"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("div",{domProps:{innerHTML:e._s(e.roleRender(t.row))}})]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"status",label:"状态",width:"80"},scopedSlots:e._u([{key:"default",fn:function(t){return[1===t.row.status?a("span",{staticStyle:{color:"#67C23A"}},[e._v("已启用")]):e._e(),e._v(" "),2===t.row.status?a("span",{staticStyle:{color:"#F56C6C"}},[e._v("已禁用")]):e._e()]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"gmtCreate",label:"添加时间",width:"160"}}),e._v(" "),a("el-table-column",{attrs:{prop:"gmtModified",label:"修改时间",width:"160"}}),e._v(" "),a("el-table-column",{attrs:{label:"操作",width:"150"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return e.onTableUpdate(t.row)}}},[e._v("修改")]),e._v(" "),a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return e.onKeysUpdate(t.row)}}},[e._v("秘钥管理")])]}}])})],1),e._v(" "),a("el-pagination",{staticStyle:{"margin-top":"5px"},attrs:{background:"","current-page":e.searchFormData.pageIndex,"page-size":e.searchFormData.pageSize,"page-sizes":[5,10,20,40],total:e.pageInfo.total,layout:"total, sizes, prev, pager, next"},on:{"size-change":e.onSizeChange,"current-change":e.onPageIndexChange}}),e._v(" "),a("el-dialog",{attrs:{title:e.isvDialogTitle,visible:e.isvDialogVisible,"close-on-click-modal":!1},on:{"update:visible":function(t){e.isvDialogVisible=t},close:e.onIsvDialogClose}},[a("el-form",{ref:"isvForm",attrs:{rules:e.rulesIsvForm,model:e.isvDialogFormData,"label-width":"120px",size:"mini"}},[a("el-form-item",{attrs:{label:"appKey"}},[0===e.isvDialogFormData.id?a("span",{staticStyle:{color:"gray"}},[e._v("(系统自动生成)")]):a("span",[e._v(e._s(e.isvDialogFormData.appKey))])]),e._v(" "),a("el-form-item",{attrs:{label:"角色"}},[a("el-checkbox-group",{model:{value:e.isvDialogFormData.roleCode,callback:function(t){e.$set(e.isvDialogFormData,"roleCode",t)},expression:"isvDialogFormData.roleCode"}},e._l(e.roles,function(t){return a("el-checkbox",{key:t.roleCode,attrs:{label:t.roleCode}},[e._v(e._s(t.description))])}),1)],1),e._v(" "),a("el-form-item",{attrs:{label:"状态"}},[a("el-radio-group",{model:{value:e.isvDialogFormData.status,callback:function(t){e.$set(e.isvDialogFormData,"status",t)},expression:"isvDialogFormData.status"}},[a("el-radio",{attrs:{label:1,name:"status"}},[e._v("启用")]),e._v(" "),a("el-radio",{attrs:{label:2,name:"status"}},[e._v("禁用")])],1)],1)],1),e._v(" "),a("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(t){e.isvDialogVisible=!1}}},[e._v("取 消")]),e._v(" "),a("el-button",{attrs:{type:"primary"},on:{click:e.onIsvDialogSave}},[e._v("保 存")])],1)],1),e._v(" "),a("el-dialog",{attrs:{title:"秘钥信息",visible:e.isvKeysDialogVisible},on:{"update:visible":function(t){e.isvKeysDialogVisible=t},close:function(t){return e.resetForm("isvKeysFrom")}}},[a("el-form",{ref:"isvKeysFrom",staticClass:"key-view",attrs:{model:e.isvKeysFormData,"label-width":"160px",size:"mini"}},[a("el-form-item",{attrs:{label:""}},[a("el-alert",{attrs:{title:"带 ★ 的分配给开发者",type:"warning",closable:!1}})],1),e._v(" "),a("el-form-item",{attrs:{label:e.selfLabel("appKey")}},[a("span",[e._v(e._s(e.isvKeysFormData.appKey))])]),e._v(" "),a("el-form-item",{attrs:{label:"签名方式"}},[1===e.isvKeysFormData.signType?a("span",[e._v("RSA")]):e._e(),e._v(" "),2===e.isvKeysFormData.signType?a("span",[e._v("MD5")]):e._e()]),e._v(" "),a("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}],attrs:{label:"秘钥格式"}},[1===e.isvKeysFormData.keyFormat?a("span",[e._v("PKCS8(JAVA适用)")]):e._e(),e._v(" "),2===e.isvKeysFormData.keyFormat?a("span",[e._v("PKCS1(非JAVA适用)")]):e._e()]),e._v(" "),a("el-form-item",{directives:[{name:"show",rawName:"v-show",value:2===e.isvKeysFormData.signType,expression:"isvKeysFormData.signType === 2"}],attrs:{label:e.selfLabel("secret")}},[a("span",[e._v(e._s(e.isvKeysFormData.secret))])]),e._v(" "),a("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[a("legend",[e._v("ISV公私钥")]),e._v(" "),a("el-form-item",{attrs:{label:"ISV公钥"}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.publicKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyIsv",t)},expression:"isvKeysFormData.publicKeyIsv"}})],1),e._v(" "),a("el-form-item",{attrs:{label:e.selfLabel("ISV私钥")}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.privateKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyIsv",t)},expression:"isvKeysFormData.privateKeyIsv"}})],1)],1),e._v(" "),a("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[a("legend",[e._v("平台公私钥")]),e._v(" "),a("el-form-item",{attrs:{label:e.selfLabel("平台公钥")}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.publicKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyPlatform",t)},expression:"isvKeysFormData.publicKeyPlatform"}})],1),e._v(" "),a("el-form-item",{attrs:{prop:"privateKeyPlatform",label:"平台私钥"}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.privateKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyPlatform",t)},expression:"isvKeysFormData.privateKeyPlatform"}})],1)],1)],1),e._v(" "),a("span",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(t){e.isvKeysDialogVisible=!1}}},[e._v("关 闭")])],1)],1)],1)},i=[],o={data:function(){return{searchFormData:{appKey:"",pageIndex:1,pageSize:10},pageInfo:{list:[],total:0},roles:[],isvDialogVisible:!1,isvDialogTitle:"新增ISV",isvDialogFormData:{id:0,status:1,roleCode:[]},rulesIsvForm:{appKey:[{required:!0,message:"不能为空",trigger:"blur"},{min:1,max:100,message:"长度在 1 到 100 个字符",trigger:"blur"}]},isvKeysDialogVisible:!1,isvKeysFormData:{appKey:"",secret:"",publicKeyIsv:"",privateKeyIsv:"",publicKeyPlatform:"",privateKeyPlatform:"",signType:""}}},created:function(){this.loadTable(),this.loadRouteRole()},methods:{loadTable:function(){this.post("isv.info.page",this.searchFormData,function(e){this.pageInfo=e.data})},loadRouteRole:function(){0===this.roles.length&&this.post("role.listall",{},function(e){this.roles=e.data})},onShowKeys:function(e){this.post("isv.keys.get",{appKey:e.appKey},function(e){var t=this;this.isvKeysDialogVisible=!0,this.$nextTick(function(){Object.assign(t.isvKeysFormData,e.data)})})},onSearchTable:function(){this.loadTable()},onTableUpdate:function(e){var t=this;this.isvDialogTitle="修改ISV",this.isvDialogVisible=!0,this.$nextTick(function(){t.post("isv.info.get",{id:e.id},function(e){for(var t=e.data,a=t.roleList,s=[],i=0;i0,expression:"roleDialogFormData.id > 0"}]},[e._v(e._s(e.roleDialogFormData.roleCode))])],1),e._v(" "),a("el-form-item",{attrs:{prop:"description",label:"角色描述"}},[a("el-input",{model:{value:e.roleDialogFormData.description,callback:function(o){e.$set(e.roleDialogFormData,"description",o)},expression:"roleDialogFormData.description"}})],1)],1),e._v(" "),a("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(o){e.roleDialogVisible=!1}}},[e._v("取 消")]),e._v(" "),a("el-button",{attrs:{type:"primary"},on:{click:e.onRoleDialogSave}},[e._v("保 存")])],1)],1)],1)},l=[],i={data:function(){return{searchFormData:{roleCode:"",pageIndex:1,pageSize:10},pageInfo:{rows:[],total:0},roleDialogVisible:!1,roleDialogTitle:"",roleDialogFormData:{id:0,roleCode:"",description:""},roleDialogFormRules:{roleCode:[{required:!0,message:"不能为空",trigger:"blur"},{min:1,max:64,message:"长度在 1 到 100 个字符",trigger:"blur"}],description:[{max:64,message:"不能超过 64 个字符",trigger:"blur"}]},rulesIsvForm:{appKey:[{required:!0,message:"不能为空",trigger:"blur"},{min:1,max:100,message:"长度在 1 到 100 个字符",trigger:"blur"}]}}},created:function(){this.loadTable()},methods:{loadTable:function(){this.post("role.page",this.searchFormData,function(e){this.pageInfo=e.data})},onTableUpdate:function(e){var o=this;this.roleDialogTitle="修改角色",this.roleDialogVisible=!0,this.$nextTick(function(){Object.assign(o.roleDialogFormData,e)})},onTableDelete:function(e){this.confirm("确认要删除角色【".concat(e.roleCode,"】吗?"),function(o){var a={id:e.id};this.post("role.del",a,function(){o(),this.tip("删除成功"),this.loadTable()})})},onRoleDialogSave:function(){var e=this;this.$refs.roleForm.validate(function(o){if(o){var a=e.roleDialogFormData.id?"role.update":"role.add";e.post(a,e.roleDialogFormData,function(){this.roleDialogVisible=!1,this.loadTable()})}})},onSizeChange:function(e){this.searchFormData.pageSize=e,this.loadTable()},onAdd:function(){this.roleDialogTitle="新增角色",this.roleDialogVisible=!0,this.roleDialogFormData.id=0},onPageIndexChange:function(e){this.searchFormData.pageIndex=e,this.loadTable()}}},r=i,n=a("2877"),s=Object(n["a"])(r,t,l,!1,null,null,null);o["default"]=s.exports}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-vue/src/router/index.js b/sop-admin/sop-admin-vue/src/router/index.js index 730aee48..6ac2aa67 100644 --- a/sop-admin/sop-admin-vue/src/router/index.js +++ b/sop-admin/sop-admin-vue/src/router/index.js @@ -91,8 +91,8 @@ export const constantRoutes = [ { path: '/isv', component: Layout, + name: 'Isv', meta: { title: 'ISV管理', icon: 'user' }, - redirect: '/isv/list', children: [ { path: 'list', @@ -100,6 +100,12 @@ export const constantRoutes = [ component: () => import('@/views/isv/index'), meta: { title: 'ISV列表' } }, + { + path: 'role', + name: 'Role', + component: () => import('@/views/isv/role'), + meta: { title: '角色管理' } + }, { path: 'keys', name: 'Keys', diff --git a/sop-admin/sop-admin-vue/src/views/isv/index.vue b/sop-admin/sop-admin-vue/src/views/isv/index.vue index 258b617f..4c08fb7f 100644 --- a/sop-admin/sop-admin-vue/src/views/isv/index.vue +++ b/sop-admin/sop-admin-vue/src/views/isv/index.vue @@ -288,7 +288,7 @@ export default { }, onIsvDialogSave: function() { const that = this - this.$refs['isvForm'].validate((valid) => { + this.$refs.isvForm.validate((valid) => { if (valid) { const uri = this.isvDialogFormData.id === 0 ? 'isv.info.add' : 'isv.info.update' that.post(uri, that.isvDialogFormData, function() { diff --git a/sop-admin/sop-admin-vue/src/views/isv/role.vue b/sop-admin/sop-admin-vue/src/views/isv/role.vue new file mode 100644 index 00000000..74507d04 --- /dev/null +++ b/sop-admin/sop-admin-vue/src/views/isv/role.vue @@ -0,0 +1,179 @@ + + + diff --git a/sop.sql b/sop.sql index 410ef133..924a39f9 100644 --- a/sop.sql +++ b/sop.sql @@ -78,7 +78,7 @@ CREATE TABLE `config_route_limit` ( CREATE TABLE `isv_info` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_key` varchar(100) NOT NULL COMMENT 'appKey', - `secret` varchar(200) NOT NULL COMMENT 'secret', + `secret` varchar(200) COMMENT 'secret', `pub_key` text COMMENT '公钥', `pri_key` text COMMENT '私钥', `status` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '1启用,2禁用', From de85e5aef91e91a5b44c2c63ca06ca5bc973d1bc Mon Sep 17 00:00:00 2001 From: tanghc Date: Sun, 30 Jun 2019 19:08:48 +0800 Subject: [PATCH 25/40] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E7=AE=A1=E7=90=86,=E4=BC=98=E5=8C=96=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sop-admin/readme.md | 2 +- sop-admin/sop-admin-front/README.md | 2 +- .../sop/adminserver/api/service/LogApi.java | 2 +- .../adminserver/api/service/ServiceApi.java | 126 ++++++++---------- .../param/LogMonitorInstanceAddParam.java | 6 +- ...ServiceInfo.java => RouteServiceInfo.java} | 2 +- .../api/service/result/ServiceInstanceVO.java | 44 ++++++ .../sop/adminserver/bean/ServiceInfo.java | 17 +++ .../sop/adminserver/bean/ServiceInstance.java | 26 ++++ .../service/RegistrationService.java | 36 +++++ .../impl/RegistrationServiceEureka.java | 104 +++++++++++++++ .../src/main/resources/public/index.html | 2 +- ...ebecd4.css => chunk-009073d4.0af16c7e.css} | 2 +- .../js/{app.61234abc.js => app.095e8b9c.js} | 2 +- ...5e409513.js => chunk-009073d4.28312808.js} | 2 +- .../static/js/chunk-2d22c2e3.46f37153.js | 1 - .../static/js/chunk-2d22c2e3.4a098244.js | 1 + .../static/js/chunk-4a59cbe4.a6360c68.js | 1 + .../static/js/chunk-4a59cbe4.b5e74cc4.js | 1 - ...f59ae895.js => chunk-6a68a33e.15951b55.js} | 2 +- .../src/views/service/limit/index.vue | 2 +- .../src/views/service/limit/index2.vue | 2 +- .../src/views/service/list/index.vue | 50 ++++--- .../src/views/service/log/index.vue | 15 +-- .../src/views/service/route/index.vue | 2 +- 25 files changed, 323 insertions(+), 129 deletions(-) rename sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/{ServiceInfo.java => RouteServiceInfo.java} (95%) create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInfo.java create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInstance.java create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java rename sop-admin/sop-admin-server/src/main/resources/public/static/css/{chunk-5f00e420.aeebecd4.css => chunk-009073d4.0af16c7e.css} (85%) rename sop-admin/sop-admin-server/src/main/resources/public/static/js/{app.61234abc.js => app.095e8b9c.js} (99%) rename sop-admin/sop-admin-server/src/main/resources/public/static/js/{chunk-5f00e420.5e409513.js => chunk-009073d4.28312808.js} (76%) delete mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d22c2e3.46f37153.js create mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d22c2e3.4a098244.js create mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-4a59cbe4.a6360c68.js delete mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-4a59cbe4.b5e74cc4.js rename sop-admin/sop-admin-server/src/main/resources/public/static/js/{chunk-6a68a33e.f59ae895.js => chunk-6a68a33e.15951b55.js} (78%) diff --git a/sop-admin/readme.md b/sop-admin/readme.md index 4e15085c..ac3691f3 100644 --- a/sop-admin/readme.md +++ b/sop-admin/readme.md @@ -1,5 +1,5 @@ # 后台admin -- sop-admin-front: admin前端layui实现(停止维护) +- sop-admin-front: admin前端layui实现(停止维护,改用sop-admin-vue) - sop-admin-server: admin服务端 - sop-admin-vue: admin前端vue实现 diff --git a/sop-admin/sop-admin-front/README.md b/sop-admin/sop-admin-front/README.md index 9815113c..708b3bf6 100644 --- a/sop-admin/sop-admin-front/README.md +++ b/sop-admin/sop-admin-front/README.md @@ -1,4 +1,4 @@ -# admin前端页面(停止维护) +# admin前端页面(停止维护,改用sop-admin-vue) 做到前后端分离。 diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java index a72a29d0..e5d79465 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java @@ -114,7 +114,7 @@ public class LogApi { @Api(name = "monitor.instance.add") @ApiDocMethod(description = "添加监控实例") void addServiceInstance(LogMonitorInstanceAddParam param) { - String ipPort = param.getIp() + ":" + param.getPort(); + String ipPort = param.getIpPort(); this.checkInstance(ipPort); Query query = new Query(); diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java index 3d2c972e..cdf2ba86 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java @@ -6,33 +6,29 @@ import com.gitee.easyopen.annotation.ApiService; import com.gitee.easyopen.doc.annotation.ApiDoc; import com.gitee.easyopen.doc.annotation.ApiDocMethod; import com.gitee.sop.adminserver.api.service.param.ServiceAddParam; -import com.gitee.sop.adminserver.api.service.param.ServiceInstanceParam; import com.gitee.sop.adminserver.api.service.param.ServiceSearchParam; -import com.gitee.sop.adminserver.api.service.result.ServiceInfo; +import com.gitee.sop.adminserver.api.service.result.RouteServiceInfo; import com.gitee.sop.adminserver.api.service.result.ServiceInfoVo; -import com.gitee.sop.adminserver.bean.EurekaApplication; -import com.gitee.sop.adminserver.bean.EurekaApps; -import com.gitee.sop.adminserver.bean.EurekaInstance; -import com.gitee.sop.adminserver.bean.EurekaUri; +import com.gitee.sop.adminserver.api.service.result.ServiceInstanceVO; +import com.gitee.sop.adminserver.bean.ServiceInfo; +import com.gitee.sop.adminserver.bean.ServiceInstance; import com.gitee.sop.adminserver.bean.ServiceRouteInfo; import com.gitee.sop.adminserver.bean.ZookeeperContext; import com.gitee.sop.adminserver.common.BizException; import com.gitee.sop.adminserver.common.ZookeeperPathExistException; import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException; +import com.gitee.sop.adminserver.service.RegistrationService; +import com.gitee.sop.adminserver.service.impl.RegistrationServiceEureka; import lombok.extern.slf4j.Slf4j; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.apache.curator.framework.recipes.cache.ChildData; import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import javax.annotation.PostConstruct; +import javax.annotation.Resource; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -46,24 +42,19 @@ import java.util.stream.Collectors; @Slf4j public class ServiceApi { + @Resource(type = RegistrationServiceEureka.class) + private RegistrationService registrationService; - OkHttpClient client = new OkHttpClient(); - - @Autowired - private Environment environment; - - private String eurekaUrl; - - @Api(name = "service.list") - @ApiDocMethod(description = "服务列表(旧)", elementClass = ServiceInfo.class) - List listServiceInfo(ServiceSearchParam param) throws Exception { + @Api(name = "zookeeper.service.list") + @ApiDocMethod(description = "zk中的服务列表", elementClass = RouteServiceInfo.class) + List listServiceInfo(ServiceSearchParam param) { String routeRootPath = ZookeeperContext.getSopRouteRootPath(); List childDataList = ZookeeperContext.getChildrenData(routeRootPath); - List serviceInfoList = childDataList.stream() + List serviceInfoList = childDataList.stream() .filter(childData -> childData.getData() != null && childData.getData().length > 0) .map(childData -> { String serviceNodeData = new String(childData.getData()); - ServiceInfo serviceInfo = JSON.parseObject(serviceNodeData, ServiceInfo.class); + RouteServiceInfo serviceInfo = JSON.parseObject(serviceNodeData, RouteServiceInfo.class); return serviceInfo; }) .filter(serviceInfo -> { @@ -121,39 +112,40 @@ public class ServiceApi { } @Api(name = "service.instance.list") - @ApiDocMethod(description = "服务列表", elementClass = ServiceInfoVo.class) - List listService(ServiceSearchParam param) throws Exception { - String json = this.requestEurekaServer(EurekaUri.QUERY_APPS); - EurekaApps eurekaApps = JSON.parseObject(json, EurekaApps.class); - - List serviceInfoVoList = new ArrayList<>(); - List applicationList = eurekaApps.getApplications().getApplication(); + @ApiDocMethod(description = "获取注册中心的服务列表", elementClass = ServiceInfoVo.class) + List listService(ServiceSearchParam param) { + List serviceInfos; + try { + serviceInfos = registrationService.listAllService(1, 99999/* 获取所有实例 */); + } catch (Exception e) { + log.error("获取服务实例失败", e); + return Collections.emptyList(); + } + List serviceInfoVoList = new ArrayList<>(); AtomicInteger idGen = new AtomicInteger(1); - applicationList.stream() - .filter(eurekaApplication -> { + serviceInfos.stream() + .filter(serviceInfo -> { if (StringUtils.isBlank(param.getServiceId())) { return true; } - return StringUtils.containsIgnoreCase(eurekaApplication.getName(), param.getServiceId()); + return StringUtils.containsIgnoreCase(serviceInfo.getServiceId(), param.getServiceId()); }) - .forEach(eurekaApplication -> { + .forEach(serviceInfo -> { int pid = idGen.getAndIncrement(); - String name = eurekaApplication.getName(); - ServiceInfoVo parent = new ServiceInfoVo(); + String serviceId = serviceInfo.getServiceId(); + ServiceInstanceVO parent = new ServiceInstanceVO(); parent.setId(pid); - parent.setName(name); + parent.setServiceId(serviceId); parent.setParentId(0); serviceInfoVoList.add(parent); - List instanceList = eurekaApplication.getInstance(); - for (EurekaInstance instance : instanceList) { - ServiceInfoVo vo = new ServiceInfoVo(); - BeanUtils.copyProperties(instance, vo); + List instanceList = serviceInfo.getInstances(); + for (ServiceInstance instance : instanceList) { + ServiceInstanceVO instanceVO = new ServiceInstanceVO(); + BeanUtils.copyProperties(instance, instanceVO); int id = idGen.getAndIncrement(); - vo.setId(id); - vo.setName(name); - vo.setParentId(pid); - vo.setServerPort(instance.fetchPort()); - serviceInfoVoList.add(vo); + instanceVO.setId(id); + instanceVO.setParentId(pid); + serviceInfoVoList.add(instanceVO); } }); @@ -162,38 +154,24 @@ public class ServiceApi { @Api(name = "service.instance.offline") @ApiDocMethod(description = "服务下线") - void serviceOffline(ServiceInstanceParam param) throws IOException { - this.requestEurekaServer(EurekaUri.OFFLINE_SERVICE, param.getServiceId(), param.getInstanceId()); + void serviceOffline(ServiceInstance param) { + try { + registrationService.offlineInstance(param); + } catch (Exception e) { + log.error("下线失败,param:{}", param, e); + throw new BizException("下线失败,请查看日志"); + } } @Api(name = "service.instance.online") @ApiDocMethod(description = "服务上线") - void serviceOnline(ServiceInstanceParam param) throws IOException { - this.requestEurekaServer(EurekaUri.ONLINE_SERVICE, param.getServiceId(), param.getInstanceId()); - } - - private String requestEurekaServer(EurekaUri eurekaUri, String... args) throws IOException { - Request request = eurekaUri.getRequest(this.eurekaUrl, args); - Response response = client.newCall(request).execute(); - if (response.isSuccessful()) { - return response.body().string(); - } else { - log.error("操作失败,url:{}, msg:{}, code:{}", eurekaUri.getUri(args), response.message(), response.code()); - throw new BizException("操作失败", String.valueOf(response.code())); - } - } - - @PostConstruct - protected void after() { - String eurekaUrls = environment.getProperty("eureka.client.serviceUrl.defaultZone"); - if (StringUtils.isBlank(eurekaUrls)) { - throw new BizException("未指定eureka.client.serviceUrl.defaultZone参数"); - } - String url = eurekaUrls.split("\\,")[0]; - if (url.endsWith("/")) { - url = eurekaUrls.substring(0, eurekaUrls.length() - 1); + void serviceOnline(ServiceInstance param) throws IOException { + try { + registrationService.onlineInstance(param); + } catch (Exception e) { + log.error("上线失败,param:{}", param, e); + throw new BizException("上线失败,请查看日志"); } - this.eurekaUrl = url; } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LogMonitorInstanceAddParam.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LogMonitorInstanceAddParam.java index bc618268..5a902152 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LogMonitorInstanceAddParam.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/param/LogMonitorInstanceAddParam.java @@ -12,8 +12,6 @@ public class LogMonitorInstanceAddParam { @NotBlank(message = "serviceId不能为空") private String serviceId; - @NotBlank(message = "ip不能为空") - private String ip; - - private int port; + @NotBlank(message = "ipPort不能为空") + private String ipPort; } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInfo.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/RouteServiceInfo.java similarity index 95% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInfo.java rename to sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/RouteServiceInfo.java index b44a4e29..26e057ce 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInfo.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/RouteServiceInfo.java @@ -7,7 +7,7 @@ import lombok.Data; * @author tanghc */ @Data -public class ServiceInfo { +public class RouteServiceInfo { @ApiDocField(description = "serviceId") private String serviceId; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java new file mode 100644 index 00000000..86656dd3 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java @@ -0,0 +1,44 @@ +package com.gitee.sop.adminserver.api.service.result; + +import com.alibaba.fastjson.annotation.JSONField; +import com.gitee.easyopen.doc.annotation.ApiDocField; +import lombok.Data; +import org.apache.commons.lang.StringUtils; + +import java.util.Date; + +/** + * @author tanghc + */ +@Data +public class ServiceInstanceVO { + @ApiDocField(description = "id") + private Integer id; + + @ApiDocField(description = "服务名称(serviceId)") + private String serviceId; + + @ApiDocField(description = "instanceId") + private String instanceId; + + @ApiDocField(description = "ipPort") + private String ipPort; + + @ApiDocField(description = "status,服务状态,UP:已上线,OUT_OF_SERVICE:已下线") + private String status; + + @ApiDocField(description = "最后更新时间") + private String lastUpdatedTimestamp; + + @ApiDocField(description = "parentId") + private Integer parentId; + + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + public Date getUpdateTime() { + if (StringUtils.isBlank(lastUpdatedTimestamp)) { + return null; + } + return new Date(Long.valueOf(lastUpdatedTimestamp)); + } + +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInfo.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInfo.java new file mode 100644 index 00000000..5344a601 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInfo.java @@ -0,0 +1,17 @@ +package com.gitee.sop.adminserver.bean; + +import lombok.Data; + +import java.util.Collections; +import java.util.List; + +/** + * @author tanghc + */ +@Data +public class ServiceInfo { + /** 服务名称 */ + private String serviceId; + /** 实例列表 */ + private List instances = Collections.emptyList(); +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInstance.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInstance.java new file mode 100644 index 00000000..42e8f865 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInstance.java @@ -0,0 +1,26 @@ +package com.gitee.sop.adminserver.bean; + +import lombok.Data; + +@Data +public class ServiceInstance { + /** + * 实例id + */ + private String instanceId; + + /** + * 服务名称 + */ + private String serviceId; + + /** + * IP 端口 + */ + private String ipPort; + + /** + * 状态,1:上线,2:下线 + */ + private String status; +} \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java new file mode 100644 index 00000000..7aa2aa02 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java @@ -0,0 +1,36 @@ +package com.gitee.sop.adminserver.service; + +import com.gitee.sop.adminserver.bean.ServiceInfo; +import com.gitee.sop.adminserver.bean.ServiceInstance; + +import java.util.List; + +/** + * @author tanghc + */ +public interface RegistrationService { + /** + * 获取所有服务列表 + * + * @param pageNo 当前页码 + * @param pageSize 分页大小 + * @return 返回服务列表 + */ + List listAllService(int pageNo, int pageSize) throws Exception; + + /** + * 服务上线 + * + * @param serviceInstance + */ + void onlineInstance(ServiceInstance serviceInstance) throws Exception; + + /** + * 服务下线 + * + * @param serviceInstance + */ + void offlineInstance(ServiceInstance serviceInstance) throws Exception; + + +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java new file mode 100644 index 00000000..d16ebd2e --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java @@ -0,0 +1,104 @@ +package com.gitee.sop.adminserver.service.impl; + +import com.alibaba.fastjson.JSON; +import com.gitee.sop.adminserver.bean.EurekaApplication; +import com.gitee.sop.adminserver.bean.EurekaApps; +import com.gitee.sop.adminserver.bean.EurekaInstance; +import com.gitee.sop.adminserver.bean.EurekaUri; +import com.gitee.sop.adminserver.bean.ServiceInfo; +import com.gitee.sop.adminserver.bean.ServiceInstance; +import com.gitee.sop.adminserver.common.BizException; +import com.gitee.sop.adminserver.service.RegistrationService; +import lombok.extern.slf4j.Slf4j; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author tanghc + */ +@Slf4j +@Service +public class RegistrationServiceEureka implements RegistrationService { + + OkHttpClient client = new OkHttpClient(); + + @Autowired + private Environment environment; + + private String eurekaUrl; + + @Override + public List listAllService(int pageNo, int pageSize) throws Exception { + String json = this.requestEurekaServer(EurekaUri.QUERY_APPS); + EurekaApps eurekaApps = JSON.parseObject(json, EurekaApps.class); + + List serviceInfoList = new ArrayList<>(); + List applicationList = eurekaApps.getApplications().getApplication(); + for (EurekaApplication eurekaApplication : applicationList) { + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.setServiceId(eurekaApplication.getName()); + List instanceList = eurekaApplication.getInstance(); + if (CollectionUtils.isNotEmpty(instanceList)) { + serviceInfo.setInstances(new ArrayList<>(instanceList.size())); + for (EurekaInstance eurekaInstance : instanceList) { + ServiceInstance serviceInstance = new ServiceInstance(); + serviceInstance.setInstanceId(eurekaInstance.getInstanceId()); + serviceInstance.setServiceId(serviceInfo.getServiceId()); + serviceInstance.setIpPort(eurekaInstance.getIpAddr() + ":" + eurekaInstance.fetchPort()); + serviceInstance.setStatus(eurekaInstance.getStatus()); + serviceInfo.getInstances().add(serviceInstance); + } + } + serviceInfoList.add(serviceInfo); + } + return serviceInfoList; + } + + + + @Override + public void onlineInstance(ServiceInstance serviceInstance) throws Exception { + this.requestEurekaServer(EurekaUri.ONLINE_SERVICE, serviceInstance.getServiceId(), serviceInstance.getInstanceId()); + } + + @Override + public void offlineInstance(ServiceInstance serviceInstance) throws Exception { + this.requestEurekaServer(EurekaUri.OFFLINE_SERVICE, serviceInstance.getServiceId(), serviceInstance.getInstanceId()); + } + + private String requestEurekaServer(EurekaUri eurekaUri, String... args) throws IOException { + Request request = eurekaUri.getRequest(this.eurekaUrl, args); + Response response = client.newCall(request).execute(); + if (response.isSuccessful()) { + return response.body().string(); + } else { + log.error("操作失败,url:{}, msg:{}, code:{}", eurekaUri.getUri(args), response.message(), response.code()); + throw new BizException("操作失败", String.valueOf(response.code())); + } + } + + @PostConstruct + protected void after() { + String eurekaUrls = environment.getProperty("eureka.client.serviceUrl.defaultZone"); + if (StringUtils.isBlank(eurekaUrls)) { + throw new BizException("未指定eureka.client.serviceUrl.defaultZone参数"); + } + // 取第一个 + String url = eurekaUrls.split("\\,")[0]; + if (url.endsWith("/")) { + url = eurekaUrls.substring(0, eurekaUrls.length() - 1); + } + this.eurekaUrl = url; + } +} diff --git a/sop-admin/sop-admin-server/src/main/resources/public/index.html b/sop-admin/sop-admin-server/src/main/resources/public/index.html index 40190d95..60193962 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/index.html +++ b/sop-admin/sop-admin-server/src/main/resources/public/index.html @@ -1 +1 @@ -SOP Admin
\ No newline at end of file +SOP Admin
\ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-5f00e420.aeebecd4.css b/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-009073d4.0af16c7e.css similarity index 85% rename from sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-5f00e420.aeebecd4.css rename to sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-009073d4.0af16c7e.css index 792df20d..7bdb9a3e 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-5f00e420.aeebecd4.css +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/css/chunk-009073d4.0af16c7e.css @@ -1 +1 @@ -.custom-tree-node{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:14px;padding-right:8px}.el-input.is-disabled .el-input__inner,.el-radio__input.is-disabled+span.el-radio__label{color:#909399}.limit-tip[data-v-0ec28e9a]{cursor:pointer;margin-left:10px} \ No newline at end of file +.custom-tree-node{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:14px;padding-right:8px}.el-input.is-disabled .el-input__inner,.el-radio__input.is-disabled+span.el-radio__label{color:#909399}.limit-tip[data-v-b81bfbde]{cursor:pointer;margin-left:10px} \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.61234abc.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.095e8b9c.js similarity index 99% rename from sop-admin/sop-admin-server/src/main/resources/public/static/js/app.61234abc.js rename to sop-admin/sop-admin-server/src/main/resources/public/static/js/app.095e8b9c.js index 94c16887..53b7189d 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.61234abc.js +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/app.095e8b9c.js @@ -1 +1 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["app"],{0:function(e,t,n){e.exports=n("56d7")},"0cb8":function(e,t,n){},"186a":function(e,t,n){"use strict";var a=n("dc52"),i=n.n(a);i.a},"18f0":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-link",use:"icon-link-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"1f59":function(e,t,n){},2536:function(e,t,n){},2635:function(e,t,n){},"2a3d":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-password",use:"icon-password-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"30c3":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-example",use:"icon-example-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"34c8":function(e,t,n){"use strict";var a=n("5332"),i=n.n(a);i.a},"405a":function(e,t,n){"use strict";var a=n("1f59"),i=n.n(a);i.a},"47f1":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-table",use:"icon-table-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"4df5":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye",use:"icon-eye-usage",viewBox:"0 0 128 64",content:''});r.a.add(s);t["default"]=s},"50be":function(e,t,n){"use strict";var a=n("2536"),i=n.n(a);i.a},"51ff":function(e,t,n){var a={"./dashboard.svg":"f782","./example.svg":"30c3","./eye-open.svg":"d7ec","./eye.svg":"4df5","./form.svg":"eb1b","./link.svg":"18f0","./nested.svg":"dcf8","./password.svg":"2a3d","./table.svg":"47f1","./tree.svg":"93cd","./user.svg":"b3b5"};function i(e){var t=o(e);return n(t)}function o(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return t}i.keys=function(){return Object.keys(a)},i.resolve=o,e.exports=i,i.id="51ff"},5332:function(e,t,n){},"56d7":function(e,t,n){"use strict";n.r(t);n("cadf"),n("551c"),n("f751"),n("097d");var a=n("2b0e"),i=(n("f5df"),n("5c96")),o=n.n(i),r=(n("0fae"),n("f0d9")),s=n.n(r),c=(n("b20f"),function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"app"}},[n("router-view")],1)}),u=[],l={name:"App"},d=l,m=n("2877"),h=Object(m["a"])(d,c,u,!1,null,null,null),f=h.exports,p=n("2f62"),v=(n("7f7f"),{sidebar:function(e){return e.app.sidebar},device:function(e){return e.app.device},token:function(e){return e.user.token},avatar:function(e){return e.user.avatar},name:function(e){return e.user.name}}),b=v,g=n("a78e"),w=n.n(g),x={sidebar:{opened:!w.a.get("sidebarStatus")||!!+w.a.get("sidebarStatus"),withoutAnimation:!1},device:"desktop"},y={TOGGLE_SIDEBAR:function(e){e.sidebar.opened=!e.sidebar.opened,e.sidebar.withoutAnimation=!1,e.sidebar.opened?w.a.set("sidebarStatus",1):w.a.set("sidebarStatus",0)},CLOSE_SIDEBAR:function(e,t){w.a.set("sidebarStatus",0),e.sidebar.opened=!1,e.sidebar.withoutAnimation=t},TOGGLE_DEVICE:function(e,t){e.device=t}},_={toggleSideBar:function(e){var t=e.commit;t("TOGGLE_SIDEBAR")},closeSideBar:function(e,t){var n=e.commit,a=t.withoutAnimation;n("CLOSE_SIDEBAR",a)},toggleDevice:function(e,t){var n=e.commit;n("TOGGLE_DEVICE",t)}},C={namespaced:!0,state:x,mutations:y,actions:_},k=n("83d6"),O=n.n(k),S=O.a.showSettings,z=O.a.fixedHeader,B=O.a.sidebarLogo,H={showSettings:S,fixedHeader:z,sidebarLogo:B},M={CHANGE_SETTING:function(e,t){var n=t.key,a=t.value;e.hasOwnProperty(n)&&(e[n]=a)}},T={changeSetting:function(e,t){var n=e.commit;n("CHANGE_SETTING",t)}},E={namespaced:!0,state:H,mutations:M,actions:T},L=n("bc3a"),$=n.n(L),V=n("5f87"),A=$.a.create({baseURL:"/api",withCredentials:!0,timeout:5e3});A.interceptors.request.use(function(e){return bt.getters.token&&(e.headers["X-Token"]=Object(V["a"])()),e},function(e){return console.log(e),Promise.reject(e)}),A.interceptors.response.use(function(e){var t=e.data;return 2e4!==t.code?(Object(i["Message"])({message:t.message||"error",type:"error",duration:5e3}),50008!==t.code&&50012!==t.code&&50014!==t.code||i["MessageBox"].confirm("You have been logged out, you can cancel to stay on this page, or log in again","Confirm logout",{confirmButtonText:"Re-Login",cancelButtonText:"Cancel",type:"warning"}).then(function(){bt.dispatch("user/resetToken").then(function(){location.reload()})}),Promise.reject(t.message||"error")):t},function(e){return console.log("err"+e),Object(i["Message"])({message:e.message,type:"error",duration:5e3}),Promise.reject(e)});var j=A;function I(e){return j({url:"/user/login",method:"post",data:e})}function P(e){return j({url:"/user/info",method:"get",params:{token:e}})}function N(){return j({url:"/user/logout",method:"post"})}var D=n("8c4f"),R=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-wrapper",class:e.classObj},["mobile"===e.device&&e.sidebar.opened?n("div",{staticClass:"drawer-bg",on:{click:e.handleClickOutside}}):e._e(),e._v(" "),n("sidebar",{staticClass:"sidebar-container"}),e._v(" "),n("div",{staticClass:"main-container"},[n("div",{class:{"fixed-header":e.fixedHeader}},[n("navbar")],1),e._v(" "),n("app-main")],1)],1)},q=[],G=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"navbar"},[n("hamburger",{staticClass:"hamburger-container",attrs:{"is-active":e.sidebar.opened},on:{toggleClick:e.toggleSideBar}}),e._v(" "),n("breadcrumb",{staticClass:"breadcrumb-container"}),e._v(" "),n("div",{staticClass:"right-menu"},[n("el-button",{staticStyle:{"margin-right":"10px"},attrs:{type:"text"},on:{click:e.doLogout}},[e._v("退出")])],1)],1)},F=[],U=n("cebc"),K=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("el-breadcrumb",{staticClass:"app-breadcrumb",attrs:{separator:"/"}},[n("transition-group",{attrs:{name:"breadcrumb"}},e._l(e.levelList,function(t,a){return n("el-breadcrumb-item",{key:t.path},["noRedirect"===t.redirect||a==e.levelList.length-1?n("span",{staticClass:"no-redirect"},[e._v(e._s(t.meta.title))]):n("a",{on:{click:function(n){return n.preventDefault(),e.handleLink(t)}}},[e._v(e._s(t.meta.title))])])}),1)],1)},W=[],J=n("bd11"),X=n.n(J),Y={data:function(){return{levelList:null}},watch:{$route:function(){this.getBreadcrumb()}},created:function(){this.getBreadcrumb()},methods:{getBreadcrumb:function(){var e=this.$route.matched.filter(function(e){return e.meta&&e.meta.title}),t=e[0];this.isDashboard(t)||(e=[{path:"/dashboard",meta:{title:"Dashboard"}}].concat(e)),this.levelList=e.filter(function(e){return e.meta&&e.meta.title&&!1!==e.meta.breadcrumb})},isDashboard:function(e){var t=e&&e.name;return!!t&&t.trim().toLocaleLowerCase()==="Dashboard".toLocaleLowerCase()},pathCompile:function(e){var t=this.$route.params,n=X.a.compile(e);return n(t)},handleLink:function(e){var t=e.redirect,n=e.path;t?this.$router.push(t):this.$router.push(this.pathCompile(n))}}},Q=Y,Z=(n("34c8"),Object(m["a"])(Q,K,W,!1,null,"62cc9144",null)),ee=Z.exports,te=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticStyle:{padding:"0 15px"},on:{click:e.toggleClick}},[n("svg",{staticClass:"hamburger",class:{"is-active":e.isActive},attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"64",height:"64"}},[n("path",{attrs:{d:"M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"}})])])},ne=[],ae={name:"Hamburger",props:{isActive:{type:Boolean,default:!1}},methods:{toggleClick:function(){this.$emit("toggleClick")}}},ie=ae,oe=(n("186a"),Object(m["a"])(ie,te,ne,!1,null,"49e15297",null)),re=oe.exports,se={components:{Breadcrumb:ee,Hamburger:re},computed:Object(U["a"])({},Object(p["b"])(["sidebar","avatar"])),methods:{toggleSideBar:function(){this.$store.dispatch("app/toggleSideBar")},doLogout:function(){this.logout()}}},ce=se,ue=(n("405a"),Object(m["a"])(ce,G,F,!1,null,"1eff5c58",null)),le=ue.exports,de=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{class:{"has-logo":e.showLogo}},[e.showLogo?n("logo",{attrs:{collapse:e.isCollapse}}):e._e(),e._v(" "),n("el-scrollbar",{attrs:{"wrap-class":"scrollbar-wrapper"}},[n("el-menu",{attrs:{"default-active":e.activeMenu,collapse:e.isCollapse,"background-color":e.variables.menuBg,"text-color":e.variables.menuText,"unique-opened":!1,"active-text-color":e.variables.menuActiveText,"collapse-transition":!1,mode:"vertical"}},e._l(e.routes,function(e){return n("sidebar-item",{key:e.path,attrs:{item:e,"base-path":e.path}})}),1)],1)],1)},me=[],he=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"sidebar-logo-container",class:{collapse:e.collapse}},[n("transition",{attrs:{name:"sidebarLogoFade"}},[e.collapse?n("router-link",{key:"collapse",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])]):n("router-link",{key:"expand",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):e._e(),e._v(" "),n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])])],1)],1)},fe=[],pe={name:"SidebarLogo",props:{collapse:{type:Boolean,required:!0}},data:function(){return{title:"SOP Admin",logo:"https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png"}}},ve=pe,be=(n("7c27"),Object(m["a"])(ve,he,fe,!1,null,"b905289c",null)),ge=be.exports,we=function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.item.hidden?e._e():n("div",{staticClass:"menu-wrapper"},[!e.hasOneShowingChild(e.item.children,e.item)||e.onlyOneChild.children&&!e.onlyOneChild.noShowingChildren||e.item.alwaysShow?n("el-submenu",{ref:"subMenu",attrs:{index:e.resolvePath(e.item.path),"popper-append-to-body":""}},[n("template",{slot:"title"},[e.item.meta?n("item",{attrs:{icon:e.item.meta&&e.item.meta.icon,title:e.item.meta.title}}):e._e()],1),e._v(" "),e._l(e.item.children,function(t){return n("sidebar-item",{key:t.path,staticClass:"nest-menu",attrs:{"is-nest":!0,item:t,"base-path":e.resolvePath(t.path)}})})],2):[e.onlyOneChild.meta?n("app-link",{attrs:{to:e.resolvePath(e.onlyOneChild.path)}},[n("el-menu-item",{class:{"submenu-title-noDropdown":!e.isNest},attrs:{index:e.resolvePath(e.onlyOneChild.path)}},[n("item",{attrs:{icon:e.onlyOneChild.meta.icon||e.item.meta&&e.item.meta.icon,title:e.onlyOneChild.meta.title}})],1)],1):e._e()]],2)},xe=[],ye=n("df7c"),_e=n.n(ye);function Ce(e){return/^(https?:|mailto:|tel:)/.test(e)}var ke,Oe,Se={name:"MenuItem",functional:!0,props:{icon:{type:String,default:""},title:{type:String,default:""}},render:function(e,t){var n=t.props,a=n.icon,i=n.title,o=[];return a&&o.push(e("svg-icon",{attrs:{"icon-class":a}})),i&&o.push(e("span",{slot:"title"},[i])),o}},ze=Se,Be=Object(m["a"])(ze,ke,Oe,!1,null,null,null),He=Be.exports,Me=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("component",e._b({},"component",e.linkProps(e.to),!1),[e._t("default")],2)},Te=[],Ee={props:{to:{type:String,required:!0}},methods:{linkProps:function(e){return Ce(e)?{is:"a",href:e,target:"_blank",rel:"noopener"}:{is:"router-link",to:e}}}},Le=Ee,$e=Object(m["a"])(Le,Me,Te,!1,null,null,null),Ve=$e.exports,Ae={computed:{device:function(){return this.$store.state.app.device}},mounted:function(){this.fixBugIniOS()},methods:{fixBugIniOS:function(){var e=this,t=this.$refs.subMenu;if(t){var n=t.handleMouseleave;t.handleMouseleave=function(t){"mobile"!==e.device&&n(t)}}}}},je={name:"SidebarItem",components:{Item:He,AppLink:Ve},mixins:[Ae],props:{item:{type:Object,required:!0},isNest:{type:Boolean,default:!1},basePath:{type:String,default:""}},data:function(){return this.onlyOneChild=null,{}},methods:{hasOneShowingChild:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1?arguments[1]:void 0,a=t.filter(function(t){return!t.hidden&&(e.onlyOneChild=t,!0)});return 1===a.length||0===a.length&&(this.onlyOneChild=Object(U["a"])({},n,{path:"",noShowingChildren:!0}),!0)},resolvePath:function(e){return Ce(e)?e:Ce(this.basePath)?this.basePath:_e.a.resolve(this.basePath,e)}}},Ie=je,Pe=Object(m["a"])(Ie,we,xe,!1,null,null,null),Ne=Pe.exports,De=n("cf1e"),Re=n.n(De),qe={components:{SidebarItem:Ne,Logo:ge},computed:Object(U["a"])({},Object(p["b"])(["sidebar"]),{routes:function(){return this.$router.options.routes},activeMenu:function(){var e=this.$route,t=e.meta,n=e.path;return t.activeMenu?t.activeMenu:n},showLogo:function(){return this.$store.state.settings.sidebarLogo},variables:function(){return Re.a},isCollapse:function(){return!this.sidebar.opened}})},Ge=qe,Fe=Object(m["a"])(Ge,de,me,!1,null,null,null),Ue=Fe.exports,Ke=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("section",{staticClass:"app-main"},[n("transition",{attrs:{name:"fade-transform",mode:"out-in"}},[n("router-view",{key:e.key})],1)],1)},We=[],Je={name:"AppMain",computed:{key:function(){return this.$route.fullPath}}},Xe=Je,Ye=(n("50be"),Object(m["a"])(Xe,Ke,We,!1,null,"43c24f68",null)),Qe=Ye.exports,Ze=document,et=Ze.body,tt=992,nt={watch:{$route:function(e){"mobile"===this.device&&this.sidebar.opened&&bt.dispatch("app/closeSideBar",{withoutAnimation:!1})}},beforeMount:function(){window.addEventListener("resize",this.$_resizeHandler)},beforeDestroy:function(){window.removeEventListener("resize",this.$_resizeHandler)},mounted:function(){var e=this.$_isMobile();e&&(bt.dispatch("app/toggleDevice","mobile"),bt.dispatch("app/closeSideBar",{withoutAnimation:!0}))},methods:{$_isMobile:function(){var e=et.getBoundingClientRect();return e.width-1'});r.a.add(s);t["default"]=s},"9f2b":function(e,t,n){"use strict";var a=n("5bb9"),i=n.n(a);i.a},b20f:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},b3b5:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-user",use:"icon-user-usage",viewBox:"0 0 130 130",content:''});r.a.add(s);t["default"]=s},cf1e:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},d7ec:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye-open",use:"icon-eye-open-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(s);t["default"]=s},dc52:function(e,t,n){},dcf8:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-nested",use:"icon-nested-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},eb1b:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-form",use:"icon-form-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},f782:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-dashboard",use:"icon-dashboard-usage",viewBox:"0 0 128 100",content:''});r.a.add(s);t["default"]=s}},[[0,"runtime","chunk-elementUI","chunk-libs"]]]); \ No newline at end of file +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["app"],{0:function(e,t,n){e.exports=n("56d7")},"0cb8":function(e,t,n){},"186a":function(e,t,n){"use strict";var a=n("dc52"),i=n.n(a);i.a},"18f0":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-link",use:"icon-link-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"1f59":function(e,t,n){},2536:function(e,t,n){},2635:function(e,t,n){},"2a3d":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-password",use:"icon-password-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"30c3":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-example",use:"icon-example-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"34c8":function(e,t,n){"use strict";var a=n("5332"),i=n.n(a);i.a},"405a":function(e,t,n){"use strict";var a=n("1f59"),i=n.n(a);i.a},"47f1":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-table",use:"icon-table-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},"4df5":function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye",use:"icon-eye-usage",viewBox:"0 0 128 64",content:''});r.a.add(s);t["default"]=s},"50be":function(e,t,n){"use strict";var a=n("2536"),i=n.n(a);i.a},"51ff":function(e,t,n){var a={"./dashboard.svg":"f782","./example.svg":"30c3","./eye-open.svg":"d7ec","./eye.svg":"4df5","./form.svg":"eb1b","./link.svg":"18f0","./nested.svg":"dcf8","./password.svg":"2a3d","./table.svg":"47f1","./tree.svg":"93cd","./user.svg":"b3b5"};function i(e){var t=o(e);return n(t)}function o(e){var t=a[e];if(!(t+1)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return t}i.keys=function(){return Object.keys(a)},i.resolve=o,e.exports=i,i.id="51ff"},5332:function(e,t,n){},"56d7":function(e,t,n){"use strict";n.r(t);n("cadf"),n("551c"),n("f751"),n("097d");var a=n("2b0e"),i=(n("f5df"),n("5c96")),o=n.n(i),r=(n("0fae"),n("f0d9")),s=n.n(r),c=(n("b20f"),function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"app"}},[n("router-view")],1)}),u=[],l={name:"App"},d=l,m=n("2877"),h=Object(m["a"])(d,c,u,!1,null,null,null),f=h.exports,p=n("2f62"),v=(n("7f7f"),{sidebar:function(e){return e.app.sidebar},device:function(e){return e.app.device},token:function(e){return e.user.token},avatar:function(e){return e.user.avatar},name:function(e){return e.user.name}}),b=v,g=n("a78e"),w=n.n(g),x={sidebar:{opened:!w.a.get("sidebarStatus")||!!+w.a.get("sidebarStatus"),withoutAnimation:!1},device:"desktop"},y={TOGGLE_SIDEBAR:function(e){e.sidebar.opened=!e.sidebar.opened,e.sidebar.withoutAnimation=!1,e.sidebar.opened?w.a.set("sidebarStatus",1):w.a.set("sidebarStatus",0)},CLOSE_SIDEBAR:function(e,t){w.a.set("sidebarStatus",0),e.sidebar.opened=!1,e.sidebar.withoutAnimation=t},TOGGLE_DEVICE:function(e,t){e.device=t}},_={toggleSideBar:function(e){var t=e.commit;t("TOGGLE_SIDEBAR")},closeSideBar:function(e,t){var n=e.commit,a=t.withoutAnimation;n("CLOSE_SIDEBAR",a)},toggleDevice:function(e,t){var n=e.commit;n("TOGGLE_DEVICE",t)}},C={namespaced:!0,state:x,mutations:y,actions:_},k=n("83d6"),O=n.n(k),S=O.a.showSettings,z=O.a.fixedHeader,B=O.a.sidebarLogo,H={showSettings:S,fixedHeader:z,sidebarLogo:B},M={CHANGE_SETTING:function(e,t){var n=t.key,a=t.value;e.hasOwnProperty(n)&&(e[n]=a)}},T={changeSetting:function(e,t){var n=e.commit;n("CHANGE_SETTING",t)}},E={namespaced:!0,state:H,mutations:M,actions:T},L=n("bc3a"),$=n.n(L),V=n("5f87"),A=$.a.create({baseURL:"/api",withCredentials:!0,timeout:5e3});A.interceptors.request.use(function(e){return bt.getters.token&&(e.headers["X-Token"]=Object(V["a"])()),e},function(e){return console.log(e),Promise.reject(e)}),A.interceptors.response.use(function(e){var t=e.data;return 2e4!==t.code?(Object(i["Message"])({message:t.message||"error",type:"error",duration:5e3}),50008!==t.code&&50012!==t.code&&50014!==t.code||i["MessageBox"].confirm("You have been logged out, you can cancel to stay on this page, or log in again","Confirm logout",{confirmButtonText:"Re-Login",cancelButtonText:"Cancel",type:"warning"}).then(function(){bt.dispatch("user/resetToken").then(function(){location.reload()})}),Promise.reject(t.message||"error")):t},function(e){return console.log("err"+e),Object(i["Message"])({message:e.message,type:"error",duration:5e3}),Promise.reject(e)});var j=A;function I(e){return j({url:"/user/login",method:"post",data:e})}function P(e){return j({url:"/user/info",method:"get",params:{token:e}})}function N(){return j({url:"/user/logout",method:"post"})}var D=n("8c4f"),R=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-wrapper",class:e.classObj},["mobile"===e.device&&e.sidebar.opened?n("div",{staticClass:"drawer-bg",on:{click:e.handleClickOutside}}):e._e(),e._v(" "),n("sidebar",{staticClass:"sidebar-container"}),e._v(" "),n("div",{staticClass:"main-container"},[n("div",{class:{"fixed-header":e.fixedHeader}},[n("navbar")],1),e._v(" "),n("app-main")],1)],1)},q=[],G=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"navbar"},[n("hamburger",{staticClass:"hamburger-container",attrs:{"is-active":e.sidebar.opened},on:{toggleClick:e.toggleSideBar}}),e._v(" "),n("breadcrumb",{staticClass:"breadcrumb-container"}),e._v(" "),n("div",{staticClass:"right-menu"},[n("el-button",{staticStyle:{"margin-right":"10px"},attrs:{type:"text"},on:{click:e.doLogout}},[e._v("退出")])],1)],1)},F=[],U=n("cebc"),K=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("el-breadcrumb",{staticClass:"app-breadcrumb",attrs:{separator:"/"}},[n("transition-group",{attrs:{name:"breadcrumb"}},e._l(e.levelList,function(t,a){return n("el-breadcrumb-item",{key:t.path},["noRedirect"===t.redirect||a==e.levelList.length-1?n("span",{staticClass:"no-redirect"},[e._v(e._s(t.meta.title))]):n("a",{on:{click:function(n){return n.preventDefault(),e.handleLink(t)}}},[e._v(e._s(t.meta.title))])])}),1)],1)},W=[],J=n("bd11"),X=n.n(J),Y={data:function(){return{levelList:null}},watch:{$route:function(){this.getBreadcrumb()}},created:function(){this.getBreadcrumb()},methods:{getBreadcrumb:function(){var e=this.$route.matched.filter(function(e){return e.meta&&e.meta.title}),t=e[0];this.isDashboard(t)||(e=[{path:"/dashboard",meta:{title:"Dashboard"}}].concat(e)),this.levelList=e.filter(function(e){return e.meta&&e.meta.title&&!1!==e.meta.breadcrumb})},isDashboard:function(e){var t=e&&e.name;return!!t&&t.trim().toLocaleLowerCase()==="Dashboard".toLocaleLowerCase()},pathCompile:function(e){var t=this.$route.params,n=X.a.compile(e);return n(t)},handleLink:function(e){var t=e.redirect,n=e.path;t?this.$router.push(t):this.$router.push(this.pathCompile(n))}}},Q=Y,Z=(n("34c8"),Object(m["a"])(Q,K,W,!1,null,"62cc9144",null)),ee=Z.exports,te=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticStyle:{padding:"0 15px"},on:{click:e.toggleClick}},[n("svg",{staticClass:"hamburger",class:{"is-active":e.isActive},attrs:{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg",width:"64",height:"64"}},[n("path",{attrs:{d:"M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"}})])])},ne=[],ae={name:"Hamburger",props:{isActive:{type:Boolean,default:!1}},methods:{toggleClick:function(){this.$emit("toggleClick")}}},ie=ae,oe=(n("186a"),Object(m["a"])(ie,te,ne,!1,null,"49e15297",null)),re=oe.exports,se={components:{Breadcrumb:ee,Hamburger:re},computed:Object(U["a"])({},Object(p["b"])(["sidebar","avatar"])),methods:{toggleSideBar:function(){this.$store.dispatch("app/toggleSideBar")},doLogout:function(){this.logout()}}},ce=se,ue=(n("405a"),Object(m["a"])(ce,G,F,!1,null,"1eff5c58",null)),le=ue.exports,de=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{class:{"has-logo":e.showLogo}},[e.showLogo?n("logo",{attrs:{collapse:e.isCollapse}}):e._e(),e._v(" "),n("el-scrollbar",{attrs:{"wrap-class":"scrollbar-wrapper"}},[n("el-menu",{attrs:{"default-active":e.activeMenu,collapse:e.isCollapse,"background-color":e.variables.menuBg,"text-color":e.variables.menuText,"unique-opened":!1,"active-text-color":e.variables.menuActiveText,"collapse-transition":!1,mode:"vertical"}},e._l(e.routes,function(e){return n("sidebar-item",{key:e.path,attrs:{item:e,"base-path":e.path}})}),1)],1)],1)},me=[],he=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"sidebar-logo-container",class:{collapse:e.collapse}},[n("transition",{attrs:{name:"sidebarLogoFade"}},[e.collapse?n("router-link",{key:"collapse",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])]):n("router-link",{key:"expand",staticClass:"sidebar-logo-link",attrs:{to:"/"}},[e.logo?n("img",{staticClass:"sidebar-logo",attrs:{src:e.logo}}):e._e(),e._v(" "),n("h1",{staticClass:"sidebar-title"},[e._v(e._s(e.title)+" ")])])],1)],1)},fe=[],pe={name:"SidebarLogo",props:{collapse:{type:Boolean,required:!0}},data:function(){return{title:"SOP Admin",logo:"https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png"}}},ve=pe,be=(n("7c27"),Object(m["a"])(ve,he,fe,!1,null,"b905289c",null)),ge=be.exports,we=function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.item.hidden?e._e():n("div",{staticClass:"menu-wrapper"},[!e.hasOneShowingChild(e.item.children,e.item)||e.onlyOneChild.children&&!e.onlyOneChild.noShowingChildren||e.item.alwaysShow?n("el-submenu",{ref:"subMenu",attrs:{index:e.resolvePath(e.item.path),"popper-append-to-body":""}},[n("template",{slot:"title"},[e.item.meta?n("item",{attrs:{icon:e.item.meta&&e.item.meta.icon,title:e.item.meta.title}}):e._e()],1),e._v(" "),e._l(e.item.children,function(t){return n("sidebar-item",{key:t.path,staticClass:"nest-menu",attrs:{"is-nest":!0,item:t,"base-path":e.resolvePath(t.path)}})})],2):[e.onlyOneChild.meta?n("app-link",{attrs:{to:e.resolvePath(e.onlyOneChild.path)}},[n("el-menu-item",{class:{"submenu-title-noDropdown":!e.isNest},attrs:{index:e.resolvePath(e.onlyOneChild.path)}},[n("item",{attrs:{icon:e.onlyOneChild.meta.icon||e.item.meta&&e.item.meta.icon,title:e.onlyOneChild.meta.title}})],1)],1):e._e()]],2)},xe=[],ye=n("df7c"),_e=n.n(ye);function Ce(e){return/^(https?:|mailto:|tel:)/.test(e)}var ke,Oe,Se={name:"MenuItem",functional:!0,props:{icon:{type:String,default:""},title:{type:String,default:""}},render:function(e,t){var n=t.props,a=n.icon,i=n.title,o=[];return a&&o.push(e("svg-icon",{attrs:{"icon-class":a}})),i&&o.push(e("span",{slot:"title"},[i])),o}},ze=Se,Be=Object(m["a"])(ze,ke,Oe,!1,null,null,null),He=Be.exports,Me=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("component",e._b({},"component",e.linkProps(e.to),!1),[e._t("default")],2)},Te=[],Ee={props:{to:{type:String,required:!0}},methods:{linkProps:function(e){return Ce(e)?{is:"a",href:e,target:"_blank",rel:"noopener"}:{is:"router-link",to:e}}}},Le=Ee,$e=Object(m["a"])(Le,Me,Te,!1,null,null,null),Ve=$e.exports,Ae={computed:{device:function(){return this.$store.state.app.device}},mounted:function(){this.fixBugIniOS()},methods:{fixBugIniOS:function(){var e=this,t=this.$refs.subMenu;if(t){var n=t.handleMouseleave;t.handleMouseleave=function(t){"mobile"!==e.device&&n(t)}}}}},je={name:"SidebarItem",components:{Item:He,AppLink:Ve},mixins:[Ae],props:{item:{type:Object,required:!0},isNest:{type:Boolean,default:!1},basePath:{type:String,default:""}},data:function(){return this.onlyOneChild=null,{}},methods:{hasOneShowingChild:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1?arguments[1]:void 0,a=t.filter(function(t){return!t.hidden&&(e.onlyOneChild=t,!0)});return 1===a.length||0===a.length&&(this.onlyOneChild=Object(U["a"])({},n,{path:"",noShowingChildren:!0}),!0)},resolvePath:function(e){return Ce(e)?e:Ce(this.basePath)?this.basePath:_e.a.resolve(this.basePath,e)}}},Ie=je,Pe=Object(m["a"])(Ie,we,xe,!1,null,null,null),Ne=Pe.exports,De=n("cf1e"),Re=n.n(De),qe={components:{SidebarItem:Ne,Logo:ge},computed:Object(U["a"])({},Object(p["b"])(["sidebar"]),{routes:function(){return this.$router.options.routes},activeMenu:function(){var e=this.$route,t=e.meta,n=e.path;return t.activeMenu?t.activeMenu:n},showLogo:function(){return this.$store.state.settings.sidebarLogo},variables:function(){return Re.a},isCollapse:function(){return!this.sidebar.opened}})},Ge=qe,Fe=Object(m["a"])(Ge,de,me,!1,null,null,null),Ue=Fe.exports,Ke=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("section",{staticClass:"app-main"},[n("transition",{attrs:{name:"fade-transform",mode:"out-in"}},[n("router-view",{key:e.key})],1)],1)},We=[],Je={name:"AppMain",computed:{key:function(){return this.$route.fullPath}}},Xe=Je,Ye=(n("50be"),Object(m["a"])(Xe,Ke,We,!1,null,"43c24f68",null)),Qe=Ye.exports,Ze=document,et=Ze.body,tt=992,nt={watch:{$route:function(e){"mobile"===this.device&&this.sidebar.opened&&bt.dispatch("app/closeSideBar",{withoutAnimation:!1})}},beforeMount:function(){window.addEventListener("resize",this.$_resizeHandler)},beforeDestroy:function(){window.removeEventListener("resize",this.$_resizeHandler)},mounted:function(){var e=this.$_isMobile();e&&(bt.dispatch("app/toggleDevice","mobile"),bt.dispatch("app/closeSideBar",{withoutAnimation:!0}))},methods:{$_isMobile:function(){var e=et.getBoundingClientRect();return e.width-1'});r.a.add(s);t["default"]=s},"9f2b":function(e,t,n){"use strict";var a=n("5bb9"),i=n.n(a);i.a},b20f:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},b3b5:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-user",use:"icon-user-usage",viewBox:"0 0 130 130",content:''});r.a.add(s);t["default"]=s},cf1e:function(e,t,n){e.exports={menuText:"#bfcbd9",menuActiveText:"#409EFF",subMenuActiveText:"#f4f4f5",menuBg:"#304156",menuHover:"#263445",subMenuBg:"#1f2d3d",subMenuHover:"#001528",sideBarWidth:"210px"}},d7ec:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-eye-open",use:"icon-eye-open-usage",viewBox:"0 0 1024 1024",content:''});r.a.add(s);t["default"]=s},dc52:function(e,t,n){},dcf8:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-nested",use:"icon-nested-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},eb1b:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-form",use:"icon-form-usage",viewBox:"0 0 128 128",content:''});r.a.add(s);t["default"]=s},f782:function(e,t,n){"use strict";n.r(t);var a=n("e017"),i=n.n(a),o=n("21a1"),r=n.n(o),s=new i.a({id:"icon-dashboard",use:"icon-dashboard-usage",viewBox:"0 0 128 100",content:''});r.a.add(s);t["default"]=s}},[[0,"runtime","chunk-elementUI","chunk-libs"]]]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-5f00e420.5e409513.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-009073d4.28312808.js similarity index 76% rename from sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-5f00e420.5e409513.js rename to sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-009073d4.28312808.js index 254cd027..746b34f6 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-5f00e420.5e409513.js +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-009073d4.28312808.js @@ -1 +1 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5f00e420"],{"0a49":function(e,t,i){var a=i("9b43"),l=i("626a"),o=i("4bf8"),r=i("9def"),n=i("cd1c");e.exports=function(e,t){var i=1==e,s=2==e,c=3==e,m=4==e,p=6==e,u=5==e||p,d=t||n;return function(t,n,g){for(var f,h,D=o(t),v=l(D),y=a(n,g,3),b=r(v.length),k=0,x=i?d(t,b):s?d(t,0):void 0;b>k;k++)if((u||k in v)&&(f=v[k],h=y(f,k,D),e))if(i)x[k]=h;else if(h)switch(e){case 3:return!0;case 5:return f;case 6:return k;case 2:x.push(f)}else if(m)return!1;return p?-1:c||m?m:x}}},1169:function(e,t,i){var a=i("2d95");e.exports=Array.isArray||function(e){return"Array"==a(e)}},1510:function(e,t,i){"use strict";i.r(t);var a=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"app-container"},[i("el-container",[i("el-aside",{staticStyle:{"min-height":"300px",width:"250px"}},[i("el-input",{staticStyle:{"margin-bottom":"20px"},attrs:{"prefix-icon":"el-icon-search",placeholder:"搜索服务...",size:"mini",clearable:""},model:{value:e.filterText,callback:function(t){e.filterText=t},expression:"filterText"}}),e._v(" "),i("el-tree",{ref:"tree2",staticClass:"filter-tree",attrs:{data:e.treeData,props:e.defaultProps,"filter-node-method":e.filterNode,"highlight-current":!0,"expand-on-click-node":!1,"empty-text":"无数据","node-key":"id","default-expand-all":""},on:{"node-click":e.onNodeClick},scopedSlots:e._u([{key:"default",fn:function(t){t.node;var a=t.data;return i("span",{staticClass:"custom-tree-node"},[i("div",[i("el-tooltip",{directives:[{name:"show",rawName:"v-show",value:a.custom,expression:"data.custom"}],staticClass:"item",attrs:{content:"自定义服务",effect:"light",placement:"left"}},[i("i",{staticClass:"el-icon-warning-outline"})]),e._v(" "),a.label.lengthsubCode:"+e.limitCode),t.push("
subMsg:"+e.limitMsg)):2===e.limitType&&t.push("令牌桶容量:"+e.tokenBucketCount),t.join("")},onLimitDialogSave:function(){var e=this;this.$refs["limitDialogForm"].validate(function(t){if(t){e.cleanCheckboxData(),e.limitDialogFormData.serviceId=e.serviceId;var i=e.limitDialogFormData.id?"config.limit.update":"config.limit.add";e.post(i,e.limitDialogFormData,function(e){this.limitDialogVisible=!1,this.loadTable()})}})},cleanCheckboxData:function(){this.checkTypeKey(1)||(this.limitDialogFormData.routeId=""),this.checkTypeKey(2)||(this.limitDialogFormData.appKey=""),this.checkTypeKey(3)||(this.limitDialogFormData.limitIp="")},onLimitTypeTipClick:function(){var e="窗口策略:每秒处理固定数量的请求,超出请求数量返回错误信息。",t="令牌桶策略:每秒放置固定数量的令牌数,每个请求进来后先去拿令牌,拿到了令牌才能继续,拿不到则等候令牌重新生成了再拿。",i=e+"
"+t;this.$alert(i,"限流策略",{dangerouslyUseHTMLString:!0})},onSizeChange:function(e){this.searchFormData.pageSize=e,this.loadTable()},onPageIndexChange:function(e){this.searchFormData.pageIndex=e,this.loadTable()},checkTypeKey:function(e){return this.limitDialogFormData.typeKey.find(function(t,i,a){return t===e})},isWindowType:function(){return 1===this.limitDialogFormData.limitType},isTokenType:function(){return 2===this.limitDialogFormData.limitType},limitRender:function(e){var t=[],i=[];return e.routeId&&(i.push(e.routeId),t.push("路由ID")),e.appKey&&(i.push(e.appKey),t.push("AppKey")),e.limitIp&&(i.push(e.limitIp),t.push("IP")),i.join(" + ")+"
("+t.join(" + ")+")"}}}),r=o,n=(i("18f8"),i("94c4"),i("2877")),s=Object(n["a"])(r,a,l,!1,null,"0ec28e9a",null);t["default"]=s.exports},"18f8":function(e,t,i){"use strict";var a=i("74a4"),l=i.n(a);l.a},"74a4":function(e,t,i){},7514:function(e,t,i){"use strict";var a=i("5ca1"),l=i("0a49")(5),o="find",r=!0;o in[]&&Array(1)[o](function(){r=!1}),a(a.P+a.F*r,"Array",{find:function(e){return l(this,e,arguments.length>1?arguments[1]:void 0)}}),i("9c6c")(o)},"94c4":function(e,t,i){"use strict";var a=i("a69e"),l=i.n(a);l.a},a69e:function(e,t,i){},cd1c:function(e,t,i){var a=i("e853");e.exports=function(e,t){return new(a(e))(t)}},e853:function(e,t,i){var a=i("d3f4"),l=i("1169"),o=i("2b4c")("species");e.exports=function(e){var t;return l(e)&&(t=e.constructor,"function"!=typeof t||t!==Array&&!l(t.prototype)||(t=void 0),a(t)&&(t=t[o],null===t&&(t=void 0))),void 0===t?Array:t}}}]); \ No newline at end of file +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-009073d4"],{"0a49":function(e,t,i){var a=i("9b43"),l=i("626a"),o=i("4bf8"),r=i("9def"),n=i("cd1c");e.exports=function(e,t){var i=1==e,s=2==e,m=3==e,c=4==e,p=6==e,u=5==e||p,d=t||n;return function(t,n,g){for(var f,h,D=o(t),v=l(D),y=a(n,g,3),b=r(v.length),k=0,x=i?d(t,b):s?d(t,0):void 0;b>k;k++)if((u||k in v)&&(f=v[k],h=y(f,k,D),e))if(i)x[k]=h;else if(h)switch(e){case 3:return!0;case 5:return f;case 6:return k;case 2:x.push(f)}else if(c)return!1;return p?-1:m||c?c:x}}},1169:function(e,t,i){var a=i("2d95");e.exports=Array.isArray||function(e){return"Array"==a(e)}},1510:function(e,t,i){"use strict";i.r(t);var a=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"app-container"},[i("el-container",[i("el-aside",{staticStyle:{"min-height":"300px",width:"250px"}},[i("el-input",{staticStyle:{"margin-bottom":"20px"},attrs:{"prefix-icon":"el-icon-search",placeholder:"搜索服务...",size:"mini",clearable:""},model:{value:e.filterText,callback:function(t){e.filterText=t},expression:"filterText"}}),e._v(" "),i("el-tree",{ref:"tree2",staticClass:"filter-tree",attrs:{data:e.treeData,props:e.defaultProps,"filter-node-method":e.filterNode,"highlight-current":!0,"expand-on-click-node":!1,"empty-text":"无数据","node-key":"id","default-expand-all":""},on:{"node-click":e.onNodeClick},scopedSlots:e._u([{key:"default",fn:function(t){t.node;var a=t.data;return i("span",{staticClass:"custom-tree-node"},[i("div",[i("el-tooltip",{directives:[{name:"show",rawName:"v-show",value:a.custom,expression:"data.custom"}],staticClass:"item",attrs:{content:"自定义服务",effect:"light",placement:"left"}},[i("i",{staticClass:"el-icon-warning-outline"})]),e._v(" "),a.label.lengthsubCode:"+e.limitCode),t.push("
subMsg:"+e.limitMsg)):2===e.limitType&&t.push("令牌桶容量:"+e.tokenBucketCount),t.join("")},onLimitDialogSave:function(){var e=this;this.$refs["limitDialogForm"].validate(function(t){if(t){e.cleanCheckboxData(),e.limitDialogFormData.serviceId=e.serviceId;var i=e.limitDialogFormData.id?"config.limit.update":"config.limit.add";e.post(i,e.limitDialogFormData,function(e){this.limitDialogVisible=!1,this.loadTable()})}})},cleanCheckboxData:function(){this.checkTypeKey(1)||(this.limitDialogFormData.routeId=""),this.checkTypeKey(2)||(this.limitDialogFormData.appKey=""),this.checkTypeKey(3)||(this.limitDialogFormData.limitIp="")},onLimitTypeTipClick:function(){var e="窗口策略:每秒处理固定数量的请求,超出请求数量返回错误信息。",t="令牌桶策略:每秒放置固定数量的令牌数,每个请求进来后先去拿令牌,拿到了令牌才能继续,拿不到则等候令牌重新生成了再拿。",i=e+"
"+t;this.$alert(i,"限流策略",{dangerouslyUseHTMLString:!0})},onSizeChange:function(e){this.searchFormData.pageSize=e,this.loadTable()},onPageIndexChange:function(e){this.searchFormData.pageIndex=e,this.loadTable()},checkTypeKey:function(e){return this.limitDialogFormData.typeKey.find(function(t,i,a){return t===e})},isWindowType:function(){return 1===this.limitDialogFormData.limitType},isTokenType:function(){return 2===this.limitDialogFormData.limitType},limitRender:function(e){var t=[],i=[];return e.routeId&&(i.push(e.routeId),t.push("路由ID")),e.appKey&&(i.push(e.appKey),t.push("AppKey")),e.limitIp&&(i.push(e.limitIp),t.push("IP")),i.join(" + ")+"
("+t.join(" + ")+")"}}}),r=o,n=(i("18f8"),i("7bbc"),i("2877")),s=Object(n["a"])(r,a,l,!1,null,"b81bfbde",null);t["default"]=s.exports},"18f8":function(e,t,i){"use strict";var a=i("74a4"),l=i.n(a);l.a},"4e11":function(e,t,i){},"74a4":function(e,t,i){},7514:function(e,t,i){"use strict";var a=i("5ca1"),l=i("0a49")(5),o="find",r=!0;o in[]&&Array(1)[o](function(){r=!1}),a(a.P+a.F*r,"Array",{find:function(e){return l(this,e,arguments.length>1?arguments[1]:void 0)}}),i("9c6c")(o)},"7bbc":function(e,t,i){"use strict";var a=i("4e11"),l=i.n(a);l.a},cd1c:function(e,t,i){var a=i("e853");e.exports=function(e,t){return new(a(e))(t)}},e853:function(e,t,i){var a=i("d3f4"),l=i("1169"),o=i("2b4c")("species");e.exports=function(e){var t;return l(e)&&(t=e.constructor,"function"!=typeof t||t!==Array&&!l(t.prototype)||(t=void 0),a(t)&&(t=t[o],null===t&&(t=void 0))),void 0===t?Array:t}}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d22c2e3.46f37153.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d22c2e3.46f37153.js deleted file mode 100644 index ef15b9c1..00000000 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d22c2e3.46f37153.js +++ /dev/null @@ -1 +0,0 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22c2e3"],{f1ac:function(t,e,a){"use strict";a.r(e);var n=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"app-container"},[a("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:t.searchFormData,size:"mini"}},[a("el-form-item",{attrs:{label:"serviceId"}},[a("el-input",{staticStyle:{width:"250px"},attrs:{clearable:!0,placeholder:"serviceId"},model:{value:t.searchFormData.serviceId,callback:function(e){t.$set(t.searchFormData,"serviceId",e)},expression:"searchFormData.serviceId"}})],1),t._v(" "),a("el-form-item",[a("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:t.onSearchTable}},[t._v("查询")])],1)],1),t._v(" "),a("el-table",{staticStyle:{width:"100%","margin-bottom":"20px"},attrs:{data:t.tableData,border:"","row-key":"id"}},[a("el-table-column",{attrs:{prop:"name",label:"服务名称(serviceId)",width:"200"}}),t._v(" "),a("el-table-column",{attrs:{prop:"instanceId",label:"instanceId",width:"250"}}),t._v(" "),a("el-table-column",{attrs:{prop:"ipAddr",label:"IP地址",width:"150"}}),t._v(" "),a("el-table-column",{attrs:{prop:"serverPort",label:"端口号",width:"100"}}),t._v(" "),a("el-table-column",{attrs:{prop:"status",label:"服务状态",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?a("el-tag",{attrs:{type:"success"}},[t._v("已上线")]):t._e(),t._v(" "),e.row.parentId>0&&"STARTING"===e.row.status?a("el-tag",{attrs:{type:"info"}},[t._v("正在启动")]):t._e(),t._v(" "),e.row.parentId>0&&"UNKNOWN"===e.row.status?a("el-tag",[t._v("未知")]):t._e(),t._v(" "),e.row.parentId>0&&("OUT_OF_SERVICE"===e.row.status||"DOWN"===e.row.status)?a("el-tag",{attrs:{type:"danger"}},[t._v("已下线")]):t._e()]}}])}),t._v(" "),a("el-table-column",{attrs:{prop:"updateTime",label:"最后更新时间",width:"160"}}),t._v(" "),a("el-table-column",{attrs:{label:"操作",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return t.onOffline(e.row)}}},[t._v("下线")]):t._e(),t._v(" "),e.row.parentId>0&&"OUT_OF_SERVICE"===e.row.status?a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return t.onOnline(e.row)}}},[t._v("上线")]):t._e()]}}])})],1)],1)},r=[],i=(a("7f7f"),a("ac6a"),{data:function(){return{searchFormData:{serviceId:""},tableData:[]}},created:function(){this.loadTable()},methods:{loadTable:function(){this.post("service.instance.list",this.searchFormData,function(t){this.tableData=this.buildTreeData(t.data)})},buildTreeData:function(t){return t.forEach(function(e){var a=e.parentId;0===a||t.forEach(function(t){if(t.id===a){var n=t.children;n||(n=[]),n.push(e),t.children=n}})}),t=t.filter(function(t){return 0===t.parentId}),t},onSearchTable:function(){this.loadTable()},onOffline:function(t){this.confirm("确定要下线【"+t.name+"】吗?",function(e){var a={serviceId:t.name,instanceId:t.instanceId};this.post("service.instance.offline",a,function(){this.tip("下线成功"),e()})})},onOnline:function(t){this.confirm("确定要上线【"+t.name+"】吗?",function(e){var a={serviceId:t.name,instanceId:t.instanceId};this.post("service.instance.online",a,function(){this.tip("上线成功"),e()})})}}}),s=i,o=a("2877"),l=Object(o["a"])(s,n,r,!1,null,null,null);e["default"]=l.exports}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d22c2e3.4a098244.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d22c2e3.4a098244.js new file mode 100644 index 00000000..bb906ed7 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-2d22c2e3.4a098244.js @@ -0,0 +1 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22c2e3"],{f1ac:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"app-container"},[n("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:t.searchFormData,size:"mini"}},[n("el-form-item",{attrs:{label:"serviceId"}},[n("el-input",{staticStyle:{width:"250px"},attrs:{clearable:!0,placeholder:"serviceId"},model:{value:t.searchFormData.serviceId,callback:function(e){t.$set(t.searchFormData,"serviceId",e)},expression:"searchFormData.serviceId"}})],1),t._v(" "),n("el-form-item",[n("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:t.onSearchTable}},[t._v("查询")])],1)],1),t._v(" "),n("el-table",{staticStyle:{width:"100%","margin-bottom":"20px"},attrs:{data:t.tableData,border:"","row-key":"id"}},[n("el-table-column",{attrs:{prop:"serviceId",label:"服务名称",width:"200"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",{domProps:{innerHTML:t._s(t.renderServiceName(e.row))}})]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"ipPort",label:"IP端口",width:"250"}}),t._v(" "),n("el-table-column",{attrs:{prop:"status",label:"服务状态",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?n("el-tag",{attrs:{type:"success"}},[t._v("已上线")]):t._e(),t._v(" "),e.row.parentId>0&&"STARTING"===e.row.status?n("el-tag",{attrs:{type:"info"}},[t._v("正在启动")]):t._e(),t._v(" "),e.row.parentId>0&&"UNKNOWN"===e.row.status?n("el-tag",[t._v("未知")]):t._e(),t._v(" "),e.row.parentId>0&&("OUT_OF_SERVICE"===e.row.status||"DOWN"===e.row.status)?n("el-tag",{attrs:{type:"danger"}},[t._v("已下线")]):t._e()]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"updateTime",label:"最后更新时间",width:"160"}}),t._v(" "),n("el-table-column",{attrs:{label:"操作",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onOffline(e.row)}}},[t._v("下线")]):t._e(),t._v(" "),e.row.parentId>0&&"OUT_OF_SERVICE"===e.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onOnline(e.row)}}},[t._v("上线")]):t._e()]}}])})],1)],1)},r=[],i=(n("ac6a"),{data:function(){return{searchFormData:{serviceId:""},tableData:[]}},created:function(){this.loadTable()},methods:{loadTable:function(){this.post("service.instance.list",this.searchFormData,function(t){this.tableData=this.buildTreeData(t.data)})},buildTreeData:function(t){return t.forEach(function(e){var n=e.parentId;0===n||t.forEach(function(t){if(t.id===n){var a=t.children;a||(a=[]),a.push(e),t.children=a}})}),t=t.filter(function(t){return 0===t.parentId}),t},onSearchTable:function(){this.loadTable()},onOffline:function(t){this.confirm("确定要下线【"+t.serviceId+"】吗?",function(e){this.post("service.instance.offline",t,function(){this.tip("下线成功"),e()})})},onOnline:function(t){this.confirm("确定要上线【"+t.serviceId+"】吗?",function(e){this.post("service.instance.online",t,function(){this.tip("上线成功"),e()})})},renderServiceName:function(t){var e="";if(t.children&&t.children.length>0){var n=t.children.filter(function(t){return"UP"===t.status}).length;e=" (".concat(n,"/").concat(t.children.length,")")}return t.serviceId+e}}}),o=i,s=n("2877"),l=Object(s["a"])(o,a,r,!1,null,null,null);e["default"]=l.exports}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-4a59cbe4.a6360c68.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-4a59cbe4.a6360c68.js new file mode 100644 index 00000000..4f96ae52 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-4a59cbe4.a6360c68.js @@ -0,0 +1 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-4a59cbe4"],{"02f4":function(t,e,n){var r=n("4588"),i=n("be13");t.exports=function(t){return function(e,n){var o,a,l=String(i(e)),c=r(n),s=l.length;return c<0||c>=s?t?"":void 0:(o=l.charCodeAt(c),o<55296||o>56319||c+1===s||(a=l.charCodeAt(c+1))<56320||a>57343?t?l.charAt(c):o:t?l.slice(c,c+2):a-56320+(o-55296<<10)+65536)}}},"0390":function(t,e,n){"use strict";var r=n("02f4")(!0);t.exports=function(t,e,n){return e+(n?r(t,e).length:1)}},"0a49":function(t,e,n){var r=n("9b43"),i=n("626a"),o=n("4bf8"),a=n("9def"),l=n("cd1c");t.exports=function(t,e){var n=1==t,c=2==t,s=3==t,u=4==t,f=6==t,d=5==t||f,v=e||l;return function(e,l,p){for(var g,h,b=o(e),m=i(b),D=r(l,p,3),x=a(m.length),y=0,_=n?v(e,x):c?v(e,0):void 0;x>y;y++)if((d||y in m)&&(g=m[y],h=D(g,y,b),t))if(n)_[y]=h;else if(h)switch(t){case 3:return!0;case 5:return g;case 6:return y;case 2:_.push(g)}else if(u)return!1;return f?-1:s||u?u:_}}},"0bfb":function(t,e,n){"use strict";var r=n("cb7c");t.exports=function(){var t=r(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},1169:function(t,e,n){var r=n("2d95");t.exports=Array.isArray||function(t){return"Array"==r(t)}},"20d6":function(t,e,n){"use strict";var r=n("5ca1"),i=n("0a49")(6),o="findIndex",a=!0;o in[]&&Array(1)[o](function(){a=!1}),r(r.P+r.F*a,"Array",{findIndex:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),n("9c6c")(o)},"214f":function(t,e,n){"use strict";n("b0c5");var r=n("2aba"),i=n("32e9"),o=n("79e5"),a=n("be13"),l=n("2b4c"),c=n("520a"),s=l("species"),u=!o(function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")}),f=function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2===n.length&&"a"===n[0]&&"b"===n[1]}();t.exports=function(t,e,n){var d=l(t),v=!o(function(){var e={};return e[d]=function(){return 7},7!=""[t](e)}),p=v?!o(function(){var e=!1,n=/a/;return n.exec=function(){return e=!0,null},"split"===t&&(n.constructor={},n.constructor[s]=function(){return n}),n[d](""),!e}):void 0;if(!v||!p||"replace"===t&&!u||"split"===t&&!f){var g=/./[d],h=n(a,d,""[t],function(t,e,n,r,i){return e.exec===c?v&&!i?{done:!0,value:g.call(e,n,r)}:{done:!0,value:t.call(n,e,r)}:{done:!1}}),b=h[0],m=h[1];r(String.prototype,t,b),i(RegExp.prototype,d,2==e?function(t,e){return m.call(t,this,e)}:function(t){return m.call(t,this)})}}},"520a":function(t,e,n){"use strict";var r=n("0bfb"),i=RegExp.prototype.exec,o=String.prototype.replace,a=i,l="lastIndex",c=function(){var t=/a/,e=/b*/g;return i.call(t,"a"),i.call(e,"a"),0!==t[l]||0!==e[l]}(),s=void 0!==/()??/.exec("")[1],u=c||s;u&&(a=function(t){var e,n,a,u,f=this;return s&&(n=new RegExp("^"+f.source+"$(?!\\s)",r.call(f))),c&&(e=f[l]),a=i.call(f,t),c&&a&&(f[l]=f.global?a.index+a[0].length:e),s&&a&&a.length>1&&o.call(a[0],n,function(){for(u=1;u]*>)/g,v=/\$([$&`']|\d\d?)/g,p=function(t){return void 0===t?t:String(t)};n("214f")("replace",2,function(t,e,n,g){return[function(r,i){var o=t(this),a=void 0==r?void 0:r[e];return void 0!==a?a.call(r,o,i):n.call(String(o),r,i)},function(t,e){var i=g(n,t,this,e);if(i.done)return i.value;var f=r(t),d=String(this),v="function"===typeof e;v||(e=String(e));var b=f.global;if(b){var m=f.unicode;f.lastIndex=0}var D=[];while(1){var x=c(f,d);if(null===x)break;if(D.push(x),!b)break;var y=String(x[0]);""===y&&(f.lastIndex=l(d,o(f.lastIndex),m))}for(var _="",w=0,I=0;I=w&&(_+=d.slice(w,k)+L,w=k+S.length)}return _+d.slice(w)}];function h(t,e,r,o,a,l){var c=r+t.length,s=o.length,u=v;return void 0!==a&&(a=i(a),u=d),n.call(l,u,function(n,i){var l;switch(i.charAt(0)){case"$":return"$";case"&":return t;case"`":return e.slice(0,r);case"'":return e.slice(c);case"<":l=a[i.slice(1,-1)];break;default:var u=+i;if(0===u)return n;if(u>s){var d=f(u/10);return 0===d?n:d<=s?void 0===o[d-1]?i.charAt(1):o[d-1]+i.charAt(1):n}l=o[u-1]}return void 0===l?"":l})}})},b0c5:function(t,e,n){"use strict";var r=n("520a");n("5ca1")({target:"RegExp",proto:!0,forced:r!==/./.exec},{exec:r})},cd1c:function(t,e,n){var r=n("e853");t.exports=function(t,e){return new(r(t))(e)}},e853:function(t,e,n){var r=n("d3f4"),i=n("1169"),o=n("2b4c")("species");t.exports=function(t){var e;return i(t)&&(e=t.constructor,"function"!=typeof e||e!==Array&&!i(e.prototype)||(e=void 0),r(e)&&(e=e[o],null===e&&(e=void 0))),void 0===e?Array:e}},ec2a:function(t,e,n){"use strict";n.r(e);var r=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"app-container"},[n("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:t.searchFormData,size:"mini"}},[n("el-form-item",[n("el-button",{attrs:{type:"primary",icon:"el-icon-plus"},on:{click:t.onAddServer}},[t._v("添加监控服务器")])],1)],1),t._v(" "),n("el-table",{staticStyle:{width:"100%","margin-bottom":"20px"},attrs:{data:t.tableData,border:"","default-expand-all":!0,"row-key":"treeId","empty-text":"请添加监控服务器"}},[n("el-table-column",{attrs:{prop:"monitorName",label:"网关实例",width:"300"},scopedSlots:t._u([{key:"default",fn:function(e){return[0===e.row.parentId?n("span",[t._v(t._s(e.row.monitorName))]):t._e()]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"serviceId",label:"serviceId",width:"200"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0?n("span",[t._v(t._s(e.row.serviceId))]):t._e()]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"name",label:"接口名 (版本号)",width:"200"},scopedSlots:t._u([{key:"default",fn:function(e){return[t._v("\n "+t._s(e.row.name+(e.row.version?" ("+e.row.version+")":""))+"\n ")]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"count",label:"出错次数",width:"100"}}),t._v(" "),n("el-table-column",{attrs:{prop:"errorMsg",label:"报错信息",width:"300"},scopedSlots:t._u([{key:"default",fn:function(e){return e.row.parentId>0?[n("div",{staticStyle:{display:"inline-block"},domProps:{innerHTML:t._s(t.showErrorMsg(e.row))}}),t._v(" "),n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onShowErrorDetail(e.row)}}},[t._v("详情")])]:void 0}}],null,!0)}),t._v(" "),n("el-table-column",{attrs:{label:"操作",width:"180"},scopedSlots:t._u([{key:"default",fn:function(e){return[0===e.row.parentId&&e.row.children?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onClearLog(e.row)}}},[t._v("清空日志")]):t._e(),t._v(" "),0===e.row.parentId?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onDelete(e.row)}}},[t._v("删除实例")]):t._e()]}}])})],1),t._v(" "),n("el-dialog",{attrs:{title:"选择服务器实例",visible:t.logDialogInstanceVisible,"close-on-click-modal":!1},on:{"update:visible":function(e){t.logDialogInstanceVisible=e}}},[n("el-form",{ref:"logDialogForm",attrs:{model:t.logDialogFormData,rules:t.rulesLog,"label-width":"150px",size:"mini"}},[n("el-form-item",[n("p",{staticStyle:{color:"#878787"}},[t._v("只能选择网关实例,其它实例不支持")])]),t._v(" "),n("el-form-item",{attrs:{prop:"instanceData",label:"服务器实例"}},[n("el-select",{staticStyle:{width:"400px"},attrs:{"value-key":"id"},model:{value:t.logDialogFormData.instanceData,callback:function(e){t.$set(t.logDialogFormData,"instanceData",e)},expression:"logDialogFormData.instanceData"}},t._l(t.serviceData,function(e){return n("el-option",{key:e.id,attrs:{label:e.serviceId+"("+e.ipPort+")",value:e,disabled:t.isOptionDisabled(e)}},[n("span",{staticStyle:{float:"left"}},[t._v(t._s(e.serviceId)+" "),t.isOptionDisabled(e)?n("span",[t._v("(已添加)")]):t._e()]),t._v(" "),n("span",{staticStyle:{float:"right",color:"#8492a6","font-size":"13px"}},[t._v(t._s(e.ipPort))])])}),1)],1)],1),t._v(" "),n("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{on:{click:function(e){t.logDialogInstanceVisible=!1}}},[t._v("取 消")]),t._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:t.onLogDialogSave}},[t._v("保 存")])],1)],1),t._v(" "),n("el-dialog",{attrs:{title:"错误详情",visible:t.logDetailVisible,width:"60%"},on:{"update:visible":function(e){t.logDetailVisible=e}}},[n("div",{staticStyle:{"overflow-x":"auto"},domProps:{innerHTML:t._s(t.errorMsgDetail)}}),t._v(" "),n("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{attrs:{type:"primary"},on:{click:function(e){t.logDetailVisible=!1}}},[t._v("关 闭")])],1)])],1)},i=[],o=(n("a481"),n("ac6a"),n("20d6"),{data:function(){return{searchFormData:{},tableData:[],serviceData:[],addedInstanceList:[],logDialogFormData:{instanceData:null},logDialogInstanceVisible:!1,logDetailVisible:!1,rulesLog:{instanceData:[{required:!0,message:"不能为空",trigger:"blur"}]},errorMsgDetail:""}},created:function(){this.loadServiceInstance(),this.loadTable()},methods:{loadServiceInstance:function(){this.post("service.instance.list",{},function(t){this.serviceData=t.data.filter(function(t){return t.instanceId&&t.instanceId.length>0})}),this.post("monitor.instance.list",{},function(t){this.addedInstanceList=t.data})},loadTable:function(){this.post("monitor.log.list",{},function(t){this.tableData=this.buildTreeData(t.data)})},isOptionDisabled:function(t){var e=t.ipPort,n=this.addedInstanceList.findIndex(function(t,n,r){return t===e});return n>-1},buildTreeData:function(t){return t.forEach(function(e){var n=e.parentId;0===n||t.forEach(function(t){if(t.treeId===n){var r=t.children;r||(r=[]),r.push(e),t.children=r}})}),t=t.filter(function(t){return 0===t.parentId}),t},showErrorMsg:function(t){var e=t.errorMsg.replace(/\/g,"");return e.substring(0,30)+"..."},onAddServer:function(){this.logDialogInstanceVisible=!0},onDelete:function(t){this.confirm("确定要删除实例【"+t.monitorName+"】吗?",function(e){this.post("monitor.instance.del",{id:t.rawId},function(t){e(),this.tip("删除成功"),this.loadTable()})})},onClearLog:function(t){this.confirm("确定要清空日志吗?",function(e){this.post("monitor.log.clear",{id:t.rawId},function(t){e(),this.tip("清空成功"),this.loadTable()})})},onShowErrorDetail:function(t){this.errorMsgDetail=t.errorMsg,this.logDetailVisible=!0},onLogDialogSave:function(){var t=this;this.$refs["logDialogForm"].validate(function(e){if(e){var n=t.logDialogFormData.instanceData;t.post("monitor.instance.add",n,function(t){this.logDialogInstanceVisible=!1,this.loadTable()})}})}}}),a=o,l=n("2877"),c=Object(l["a"])(a,r,i,!1,null,null,null);e["default"]=c.exports}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-4a59cbe4.b5e74cc4.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-4a59cbe4.b5e74cc4.js deleted file mode 100644 index 3b814941..00000000 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-4a59cbe4.b5e74cc4.js +++ /dev/null @@ -1 +0,0 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-4a59cbe4"],{"02f4":function(t,e,r){var n=r("4588"),i=r("be13");t.exports=function(t){return function(e,r){var o,a,l=String(i(e)),c=n(r),s=l.length;return c<0||c>=s?t?"":void 0:(o=l.charCodeAt(c),o<55296||o>56319||c+1===s||(a=l.charCodeAt(c+1))<56320||a>57343?t?l.charAt(c):o:t?l.slice(c,c+2):a-56320+(o-55296<<10)+65536)}}},"0390":function(t,e,r){"use strict";var n=r("02f4")(!0);t.exports=function(t,e,r){return e+(r?n(t,e).length:1)}},"0a49":function(t,e,r){var n=r("9b43"),i=r("626a"),o=r("4bf8"),a=r("9def"),l=r("cd1c");t.exports=function(t,e){var r=1==t,c=2==t,s=3==t,u=4==t,d=6==t,f=5==t||d,v=e||l;return function(e,l,p){for(var g,h,b=o(e),m=i(b),D=n(l,p,3),x=a(m.length),y=0,_=r?v(e,x):c?v(e,0):void 0;x>y;y++)if((f||y in m)&&(g=m[y],h=D(g,y,b),t))if(r)_[y]=h;else if(h)switch(t){case 3:return!0;case 5:return g;case 6:return y;case 2:_.push(g)}else if(u)return!1;return d?-1:s||u?u:_}}},"0bfb":function(t,e,r){"use strict";var n=r("cb7c");t.exports=function(){var t=n(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},1169:function(t,e,r){var n=r("2d95");t.exports=Array.isArray||function(t){return"Array"==n(t)}},"20d6":function(t,e,r){"use strict";var n=r("5ca1"),i=r("0a49")(6),o="findIndex",a=!0;o in[]&&Array(1)[o](function(){a=!1}),n(n.P+n.F*a,"Array",{findIndex:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),r("9c6c")(o)},"214f":function(t,e,r){"use strict";r("b0c5");var n=r("2aba"),i=r("32e9"),o=r("79e5"),a=r("be13"),l=r("2b4c"),c=r("520a"),s=l("species"),u=!o(function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")}),d=function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var r="ab".split(t);return 2===r.length&&"a"===r[0]&&"b"===r[1]}();t.exports=function(t,e,r){var f=l(t),v=!o(function(){var e={};return e[f]=function(){return 7},7!=""[t](e)}),p=v?!o(function(){var e=!1,r=/a/;return r.exec=function(){return e=!0,null},"split"===t&&(r.constructor={},r.constructor[s]=function(){return r}),r[f](""),!e}):void 0;if(!v||!p||"replace"===t&&!u||"split"===t&&!d){var g=/./[f],h=r(a,f,""[t],function(t,e,r,n,i){return e.exec===c?v&&!i?{done:!0,value:g.call(e,r,n)}:{done:!0,value:t.call(r,e,n)}:{done:!1}}),b=h[0],m=h[1];n(String.prototype,t,b),i(RegExp.prototype,f,2==e?function(t,e){return m.call(t,this,e)}:function(t){return m.call(t,this)})}}},"520a":function(t,e,r){"use strict";var n=r("0bfb"),i=RegExp.prototype.exec,o=String.prototype.replace,a=i,l="lastIndex",c=function(){var t=/a/,e=/b*/g;return i.call(t,"a"),i.call(e,"a"),0!==t[l]||0!==e[l]}(),s=void 0!==/()??/.exec("")[1],u=c||s;u&&(a=function(t){var e,r,a,u,d=this;return s&&(r=new RegExp("^"+d.source+"$(?!\\s)",n.call(d))),c&&(e=d[l]),a=i.call(d,t),c&&a&&(d[l]=d.global?a.index+a[0].length:e),s&&a&&a.length>1&&o.call(a[0],r,function(){for(u=1;u]*>)/g,v=/\$([$&`']|\d\d?)/g,p=function(t){return void 0===t?t:String(t)};r("214f")("replace",2,function(t,e,r,g){return[function(n,i){var o=t(this),a=void 0==n?void 0:n[e];return void 0!==a?a.call(n,o,i):r.call(String(o),n,i)},function(t,e){var i=g(r,t,this,e);if(i.done)return i.value;var d=n(t),f=String(this),v="function"===typeof e;v||(e=String(e));var b=d.global;if(b){var m=d.unicode;d.lastIndex=0}var D=[];while(1){var x=c(d,f);if(null===x)break;if(D.push(x),!b)break;var y=String(x[0]);""===y&&(d.lastIndex=l(f,o(d.lastIndex),m))}for(var _="",w=0,I=0;I=w&&(_+=f.slice(w,k)+L,w=k+S.length)}return _+f.slice(w)}];function h(t,e,n,o,a,l){var c=n+t.length,s=o.length,u=v;return void 0!==a&&(a=i(a),u=f),r.call(l,u,function(r,i){var l;switch(i.charAt(0)){case"$":return"$";case"&":return t;case"`":return e.slice(0,n);case"'":return e.slice(c);case"<":l=a[i.slice(1,-1)];break;default:var u=+i;if(0===u)return r;if(u>s){var f=d(u/10);return 0===f?r:f<=s?void 0===o[f-1]?i.charAt(1):o[f-1]+i.charAt(1):r}l=o[u-1]}return void 0===l?"":l})}})},b0c5:function(t,e,r){"use strict";var n=r("520a");r("5ca1")({target:"RegExp",proto:!0,forced:n!==/./.exec},{exec:n})},cd1c:function(t,e,r){var n=r("e853");t.exports=function(t,e){return new(n(t))(e)}},e853:function(t,e,r){var n=r("d3f4"),i=r("1169"),o=r("2b4c")("species");t.exports=function(t){var e;return i(t)&&(e=t.constructor,"function"!=typeof e||e!==Array&&!i(e.prototype)||(e=void 0),n(e)&&(e=e[o],null===e&&(e=void 0))),void 0===e?Array:e}},ec2a:function(t,e,r){"use strict";r.r(e);var n=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",{staticClass:"app-container"},[r("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:t.searchFormData,size:"mini"}},[r("el-form-item",[r("el-button",{attrs:{type:"primary",icon:"el-icon-plus"},on:{click:t.onAddServer}},[t._v("添加监控服务器")])],1)],1),t._v(" "),r("el-table",{staticStyle:{width:"100%","margin-bottom":"20px"},attrs:{data:t.tableData,border:"","default-expand-all":!0,"row-key":"treeId","empty-text":"请添加监控服务器"}},[r("el-table-column",{attrs:{prop:"monitorName",label:"网关实例",width:"300"},scopedSlots:t._u([{key:"default",fn:function(e){return[0===e.row.parentId?r("span",[t._v(t._s(e.row.monitorName))]):t._e()]}}])}),t._v(" "),r("el-table-column",{attrs:{prop:"serviceId",label:"serviceId",width:"200"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0?r("span",[t._v(t._s(e.row.serviceId))]):t._e()]}}])}),t._v(" "),r("el-table-column",{attrs:{prop:"name",label:"接口名 (版本号)",width:"200"},scopedSlots:t._u([{key:"default",fn:function(e){return[t._v("\n "+t._s(e.row.name+(e.row.version?" ("+e.row.version+")":""))+"\n ")]}}])}),t._v(" "),r("el-table-column",{attrs:{prop:"count",label:"出错次数",width:"100"}}),t._v(" "),r("el-table-column",{attrs:{prop:"errorMsg",label:"报错信息",width:"300"},scopedSlots:t._u([{key:"default",fn:function(e){return e.row.parentId>0?[r("div",{staticStyle:{display:"inline-block"},domProps:{innerHTML:t._s(t.showErrorMsg(e.row))}}),t._v(" "),r("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(r){return t.onShowErrorDetail(e.row)}}},[t._v("详情")])]:void 0}}],null,!0)}),t._v(" "),r("el-table-column",{attrs:{label:"操作",width:"180"},scopedSlots:t._u([{key:"default",fn:function(e){return[0===e.row.parentId&&e.row.children?r("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(r){return t.onClearLog(e.row)}}},[t._v("清空日志")]):t._e(),t._v(" "),0===e.row.parentId?r("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(r){return t.onDelete(e.row)}}},[t._v("删除实例")]):t._e()]}}])})],1),t._v(" "),r("el-dialog",{attrs:{title:"选择服务器实例",visible:t.logDialogInstanceVisible,"close-on-click-modal":!1},on:{"update:visible":function(e){t.logDialogInstanceVisible=e}}},[r("el-form",{ref:"logDialogForm",attrs:{model:t.logDialogFormData,rules:t.rulesLog,"label-width":"150px",size:"mini"}},[r("el-form-item",[r("p",{staticStyle:{color:"#878787"}},[t._v("只能选择网关实例,其它实例不支持")])]),t._v(" "),r("el-form-item",{attrs:{prop:"instanceData",label:"服务器实例"}},[r("el-select",{staticStyle:{width:"400px"},attrs:{"value-key":"id"},model:{value:t.logDialogFormData.instanceData,callback:function(e){t.$set(t.logDialogFormData,"instanceData",e)},expression:"logDialogFormData.instanceData"}},t._l(t.serviceData,function(e){return r("el-option",{key:e.id,attrs:{label:e.name+"("+e.ipAddr+":"+e.serverPort+")",value:e,disabled:t.isOptionDisabled(e)}},[r("span",{staticStyle:{float:"left"}},[t._v(t._s(e.name)+" "),t.isOptionDisabled(e)?r("span",[t._v("(已添加)")]):t._e()]),t._v(" "),r("span",{staticStyle:{float:"right",color:"#8492a6","font-size":"13px"}},[t._v(t._s(e.ipAddr+":"+e.serverPort))])])}),1)],1)],1),t._v(" "),r("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[r("el-button",{on:{click:function(e){t.logDialogInstanceVisible=!1}}},[t._v("取 消")]),t._v(" "),r("el-button",{attrs:{type:"primary"},on:{click:t.onLogDialogSave}},[t._v("保 存")])],1)],1),t._v(" "),r("el-dialog",{attrs:{title:"错误详情",visible:t.logDetailVisible,width:"60%"},on:{"update:visible":function(e){t.logDetailVisible=e}}},[r("div",{staticStyle:{"overflow-x":"auto"},domProps:{innerHTML:t._s(t.errorMsgDetail)}}),t._v(" "),r("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[r("el-button",{attrs:{type:"primary"},on:{click:function(e){t.logDetailVisible=!1}}},[t._v("关 闭")])],1)])],1)},i=[],o=(r("a481"),r("ac6a"),r("20d6"),{data:function(){return{searchFormData:{},tableData:[],serviceData:[],addedInstanceList:[],logDialogFormData:{instanceData:null},logDialogInstanceVisible:!1,logDetailVisible:!1,rulesLog:{instanceData:[{required:!0,message:"不能为空",trigger:"blur"}]},errorMsgDetail:""}},created:function(){this.loadServiceInstance(),this.loadTable()},methods:{loadServiceInstance:function(){this.post("service.instance.list",{},function(t){this.serviceData=t.data.filter(function(t){return t.instanceId&&t.instanceId.length>0})}),this.post("monitor.instance.list",{},function(t){this.addedInstanceList=t.data})},loadTable:function(){this.post("monitor.log.list",{},function(t){this.tableData=this.buildTreeData(t.data)})},isOptionDisabled:function(t){var e=t.ipAddr+":"+t.serverPort,r=this.addedInstanceList.findIndex(function(t,r,n){return t===e});return r>-1},buildTreeData:function(t){return t.forEach(function(e){var r=e.parentId;0===r||t.forEach(function(t){if(t.treeId===r){var n=t.children;n||(n=[]),n.push(e),t.children=n}})}),t=t.filter(function(t){return 0===t.parentId}),t},showErrorMsg:function(t){var e=t.errorMsg.replace(/\/g,"");return e.substring(0,30)+"..."},onAddServer:function(){this.logDialogInstanceVisible=!0},onDelete:function(t){this.confirm("确定要删除实例【"+t.monitorName+"】吗?",function(e){this.post("monitor.instance.del",{id:t.rawId},function(t){e(),this.tip("删除成功"),this.loadTable()})})},onClearLog:function(t){this.confirm("确定要清空日志吗?",function(e){this.post("monitor.log.clear",{id:t.rawId},function(t){e(),this.tip("清空成功"),this.loadTable()})})},onShowErrorDetail:function(t){this.errorMsgDetail=t.errorMsg,this.logDetailVisible=!0},onLogDialogSave:function(){var t=this;this.$refs["logDialogForm"].validate(function(e){if(e){var r=t.logDialogFormData.instanceData,n={serviceId:r.serviceId,ip:r.ipAddr,port:r.serverPort};t.post("monitor.instance.add",n,function(t){this.logDialogInstanceVisible=!1,this.loadTable()})}})}}}),a=o,l=r("2877"),c=Object(l["a"])(a,n,i,!1,null,null,null);e["default"]=c.exports}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-6a68a33e.f59ae895.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-6a68a33e.15951b55.js similarity index 78% rename from sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-6a68a33e.f59ae895.js rename to sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-6a68a33e.15951b55.js index bfe7aeae..2535ff21 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-6a68a33e.f59ae895.js +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-6a68a33e.15951b55.js @@ -1 +1 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-6a68a33e"],{1248:function(e,t,o){"use strict";o.r(t);var a=function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("div",{staticClass:"app-container"},[o("el-container",[o("el-aside",{staticStyle:{"min-height":"300px",width:"250px"}},[o("el-button",{attrs:{type:"primary",plain:"",size:"mini",icon:"el-icon-plus"},on:{click:function(t){return t.stopPropagation(),e.addService(t)}}},[e._v("\n 新建服务\n ")]),e._v(" "),o("el-input",{staticStyle:{"margin-bottom":"10px","margin-top":"10px"},attrs:{"prefix-icon":"el-icon-search",placeholder:"搜索服务...",size:"mini",clearable:""},model:{value:e.filterText,callback:function(t){e.filterText=t},expression:"filterText"}}),e._v(" "),o("el-tree",{ref:"serviceTree",staticClass:"filter-tree",attrs:{data:e.treeData,props:e.defaultProps,"filter-node-method":e.filterNode,"highlight-current":!0,"expand-on-click-node":!1,"empty-text":"无数据","node-key":"serviceId","default-expand-all":""},on:{"node-click":e.onNodeClick},scopedSlots:e._u([{key:"default",fn:function(t){t.node;var a=t.data;return o("span",{staticClass:"custom-tree-node"},[o("div",[o("el-tooltip",{directives:[{name:"show",rawName:"v-show",value:a.custom,expression:"data.custom"}],staticClass:"item",attrs:{content:"自定义服务",effect:"light",placement:"left"}},[o("i",{staticClass:"el-icon-warning-outline"})]),e._v(" "),a.label.length0?t.join(", "):'未授权'},onRouteDialogSave:function(){var e=this;this.$refs.routeDialogFormRef.validate(function(t){if(t){var o=e.routeDialogFormData.id?"route.update":"route.add";e.routeDialogFormData.serviceId=e.serviceId,e.post(o,e.routeDialogFormData,function(){this.routeDialogVisible=!1,this.loadTable()})}})},onAuthDialogSave:function(){this.post("route.role.update",this.authDialogFormData,function(){this.authDialogVisible=!1,this.loadTable()})},addService:function(){this.addServiceDialogVisible=!0},closeAddServiceDlg:function(){this.$refs.addServiceForm.resetFields()},onAddService:function(){var e=this;this.$refs.addServiceForm.validate(function(t){t&&e.post("service.custom.add",e.addServiceForm,function(e){this.addServiceDialogVisible=!1,this.tip("添加成功"),this.loadTree()})})},onDelService:function(e){var t=e.serviceId;this.confirm("确认要删除服务"+t+"吗,【对应的路由配置会一起删除】",function(e){var o={serviceId:t};this.post("service.custom.del",o,function(){e(),this.tip("删除成功"),this.loadTree()})})}}},l=r,s=(o("55a2"),o("2877")),n=Object(s["a"])(l,a,i,!1,null,null,null);t["default"]=n.exports},"55a2":function(e,t,o){"use strict";var a=o("b294"),i=o.n(a);i.a},b294:function(e,t,o){}}]); \ No newline at end of file +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-6a68a33e"],{1248:function(e,t,o){"use strict";o.r(t);var a=function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("div",{staticClass:"app-container"},[o("el-container",[o("el-aside",{staticStyle:{"min-height":"300px",width:"250px"}},[o("el-button",{attrs:{type:"primary",plain:"",size:"mini",icon:"el-icon-plus"},on:{click:function(t){return t.stopPropagation(),e.addService(t)}}},[e._v("\n 新建服务\n ")]),e._v(" "),o("el-input",{staticStyle:{"margin-bottom":"10px","margin-top":"10px"},attrs:{"prefix-icon":"el-icon-search",placeholder:"搜索服务...",size:"mini",clearable:""},model:{value:e.filterText,callback:function(t){e.filterText=t},expression:"filterText"}}),e._v(" "),o("el-tree",{ref:"serviceTree",staticClass:"filter-tree",attrs:{data:e.treeData,props:e.defaultProps,"filter-node-method":e.filterNode,"highlight-current":!0,"expand-on-click-node":!1,"empty-text":"无数据","node-key":"serviceId","default-expand-all":""},on:{"node-click":e.onNodeClick},scopedSlots:e._u([{key:"default",fn:function(t){t.node;var a=t.data;return o("span",{staticClass:"custom-tree-node"},[o("div",[o("el-tooltip",{directives:[{name:"show",rawName:"v-show",value:a.custom,expression:"data.custom"}],staticClass:"item",attrs:{content:"自定义服务",effect:"light",placement:"left"}},[o("i",{staticClass:"el-icon-warning-outline"})]),e._v(" "),a.label.length0?t.join(", "):'未授权'},onRouteDialogSave:function(){var e=this;this.$refs.routeDialogFormRef.validate(function(t){if(t){var o=e.routeDialogFormData.id?"route.update":"route.add";e.routeDialogFormData.serviceId=e.serviceId,e.post(o,e.routeDialogFormData,function(){this.routeDialogVisible=!1,this.loadTable()})}})},onAuthDialogSave:function(){this.post("route.role.update",this.authDialogFormData,function(){this.authDialogVisible=!1,this.loadTable()})},addService:function(){this.addServiceDialogVisible=!0},closeAddServiceDlg:function(){this.$refs.addServiceForm.resetFields()},onAddService:function(){var e=this;this.$refs.addServiceForm.validate(function(t){t&&e.post("service.custom.add",e.addServiceForm,function(e){this.addServiceDialogVisible=!1,this.tip("添加成功"),this.loadTree()})})},onDelService:function(e){var t=e.serviceId;this.confirm("确认要删除服务"+t+"吗,【对应的路由配置会一起删除】",function(e){var o={serviceId:t};this.post("service.custom.del",o,function(){e(),this.tip("删除成功"),this.loadTree()})})}}},l=r,s=(o("55a2"),o("2877")),n=Object(s["a"])(l,a,i,!1,null,null,null);t["default"]=n.exports},"55a2":function(e,t,o){"use strict";var a=o("b294"),i=o.n(a);i.a},b294:function(e,t,o){}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-vue/src/views/service/limit/index.vue b/sop-admin/sop-admin-vue/src/views/service/limit/index.vue index ac9e0fbe..1e6ada92 100644 --- a/sop-admin/sop-admin-vue/src/views/service/limit/index.vue +++ b/sop-admin/sop-admin-vue/src/views/service/limit/index.vue @@ -211,7 +211,7 @@ export default { methods: { // 加载树 loadTree: function() { - this.post('service.list', {}, function(resp) { + this.post('zookeeper.service.list', {}, function(resp) { const respData = resp.data this.treeData = this.convertToTreeData(respData, 0) }) diff --git a/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue b/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue index 03ec06fe..1424c84f 100644 --- a/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue +++ b/sop-admin/sop-admin-vue/src/views/service/limit/index2.vue @@ -337,7 +337,7 @@ export default { methods: { // 加载树 loadTree: function() { - this.post('service.list', {}, function(resp) { + this.post('zookeeper.service.list', {}, function(resp) { const respData = resp.data this.treeData = this.convertToTreeData(respData, 0) }) diff --git a/sop-admin/sop-admin-vue/src/views/service/list/index.vue b/sop-admin/sop-admin-vue/src/views/service/list/index.vue index 511c2052..9572923c 100644 --- a/sop-admin/sop-admin-vue/src/views/service/list/index.vue +++ b/sop-admin/sop-admin-vue/src/views/service/list/index.vue @@ -15,25 +15,19 @@ row-key="id" > + > + + - - 0) { + const onlineCount = row.children.filter(el => { + return el.status === 'UP' + }).length + instanceCount = ` (${onlineCount}/${row.children.length})` + } + return row.serviceId + instanceCount } } } diff --git a/sop-admin/sop-admin-vue/src/views/service/log/index.vue b/sop-admin/sop-admin-vue/src/views/service/log/index.vue index d9a15450..506d8010 100644 --- a/sop-admin/sop-admin-vue/src/views/service/log/index.vue +++ b/sop-admin/sop-admin-vue/src/views/service/log/index.vue @@ -85,12 +85,12 @@ - {{ item.name }} (已添加) - {{ item.ipAddr + ':' + item.serverPort }} + {{ item.serviceId }} (已添加) + {{ item.ipPort }} @@ -156,7 +156,7 @@ export default { }) }, isOptionDisabled: function(item) { - const ipPort = item.ipAddr + ':' + item.serverPort + const ipPort = item.ipPort const index = this.addedInstanceList.findIndex((value, index, arr) => { return value === ipPort }) @@ -218,12 +218,7 @@ export default { this.$refs['logDialogForm'].validate((valid) => { if (valid) { const instanceData = this.logDialogFormData.instanceData - const data = { - serviceId: instanceData.serviceId, - ip: instanceData.ipAddr, - port: instanceData.serverPort - } - this.post('monitor.instance.add', data, function(resp) { + this.post('monitor.instance.add', instanceData, function(resp) { this.logDialogInstanceVisible = false this.loadTable() }) diff --git a/sop-admin/sop-admin-vue/src/views/service/route/index.vue b/sop-admin/sop-admin-vue/src/views/service/route/index.vue index f85a0a80..8ef40687 100644 --- a/sop-admin/sop-admin-vue/src/views/service/route/index.vue +++ b/sop-admin/sop-admin-vue/src/views/service/route/index.vue @@ -343,7 +343,7 @@ export default { methods: { // 加载树 loadTree: function() { - this.post('service.list', {}, function(resp) { + this.post('zookeeper.service.list', {}, function(resp) { const respData = resp.data this.treeData = this.convertToTreeData(respData, 0) this.$nextTick(() => { From 6fc49f2699b0788fb788cd48183f4485b06391c4 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 1 Jul 2019 16:41:37 +0800 Subject: [PATCH 26/40] =?UTF-8?q?nacos=E6=B3=A8=E5=86=8C=E4=B8=AD=E5=BF=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/docs/_sidebar.md | 55 ++++----- doc/docs/files/10106_nacos注册中心.md | 113 ++++++++++++++++++ sop-admin/sop-admin-server/pom.xml | 22 ++-- .../adminserver/api/service/ServiceApi.java | 21 ++-- .../api/service/result/ServiceInstanceVO.java | 10 ++ .../adminserver/config/RegistryConfig.java | 12 ++ .../src/main/resources/application-dev.yml | 14 ++- sop-common/pom.xml | 3 +- sop-common/readme.md | 3 + sop-common/sop-gateway-common/readme.md | 2 +- sop-common/sop-registry-api/pom.xml | 74 ++++++++++++ sop-common/sop-registry-api/readme.md | 3 + .../registryapi}/bean/EurekaApplication.java | 2 +- .../registryapi}/bean/EurekaApplications.java | 2 +- .../sop/registryapi}/bean/EurekaApps.java | 2 +- .../sop/registryapi}/bean/EurekaInstance.java | 2 +- .../sop/registryapi}/bean/EurekaUri.java | 27 +++-- .../sop/registryapi}/bean/ServiceInfo.java | 13 +- .../registryapi}/bean/ServiceInstance.java | 14 ++- .../config/BaseRegistryConfig.java | 36 ++++++ .../registryapi/service/RegistryService.java | 8 +- .../service/impl/RegistryServiceEureka.java | 58 ++++----- .../service/impl/RegistryServiceNacos.java | 106 ++++++++++++++++ sop-example/sop-book/sop-book-web/pom.xml | 18 +++ .../sop/bookweb/controller/ApiResult.java | 2 - .../src/main/resources/application-dev.yml | 16 ++- sop-example/sop-story/sop-story-web/pom.xml | 16 +++ .../storyweb/controller/AlipayController.java | 2 +- .../src/main/resources/application-dev.yml | 17 +-- sop-gateway/pom.xml | 14 +++ .../src/main/resources/application-dev.yml | 17 +-- .../java/com/gitee/sop/LoadBalanceTest.java | 64 ++++++++++ sop-website/website-server/pom.xml | 7 ++ .../websiteserver/config/RegistryConfig.java | 12 ++ .../controller/SandboxController.java | 13 +- .../websiteserver/manager/DocManagerImpl.java | 89 +++----------- .../src/main/resources/application-dev.yml | 12 +- 37 files changed, 676 insertions(+), 225 deletions(-) create mode 100644 doc/docs/files/10106_nacos注册中心.md create mode 100644 sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/RegistryConfig.java create mode 100644 sop-common/sop-registry-api/pom.xml create mode 100644 sop-common/sop-registry-api/readme.md rename {sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver => sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi}/bean/EurekaApplication.java (81%) rename {sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver => sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi}/bean/EurekaApplications.java (80%) rename {sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver => sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi}/bean/EurekaApps.java (76%) rename {sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver => sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi}/bean/EurekaInstance.java (93%) rename {sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver => sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi}/bean/EurekaUri.java (64%) rename {sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver => sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi}/bean/ServiceInfo.java (52%) rename {sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver => sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi}/bean/ServiceInstance.java (56%) create mode 100644 sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/config/BaseRegistryConfig.java rename sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java => sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java (76%) rename sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java => sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java (61%) create mode 100644 sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java create mode 100644 sop-test/src/test/java/com/gitee/sop/LoadBalanceTest.java create mode 100644 sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/RegistryConfig.java diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index c18e4b3a..63118b5d 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,29 +1,30 @@ -* [首页](/?t=1561689549009) +* [首页](/?t=1561970396914) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1561689549011) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561689549027) - * [新增接口](files/10020_新增接口.md?t=1561689549027) - * [业务参数校验](files/10030_业务参数校验.md?t=1561689549028) - * [错误处理](files/10040_错误处理.md?t=1561689549028) - * [编写文档](files/10041_编写文档.md?t=1561689549028) - * [接口交互详解](files/10050_接口交互详解.md?t=1561689549028) - * [easyopen支持](files/10070_easyopen支持.md?t=1561689549028) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561689549028) - * [ISV管理](files/10085_ISV管理.md?t=1561689549028) - * [自定义路由](files/10086_自定义路由.md?t=1561689549028) - * [路由授权](files/10090_路由授权.md?t=1561689549028) - * [接口限流](files/10092_接口限流.md?t=1561689549029) - * [监控日志](files/10093_监控日志.md?t=1561689549029) - * [SDK开发](files/10095_SDK开发.md?t=1561689549029) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561689549029) - * [应用授权](files/10097_应用授权.md?t=1561689549029) - * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561689549029) - * [对接前端](files/10100_对接前端.md?t=1561689549029) - * [自定义过滤器](files/10102_自定义过滤器.md?t=1561689549029) - * [文件上传](files/10104_文件上传.md?t=1561689549029) + * [快速体验](files/10010_快速体验.md?t=1561970396914) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561970396931) + * [新增接口](files/10020_新增接口.md?t=1561970396931) + * [业务参数校验](files/10030_业务参数校验.md?t=1561970396931) + * [错误处理](files/10040_错误处理.md?t=1561970396931) + * [编写文档](files/10041_编写文档.md?t=1561970396931) + * [接口交互详解](files/10050_接口交互详解.md?t=1561970396931) + * [easyopen支持](files/10070_easyopen支持.md?t=1561970396932) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561970396932) + * [ISV管理](files/10085_ISV管理.md?t=1561970396932) + * [自定义路由](files/10086_自定义路由.md?t=1561970396932) + * [路由授权](files/10090_路由授权.md?t=1561970396932) + * [接口限流](files/10092_接口限流.md?t=1561970396932) + * [监控日志](files/10093_监控日志.md?t=1561970396932) + * [SDK开发](files/10095_SDK开发.md?t=1561970396932) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561970396932) + * [应用授权](files/10097_应用授权.md?t=1561970396932) + * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561970396932) + * [对接前端](files/10100_对接前端.md?t=1561970396933) + * [自定义过滤器](files/10102_自定义过滤器.md?t=1561970396933) + * [文件上传](files/10104_文件上传.md?t=1561970396933) + * [nacos注册中心](files/10106_nacos注册中心.md?t=1561970396933) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561689549029) - * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561689549030) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561689549030) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561689549030) - * [常见问题](files/90100_常见问题.md?t=1561689549030) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561970396933) + * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561970396933) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561970396933) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561970396933) + * [常见问题](files/90100_常见问题.md?t=1561970396933) diff --git a/doc/docs/files/10106_nacos注册中心.md b/doc/docs/files/10106_nacos注册中心.md new file mode 100644 index 00000000..a06a4f5a --- /dev/null +++ b/doc/docs/files/10106_nacos注册中心.md @@ -0,0 +1,113 @@ +# nacos注册中心 + +完整代码在`registry-nacos`分支 + +SOP默认使用eureka注册中心,如果要换成nacos注册中心,步骤如下: + +- 实现`com.gitee.sop.registryapi.service.RegistryService`接口 + +1.找到`SOP/sop-common/sop-registry-api`工程,在service.impl包下新建一个类,实现RegistryService接口 + +```java +public class RegistryServiceNacos implements RegistryService { + + @Override + public List listAllService(int pageNo, int pageSize) throws Exception { + // TODO: 返回服务实例 + } + + @Override + public void onlineInstance(ServiceInstance serviceInstance) throws Exception { + // TODO: 实例上线 + } + + @Override + public void offlineInstance(ServiceInstance serviceInstance) throws Exception { + // TODO: 实例下线 + } +} +``` + +2.在`com.gitee.sop.registryapi.config.BaseRegistryConfig`中新增 + +```java +/** + * 当配置了registry.name=nacos生效 + * + * @return + */ +@Bean +@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos") +RegistryService registryServiceNacos() { + return new RegistryServiceNacos(); +} +``` + +其中`@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos")` +表示`application.properties`配置了`registry.name=nacos`参数才能生效,registry.name=nacos下文会讲到。 + + +- 微服务端修改 + +1.修改微服务应用pom.xml,注释eureka服务发现依赖,添加nacos服务发现依赖 + +```xml + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + 0.2.2.RELEASE + + +``` + +2.yml文件新增nacos配置,并注释掉eureka相关配置 + +```yaml +spring: + cloud: + # nacos注册中心,和eureka只能用一个 + nacos: + discovery: + server-addr: 127.0.0.1:8848 +``` + +- 网关修改 + +找到`sop-gateway`工程,步骤同上 + +- SOP-admin修改 + + +修改yml文件,新增nacos服务器地址,`registry.name`填nacos + +```yaml +# 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 +registry: + # 使用哪个配置中心,使用eureka,填eureka;使用nacos填nacos + name: nacos + eureka-server-addr: http://localhost:1111/eureka/ + nacos-server-addr: 127.0.0.1:8848 +``` + +- website-server修改 + +步骤同`SOP-admin修改` + +如果要改成consul注册中心,可参照以上步骤。 + +- 参考资料 + +1.[nacos介绍及安装](https://nacos.io/zh-cn/docs/quick-start.html) +2.[nacos spring cloud注册发现](https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html) diff --git a/sop-admin/sop-admin-server/pom.xml b/sop-admin/sop-admin-server/pom.xml index 6ddcf87f..97c43720 100644 --- a/sop-admin/sop-admin-server/pom.xml +++ b/sop-admin/sop-admin-server/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 2.0.3.RELEASE + 2.1.4.RELEASE @@ -27,12 +27,12 @@ - + sop-registry-api + 1.11.0-SNAPSHOT + + net.oschina.durcframework @@ -78,12 +78,6 @@ - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - - org.springframework.boot spring-boot-starter-web @@ -109,6 +103,12 @@ 1.18.4 provided + + org.springframework.cloud + spring-cloud-commons + 2.1.0.RELEASE + compile + diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java index cdf2ba86..05f6c147 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/ServiceApi.java @@ -10,22 +10,21 @@ import com.gitee.sop.adminserver.api.service.param.ServiceSearchParam; import com.gitee.sop.adminserver.api.service.result.RouteServiceInfo; import com.gitee.sop.adminserver.api.service.result.ServiceInfoVo; import com.gitee.sop.adminserver.api.service.result.ServiceInstanceVO; -import com.gitee.sop.adminserver.bean.ServiceInfo; -import com.gitee.sop.adminserver.bean.ServiceInstance; import com.gitee.sop.adminserver.bean.ServiceRouteInfo; import com.gitee.sop.adminserver.bean.ZookeeperContext; import com.gitee.sop.adminserver.common.BizException; import com.gitee.sop.adminserver.common.ZookeeperPathExistException; import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException; -import com.gitee.sop.adminserver.service.RegistrationService; -import com.gitee.sop.adminserver.service.impl.RegistrationServiceEureka; +import com.gitee.sop.registryapi.bean.ServiceInfo; +import com.gitee.sop.registryapi.bean.ServiceInstance; +import com.gitee.sop.registryapi.service.RegistryService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.apache.curator.framework.recipes.cache.ChildData; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; -import javax.annotation.Resource; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -42,8 +41,8 @@ import java.util.stream.Collectors; @Slf4j public class ServiceApi { - @Resource(type = RegistrationServiceEureka.class) - private RegistrationService registrationService; + @Autowired + private RegistryService registryService; @Api(name = "zookeeper.service.list") @ApiDocMethod(description = "zk中的服务列表", elementClass = RouteServiceInfo.class) @@ -113,10 +112,10 @@ public class ServiceApi { @Api(name = "service.instance.list") @ApiDocMethod(description = "获取注册中心的服务列表", elementClass = ServiceInfoVo.class) - List listService(ServiceSearchParam param) { + List listService(ServiceSearchParam param) { List serviceInfos; try { - serviceInfos = registrationService.listAllService(1, 99999/* 获取所有实例 */); + serviceInfos = registryService.listAllService(1, 99999/* 获取所有实例 */); } catch (Exception e) { log.error("获取服务实例失败", e); return Collections.emptyList(); @@ -156,7 +155,7 @@ public class ServiceApi { @ApiDocMethod(description = "服务下线") void serviceOffline(ServiceInstance param) { try { - registrationService.offlineInstance(param); + registryService.offlineInstance(param); } catch (Exception e) { log.error("下线失败,param:{}", param, e); throw new BizException("下线失败,请查看日志"); @@ -167,7 +166,7 @@ public class ServiceApi { @ApiDocMethod(description = "服务上线") void serviceOnline(ServiceInstance param) throws IOException { try { - registrationService.onlineInstance(param); + registryService.onlineInstance(param); } catch (Exception e) { log.error("上线失败,param:{}", param, e); throw new BizException("上线失败,请查看日志"); diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java index 86656dd3..e7280367 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/result/ServiceInstanceVO.java @@ -24,6 +24,12 @@ public class ServiceInstanceVO { @ApiDocField(description = "ipPort") private String ipPort; + @ApiDocField(description = "ip") + private String ip; + + @ApiDocField(description = "port") + private int port; + @ApiDocField(description = "status,服务状态,UP:已上线,OUT_OF_SERVICE:已下线") private String status; @@ -41,4 +47,8 @@ public class ServiceInstanceVO { return new Date(Long.valueOf(lastUpdatedTimestamp)); } + public String getIpPort() { + return ip != null && port > 0 ? ip + ":" + port : ""; + } + } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/RegistryConfig.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/RegistryConfig.java new file mode 100644 index 00000000..57b9e819 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/RegistryConfig.java @@ -0,0 +1,12 @@ +package com.gitee.sop.adminserver.config; + +import com.gitee.sop.registryapi.config.BaseRegistryConfig; +import org.springframework.context.annotation.Configuration; + +/** + * @author tanghc + */ +@Configuration +public class RegistryConfig extends BaseRegistryConfig { + +} diff --git a/sop-admin/sop-admin-server/src/main/resources/application-dev.yml b/sop-admin/sop-admin-server/src/main/resources/application-dev.yml index bd7864c9..af585325 100644 --- a/sop-admin/sop-admin-server/src/main/resources/application-dev.yml +++ b/sop-admin/sop-admin-server/src/main/resources/application-dev.yml @@ -12,6 +12,8 @@ spring: name: sop-admin cloud: + + # zookeeper地址,根据实际情况修改 zookeeper: connect-string: localhost:2181 baseSleepTimeMs: 3000 @@ -31,12 +33,12 @@ easyopen: ignore-validate: true # 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 -eureka: - port: 1111 - host: localhost - client: - serviceUrl: - defaultZone: http://${eureka.host}:${eureka.port}/eureka/ +registry: + eureka-server-addr: http://localhost:1111/eureka/ + nacos-server-addr: 127.0.0.1:8848 + # 使用哪个配置中心,使用eureka,填eureka;使用nacos填nacos + name: nacos + # 根据实际情况改 logging: diff --git a/sop-common/pom.xml b/sop-common/pom.xml index a906e604..3a5a7675 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -37,7 +37,8 @@ sop-gateway-common sop-service-common - + sop-registry-api + diff --git a/sop-common/readme.md b/sop-common/readme.md index 2db2642a..293c40bc 100644 --- a/sop-common/readme.md +++ b/sop-common/readme.md @@ -1,8 +1,11 @@ # sop-common - sop-gateway-common:提供给网关使用 +- sop-registry-api:注册中心API - sop-service-common:提供给微服务端使用,需要打成jar +正式开发请将这些模块上传的maven私服 + - 打包成jar:`mvn clean package` - 上传到本机仓库:`mvn clean install` - 上传到maven私服:`mvn clean deploy` \ No newline at end of file diff --git a/sop-common/sop-gateway-common/readme.md b/sop-common/sop-gateway-common/readme.md index 05c58128..3bcf9b86 100644 --- a/sop-common/sop-gateway-common/readme.md +++ b/sop-common/sop-gateway-common/readme.md @@ -1,3 +1,3 @@ # sop-gateway-common -zuul通用组件,主要封装网关的一些功能。 +网关通用组件,主要封装网关的一些功能。 diff --git a/sop-common/sop-registry-api/pom.xml b/sop-common/sop-registry-api/pom.xml new file mode 100644 index 00000000..3a46bfea --- /dev/null +++ b/sop-common/sop-registry-api/pom.xml @@ -0,0 +1,74 @@ + + + + 4.0.0 + com.gitee.sop + sop-registry-api + 1.11.0-SNAPSHOT + + + UTF-8 + UTF-8 + 1.8 + 3.11.0 + + + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + + + + + com.alibaba.nacos + nacos-client + 1.0.1 + + + + org.springframework + spring-context + 5.1.6.RELEASE + true + + + org.projectlombok + lombok + 1.18.6 + true + + + org.springframework.boot + spring-boot-autoconfigure + 2.1.4.RELEASE + true + + + + junit + junit + 4.11 + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + UTF-8 + + + + + + diff --git a/sop-common/sop-registry-api/readme.md b/sop-common/sop-registry-api/readme.md new file mode 100644 index 00000000..8c55f465 --- /dev/null +++ b/sop-common/sop-registry-api/readme.md @@ -0,0 +1,3 @@ +# sop-registry-api + +统一各注册中心接口 \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplication.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplication.java similarity index 81% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplication.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplication.java index 91d73122..21fdcb3d 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplication.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplication.java @@ -1,4 +1,4 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplications.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplications.java similarity index 80% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplications.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplications.java index 7dc08e21..7baa0fbf 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApplications.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApplications.java @@ -1,4 +1,4 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApps.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApps.java similarity index 76% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApps.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApps.java index f52440d2..653e7e64 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaApps.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaApps.java @@ -1,4 +1,4 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaInstance.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaInstance.java similarity index 93% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaInstance.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaInstance.java index acc37d9c..60cddf34 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaInstance.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaInstance.java @@ -1,4 +1,4 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; import org.springframework.util.CollectionUtils; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaUri.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java similarity index 64% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaUri.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java index 5f70f86b..1d7b39e8 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/EurekaUri.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java @@ -1,11 +1,9 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import okhttp3.MediaType; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.internal.http.HttpMethod; -import org.apache.commons.lang.ArrayUtils; -import org.springframework.web.bind.annotation.RequestMethod; /** * https://github.com/Netflix/eureka/wiki/Eureka-REST-operations @@ -17,22 +15,22 @@ public enum EurekaUri { /** * 查询所有实例 Query for all instances */ - QUERY_APPS(RequestMethod.GET, "/apps"), + QUERY_APPS("GET", "/apps"), /** * 下线 Take instance out of service */ - OFFLINE_SERVICE(RequestMethod.PUT, "/apps/%s/%s/status?value=OUT_OF_SERVICE"), + OFFLINE_SERVICE("PUT", "/apps/%s/%s/status?value=OUT_OF_SERVICE"), /** * 上线 Move instance back into service (remove override) */ - ONLINE_SERVICE(RequestMethod.DELETE, "/apps/%s/%s/status?value=UP"), + ONLINE_SERVICE("DELETE", "/apps/%s/%s/status?value=UP"), ; public static final String URL_PREFIX = "/"; String uri; - RequestMethod requestMethod; + String requestMethod; - EurekaUri(RequestMethod httpMethod, String uri) { + EurekaUri(String httpMethod, String uri) { if (!uri.startsWith(URL_PREFIX)) { uri = "/" + uri; } @@ -41,10 +39,13 @@ public enum EurekaUri { } public String getUri(String... args) { - if (ArrayUtils.isEmpty(args)) { + if (args == null || args.length == 0) { return uri; } - Object[] param = ArrayUtils.clone(args); + Object[] param = new Object[args.length]; + for (int i = 0; i < args.length; i++) { + param[i] = args[i]; + } return String.format(uri, param); } @@ -59,12 +60,12 @@ public enum EurekaUri { } public Request.Builder getBuilder() { - String method = requestMethod.name(); + String method = requestMethod; RequestBody requestBody = null; if (HttpMethod.requiresRequestBody(method)) { - MediaType contentType = MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE); + MediaType contentType = MediaType.parse("application/json"); requestBody = RequestBody.create(contentType, "{}"); } - return new Request.Builder().method(requestMethod.name(), requestBody); + return new Request.Builder().method(requestMethod, requestBody); } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInfo.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInfo.java similarity index 52% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInfo.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInfo.java index 5344a601..2d19dd58 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInfo.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInfo.java @@ -1,6 +1,7 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import java.util.Collections; import java.util.List; @@ -8,10 +9,16 @@ import java.util.List; /** * @author tanghc */ -@Data +@Getter +@Setter public class ServiceInfo { /** 服务名称 */ private String serviceId; /** 实例列表 */ private List instances = Collections.emptyList(); + + @Override + public String toString() { + return "服务名称: " + serviceId + ", 实例数:" + instances.size(); + } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInstance.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInstance.java similarity index 56% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInstance.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInstance.java index 42e8f865..9017dbaa 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ServiceInstance.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/ServiceInstance.java @@ -1,4 +1,4 @@ -package com.gitee.sop.adminserver.bean; +package com.gitee.sop.registryapi.bean; import lombok.Data; @@ -15,12 +15,18 @@ public class ServiceInstance { private String serviceId; /** - * IP 端口 + * ip */ - private String ipPort; + private String ip; /** - * 状态,1:上线,2:下线 + * port + */ + private int port; + + /** + * 服务状态,UP:已上线,OUT_OF_SERVICE:已下线 */ private String status; + } \ No newline at end of file diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/config/BaseRegistryConfig.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/config/BaseRegistryConfig.java new file mode 100644 index 00000000..047eb03d --- /dev/null +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/config/BaseRegistryConfig.java @@ -0,0 +1,36 @@ +package com.gitee.sop.registryapi.config; + +import com.gitee.sop.registryapi.service.RegistryService; +import com.gitee.sop.registryapi.service.impl.RegistryServiceEureka; +import com.gitee.sop.registryapi.service.impl.RegistryServiceNacos; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; + +/** + * @author tanghc + */ +public class BaseRegistryConfig { + + /** + * 当配置了registry.name=eureka生效 + * + * @return + */ + @Bean + @ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "eureka") + RegistryService registryServiceEureka() { + return new RegistryServiceEureka(); + } + + /** + * 当配置了registry.name=nacos生效 + * + * @return + */ + @Bean + @ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos") + RegistryService registryServiceNacos() { + return new RegistryServiceNacos(); + } + +} diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java similarity index 76% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java index 7aa2aa02..974e724e 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RegistrationService.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/RegistryService.java @@ -1,14 +1,14 @@ -package com.gitee.sop.adminserver.service; +package com.gitee.sop.registryapi.service; -import com.gitee.sop.adminserver.bean.ServiceInfo; -import com.gitee.sop.adminserver.bean.ServiceInstance; +import com.gitee.sop.registryapi.bean.ServiceInfo; +import com.gitee.sop.registryapi.bean.ServiceInstance; import java.util.List; /** * @author tanghc */ -public interface RegistrationService { +public interface RegistryService { /** * 获取所有服务列表 * diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java similarity index 61% rename from sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java rename to sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java index d16ebd2e..64eada4e 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/impl/RegistrationServiceEureka.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceEureka.java @@ -1,45 +1,43 @@ -package com.gitee.sop.adminserver.service.impl; +package com.gitee.sop.registryapi.service.impl; import com.alibaba.fastjson.JSON; -import com.gitee.sop.adminserver.bean.EurekaApplication; -import com.gitee.sop.adminserver.bean.EurekaApps; -import com.gitee.sop.adminserver.bean.EurekaInstance; -import com.gitee.sop.adminserver.bean.EurekaUri; -import com.gitee.sop.adminserver.bean.ServiceInfo; -import com.gitee.sop.adminserver.bean.ServiceInstance; -import com.gitee.sop.adminserver.common.BizException; -import com.gitee.sop.adminserver.service.RegistrationService; +import com.gitee.sop.registryapi.bean.EurekaApplication; +import com.gitee.sop.registryapi.bean.EurekaApps; +import com.gitee.sop.registryapi.bean.EurekaInstance; +import com.gitee.sop.registryapi.bean.EurekaUri; +import com.gitee.sop.registryapi.bean.ServiceInfo; +import com.gitee.sop.registryapi.bean.ServiceInstance; +import com.gitee.sop.registryapi.service.RegistryService; import lombok.extern.slf4j.Slf4j; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.CollectionUtils; -import javax.annotation.PostConstruct; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** + * eureka接口实现 * @author tanghc */ @Slf4j -@Service -public class RegistrationServiceEureka implements RegistrationService { +public class RegistryServiceEureka implements RegistryService { OkHttpClient client = new OkHttpClient(); - @Autowired - private Environment environment; - + @Value("${registry.eureka-server-addr:}") private String eurekaUrl; @Override public List listAllService(int pageNo, int pageSize) throws Exception { + if (StringUtils.isBlank(eurekaUrl)) { + return Collections.emptyList(); + } String json = this.requestEurekaServer(EurekaUri.QUERY_APPS); EurekaApps eurekaApps = JSON.parseObject(json, EurekaApps.class); @@ -49,13 +47,14 @@ public class RegistrationServiceEureka implements RegistrationService { ServiceInfo serviceInfo = new ServiceInfo(); serviceInfo.setServiceId(eurekaApplication.getName()); List instanceList = eurekaApplication.getInstance(); - if (CollectionUtils.isNotEmpty(instanceList)) { + if (!CollectionUtils.isEmpty(instanceList)) { serviceInfo.setInstances(new ArrayList<>(instanceList.size())); for (EurekaInstance eurekaInstance : instanceList) { ServiceInstance serviceInstance = new ServiceInstance(); serviceInstance.setInstanceId(eurekaInstance.getInstanceId()); serviceInstance.setServiceId(serviceInfo.getServiceId()); - serviceInstance.setIpPort(eurekaInstance.getIpAddr() + ":" + eurekaInstance.fetchPort()); + serviceInstance.setIp(eurekaInstance.getIpAddr()); + serviceInstance.setPort(Integer.valueOf(eurekaInstance.fetchPort())); serviceInstance.setStatus(eurekaInstance.getStatus()); serviceInfo.getInstances().add(serviceInstance); } @@ -84,21 +83,8 @@ public class RegistrationServiceEureka implements RegistrationService { return response.body().string(); } else { log.error("操作失败,url:{}, msg:{}, code:{}", eurekaUri.getUri(args), response.message(), response.code()); - throw new BizException("操作失败", String.valueOf(response.code())); + throw new RuntimeException("操作失败"); } } - @PostConstruct - protected void after() { - String eurekaUrls = environment.getProperty("eureka.client.serviceUrl.defaultZone"); - if (StringUtils.isBlank(eurekaUrls)) { - throw new BizException("未指定eureka.client.serviceUrl.defaultZone参数"); - } - // 取第一个 - String url = eurekaUrls.split("\\,")[0]; - if (url.endsWith("/")) { - url = eurekaUrls.substring(0, eurekaUrls.length() - 1); - } - this.eurekaUrl = url; - } } diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java new file mode 100644 index 00000000..4d72b98b --- /dev/null +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java @@ -0,0 +1,106 @@ +package com.gitee.sop.registryapi.service.impl; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.naming.NamingFactory; +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.api.naming.pojo.Instance; +import com.alibaba.nacos.api.naming.pojo.ListView; +import com.gitee.sop.registryapi.bean.ServiceInfo; +import com.gitee.sop.registryapi.bean.ServiceInstance; +import com.gitee.sop.registryapi.service.RegistryService; +import okhttp3.FormBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.CollectionUtils; + +import javax.annotation.PostConstruct; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * nacos接口实现 + * @author tanghc + */ +public class RegistryServiceNacos implements RegistryService { + + OkHttpClient client = new OkHttpClient(); + + @Value("${registry.nacos-server-addr:}") + private String nacosAddr; + + private NamingService namingService; + + @PostConstruct + public void after() throws NacosException { + if (StringUtils.isNotBlank(nacosAddr)) { + namingService = NamingFactory.createNamingService(nacosAddr); + } + } + + @Override + public List listAllService(int pageNo, int pageSize) throws Exception { + ListView servicesOfServer = namingService.getServicesOfServer(pageNo, pageSize); + List serverList = servicesOfServer.getData(); + List serviceInfoList = new ArrayList<>(); + for (String serviceName : serverList) { + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.setServiceId(serviceName); + List instanceList = namingService.getAllInstances(serviceName); + if (!CollectionUtils.isEmpty(instanceList)) { + serviceInfo.setInstances(new ArrayList<>(instanceList.size())); + for (Instance instance : instanceList) { + ServiceInstance serviceInstance = new ServiceInstance(); + serviceInstance.setInstanceId(instance.getInstanceId()); + serviceInstance.setServiceId(serviceInfo.getServiceId()); + serviceInstance.setIp(instance.getIp()); + serviceInstance.setPort(instance.getPort()); + boolean isOnline = instance.getWeight() > 0; + String status = isOnline ? "UP" : "OUT_OF_SERVICE"; + serviceInstance.setStatus(status); + serviceInfo.getInstances().add(serviceInstance); + } + } + serviceInfoList.add(serviceInfo); + } + return serviceInfoList; + } + + @Override + public void onlineInstance(ServiceInstance serviceInstance) throws Exception { + Map params = new HashMap<>(); + // 上线,把权重设置成1 + params.put("weight", "1"); + this.updateInstance(serviceInstance, params); + } + + @Override + public void offlineInstance(ServiceInstance serviceInstance) throws Exception { + Map params = new HashMap<>(); + // 下线,把权重设置成0 + params.put("weight", "0"); + this.updateInstance(serviceInstance, params); + } + + private Response updateInstance(ServiceInstance serviceInstance, Map params) throws IOException { + FormBody.Builder builder = new FormBody.Builder(); + for (Map.Entry entry : params.entrySet()) { + builder.add(entry.getKey(), String.valueOf(entry.getValue())); + } + builder.add("serviceName", serviceInstance.getServiceId()) + .add("ip", serviceInstance.getIp()) + .add("port", String.valueOf(serviceInstance.getPort())); + FormBody formBody = builder.build(); + final Request request = new Request.Builder() + .url("http://" + nacosAddr + "/nacos/v1/ns/instance") + .put(formBody) + .build(); + + return client.newCall(request).execute(); + } +} diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml index 8e1e2e1b..60606be9 100644 --- a/sop-example/sop-book/sop-book-web/pom.xml +++ b/sop-example/sop-book/sop-book-web/pom.xml @@ -36,10 +36,28 @@ sop-story-api 1.0-SNAPSHOT + + + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + 0.2.2.RELEASE + + + + org.springframework.cloud spring-cloud-starter-openfeign diff --git a/sop-example/sop-book/sop-book-web/src/main/java/com/gitee/sop/bookweb/controller/ApiResult.java b/sop-example/sop-book/sop-book-web/src/main/java/com/gitee/sop/bookweb/controller/ApiResult.java index a39434b8..a102dfa8 100644 --- a/sop-example/sop-book/sop-book-web/src/main/java/com/gitee/sop/bookweb/controller/ApiResult.java +++ b/sop-example/sop-book/sop-book-web/src/main/java/com/gitee/sop/bookweb/controller/ApiResult.java @@ -1,6 +1,5 @@ package com.gitee.sop.bookweb.controller; -import com.thoughtworks.xstream.annotations.XStreamAlias; import lombok.Data; /** @@ -48,7 +47,6 @@ import lombok.Data; * * @author tanghc */ -@XStreamAlias("response") @Data public class ApiResult { diff --git a/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml b/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml index edb92dec..4f39516a 100644 --- a/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml +++ b/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml @@ -10,12 +10,16 @@ spring: # zookeeper配置 connect-string: localhost:2181 -eureka: - port: 1111 - host: localhost - client: - serviceUrl: - defaultZone: http://${eureka.host}:${eureka.port}/eureka/ + # nacos注册中心,和eureka只能用一个 + nacos: + discovery: + server-addr: 127.0.0.1:8848 + +# eureka注册中心,如果使用nacos注册中心,这里要注释掉 +#eureka: +# client: +# serviceUrl: +# defaultZone: http://localhost:1111/eureka/ # dubbo consumer demo: diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index ce13c01c..003081e0 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -31,10 +31,26 @@ sop-story-api 1.0-SNAPSHOT + + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + 0.2.2.RELEASE + + + org.springframework.cloud spring-cloud-starter-openfeign diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java index ae690ad4..083cdc50 100644 --- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java @@ -87,7 +87,7 @@ public class AlipayController { public Story getStory() { Story story = new Story(); story.setId(1); - story.setName("海底小纵队(alipay.story.get)"); + story.setName("海底小纵队(alipay.story.get),2222"); return story; } diff --git a/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml b/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml index 3a06f369..62354b7a 100644 --- a/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml +++ b/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml @@ -10,13 +10,16 @@ spring: zookeeper: connect-string: localhost:2181 -# 注册中心 -eureka: - port: 1111 - host: localhost - client: - serviceUrl: - defaultZone: http://${eureka.host}:${eureka.port}/eureka/ + # nacos注册中心,和eureka只能用一个 + nacos: + discovery: + server-addr: 127.0.0.1:8848 + +# eureka注册中心,如果使用nacos注册中心,这里要注释掉 +#eureka: +# client: +# serviceUrl: +# defaultZone: http://localhost:1111/eureka/ # dubbo provider dubbo: diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index 04d45bef..78edce77 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -65,10 +65,24 @@ runtime + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + 0.2.2.RELEASE + + diff --git a/sop-gateway/src/main/resources/application-dev.yml b/sop-gateway/src/main/resources/application-dev.yml index 02b73a56..c025fd63 100644 --- a/sop-gateway/src/main/resources/application-dev.yml +++ b/sop-gateway/src/main/resources/application-dev.yml @@ -19,13 +19,6 @@ ribbon: # 请谨慎设置,因为post请求大多都是写入请求,如果要支持重试,确保服务的幂等性 OkToRetryOnAllOperations: false -# 注册中心,根据实际情况修改 -eureka: - serverAddr: localhost:1111 - client: - serviceUrl: - defaultZone: http://${eureka.serverAddr}/eureka/ - spring: application: name: api-gateway @@ -41,6 +34,16 @@ spring: lower-case-service-id: true enabled: true + # nacos注册中心,和eureka只能用一个 + nacos: + discovery: + server-addr: 127.0.0.1:8848 + +# eureka注册中心,如果使用nacos注册中心,这里要注释掉 +#eureka: +# client: +# serviceUrl: +# defaultZone: http://localhost:1111/eureka/ # 数据源,根据实际情况修改 datasource: diff --git a/sop-test/src/test/java/com/gitee/sop/LoadBalanceTest.java b/sop-test/src/test/java/com/gitee/sop/LoadBalanceTest.java new file mode 100644 index 00000000..f9bbaa3b --- /dev/null +++ b/sop-test/src/test/java/com/gitee/sop/LoadBalanceTest.java @@ -0,0 +1,64 @@ +package com.gitee.sop; + +import com.alibaba.fastjson.JSON; +import com.gitee.sop.alipay.AlipayApiException; +import com.gitee.sop.alipay.AlipaySignature; +import org.junit.Test; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +public class LoadBalanceTest extends TestBase { + + String url = "http://localhost:8081/api"; // zuul + String appId = "2019032617262200001"; + // 支付宝私钥 + String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJv1pQFqWNA/++OYEV7WYXwexZK/J8LY1OWlP9X0T6wHFOvxNKRvMkJ5544SbgsJpVcvRDPrcxmhPbi/sAhdO4x2PiPKIz9Yni2OtYCCeaiE056B+e1O2jXoLeXbfi9fPivJZkxH/tb4xfLkH3bA8ZAQnQsoXA0SguykMRZntF0TndUfvDrLqwhlR8r5iRdZLB6F8o8qXH6UPDfNEnf/K8wX5T4EB1b8x8QJ7Ua4GcIUqeUxGHdQpzNbJdaQvoi06lgccmL+PHzminkFYON7alj1CjDN833j7QMHdPtS9l7B67fOU/p2LAAkPMtoVBfxQt9aFj7B8rEhGCz02iJIBAgMBAAECggEARqOuIpY0v6WtJBfmR3lGIOOokLrhfJrGTLF8CiZMQha+SRJ7/wOLPlsH9SbjPlopyViTXCuYwbzn2tdABigkBHYXxpDV6CJZjzmRZ+FY3S/0POlTFElGojYUJ3CooWiVfyUMhdg5vSuOq0oCny53woFrf32zPHYGiKdvU5Djku1onbDU0Lw8w+5tguuEZ76kZ/lUcccGy5978FFmYpzY/65RHCpvLiLqYyWTtaNT1aQ/9pw4jX9HO9NfdJ9gYFK8r/2f36ZE4hxluAfeOXQfRC/WhPmiw/ReUhxPznG/WgKaa/OaRtAx3inbQ+JuCND7uuKeRe4osP2jLPHPP6AUwQKBgQDUNu3BkLoKaimjGOjCTAwtp71g1oo+k5/uEInAo7lyEwpV0EuUMwLA/HCqUgR4K9pyYV+Oyb8d6f0+Hz0BMD92I2pqlXrD7xV2WzDvyXM3s63NvorRooKcyfd9i6ccMjAyTR2qfLkxv0hlbBbsPHz4BbU63xhTJp3Ghi0/ey/1HQKBgQC2VsgqC6ykfSidZUNLmQZe3J0p/Qf9VLkfrQ+xaHapOs6AzDU2H2osuysqXTLJHsGfrwVaTs00ER2z8ljTJPBUtNtOLrwNRlvgdnzyVAKHfOgDBGwJgiwpeE9voB1oAV/mXqSaUWNnuwlOIhvQEBwekqNyWvhLqC7nCAIhj3yvNQKBgQCqYbeec56LAhWP903Zwcj9VvG7sESqXUhIkUqoOkuIBTWFFIm54QLTA1tJxDQGb98heoCIWf5x/A3xNI98RsqNBX5JON6qNWjb7/dobitti3t99v/ptDp9u8JTMC7penoryLKK0Ty3bkan95Kn9SC42YxaSghzqkt+uvfVQgiNGQKBgGxU6P2aDAt6VNwWosHSe+d2WWXt8IZBhO9d6dn0f7ORvcjmCqNKTNGgrkewMZEuVcliueJquR47IROdY8qmwqcBAN7Vg2K7r7CPlTKAWTRYMJxCT1Hi5gwJb+CZF3+IeYqsJk2NF2s0w5WJTE70k1BSvQsfIzAIDz2yE1oPHvwVAoGAA6e+xQkVH4fMEph55RJIZ5goI4Y76BSvt2N5OKZKd4HtaV+eIhM3SDsVYRLIm9ZquJHMiZQGyUGnsvrKL6AAVNK7eQZCRDk9KQz+0GKOGqku0nOZjUbAu6A2/vtXAaAuFSFx1rUQVVjFulLexkXR3KcztL1Qu2k5pB6Si0K/uwQ="; + + // 测试稳定性 + @Test + public void testLoadBalance() throws Exception { + int i = 0; + while (i++ < 50) { + doTest(); + Thread.sleep(3000); + } + } + + private void doTest() throws AlipayApiException { + // 公共请求参数 + Map params = new HashMap(); + params.put("app_id", appId); + params.put("method", "alipay.story.get"); + params.put("format", "json"); + params.put("charset", "utf-8"); + params.put("sign_type", "RSA2"); + params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + params.put("version", "1.0"); + + // 业务参数 + Map bizContent = new HashMap<>(); + bizContent.put("id", "1"); + bizContent.put("name", "葫芦娃"); + + params.put("biz_content", JSON.toJSONString(bizContent)); + +// System.out.println("----------- 请求信息 -----------"); +// System.out.println("请求参数:" + buildParamQuery(params)); +// System.out.println("商户秘钥:" + privateKey); + String content = AlipaySignature.getSignContent(params); +// System.out.println("待签名内容:" + content); + String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8"); +// System.out.println("签名(sign):" + sign); + + params.put("sign", sign); + +// System.out.println("----------- 返回结果 -----------"); + String responseData = get(url, params);// 发送请求 + System.out.println(responseData); + } + +} diff --git a/sop-website/website-server/pom.xml b/sop-website/website-server/pom.xml index b181b624..30464050 100644 --- a/sop-website/website-server/pom.xml +++ b/sop-website/website-server/pom.xml @@ -21,6 +21,13 @@ + + + com.gitee.sop + sop-registry-api + 1.11.0-SNAPSHOT + + org.springframework.boot spring-boot-starter-web diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/RegistryConfig.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/RegistryConfig.java new file mode 100644 index 00000000..1721a2d1 --- /dev/null +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/config/RegistryConfig.java @@ -0,0 +1,12 @@ +package com.gitee.sop.websiteserver.config; + +import com.gitee.sop.registryapi.config.BaseRegistryConfig; +import org.springframework.context.annotation.Configuration; + +/** + * @author tanghc + */ +@Configuration +public class RegistryConfig extends BaseRegistryConfig { + +} \ No newline at end of file diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java index 97c8b0bb..2d22ab6d 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java @@ -3,6 +3,7 @@ package com.gitee.sop.websiteserver.controller; import com.gitee.sop.websiteserver.sign.AlipayApiException; import com.gitee.sop.websiteserver.sign.AlipaySignature; import lombok.Data; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; @@ -30,6 +31,7 @@ import java.util.stream.Collectors; * 沙箱环境代理类 * @author tanghc */ +@Slf4j @RestController @RequestMapping("sandbox") public class SandboxController { @@ -45,8 +47,8 @@ public class SandboxController { , @RequestParam String version , @RequestParam String bizContent) throws AlipayApiException { - Assert.isTrue(StringUtils.isNotBlank(appId), "appId不能为空"); - Assert.isTrue(StringUtils.isNotBlank(privateKey), "privateKey不能为空"); + Assert.isTrue(StringUtils.isNotBlank(appId), "AppId不能为空"); + Assert.isTrue(StringUtils.isNotBlank(privateKey), "PrivateKey不能为空"); Assert.isTrue(StringUtils.isNotBlank(method), "method不能为空"); // 公共请求参数 @@ -69,7 +71,12 @@ public class SandboxController { String content = AlipaySignature.getSignContent(params); result.beforeSign = content; - String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8"); + String sign = null; + try { + sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8"); + } catch (AlipayApiException e) { + throw new RuntimeException("构建签名失败"); + } result.sign = sign; params.put("sign", sign); diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java index 97c8ad2c..fa3adabb 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java @@ -3,19 +3,13 @@ package com.gitee.sop.websiteserver.manager; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; +import com.gitee.sop.registryapi.bean.ServiceInfo; +import com.gitee.sop.registryapi.bean.ServiceInstance; +import com.gitee.sop.registryapi.service.RegistryService; import com.gitee.sop.websiteserver.bean.DocInfo; import com.gitee.sop.websiteserver.bean.DocItem; -import com.gitee.sop.websiteserver.bean.EurekaApplication; -import com.gitee.sop.websiteserver.bean.EurekaApps; -import com.gitee.sop.websiteserver.bean.EurekaInstance; -import com.gitee.sop.websiteserver.bean.EurekaUri; import com.gitee.sop.websiteserver.bean.ZookeeperContext; -import com.gitee.sop.websiteserver.vo.ServiceInfoVO; import lombok.extern.slf4j.Slf4j; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.apache.commons.lang.StringUtils; import org.apache.curator.framework.recipes.cache.TreeCacheEvent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; @@ -26,8 +20,6 @@ import org.springframework.util.DigestUtils; import org.springframework.web.client.RestTemplate; import javax.annotation.PostConstruct; -import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -53,8 +45,6 @@ public class DocManagerImpl implements DocManager { Map docItemMap = new HashMap<>(); - OkHttpClient client = new OkHttpClient(); - RestTemplate restTemplate = new RestTemplate(); DocParser swaggerDocParser = new SwaggerDocParser(); @@ -70,33 +60,35 @@ public class DocManagerImpl implements DocManager { @Autowired private Environment environment; - private String eurekaUrl; + @Autowired + private RegistryService registryService; private volatile boolean listenInited; @Override public void load() { try { - // {"STORY-SERVICE":[{"ipAddr":"10.1.30.54","name":"STORY-SERVICE","serverPort":"2222"}],"API-GATEWAY":[{"ipAddr":"10.1.30.54","name":"API-GATEWAY","serverPort":"8081"}]} - Map> listMap = this.getAllServiceList(); - log.info("服务列表:{}", JSON.toJSONString(listMap.keySet())); - listMap.entrySet() + List serviceInfoList = registryService.listAllService(1, 9999); + log.info("服务列表:{}", serviceInfoList); + + serviceInfoList .stream() // 网关没有文档提供,需要排除 - .filter(entry -> !"API-GATEWAY".equalsIgnoreCase(entry.getKey())) - .forEach(entry -> { - ServiceInfoVO serviceInfoVo = entry.getValue().get(0); - loadDocInfo(serviceInfoVo); - }); + .filter(serviceInfo -> !"API-GATEWAY".equalsIgnoreCase(serviceInfo.getServiceId())) + .filter(serviceInfo -> !serviceInfo.getInstances().isEmpty()) + .map(serviceInfo -> serviceInfo.getInstances().get(0)) + .collect(Collectors.toList()) + .forEach(this::loadDocInfo); } catch (Exception e) { log.error("加载失败", e); } } - protected void loadDocInfo(ServiceInfoVO serviceInfoVo) { + protected void loadDocInfo(ServiceInstance serviceInstance) { String query = this.buildQuery(); - String url = "http://" + serviceInfoVo.getIpAddr() + ":" + serviceInfoVo.getServerPort() + "/v2/api-docs" + query; + String url = "http://" + serviceInstance.getIpPort() + "/v2/api-docs" + query; try { + log.info("读取swagger文档,url:{}", url); ResponseEntity entity = restTemplate.getForEntity(url, String.class); if (entity.getStatusCode() != HttpStatus.OK) { throw new IllegalAccessException("无权访问"); @@ -144,55 +136,8 @@ public class DocManagerImpl implements DocManager { return docDefinitionMap.values(); } - protected Map> getAllServiceList() throws IOException { - String json = this.requestEurekaServer(EurekaUri.QUERY_APPS); - EurekaApps eurekaApps = JSON.parseObject(json, EurekaApps.class); - - List serviceInfoVoList = new ArrayList<>(); - List applicationList = eurekaApps.getApplications().getApplication(); - applicationList.stream() - .forEach(eurekaApplication -> { - List instanceList = eurekaApplication.getInstance(); - for (EurekaInstance instance : instanceList) { - if ("UP".equals(instance.getStatus())) { - ServiceInfoVO vo = new ServiceInfoVO(); - vo.setName(eurekaApplication.getName()); - vo.setIpAddr(instance.getIpAddr()); - vo.setServerPort(instance.fetchPort()); - serviceInfoVoList.add(vo); - } - } - }); - - Map> listMap = serviceInfoVoList.stream() - .collect(Collectors.groupingBy(ServiceInfoVO::getName)); - - return listMap; - } - - protected String requestEurekaServer(EurekaUri eurekaUri, String... args) throws IOException { - Request request = eurekaUri.getRequest(this.eurekaUrl, args); - Response response = client.newCall(request).execute(); - if (response.isSuccessful()) { - return response.body().string(); - } else { - log.error("操作失败,url:{}, msg:{}, code:{}", eurekaUri.getUri(args), response.message(), response.code()); - throw new RuntimeException("操作失败"); - } - } - @PostConstruct protected void after() throws Exception { - String eurekaUrls = environment.getProperty("eureka.client.serviceUrl.defaultZone"); - if (StringUtils.isBlank(eurekaUrls)) { - throw new IllegalArgumentException("未指定eureka.client.serviceUrl.defaultZone参数"); - } - String url = eurekaUrls.split("\\,")[0]; - if (url.endsWith("/")) { - url = eurekaUrls.substring(0, eurekaUrls.length() - 1); - } - this.eurekaUrl = url; - this.listenServiceId(); } diff --git a/sop-website/website-server/src/main/resources/application-dev.yml b/sop-website/website-server/src/main/resources/application-dev.yml index 3ec0b465..d6181365 100644 --- a/sop-website/website-server/src/main/resources/application-dev.yml +++ b/sop-website/website-server/src/main/resources/application-dev.yml @@ -1,12 +1,12 @@ server: port: 8083 -# 注册中心 -eureka: - serverAddr: localhost:1111 - client: - serviceUrl: - defaultZone: http://${eureka.serverAddr}/eureka/ +# 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 +registry: + # 使用哪个配置中心,使用eureka,填eureka;使用nacos填nacos + name: nacos + eureka-server-addr: http://localhost:1111/eureka/ + nacos-server-addr: 127.0.0.1:8848 spring: application: From 1c23d3b32c3deec9e19e929f153f5bd8386ab854 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 1 Jul 2019 16:46:08 +0800 Subject: [PATCH 27/40] update --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2e7afd2b..16037ee1 100644 --- a/README.md +++ b/README.md @@ -45,9 +45,11 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 - 应用授权 - 监控日志 -## 后期规划 +## 分支说明 -- 调试工具 +- develop: 日常开发分支 +- registry-nacos:使用nacos作为注册中心 +- SpringCloudGateway:网关使用spring cloud gateway,仅做体验用,不推荐 ## admin界面预览 From 4bc76f497d83932bb6f8e5ff925d94d64a63ac56 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 1 Jul 2019 17:49:45 +0800 Subject: [PATCH 28/40] update --- .../src/main/resources/application-dev.yml | 2 +- .../gitee/sop/registryapi/bean/EurekaUri.java | 3 +++ sop-example/sop-book/sop-book-web/pom.xml | 7 ++++--- .../src/main/resources/application-dev.yml | 14 +++++++------- sop-example/sop-story/sop-story-web/pom.xml | 7 ++++--- .../src/main/resources/application-dev.yml | 14 +++++++------- sop-gateway/pom.xml | 7 ++++--- .../src/main/resources/application-dev.yml | 18 +++++++++--------- 8 files changed, 39 insertions(+), 33 deletions(-) diff --git a/sop-admin/sop-admin-server/src/main/resources/application-dev.yml b/sop-admin/sop-admin-server/src/main/resources/application-dev.yml index af585325..8bed2221 100644 --- a/sop-admin/sop-admin-server/src/main/resources/application-dev.yml +++ b/sop-admin/sop-admin-server/src/main/resources/application-dev.yml @@ -37,7 +37,7 @@ registry: eureka-server-addr: http://localhost:1111/eureka/ nacos-server-addr: 127.0.0.1:8848 # 使用哪个配置中心,使用eureka,填eureka;使用nacos填nacos - name: nacos + name: eureka # 根据实际情况改 diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java index 1d7b39e8..8a229ca7 100644 --- a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/EurekaUri.java @@ -50,6 +50,9 @@ public enum EurekaUri { } public Request getRequest(String url, String... args) { + if (url.endsWith("/")) { + url = url.substring(0, url.length() - 1); + } String requestUrl = url + getUri(args); Request request = this.getBuilder() .url(requestUrl) diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml index 60606be9..e468ab30 100644 --- a/sop-example/sop-book/sop-book-web/pom.xml +++ b/sop-example/sop-book/sop-book-web/pom.xml @@ -39,22 +39,23 @@ - org.springframework.cloud spring-cloud-starter-netflix-eureka-client - --> + + org.springframework.cloud spring-cloud-starter-alibaba-nacos-discovery 0.2.2.RELEASE + --> diff --git a/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml b/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml index 4f39516a..649fcf39 100644 --- a/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml +++ b/sop-example/sop-book/sop-book-web/src/main/resources/application-dev.yml @@ -11,15 +11,15 @@ spring: connect-string: localhost:2181 # nacos注册中心,和eureka只能用一个 - nacos: - discovery: - server-addr: 127.0.0.1:8848 +# nacos: +# discovery: +# server-addr: 127.0.0.1:8848 # eureka注册中心,如果使用nacos注册中心,这里要注释掉 -#eureka: -# client: -# serviceUrl: -# defaultZone: http://localhost:1111/eureka/ +eureka: + client: + serviceUrl: + defaultZone: http://localhost:1111/eureka/ # dubbo consumer demo: diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index 003081e0..a38c4620 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -33,22 +33,23 @@ - org.springframework.cloud spring-cloud-starter-netflix-eureka-client - --> + + org.springframework.cloud spring-cloud-starter-alibaba-nacos-discovery 0.2.2.RELEASE + --> diff --git a/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml b/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml index 62354b7a..59f250ab 100644 --- a/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml +++ b/sop-example/sop-story/sop-story-web/src/main/resources/application-dev.yml @@ -11,15 +11,15 @@ spring: connect-string: localhost:2181 # nacos注册中心,和eureka只能用一个 - nacos: - discovery: - server-addr: 127.0.0.1:8848 +# nacos: +# discovery: +# server-addr: 127.0.0.1:8848 # eureka注册中心,如果使用nacos注册中心,这里要注释掉 -#eureka: -# client: -# serviceUrl: -# defaultZone: http://localhost:1111/eureka/ +eureka: + client: + serviceUrl: + defaultZone: http://localhost:1111/eureka/ # dubbo provider dubbo: diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index 78edce77..aa4f3a25 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -66,22 +66,23 @@ - org.springframework.cloud spring-cloud-starter-netflix-eureka-client - --> + + org.springframework.cloud spring-cloud-starter-alibaba-nacos-discovery 0.2.2.RELEASE + --> diff --git a/sop-gateway/src/main/resources/application-dev.yml b/sop-gateway/src/main/resources/application-dev.yml index c025fd63..568556ce 100644 --- a/sop-gateway/src/main/resources/application-dev.yml +++ b/sop-gateway/src/main/resources/application-dev.yml @@ -19,6 +19,12 @@ ribbon: # 请谨慎设置,因为post请求大多都是写入请求,如果要支持重试,确保服务的幂等性 OkToRetryOnAllOperations: false +# eureka注册中心,如果使用nacos注册中心,这里要注释掉 +eureka: + client: + serviceUrl: + defaultZone: http://localhost:1111/eureka/ + spring: application: name: api-gateway @@ -35,15 +41,9 @@ spring: enabled: true # nacos注册中心,和eureka只能用一个 - nacos: - discovery: - server-addr: 127.0.0.1:8848 - -# eureka注册中心,如果使用nacos注册中心,这里要注释掉 -#eureka: -# client: -# serviceUrl: -# defaultZone: http://localhost:1111/eureka/ +# nacos: +# discovery: +# server-addr: 127.0.0.1:8848 # 数据源,根据实际情况修改 datasource: From fa9ffa88c264ffcac3cd196476febcdca9a216a9 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 1 Jul 2019 18:24:32 +0800 Subject: [PATCH 29/40] 1.12.0 --- doc/docs/_sidebar.md | 57 ++++----- doc/docs/files/10106_nacos注册中心.md | 55 +-------- doc/docs/files/10107_扩展其它注册中心.md | 112 ++++++++++++++++++ sop-admin/sop-admin-server/pom.xml | 2 +- .../src/main/resources/application-dev.yml | 3 +- sop-common/pom.xml | 2 +- sop-common/sop-gateway-common/pom.xml | 4 +- sop-common/sop-registry-api/pom.xml | 2 +- sop-common/sop-service-common/pom.xml | 4 +- sop-example/sop-auth/pom.xml | 2 +- sop-example/sop-book/sop-book-web/pom.xml | 2 +- sop-example/sop-easyopen/pom.xml | 2 +- sop-example/sop-springmvc/pom.xml | 2 +- sop-example/sop-story/sop-story-web/pom.xml | 2 +- sop-gateway/pom.xml | 2 +- sop-website/website-server/pom.xml | 2 +- .../src/main/resources/application-dev.yml | 5 +- 17 files changed, 166 insertions(+), 94 deletions(-) create mode 100644 doc/docs/files/10107_扩展其它注册中心.md diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index 63118b5d..5a51e16b 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,30 +1,31 @@ -* [首页](/?t=1561970396914) +* [首页](/?t=1561975674071) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1561970396914) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561970396931) - * [新增接口](files/10020_新增接口.md?t=1561970396931) - * [业务参数校验](files/10030_业务参数校验.md?t=1561970396931) - * [错误处理](files/10040_错误处理.md?t=1561970396931) - * [编写文档](files/10041_编写文档.md?t=1561970396931) - * [接口交互详解](files/10050_接口交互详解.md?t=1561970396931) - * [easyopen支持](files/10070_easyopen支持.md?t=1561970396932) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561970396932) - * [ISV管理](files/10085_ISV管理.md?t=1561970396932) - * [自定义路由](files/10086_自定义路由.md?t=1561970396932) - * [路由授权](files/10090_路由授权.md?t=1561970396932) - * [接口限流](files/10092_接口限流.md?t=1561970396932) - * [监控日志](files/10093_监控日志.md?t=1561970396932) - * [SDK开发](files/10095_SDK开发.md?t=1561970396932) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561970396932) - * [应用授权](files/10097_应用授权.md?t=1561970396932) - * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561970396932) - * [对接前端](files/10100_对接前端.md?t=1561970396933) - * [自定义过滤器](files/10102_自定义过滤器.md?t=1561970396933) - * [文件上传](files/10104_文件上传.md?t=1561970396933) - * [nacos注册中心](files/10106_nacos注册中心.md?t=1561970396933) + * [快速体验](files/10010_快速体验.md?t=1561975674073) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561975674089) + * [新增接口](files/10020_新增接口.md?t=1561975674089) + * [业务参数校验](files/10030_业务参数校验.md?t=1561975674090) + * [错误处理](files/10040_错误处理.md?t=1561975674090) + * [编写文档](files/10041_编写文档.md?t=1561975674090) + * [接口交互详解](files/10050_接口交互详解.md?t=1561975674090) + * [easyopen支持](files/10070_easyopen支持.md?t=1561975674090) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561975674090) + * [ISV管理](files/10085_ISV管理.md?t=1561975674090) + * [自定义路由](files/10086_自定义路由.md?t=1561975674090) + * [路由授权](files/10090_路由授权.md?t=1561975674090) + * [接口限流](files/10092_接口限流.md?t=1561975674090) + * [监控日志](files/10093_监控日志.md?t=1561975674091) + * [SDK开发](files/10095_SDK开发.md?t=1561975674091) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561975674091) + * [应用授权](files/10097_应用授权.md?t=1561975674091) + * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561975674091) + * [对接前端](files/10100_对接前端.md?t=1561975674091) + * [自定义过滤器](files/10102_自定义过滤器.md?t=1561975674091) + * [文件上传](files/10104_文件上传.md?t=1561975674091) + * [nacos注册中心](files/10106_nacos注册中心.md?t=1561975674091) + * [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1561975674091) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561970396933) - * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561970396933) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561970396933) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561970396933) - * [常见问题](files/90100_常见问题.md?t=1561970396933) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561975674092) + * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561975674092) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561975674092) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561975674092) + * [常见问题](files/90100_常见问题.md?t=1561975674092) diff --git a/doc/docs/files/10106_nacos注册中心.md b/doc/docs/files/10106_nacos注册中心.md index a06a4f5a..ba28927a 100644 --- a/doc/docs/files/10106_nacos注册中心.md +++ b/doc/docs/files/10106_nacos注册中心.md @@ -1,51 +1,6 @@ # nacos注册中心 -完整代码在`registry-nacos`分支 - -SOP默认使用eureka注册中心,如果要换成nacos注册中心,步骤如下: - -- 实现`com.gitee.sop.registryapi.service.RegistryService`接口 - -1.找到`SOP/sop-common/sop-registry-api`工程,在service.impl包下新建一个类,实现RegistryService接口 - -```java -public class RegistryServiceNacos implements RegistryService { - - @Override - public List listAllService(int pageNo, int pageSize) throws Exception { - // TODO: 返回服务实例 - } - - @Override - public void onlineInstance(ServiceInstance serviceInstance) throws Exception { - // TODO: 实例上线 - } - - @Override - public void offlineInstance(ServiceInstance serviceInstance) throws Exception { - // TODO: 实例下线 - } -} -``` - -2.在`com.gitee.sop.registryapi.config.BaseRegistryConfig`中新增 - -```java -/** - * 当配置了registry.name=nacos生效 - * - * @return - */ -@Bean -@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos") -RegistryService registryServiceNacos() { - return new RegistryServiceNacos(); -} -``` - -其中`@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos")` -表示`application.properties`配置了`registry.name=nacos`参数才能生效,registry.name=nacos下文会讲到。 - +使用nacos作为注册中心,步骤如下: - 微服务端修改 @@ -90,15 +45,16 @@ spring: - SOP-admin修改 -修改yml文件,新增nacos服务器地址,`registry.name`填nacos +修改yml文件,设置nacos服务器地址,`registry.name`填nacos ```yaml # 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 registry: - # 使用哪个配置中心,使用eureka,填eureka;使用nacos填nacos - name: nacos eureka-server-addr: http://localhost:1111/eureka/ + # nacos服务器地址 nacos-server-addr: 127.0.0.1:8848 + # 使用eureka,填:eureka,使用nacos填:nacos + name: nacos ``` - website-server修改 @@ -110,4 +66,5 @@ registry: - 参考资料 1.[nacos介绍及安装](https://nacos.io/zh-cn/docs/quick-start.html) + 2.[nacos spring cloud注册发现](https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html) diff --git a/doc/docs/files/10107_扩展其它注册中心.md b/doc/docs/files/10107_扩展其它注册中心.md new file mode 100644 index 00000000..f52d701c --- /dev/null +++ b/doc/docs/files/10107_扩展其它注册中心.md @@ -0,0 +1,112 @@ +# 扩展其它注册中心 + +**注: nacos注册中心已经实现,本篇以nacos为例介绍如何扩展,如果要改成consul,可按照此方式进行修改** + +SOP默认使用eureka注册中心,如果要换成nacos注册中心,步骤如下: + +- 实现`com.gitee.sop.registryapi.service.RegistryService`接口 + +1.找到`SOP/sop-common/sop-registry-api`工程,在service.impl包下新建一个类,实现RegistryService接口 + +```java +public class RegistryServiceNacos implements RegistryService { + + @Override + public List listAllService(int pageNo, int pageSize) throws Exception { + // TODO: 返回服务实例 + } + + @Override + public void onlineInstance(ServiceInstance serviceInstance) throws Exception { + // TODO: 实例上线 + } + + @Override + public void offlineInstance(ServiceInstance serviceInstance) throws Exception { + // TODO: 实例下线 + } +} +``` + +2.在`com.gitee.sop.registryapi.config.BaseRegistryConfig`中新增 + +```java +/** + * 当配置了registry.name=nacos生效 + * + * @return + */ +@Bean +@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos") +RegistryService registryServiceNacos() { + return new RegistryServiceNacos(); +} +``` + +其中`@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos")` +表示`application.properties`配置了`registry.name=nacos`参数才能生效,registry.name=nacos下文会讲到。 + + +- 微服务端修改 + +1.修改微服务应用pom.xml,注释eureka服务发现依赖,添加nacos服务发现依赖 + +```xml + + + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + 0.2.2.RELEASE + + +``` + +2.yml文件新增nacos配置,并注释掉eureka相关配置 + +```yaml +spring: + cloud: + # nacos注册中心,和eureka只能用一个 + nacos: + discovery: + server-addr: 127.0.0.1:8848 +``` + +- 网关修改 + +找到`sop-gateway`工程,步骤同上 + +- SOP-admin修改 + + +修改yml文件,新增nacos服务器地址,`registry.name`填nacos + +```yaml +# 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 +registry: + # 使用eureka,填:eureka,使用nacos填:nacos + name: nacos + eureka-server-addr: http://localhost:1111/eureka/ + nacos-server-addr: 127.0.0.1:8848 +``` + +- website-server修改 + +步骤同`SOP-admin修改` + +- 参考资料 + +1.[nacos介绍及安装](https://nacos.io/zh-cn/docs/quick-start.html) + +2.[nacos spring cloud注册发现](https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html) diff --git a/sop-admin/sop-admin-server/pom.xml b/sop-admin/sop-admin-server/pom.xml index 97c43720..f3e41d94 100644 --- a/sop-admin/sop-admin-server/pom.xml +++ b/sop-admin/sop-admin-server/pom.xml @@ -30,7 +30,7 @@ com.gitee.sop sop-registry-api - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT diff --git a/sop-admin/sop-admin-server/src/main/resources/application-dev.yml b/sop-admin/sop-admin-server/src/main/resources/application-dev.yml index 8bed2221..64b56db8 100644 --- a/sop-admin/sop-admin-server/src/main/resources/application-dev.yml +++ b/sop-admin/sop-admin-server/src/main/resources/application-dev.yml @@ -35,8 +35,9 @@ easyopen: # 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 registry: eureka-server-addr: http://localhost:1111/eureka/ + # nacos服务器地址 nacos-server-addr: 127.0.0.1:8848 - # 使用哪个配置中心,使用eureka,填eureka;使用nacos填nacos + # 使用eureka,填:eureka,使用nacos填:nacos name: eureka diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 3a5a7675..627e7d0d 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.sop sop-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT pom diff --git a/sop-common/sop-gateway-common/pom.xml b/sop-common/sop-gateway-common/pom.xml index 72958b00..8532ebda 100644 --- a/sop-common/sop-gateway-common/pom.xml +++ b/sop-common/sop-gateway-common/pom.xml @@ -5,11 +5,11 @@ com.gitee.sop sop-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../pom.xml sop-gateway-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT jar sop-gateway-common diff --git a/sop-common/sop-registry-api/pom.xml b/sop-common/sop-registry-api/pom.xml index 3a46bfea..83bd1dd1 100644 --- a/sop-common/sop-registry-api/pom.xml +++ b/sop-common/sop-registry-api/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.sop sop-registry-api - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT UTF-8 diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml index 7d94da07..cda7acb7 100644 --- a/sop-common/sop-service-common/pom.xml +++ b/sop-common/sop-service-common/pom.xml @@ -6,11 +6,11 @@ com.gitee.sop sop-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT ../pom.xml sop-service-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT jar sop-service-common diff --git a/sop-example/sop-auth/pom.xml b/sop-example/sop-auth/pom.xml index b7252cce..c51520ed 100644 --- a/sop-example/sop-auth/pom.xml +++ b/sop-example/sop-auth/pom.xml @@ -26,7 +26,7 @@ com.gitee.sop sop-service-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT org.springframework.cloud diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml index e468ab30..e0443e6b 100644 --- a/sop-example/sop-book/sop-book-web/pom.xml +++ b/sop-example/sop-book/sop-book-web/pom.xml @@ -24,7 +24,7 @@ com.gitee.sop sop-service-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT com.gitee.sop diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml index e7daadb3..f4bd1d23 100644 --- a/sop-example/sop-easyopen/pom.xml +++ b/sop-example/sop-easyopen/pom.xml @@ -29,7 +29,7 @@ com.gitee.sop sop-service-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT org.springframework.cloud diff --git a/sop-example/sop-springmvc/pom.xml b/sop-example/sop-springmvc/pom.xml index fa52325f..0aea2861 100644 --- a/sop-example/sop-springmvc/pom.xml +++ b/sop-example/sop-springmvc/pom.xml @@ -20,7 +20,7 @@ com.gitee.sop sop-service-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index a38c4620..670cea0d 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -24,7 +24,7 @@ com.gitee.sop sop-service-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT com.gitee.sop diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index aa4f3a25..cef66f3a 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -23,7 +23,7 @@ com.gitee.sop sop-gateway-common - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT diff --git a/sop-website/website-server/pom.xml b/sop-website/website-server/pom.xml index 30464050..2e35282c 100644 --- a/sop-website/website-server/pom.xml +++ b/sop-website/website-server/pom.xml @@ -25,7 +25,7 @@ com.gitee.sop sop-registry-api - 1.11.0-SNAPSHOT + 1.12.0-SNAPSHOT diff --git a/sop-website/website-server/src/main/resources/application-dev.yml b/sop-website/website-server/src/main/resources/application-dev.yml index d6181365..79f736b6 100644 --- a/sop-website/website-server/src/main/resources/application-dev.yml +++ b/sop-website/website-server/src/main/resources/application-dev.yml @@ -3,10 +3,11 @@ server: # 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 registry: - # 使用哪个配置中心,使用eureka,填eureka;使用nacos填nacos - name: nacos eureka-server-addr: http://localhost:1111/eureka/ + # nacos服务器地址 nacos-server-addr: 127.0.0.1:8848 + # 使用eureka,填:eureka,使用nacos填:nacos + name: eureka spring: application: From 7f42b3227ba4c9c175aff65696b4c2fbd26146d5 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 1 Jul 2019 18:25:10 +0800 Subject: [PATCH 30/40] 1.12.0 --- changelog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/changelog.md b/changelog.md index c7b21f49..89035399 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,10 @@ # changelog +## 1.12.0 + +- admin后台新增角色管理 +- 支持nacos作为注册中心 + ## 1.11.0 - 秘钥管理改造 From a0941c63ed74d172de83ff1f7b03ab9b4f7341d7 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 1 Jul 2019 20:01:27 +0800 Subject: [PATCH 31/40] update --- doc/docs/files/10106_nacos注册中心.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/docs/files/10106_nacos注册中心.md b/doc/docs/files/10106_nacos注册中心.md index ba28927a..bf396475 100644 --- a/doc/docs/files/10106_nacos注册中心.md +++ b/doc/docs/files/10106_nacos注册中心.md @@ -2,9 +2,27 @@ 使用nacos作为注册中心,步骤如下: +- 准备工作 + +1.安装nacos,前往[最新稳定版本](https://github.com/alibaba/nacos/releases),下载最新版nacos + +2.启动nacos服务器,cd nacos/bin + +Linux/Unix/Mac,启动命令(standalone代表着单机模式运行,非集群模式): + +`sh startup.sh -m standalone` + +Windows,启动命令: + +`cmd startup.cmd` + +或者双击startup.cmd运行文件。 + +更多访问:https://nacos.io/zh-cn/docs/quick-start.html + - 微服务端修改 -1.修改微服务应用pom.xml,注释eureka服务发现依赖,添加nacos服务发现依赖 +1.修改微服务应用pom,打开`sop-example/sop-story/sop-story-web/pom.xml`,注释eureka服务发现依赖,添加nacos服务发现依赖 ```xml From f0a0c04581c4ad084b03d279938c6bef1c7ab477 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 1 Jul 2019 20:51:40 +0800 Subject: [PATCH 32/40] 1.12.0 --- .../com/gitee/sop/adminserver/bean/SopAdminConstants.java | 5 ----- .../com/gitee/sop/adminserver/bean/ZookeeperContext.java | 5 ----- .../java/com/gitee/sop/gatewaycommon/bean/SopConstants.java | 5 ----- .../gitee/sop/gatewaycommon/manager/ZookeeperContext.java | 5 ----- 4 files changed, 20 deletions(-) diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/SopAdminConstants.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/SopAdminConstants.java index 9f411a09..958a1977 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/SopAdminConstants.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/SopAdminConstants.java @@ -9,11 +9,6 @@ public class SopAdminConstants { */ public static final String SOP_SERVICE_ROUTE_PATH = "/com.gitee.sop.route"; - /** - * zookeeper存放路由授权信息根目录 - */ - public static final String SOP_ROUTE_PERMISSION_PATH = "/com.gitee.sop.isv.route.permission"; - /** * 消息监听路径 */ diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java index 2f2ae540..c97e585e 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java @@ -20,7 +20,6 @@ import java.util.Collections; import java.util.List; import static com.gitee.sop.adminserver.bean.SopAdminConstants.SOP_MSG_CHANNEL_PATH; -import static com.gitee.sop.adminserver.bean.SopAdminConstants.SOP_ROUTE_PERMISSION_PATH; /** * @author tanghc @@ -77,10 +76,6 @@ public class ZookeeperContext { return serviceIdPath + "/" + routeId; } - public static String getRoutePermissionPath() { - return SOP_ROUTE_PERMISSION_PATH; - } - public static String getIsvInfoChannelPath() { return SOP_MSG_CHANNEL_PATH + "/isvinfo"; } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java index d97e921a..c0ba6457 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java @@ -45,11 +45,6 @@ public class SopConstants { */ public static final String SOP_SERVICE_ROUTE_PATH = "/com.gitee.sop.route"; - /** - * zookeeper存放路由授权信息根目录 - */ - public static final String SOP_ROUTE_PERMISSION_PATH = "/com.gitee.sop.isv.route.permission"; - /** * 消息监听路径 */ diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java index a72b0621..7507e653 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java @@ -18,7 +18,6 @@ import java.util.List; import java.util.function.Consumer; import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_MSG_CHANNEL_PATH; -import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_ROUTE_PERMISSION_PATH; import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_SERVICE_ROUTE_PATH; /** @@ -60,10 +59,6 @@ public class ZookeeperContext { return SOP_SERVICE_ROUTE_PATH; } - public static String getRoutePermissionPath() { - return SOP_ROUTE_PERMISSION_PATH; - } - public static String getIsvInfoChannelPath() { return SOP_MSG_CHANNEL_PATH + "/isvinfo"; } From 6882ef5415f7d5792da089733b0d87a690d6f9e8 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 1 Jul 2019 20:53:47 +0800 Subject: [PATCH 33/40] 1.12.0 --- .../com/gitee/sop/websiteserver/manager/DocManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java index fa3adabb..4837f7a3 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java @@ -86,7 +86,7 @@ public class DocManagerImpl implements DocManager { protected void loadDocInfo(ServiceInstance serviceInstance) { String query = this.buildQuery(); - String url = "http://" + serviceInstance.getIpPort() + "/v2/api-docs" + query; + String url = "http://" + serviceInstance.getIp() + ":" + serviceInstance.getPort() + "/v2/api-docs" + query; try { log.info("读取swagger文档,url:{}", url); ResponseEntity entity = restTemplate.getForEntity(url, String.class); From 8cbe2e71d600ee78405a042cca72b3250ca0ed2d Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 2 Jul 2019 12:04:58 +0800 Subject: [PATCH 34/40] update --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 16037ee1..da66708a 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,6 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 - 应用授权 - 监控日志 -## 分支说明 - -- develop: 日常开发分支 -- registry-nacos:使用nacos作为注册中心 -- SpringCloudGateway:网关使用spring cloud gateway,仅做体验用,不推荐 ## admin界面预览 From 8d8e39eadf09f66373b443ffa872b2899819cff8 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 2 Jul 2019 14:55:55 +0800 Subject: [PATCH 35/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E7=9B=91=E6=8E=A7=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/gitee/sop/adminserver/api/service/LogApi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java index e5d79465..e8f8060c 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/LogApi.java @@ -80,7 +80,7 @@ public class LogApi { } } catch (Exception e) { log.error("获取日志信息出错", e); - throw new BizException("获取日志信息出错"); + logMonitorInstanceVOParent.setMonitorName(logMonitorInstanceVOParent.getMonitorName() + "(请求出错)"); } } Collections.sort(ret, Comparator.comparing(LogMonitorInstanceVO::getCount)); From 42a868b76964f111614a918f219d57e576e7ffb0 Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 4 Jul 2019 17:35:44 +0800 Subject: [PATCH 36/40] =?UTF-8?q?=E4=BC=98=E5=8C=96admin=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gitee/sop/adminserver/api/isv/IsvApi.java | 25 +++- .../api/isv/param/IsvKeysFormUpdate.java | 5 - .../sop/adminserver/api/service/RouteApi.java | 51 ++++--- .../adminserver/bean/IsvRoutePermission.java | 1 + .../adminserver/bean/SopAdminConstants.java | 2 + .../adminserver/bean/ZookeeperContext.java | 124 +++++++++++++++--- .../sop/adminserver/config/WebConfig.java | 12 ++ .../service/RoutePermissionService.java | 43 +++++- .../src/main/resources/application-dev.yml | 4 + .../src/main/resources/public/index.html | 2 +- ...e7e4b6d5.js => chunk-25908fca.9d8bc0b6.js} | 2 +- ...15951b55.js => chunk-6a68a33e.b6685cb9.js} | 2 +- .../static/js/chunk-73b2dcec.094bb2fa.js | 1 - .../static/js/chunk-73b2dcec.14f248eb.js | 1 + .../gitee/sop/adminserver/CuratorTest.java | 45 +++++++ .../sop-admin-vue/src/views/isv/index.vue | 4 - .../sop-admin-vue/src/views/isv/keys.vue | 6 - .../src/views/service/route/index.vue | 4 +- .../bean/IsvRoutePermission.java | 1 + .../manager/ZookeeperContext.java | 24 +++- .../manager/DbIsvRoutePermissionManager.java | 15 ++- 21 files changed, 294 insertions(+), 80 deletions(-) rename sop-admin/sop-admin-server/src/main/resources/public/static/js/{chunk-25908fca.e7e4b6d5.js => chunk-25908fca.9d8bc0b6.js} (50%) rename sop-admin/sop-admin-server/src/main/resources/public/static/js/{chunk-6a68a33e.15951b55.js => chunk-6a68a33e.b6685cb9.js} (58%) delete mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.094bb2fa.js create mode 100644 sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.14f248eb.js create mode 100644 sop-admin/sop-admin-server/src/test/java/com/gitee/sop/adminserver/CuratorTest.java diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java index 27755aa8..273c3553 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/IsvApi.java @@ -41,13 +41,16 @@ import com.gitee.sop.adminserver.service.RoutePermissionService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.transaction.annotation.Transactional; import javax.validation.constraints.NotBlank; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -58,7 +61,15 @@ import java.util.stream.Collectors; @Slf4j public class IsvApi { - public static final int SIGN_TYPE_RSA2 = 1; + public static final byte SIGN_TYPE_RSA = 1; + public static final byte SIGN_TYPE_MD5 = 2; + + static Map SIGN_TYPE_MAP = new HashMap<>(); + static { + SIGN_TYPE_MAP.put("rsa", (byte) SIGN_TYPE_RSA); + SIGN_TYPE_MAP.put("md5", (byte) SIGN_TYPE_MD5); + } + @Autowired IsvInfoMapper isvInfoMapper; @@ -74,6 +85,9 @@ public class IsvApi { @Autowired RoutePermissionService routePermissionService; + @Value("${sop.sign-type}") + private String sopSignType; + @Api(name = "isv.info.page") @ApiDocMethod(description = "isv列表", results = { @ApiDocField(name = "pageIndex", description = "第几页", dataType = DataType.INT, example = "1"), @@ -118,6 +132,7 @@ public class IsvApi { CopyUtil.copyProperties(isvKeys, isvDetailVO); } isvDetailVO.setAppKey(appKey); + isvDetailVO.setSignType(getSignType()); return isvDetailVO; } @@ -168,12 +183,17 @@ public class IsvApi { IsvKeysGenVO isvKeysGenVO = this.createIsvKeys(); IsvKeys isvKeys = new IsvKeys(); isvKeys.setAppKey(appKey); + isvKeys.setSignType(getSignType()); CopyUtil.copyPropertiesIgnoreNull(isvKeysGenVO, isvKeys); isvKeysMapper.saveIgnoreNull(isvKeys); this.sendChannelMsg(rec.getAppKey()); } + private byte getSignType() { + return SIGN_TYPE_MAP.getOrDefault(sopSignType, SIGN_TYPE_RSA); + } + @Api(name = "isv.info.update") @ApiDocMethod(description = "修改isv") @Transactional(rollbackFor = Exception.class) @@ -194,6 +214,7 @@ public class IsvApi { if (isvKeys == null) { isvKeys = new IsvKeys(); CopyUtil.copyPropertiesIgnoreNull(param, isvKeys); + isvKeys.setSignType(getSignType()); isvKeysMapper.saveIgnoreNull(isvKeys); } else { CopyUtil.copyPropertiesIgnoreNull(param, isvKeys); @@ -279,7 +300,7 @@ public class IsvApi { routePermissionService.sendIsvRolePermissionToZookeeper(isvInfo.getAppKey(), roleCodeList); } catch (Exception e) { log.error("保存到zookeeper中失败,isvInfo:{}, roleCodeList:{}", isvInfo, roleCodeList); - throw new BizException("保存失败,请查看日志"); + throw new BizException("同步zookeeper失败,请查看网关日志"); } } } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/IsvKeysFormUpdate.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/IsvKeysFormUpdate.java index d558142f..652db61e 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/IsvKeysFormUpdate.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/isv/param/IsvKeysFormUpdate.java @@ -7,7 +7,6 @@ import org.hibernate.validator.constraints.Length; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; /** * @author tanghc @@ -45,8 +44,4 @@ public class IsvKeysFormUpdate { /** 平台生成的私钥, 数据库字段:private_key_platform */ @ApiDocField(description = "平台生成的私钥") private String privateKeyPlatform; - - @ApiDocField(description = "签名类型:1:RSA2,2:MD5") - @NotNull(message = "signType不能为空") - private Byte signType; } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java index 526ebba6..8b582df2 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/api/service/RouteApi.java @@ -6,7 +6,6 @@ import com.gitee.easyopen.annotation.ApiService; import com.gitee.easyopen.doc.annotation.ApiDoc; import com.gitee.easyopen.doc.annotation.ApiDocMethod; import com.gitee.easyopen.util.CopyUtil; -import com.gitee.fastmybatis.core.query.Query; import com.gitee.sop.adminserver.api.isv.result.RoleVO; import com.gitee.sop.adminserver.api.service.param.RouteAddParam; import com.gitee.sop.adminserver.api.service.param.RouteDeleteParam; @@ -22,7 +21,6 @@ import com.gitee.sop.adminserver.common.ZookeeperPathExistException; import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException; import com.gitee.sop.adminserver.entity.ConfigRouteBase; import com.gitee.sop.adminserver.entity.PermRole; -import com.gitee.sop.adminserver.entity.PermRolePermission; import com.gitee.sop.adminserver.mapper.ConfigRouteBaseMapper; import com.gitee.sop.adminserver.mapper.PermRoleMapper; import com.gitee.sop.adminserver.mapper.PermRolePermissionMapper; @@ -30,14 +28,11 @@ import com.gitee.sop.adminserver.service.RouteConfigService; import com.gitee.sop.adminserver.service.RoutePermissionService; import com.gitee.sop.adminserver.service.RouteService; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -188,6 +183,11 @@ public class RouteApi { return this.getRouteRole(param.getId()); } + /** + * 获取路由对应的角色 + * @param id routeId + * @return + */ private List getRouteRole(String id) { return permRolePermissionMapper.listByColumn("route_id", id) .stream() @@ -203,33 +203,28 @@ public class RouteApi { @Api(name = "route.role.update") @ApiDocMethod(description = "更新路由对应的角色") - @Transactional(rollbackFor = Exception.class) public void updateRouteRole(RoutePermissionParam param) { - String routeId = param.getRouteId(); - // 删除所有数据 - Query delQuery = new Query(); - delQuery.eq("route_id", routeId); - permRolePermissionMapper.deleteByQuery(delQuery); - - List roleCodes = param.getRoleCode(); - if (CollectionUtils.isNotEmpty(roleCodes)) { - List tobeSave = new ArrayList<>(roleCodes.size()); - for (String roleCode : roleCodes) { - PermRolePermission permRolePermission = new PermRolePermission(); - permRolePermission.setRoleCode(roleCode); - permRolePermission.setRouteId(routeId); - tobeSave.add(permRolePermission); - } - // 批量添加 - permRolePermissionMapper.saveBatch(tobeSave); - } - + RoutePermissionParam oldRoutePermission = this.buildOldRoutePermission(param.getRouteId()); + routePermissionService.updateRoutePermission(param); try { - routePermissionService.sendRoutePermissionReloadMsg(); + routePermissionService.sendRoutePermissionReloadMsg(oldRoutePermission); } catch (Exception e) { - log.info("消息推送--路由权限(reload)失败", e); - throw new BizException("修改失败,请查看日志"); + log.error("消息推送--路由权限(reload)失败", e); + // 回滚 + routePermissionService.updateRoutePermission(oldRoutePermission); + throw new BizException(e.getMessage()); } } + private RoutePermissionParam buildOldRoutePermission(String routeId) { + List routeRole = this.getRouteRole(routeId); + List roleCodeList = routeRole.stream() + .map(RoleVO::getRoleCode) + .collect(Collectors.toList()); + RoutePermissionParam routePermissionParam = new RoutePermissionParam(); + routePermissionParam.setRouteId(routeId); + routePermissionParam.setRoleCode(roleCodeList); + return routePermissionParam; + } + } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/IsvRoutePermission.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/IsvRoutePermission.java index ca5ee89a..043b99e6 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/IsvRoutePermission.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/IsvRoutePermission.java @@ -13,4 +13,5 @@ public class IsvRoutePermission { private String appKey; private List routeIdList; private String routeIdListMd5; + private String listenPath; } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/SopAdminConstants.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/SopAdminConstants.java index 958a1977..ba4cf281 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/SopAdminConstants.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/SopAdminConstants.java @@ -14,4 +14,6 @@ public class SopAdminConstants { */ public static final String SOP_MSG_CHANNEL_PATH = "/com.gitee.sop.channel"; + public static final String RELOAD_ROUTE_PERMISSION_PATH = "/com.gitee.sop.route.permission.reload"; + } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java index c97e585e..5d645ae9 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java @@ -4,54 +4,67 @@ import com.gitee.sop.adminserver.common.ZookeeperOperationException; import com.gitee.sop.adminserver.common.ZookeeperPathExistException; import com.gitee.sop.adminserver.common.ZookeeperPathNotExistException; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.recipes.cache.ChildData; +import org.apache.curator.framework.recipes.cache.NodeCache; +import org.apache.curator.framework.recipes.cache.NodeCacheListener; import org.apache.curator.framework.recipes.cache.PathChildrenCache; import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.data.Stat; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.util.Assert; -import javax.annotation.PostConstruct; +import java.io.Closeable; import java.util.Collections; import java.util.List; +import java.util.function.Consumer; import static com.gitee.sop.adminserver.bean.SopAdminConstants.SOP_MSG_CHANNEL_PATH; /** * @author tanghc */ -@Configuration @Slf4j public class ZookeeperContext { private static CuratorFramework client; - @Value("${spring.cloud.zookeeper.connect-string}") - private String zookeeperServerAddr; + private static Environment environment; - @Value("${spring.cloud.zookeeper.baseSleepTimeMs}") - private String baseSleepTimeMs; + public static void setEnvironment(Environment environment) { + Assert.notNull(environment, "environment不能为null"); + ZookeeperContext.environment = environment; + initZookeeperClient(); + } - @Value("${spring.cloud.zookeeper.maxRetries}") - private String maxRetries; + public synchronized static void initZookeeperClient() { + if (client != null) { + return; + } + setClient(createClient()); + } - @PostConstruct - protected void after() { + public static CuratorFramework createClient() { + String zookeeperServerAddr = environment.getProperty("spring.cloud.zookeeper.connect-string"); if (StringUtils.isBlank(zookeeperServerAddr)) { - throw new IllegalArgumentException("未指定spring.cloud.zookeeper.connect-string参数"); + throw new RuntimeException("未指定spring.cloud.zookeeper.connect-string参数"); } + String baseSleepTimeMs = environment.getProperty("spring.cloud.zookeeper.baseSleepTimeMs"); + String maxRetries = environment.getProperty("spring.cloud.zookeeper.maxRetries"); + log.info("初始化zookeeper客户端,zookeeperServerAddr:{}, baseSleepTimeMs:{}, maxRetries:{}", + zookeeperServerAddr, baseSleepTimeMs, maxRetries); CuratorFramework client = CuratorFrameworkFactory.builder() .connectString(zookeeperServerAddr) .retryPolicy(new ExponentialBackoffRetry(NumberUtils.toInt(baseSleepTimeMs, 3000), NumberUtils.toInt(maxRetries, 3))) .build(); client.start(); - - setClient(client); + return client; } public static String getSopRouteRootPath() { @@ -129,6 +142,7 @@ public class ZookeeperContext { /** * 创建新的path,并赋值。如果path已存在抛异常 + * * @param path 待创建的path * @param data 值 * @throws ZookeeperPathExistException @@ -138,9 +152,26 @@ public class ZookeeperContext { throw new ZookeeperPathExistException("path " + path + " 已存在"); } try { - return getClient().create() + return addPath(path, CreateMode.PERSISTENT, data); + } catch (Exception e) { + throw new ZookeeperOperationException("addPath error path=" + path, e); + } + } + + /** + * 添加节点 + * + * @param path 待创建的path + * @param createMode 节点类型 + * @param data 节点数据 + * @return + */ + public static String addPath(String path, CreateMode createMode, String data) { + try { + return getClient().create() // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点 .creatingParentContainersIfNeeded() + .withMode(createMode) .forPath(path, data.getBytes()); } catch (Exception e) { throw new ZookeeperOperationException("addPath error path=" + path, e); @@ -149,6 +180,7 @@ public class ZookeeperContext { /** * 删除节点及子节点 + * * @param path */ public static void deletePathDeep(String path) { @@ -157,12 +189,13 @@ public class ZookeeperContext { .deletingChildrenIfNeeded() .forPath(path); } catch (Exception e) { - throw new ZookeeperOperationException("deletePathDeep error path=" + path, e); } } + /** * 创建新的path,并赋值。如果path已存在则不创建 + * * @param path 待创建的path * @param data 值 */ @@ -171,10 +204,7 @@ public class ZookeeperContext { return path; } try { - return getClient().create() - // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点 - .creatingParentContainersIfNeeded() - .forPath(path, data.getBytes()); + return addPath(path, data); } catch (Exception e) { throw new ZookeeperOperationException("addPathQuietly error path=" + path, e); } @@ -182,6 +212,7 @@ public class ZookeeperContext { /** * 新建或保存节点 + * * @param path * @param data * @return @@ -201,6 +232,7 @@ public class ZookeeperContext { /** * 获取节点内容 + * * @param path * @return * @throws ZookeeperPathNotExistException @@ -247,4 +279,54 @@ public class ZookeeperContext { return childrenCache; } + /** + * 监听一个节点 + * + * @param path + * @param onChange 节点修改后触发 + * @return 返回path + * @throws Exception + */ + public static void listenTempPath(String path, Consumer onChange) throws Exception { + String initData = "{}"; + CuratorFramework client = createClient(); + client.create() + // 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点 + .creatingParentContainersIfNeeded() + .withMode(CreateMode.EPHEMERAL) + .forPath(path, initData.getBytes()); + + final NodeCache cache = new NodeCache(client, path, false); + cache.getListenable().addListener(new NodeCacheListener() { + @Override + public void nodeChanged() throws Exception { + byte[] nodeData = cache.getCurrentData().getData(); + String data = new String(nodeData); + if (!initData.equals(data)) { + onChange.accept(data); + new Thread(new ZKClose(cache, client)).start(); + } + } + }); + cache.start(); + } + + static class ZKClose implements Runnable { + Closeable[] closes; + + public ZKClose(Closeable ...closes) { + this.closes = closes; + } + + @Override + public void run() { + try { + Thread.sleep(2000); + IOUtils.closeQuietly(closes); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/WebConfig.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/WebConfig.java index 7c8be1f3..07dabc5d 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/WebConfig.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/config/WebConfig.java @@ -8,13 +8,17 @@ import com.gitee.easyopen.ApiParamParser; import com.gitee.easyopen.ParamNames; import com.gitee.easyopen.interceptor.ApiInterceptor; import com.gitee.easyopen.session.ApiSessionManager; +import com.gitee.sop.adminserver.bean.ZookeeperContext; import com.gitee.sop.adminserver.interceptor.LoginInterceptor; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; @@ -29,6 +33,9 @@ public class WebConfig { @Value("${admin.access-token.timeout-minutes}") private String accessTokenTimeout; + @Autowired + private Environment environment; + @Bean ApiConfig apiConfig() { ApiConfig apiConfig = new ApiConfig(); @@ -59,4 +66,9 @@ public class WebConfig { return apiConfig; } + @PostConstruct + public void after() { + ZookeeperContext.setEnvironment(environment); + } + } \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java index 3600a31f..70fbfe31 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java @@ -2,8 +2,10 @@ package com.gitee.sop.adminserver.service; import com.alibaba.fastjson.JSON; import com.gitee.fastmybatis.core.query.Query; +import com.gitee.sop.adminserver.api.service.param.RoutePermissionParam; import com.gitee.sop.adminserver.bean.ChannelMsg; import com.gitee.sop.adminserver.bean.IsvRoutePermission; +import com.gitee.sop.adminserver.bean.SopAdminConstants; import com.gitee.sop.adminserver.bean.ZookeeperContext; import com.gitee.sop.adminserver.entity.PermIsvRole; import com.gitee.sop.adminserver.entity.PermRolePermission; @@ -16,6 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -93,12 +96,48 @@ public class RoutePermissionService { /** * 推送所有路由权限到zookeeper */ - public void sendRoutePermissionReloadMsg() throws Exception { - ChannelMsg channelMsg = new ChannelMsg("reload", null); + public synchronized void sendRoutePermissionReloadMsg(RoutePermissionParam oldRoutePermission) throws Exception { + String listenPath = SopAdminConstants.RELOAD_ROUTE_PERMISSION_PATH + "/" + System.currentTimeMillis(); + ZookeeperContext.listenTempPath(listenPath, code -> { + // 0成功 + if (!"0".equals(code)) { + log.error("推送所有路由权限到zookeeper失败,进行回滚,msg: {},oldRoutePermission:{}", code, JSON.toJSONString(oldRoutePermission)); + // 回滚 + this.updateRoutePermission(oldRoutePermission); + } + }); + IsvRoutePermission isvRoutePermission = new IsvRoutePermission(); + isvRoutePermission.setListenPath(listenPath); + ChannelMsg channelMsg = new ChannelMsg("reload", isvRoutePermission); String jsonData = JSON.toJSONString(channelMsg); String path = ZookeeperContext.getIsvRoutePermissionChannelPath(); log.info("消息推送--路由权限(reload), path:{}, data:{}", path, jsonData); ZookeeperContext.createOrUpdateData(path, jsonData); } + /** + * 更新路由权限 + * + * @param param + */ + public synchronized void updateRoutePermission(RoutePermissionParam param) { + String routeId = param.getRouteId(); + // 删除所有数据 + Query delQuery = new Query(); + delQuery.eq("route_id", routeId); + permRolePermissionMapper.deleteByQuery(delQuery); + + List roleCodes = param.getRoleCode(); + if (org.apache.commons.collections.CollectionUtils.isNotEmpty(roleCodes)) { + List tobeSave = new ArrayList<>(roleCodes.size()); + for (String roleCode : roleCodes) { + PermRolePermission permRolePermission = new PermRolePermission(); + permRolePermission.setRoleCode(roleCode); + permRolePermission.setRouteId(routeId); + tobeSave.add(permRolePermission); + } + // 批量添加 + permRolePermissionMapper.saveBatch(tobeSave); + } + } } diff --git a/sop-admin/sop-admin-server/src/main/resources/application-dev.yml b/sop-admin/sop-admin-server/src/main/resources/application-dev.yml index 64b56db8..0064c80c 100644 --- a/sop-admin/sop-admin-server/src/main/resources/application-dev.yml +++ b/sop-admin/sop-admin-server/src/main/resources/application-dev.yml @@ -6,6 +6,10 @@ admin: access-token: timeout-minutes: 30 +sop: + # 签名方式,rsa:支付宝开放平台签名方式,md5:淘宝开放平台签名方式 + sign-type: rsa + # 不用改 spring: application: diff --git a/sop-admin/sop-admin-server/src/main/resources/public/index.html b/sop-admin/sop-admin-server/src/main/resources/public/index.html index 60193962..db9c4412 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/index.html +++ b/sop-admin/sop-admin-server/src/main/resources/public/index.html @@ -1 +1 @@ -SOP Admin
\ No newline at end of file +SOP Admin
\ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.e7e4b6d5.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.9d8bc0b6.js similarity index 50% rename from sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.e7e4b6d5.js rename to sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.9d8bc0b6.js index 08f5eef6..ec5a6661 100644 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.e7e4b6d5.js +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-25908fca.9d8bc0b6.js @@ -1 +1 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-25908fca"],{"021d":function(e,t,a){},"0bac":function(e,t,a){"use strict";var s=a("021d"),i=a.n(s);i.a},cb56:function(e,t,a){"use strict";a.r(t);var s=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"app-container"},[a("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:e.searchFormData,size:"mini"}},[a("el-form-item",{attrs:{label:"appKey"}},[a("el-input",{staticStyle:{width:"250px"},attrs:{clearable:!0,placeholder:"appKey"},model:{value:e.searchFormData.appKey,callback:function(t){e.$set(e.searchFormData,"appKey",t)},expression:"searchFormData.appKey"}})],1),e._v(" "),a("el-form-item",[a("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:e.onSearchTable}},[e._v("查询")])],1)],1),e._v(" "),a("el-button",{staticStyle:{"margin-bottom":"10px"},attrs:{type:"primary",size:"mini",icon:"el-icon-plus"},on:{click:e.onAdd}},[e._v("新增ISV")]),e._v(" "),a("el-table",{attrs:{data:e.pageInfo.list,border:"",fit:"","highlight-current-row":""}},[a("el-table-column",{attrs:{prop:"id",label:"ID",width:"80"}}),e._v(" "),a("el-table-column",{attrs:{prop:"appKey",label:"appKey",width:"250"}}),e._v(" "),a("el-table-column",{attrs:{prop:"",label:"秘钥",width:"80"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return e.onShowKeys(t.row)}}},[e._v("查看")])]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"roleList",label:"角色"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("div",{domProps:{innerHTML:e._s(e.roleRender(t.row))}})]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"status",label:"状态",width:"80"},scopedSlots:e._u([{key:"default",fn:function(t){return[1===t.row.status?a("span",{staticStyle:{color:"#67C23A"}},[e._v("已启用")]):e._e(),e._v(" "),2===t.row.status?a("span",{staticStyle:{color:"#F56C6C"}},[e._v("已禁用")]):e._e()]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"gmtCreate",label:"添加时间",width:"160"}}),e._v(" "),a("el-table-column",{attrs:{prop:"gmtModified",label:"修改时间",width:"160"}}),e._v(" "),a("el-table-column",{attrs:{label:"操作",width:"150"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return e.onTableUpdate(t.row)}}},[e._v("修改")]),e._v(" "),a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return e.onKeysUpdate(t.row)}}},[e._v("秘钥管理")])]}}])})],1),e._v(" "),a("el-pagination",{staticStyle:{"margin-top":"5px"},attrs:{background:"","current-page":e.searchFormData.pageIndex,"page-size":e.searchFormData.pageSize,"page-sizes":[5,10,20,40],total:e.pageInfo.total,layout:"total, sizes, prev, pager, next"},on:{"size-change":e.onSizeChange,"current-change":e.onPageIndexChange}}),e._v(" "),a("el-dialog",{attrs:{title:e.isvDialogTitle,visible:e.isvDialogVisible,"close-on-click-modal":!1},on:{"update:visible":function(t){e.isvDialogVisible=t},close:e.onIsvDialogClose}},[a("el-form",{ref:"isvForm",attrs:{rules:e.rulesIsvForm,model:e.isvDialogFormData,"label-width":"120px",size:"mini"}},[a("el-form-item",{attrs:{label:"appKey"}},[0===e.isvDialogFormData.id?a("span",{staticStyle:{color:"gray"}},[e._v("(系统自动生成)")]):a("span",[e._v(e._s(e.isvDialogFormData.appKey))])]),e._v(" "),a("el-form-item",{attrs:{label:"角色"}},[a("el-checkbox-group",{model:{value:e.isvDialogFormData.roleCode,callback:function(t){e.$set(e.isvDialogFormData,"roleCode",t)},expression:"isvDialogFormData.roleCode"}},e._l(e.roles,function(t){return a("el-checkbox",{key:t.roleCode,attrs:{label:t.roleCode}},[e._v(e._s(t.description))])}),1)],1),e._v(" "),a("el-form-item",{attrs:{label:"状态"}},[a("el-radio-group",{model:{value:e.isvDialogFormData.status,callback:function(t){e.$set(e.isvDialogFormData,"status",t)},expression:"isvDialogFormData.status"}},[a("el-radio",{attrs:{label:1,name:"status"}},[e._v("启用")]),e._v(" "),a("el-radio",{attrs:{label:2,name:"status"}},[e._v("禁用")])],1)],1)],1),e._v(" "),a("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(t){e.isvDialogVisible=!1}}},[e._v("取 消")]),e._v(" "),a("el-button",{attrs:{type:"primary"},on:{click:e.onIsvDialogSave}},[e._v("保 存")])],1)],1),e._v(" "),a("el-dialog",{attrs:{title:"秘钥信息",visible:e.isvKeysDialogVisible},on:{"update:visible":function(t){e.isvKeysDialogVisible=t},close:function(t){return e.resetForm("isvKeysFrom")}}},[a("el-form",{ref:"isvKeysFrom",staticClass:"key-view",attrs:{model:e.isvKeysFormData,"label-width":"160px",size:"mini"}},[a("el-form-item",{attrs:{label:""}},[a("el-alert",{attrs:{title:"带 ★ 的分配给开发者",type:"warning",closable:!1}})],1),e._v(" "),a("el-form-item",{attrs:{label:e.selfLabel("appKey")}},[a("span",[e._v(e._s(e.isvKeysFormData.appKey))])]),e._v(" "),a("el-form-item",{attrs:{label:"签名方式"}},[1===e.isvKeysFormData.signType?a("span",[e._v("RSA")]):e._e(),e._v(" "),2===e.isvKeysFormData.signType?a("span",[e._v("MD5")]):e._e()]),e._v(" "),a("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}],attrs:{label:"秘钥格式"}},[1===e.isvKeysFormData.keyFormat?a("span",[e._v("PKCS8(JAVA适用)")]):e._e(),e._v(" "),2===e.isvKeysFormData.keyFormat?a("span",[e._v("PKCS1(非JAVA适用)")]):e._e()]),e._v(" "),a("el-form-item",{directives:[{name:"show",rawName:"v-show",value:2===e.isvKeysFormData.signType,expression:"isvKeysFormData.signType === 2"}],attrs:{label:e.selfLabel("secret")}},[a("span",[e._v(e._s(e.isvKeysFormData.secret))])]),e._v(" "),a("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[a("legend",[e._v("ISV公私钥")]),e._v(" "),a("el-form-item",{attrs:{label:"ISV公钥"}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.publicKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyIsv",t)},expression:"isvKeysFormData.publicKeyIsv"}})],1),e._v(" "),a("el-form-item",{attrs:{label:e.selfLabel("ISV私钥")}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.privateKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyIsv",t)},expression:"isvKeysFormData.privateKeyIsv"}})],1)],1),e._v(" "),a("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[a("legend",[e._v("平台公私钥")]),e._v(" "),a("el-form-item",{attrs:{label:e.selfLabel("平台公钥")}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.publicKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyPlatform",t)},expression:"isvKeysFormData.publicKeyPlatform"}})],1),e._v(" "),a("el-form-item",{attrs:{prop:"privateKeyPlatform",label:"平台私钥"}},[a("el-input",{attrs:{type:"textarea",readonly:""},model:{value:e.isvKeysFormData.privateKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyPlatform",t)},expression:"isvKeysFormData.privateKeyPlatform"}})],1)],1)],1),e._v(" "),a("span",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[a("el-button",{on:{click:function(t){e.isvKeysDialogVisible=!1}}},[e._v("关 闭")])],1)],1)],1)},i=[],o={data:function(){return{searchFormData:{appKey:"",pageIndex:1,pageSize:10},pageInfo:{list:[],total:0},roles:[],isvDialogVisible:!1,isvDialogTitle:"新增ISV",isvDialogFormData:{id:0,status:1,roleCode:[]},rulesIsvForm:{appKey:[{required:!0,message:"不能为空",trigger:"blur"},{min:1,max:100,message:"长度在 1 到 100 个字符",trigger:"blur"}]},isvKeysDialogVisible:!1,isvKeysFormData:{appKey:"",secret:"",publicKeyIsv:"",privateKeyIsv:"",publicKeyPlatform:"",privateKeyPlatform:"",signType:""}}},created:function(){this.loadTable(),this.loadRouteRole()},methods:{loadTable:function(){this.post("isv.info.page",this.searchFormData,function(e){this.pageInfo=e.data})},loadRouteRole:function(){0===this.roles.length&&this.post("role.listall",{},function(e){this.roles=e.data})},onShowKeys:function(e){this.post("isv.keys.get",{appKey:e.appKey},function(e){var t=this;this.isvKeysDialogVisible=!0,this.$nextTick(function(){Object.assign(t.isvKeysFormData,e.data)})})},onSearchTable:function(){this.loadTable()},onTableUpdate:function(e){var t=this;this.isvDialogTitle="修改ISV",this.isvDialogVisible=!0,this.$nextTick(function(){t.post("isv.info.get",{id:e.id},function(e){for(var t=e.data,a=t.roleList,s=[],i=0;i0?t.join(", "):'未授权'},onRouteDialogSave:function(){var e=this;this.$refs.routeDialogFormRef.validate(function(t){if(t){var o=e.routeDialogFormData.id?"route.update":"route.add";e.routeDialogFormData.serviceId=e.serviceId,e.post(o,e.routeDialogFormData,function(){this.routeDialogVisible=!1,this.loadTable()})}})},onAuthDialogSave:function(){this.post("route.role.update",this.authDialogFormData,function(){this.authDialogVisible=!1,this.loadTable()})},addService:function(){this.addServiceDialogVisible=!0},closeAddServiceDlg:function(){this.$refs.addServiceForm.resetFields()},onAddService:function(){var e=this;this.$refs.addServiceForm.validate(function(t){t&&e.post("service.custom.add",e.addServiceForm,function(e){this.addServiceDialogVisible=!1,this.tip("添加成功"),this.loadTree()})})},onDelService:function(e){var t=e.serviceId;this.confirm("确认要删除服务"+t+"吗,【对应的路由配置会一起删除】",function(e){var o={serviceId:t};this.post("service.custom.del",o,function(){e(),this.tip("删除成功"),this.loadTree()})})}}},l=r,s=(o("55a2"),o("2877")),n=Object(s["a"])(l,a,i,!1,null,null,null);t["default"]=n.exports},"55a2":function(e,t,o){"use strict";var a=o("b294"),i=o.n(a);i.a},b294:function(e,t,o){}}]); \ No newline at end of file +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-6a68a33e"],{1248:function(e,t,o){"use strict";o.r(t);var a=function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("div",{staticClass:"app-container"},[o("el-container",[o("el-aside",{staticStyle:{"min-height":"300px",width:"250px"}},[o("el-button",{attrs:{type:"primary",plain:"",size:"mini",icon:"el-icon-plus"},on:{click:function(t){return t.stopPropagation(),e.addService(t)}}},[e._v("\n 新建服务\n ")]),e._v(" "),o("el-input",{staticStyle:{"margin-bottom":"10px","margin-top":"10px"},attrs:{"prefix-icon":"el-icon-search",placeholder:"搜索服务...",size:"mini",clearable:""},model:{value:e.filterText,callback:function(t){e.filterText=t},expression:"filterText"}}),e._v(" "),o("el-tree",{ref:"serviceTree",staticClass:"filter-tree",attrs:{data:e.treeData,props:e.defaultProps,"filter-node-method":e.filterNode,"highlight-current":!0,"expand-on-click-node":!1,"empty-text":"无数据","node-key":"serviceId","default-expand-all":""},on:{"node-click":e.onNodeClick},scopedSlots:e._u([{key:"default",fn:function(t){t.node;var a=t.data;return o("span",{staticClass:"custom-tree-node"},[o("div",[o("el-tooltip",{directives:[{name:"show",rawName:"v-show",value:a.custom,expression:"data.custom"}],staticClass:"item",attrs:{content:"自定义服务",effect:"light",placement:"left"}},[o("i",{staticClass:"el-icon-warning-outline"})]),e._v(" "),a.label.length0?t.join(", "):'未授权'},onRouteDialogSave:function(){var e=this;this.$refs.routeDialogFormRef.validate(function(t){if(t){var o=e.routeDialogFormData.id?"route.update":"route.add";e.routeDialogFormData.serviceId=e.serviceId,e.post(o,e.routeDialogFormData,function(){this.routeDialogVisible=!1,this.loadTable()})}})},onAuthDialogSave:function(){this.post("route.role.update",this.authDialogFormData,function(){this.authDialogVisible=!1,this.loadTable()})},addService:function(){this.addServiceDialogVisible=!0},closeAddServiceDlg:function(){this.$refs.addServiceForm.resetFields()},onAddService:function(){var e=this;this.$refs.addServiceForm.validate(function(t){t&&e.post("service.custom.add",e.addServiceForm,function(e){this.addServiceDialogVisible=!1,this.tip("添加成功"),this.loadTree()})})},onDelService:function(e){var t=e.serviceId;this.confirm("确认要删除服务"+t+"吗,【对应的路由配置会一起删除】",function(e){var o={serviceId:t};this.post("service.custom.del",o,function(){e(),this.tip("删除成功"),this.loadTree()})})}}},l=r,s=(o("55a2"),o("2877")),n=Object(s["a"])(l,a,i,!1,null,null,null);t["default"]=n.exports},"55a2":function(e,t,o){"use strict";var a=o("b294"),i=o.n(a);i.a},b294:function(e,t,o){}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.094bb2fa.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.094bb2fa.js deleted file mode 100644 index fa16b15b..00000000 --- a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.094bb2fa.js +++ /dev/null @@ -1 +0,0 @@ -(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-73b2dcec"],{"29fd":function(e,t,s){},"3bf7":function(e,t,s){"use strict";s.r(t);var a=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"app-container"},[s("el-button",{staticClass:"el-icon-back",attrs:{type:"text"},on:{click:e.onBack}},[e._v("返回")]),e._v(" "),s("el-form",{ref:"isvKeysForm",staticStyle:{width:"700px"},attrs:{rules:e.rulesIsvKeysForm,model:e.isvKeysFormData,"label-width":"160px",size:"mini"}},[s("el-form-item",{attrs:{label:""}},[s("el-alert",{attrs:{title:"带 ★ 的分配给开发者",type:"warning",closable:!1}})],1),e._v(" "),s("el-form-item",{attrs:{label:e.selfLabel("appKey")}},[s("div",[e._v(e._s(e.isvKeysFormData.appKey))])]),e._v(" "),s("el-form-item",{attrs:{label:"签名方式"}},[s("el-radio-group",{model:{value:e.isvKeysFormData.signType,callback:function(t){e.$set(e.isvKeysFormData,"signType",t)},expression:"isvKeysFormData.signType"}},[s("el-radio",{attrs:{label:1,name:"status"}},[e._v("RSA")]),e._v(" "),s("el-radio",{attrs:{label:2,name:"status"}},[e._v("MD5")])],1)],1),e._v(" "),s("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}],attrs:{label:"秘钥格式"}},[s("el-radio-group",{model:{value:e.isvKeysFormData.keyFormat,callback:function(t){e.$set(e.isvKeysFormData,"keyFormat",t)},expression:"isvKeysFormData.keyFormat"}},[s("el-radio",{attrs:{label:1,name:"keyFormat"}},[e._v("PKCS8(JAVA适用)")]),e._v(" "),s("el-radio",{attrs:{label:2,name:"keyFormat"}},[e._v("PKCS1(非JAVA适用)")])],1)],1),e._v(" "),s("el-form-item",{directives:[{name:"show",rawName:"v-show",value:2===e.isvKeysFormData.signType,expression:"isvKeysFormData.signType === 2"}],attrs:{prop:"secret",label:e.selfLabel("secret")}},[s("el-input",{model:{value:e.isvKeysFormData.secret,callback:function(t){e.$set(e.isvKeysFormData,"secret",t)},expression:"isvKeysFormData.secret"}}),e._v(" "),s("el-button",{attrs:{type:"text"},on:{click:e.onGenSecret}},[e._v("重新生成")])],1),e._v(" "),s("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[s("legend",[e._v("ISV公私钥")]),e._v(" "),s("el-form-item",{staticClass:"gen-key"},[s("el-button",{attrs:{type:"text"},on:{click:e.onGenKeysIsv}},[e._v("重新生成")])],1),e._v(" "),s("el-form-item",{attrs:{prop:"publicKeyIsv",label:"ISV公钥"}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.publicKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyIsv",t)},expression:"isvKeysFormData.publicKeyIsv"}})],1),e._v(" "),s("el-form-item",{attrs:{prop:"privateKeyIsv",label:e.selfLabel("ISV私钥")}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.privateKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyIsv",t)},expression:"isvKeysFormData.privateKeyIsv"}})],1)],1),e._v(" "),s("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[s("legend",[e._v("平台公私钥")]),e._v(" "),s("el-form-item",{staticClass:"gen-key"},[s("el-button",{attrs:{type:"text"},on:{click:e.onGenKeysPlatform}},[e._v("重新生成")])],1),e._v(" "),s("el-form-item",{attrs:{prop:"publicKeyPlatform",label:e.selfLabel("平台公钥")}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.publicKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyPlatform",t)},expression:"isvKeysFormData.publicKeyPlatform"}})],1),e._v(" "),s("el-form-item",{attrs:{prop:"privateKeyPlatform",label:"平台私钥"}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.privateKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyPlatform",t)},expression:"isvKeysFormData.privateKeyPlatform"}})],1)],1),e._v(" "),s("el-form-item",[s("el-button",{attrs:{type:"primary"},on:{click:e.onSubmit}},[e._v("保存")]),e._v(" "),s("el-button",{on:{click:e.onBack}},[e._v("取消")])],1)],1)],1)},i=[],r={data:function(){var e=this,t=function(t,s,a){2===e.isvKeysFormData.signType&&(""===s&&a(new Error("不能为空")),s.length>200&&a(new Error("长度不能超过200"))),a()},s=function(t,s,a){1===e.isvKeysFormData.signType&&""===s&&a(new Error("不能为空")),a()};return{isvKeysFormData:{appKey:"",secret:"",keyFormat:1,publicKeyIsv:"",privateKeyIsv:"",publicKeyPlatform:"",privateKeyPlatform:"",signType:1},rulesIsvKeysForm:{secret:[{validator:t,trigger:"blur"}],publicKeyIsv:[{validator:s,trigger:"blur"}],privateKeyIsv:[{validator:s,trigger:"blur"}]}}},created:function(){var e=this.$route.query;this.isvKeysFormData.appKey=e.appKey,this.loadForm()},methods:{loadForm:function(){this.post("isv.keys.get",{appKey:this.isvKeysFormData.appKey},function(e){Object.assign(this.isvKeysFormData,e.data)})},selfLabel:function(e){return"★ "+e},onSubmit:function(){var e=this;this.$refs.isvKeysForm.validate(function(t){t&&e.post("isv.keys.update",e.isvKeysFormData,function(){this.tip("保存成功")})})},onBack:function(){this.$router.push({path:"list"})},onGenKeysPlatform:function(){this.post("isv.keys.gen",{},function(e){this.tip("生成公私钥成功");var t=e.data;this.isvKeysFormData.publicKeyPlatform=t.publicKey,this.isvKeysFormData.privateKeyPlatform=t.privateKey})},onGenKeysIsv:function(){this.post("isv.keys.gen",{keyFormat:this.isvKeysFormData.keyFormat},function(e){this.tip("生成公私钥成功");var t=e.data;this.isvKeysFormData.publicKeyIsv=t.publicKey,this.isvKeysFormData.privateKeyIsv=t.privateKey})},onGenSecret:function(){this.post("isv.secret.gen",{},function(e){this.isvKeysFormData.secret=e.data})},showKeys:function(){return 1===this.isvKeysFormData.signType}}},o=r,l=(s("8b91"),s("2877")),n=Object(l["a"])(o,a,i,!1,null,null,null);t["default"]=n.exports},"8b91":function(e,t,s){"use strict";var a=s("29fd"),i=s.n(a);i.a}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.14f248eb.js b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.14f248eb.js new file mode 100644 index 00000000..d4f46ee6 --- /dev/null +++ b/sop-admin/sop-admin-server/src/main/resources/public/static/js/chunk-73b2dcec.14f248eb.js @@ -0,0 +1 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-73b2dcec"],{"29fd":function(e,t,s){},"3bf7":function(e,t,s){"use strict";s.r(t);var a=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"app-container"},[s("el-button",{staticClass:"el-icon-back",attrs:{type:"text"},on:{click:e.onBack}},[e._v("返回")]),e._v(" "),s("el-form",{ref:"isvKeysForm",staticStyle:{width:"700px"},attrs:{rules:e.rulesIsvKeysForm,model:e.isvKeysFormData,"label-width":"160px",size:"mini"}},[s("el-form-item",{attrs:{label:""}},[s("el-alert",{attrs:{title:"带 ★ 的分配给开发者",type:"warning",closable:!1}})],1),e._v(" "),s("el-form-item",{attrs:{label:e.selfLabel("appKey")}},[s("div",[e._v(e._s(e.isvKeysFormData.appKey))])]),e._v(" "),s("el-form-item",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}],attrs:{label:"秘钥格式"}},[s("el-radio-group",{model:{value:e.isvKeysFormData.keyFormat,callback:function(t){e.$set(e.isvKeysFormData,"keyFormat",t)},expression:"isvKeysFormData.keyFormat"}},[s("el-radio",{attrs:{label:1,name:"keyFormat"}},[e._v("PKCS8(JAVA适用)")]),e._v(" "),s("el-radio",{attrs:{label:2,name:"keyFormat"}},[e._v("PKCS1(非JAVA适用)")])],1)],1),e._v(" "),s("el-form-item",{directives:[{name:"show",rawName:"v-show",value:2===e.isvKeysFormData.signType,expression:"isvKeysFormData.signType === 2"}],attrs:{prop:"secret",label:e.selfLabel("secret")}},[s("el-input",{model:{value:e.isvKeysFormData.secret,callback:function(t){e.$set(e.isvKeysFormData,"secret",t)},expression:"isvKeysFormData.secret"}}),e._v(" "),s("el-button",{attrs:{type:"text"},on:{click:e.onGenSecret}},[e._v("重新生成")])],1),e._v(" "),s("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[s("legend",[e._v("ISV公私钥")]),e._v(" "),s("el-form-item",{staticClass:"gen-key"},[s("el-button",{attrs:{type:"text"},on:{click:e.onGenKeysIsv}},[e._v("重新生成")])],1),e._v(" "),s("el-form-item",{attrs:{prop:"publicKeyIsv",label:"ISV公钥"}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.publicKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyIsv",t)},expression:"isvKeysFormData.publicKeyIsv"}})],1),e._v(" "),s("el-form-item",{attrs:{prop:"privateKeyIsv",label:e.selfLabel("ISV私钥")}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.privateKeyIsv,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyIsv",t)},expression:"isvKeysFormData.privateKeyIsv"}})],1)],1),e._v(" "),s("fieldset",{directives:[{name:"show",rawName:"v-show",value:e.showKeys(),expression:"showKeys()"}]},[s("legend",[e._v("平台公私钥")]),e._v(" "),s("el-form-item",{staticClass:"gen-key"},[s("el-button",{attrs:{type:"text"},on:{click:e.onGenKeysPlatform}},[e._v("重新生成")])],1),e._v(" "),s("el-form-item",{attrs:{prop:"publicKeyPlatform",label:e.selfLabel("平台公钥")}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.publicKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"publicKeyPlatform",t)},expression:"isvKeysFormData.publicKeyPlatform"}})],1),e._v(" "),s("el-form-item",{attrs:{prop:"privateKeyPlatform",label:"平台私钥"}},[s("el-input",{attrs:{type:"textarea"},model:{value:e.isvKeysFormData.privateKeyPlatform,callback:function(t){e.$set(e.isvKeysFormData,"privateKeyPlatform",t)},expression:"isvKeysFormData.privateKeyPlatform"}})],1)],1),e._v(" "),s("el-form-item",[s("el-button",{attrs:{type:"primary"},on:{click:e.onSubmit}},[e._v("保存")]),e._v(" "),s("el-button",{on:{click:e.onBack}},[e._v("取消")])],1)],1)],1)},i=[],r={data:function(){var e=this,t=function(t,s,a){2===e.isvKeysFormData.signType&&(""===s&&a(new Error("不能为空")),s.length>200&&a(new Error("长度不能超过200"))),a()},s=function(t,s,a){1===e.isvKeysFormData.signType&&""===s&&a(new Error("不能为空")),a()};return{isvKeysFormData:{appKey:"",secret:"",keyFormat:1,publicKeyIsv:"",privateKeyIsv:"",publicKeyPlatform:"",privateKeyPlatform:"",signType:1},rulesIsvKeysForm:{secret:[{validator:t,trigger:"blur"}],publicKeyIsv:[{validator:s,trigger:"blur"}],privateKeyIsv:[{validator:s,trigger:"blur"}]}}},created:function(){var e=this.$route.query;this.isvKeysFormData.appKey=e.appKey,this.loadForm()},methods:{loadForm:function(){this.post("isv.keys.get",{appKey:this.isvKeysFormData.appKey},function(e){Object.assign(this.isvKeysFormData,e.data)})},selfLabel:function(e){return"★ "+e},onSubmit:function(){var e=this;this.$refs.isvKeysForm.validate(function(t){t&&e.post("isv.keys.update",e.isvKeysFormData,function(){this.tip("保存成功")})})},onBack:function(){this.$router.push({path:"list"})},onGenKeysPlatform:function(){this.post("isv.keys.gen",{},function(e){this.tip("生成公私钥成功");var t=e.data;this.isvKeysFormData.publicKeyPlatform=t.publicKey,this.isvKeysFormData.privateKeyPlatform=t.privateKey})},onGenKeysIsv:function(){this.post("isv.keys.gen",{keyFormat:this.isvKeysFormData.keyFormat},function(e){this.tip("生成公私钥成功");var t=e.data;this.isvKeysFormData.publicKeyIsv=t.publicKey,this.isvKeysFormData.privateKeyIsv=t.privateKey})},onGenSecret:function(){this.post("isv.secret.gen",{},function(e){this.isvKeysFormData.secret=e.data})},showKeys:function(){return 1===this.isvKeysFormData.signType}}},o=r,l=(s("8b91"),s("2877")),n=Object(l["a"])(o,a,i,!1,null,null,null);t["default"]=n.exports},"8b91":function(e,t,s){"use strict";var a=s("29fd"),i=s.n(a);i.a}}]); \ No newline at end of file diff --git a/sop-admin/sop-admin-server/src/test/java/com/gitee/sop/adminserver/CuratorTest.java b/sop-admin/sop-admin-server/src/test/java/com/gitee/sop/adminserver/CuratorTest.java new file mode 100644 index 00000000..7cf5c1ed --- /dev/null +++ b/sop-admin/sop-admin-server/src/test/java/com/gitee/sop/adminserver/CuratorTest.java @@ -0,0 +1,45 @@ +package com.gitee.sop.adminserver; + +import com.gitee.sop.adminserver.bean.SopAdminConstants; +import junit.framework.TestCase; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.zookeeper.data.Stat; + +public class CuratorTest extends TestCase { + + private static String zookeeperServerAddr = "localhost:2181"; + + static CuratorFramework client; + + public CuratorTest() { + client = CuratorFrameworkFactory.builder() + .connectString(zookeeperServerAddr) + .retryPolicy(new ExponentialBackoffRetry(1000, 3)) + .build(); + + client.start(); + } + + /** + * 递归删除节点,只能在测试环境用。 + * + * @throws Exception + */ + public void testDel() { + try { + client.delete() + .deletingChildrenIfNeeded() + .forPath(SopAdminConstants.RELOAD_ROUTE_PERMISSION_PATH); + } catch (Exception e) { + } + } + + public void testCheck() throws Exception { + String path = SopAdminConstants.RELOAD_ROUTE_PERMISSION_PATH + "/1562231019332"; + Stat stat = client.checkExists().forPath(path); + System.out.println(path + (stat == null ? "不存在" : "存在")); + } + +} \ No newline at end of file diff --git a/sop-admin/sop-admin-vue/src/views/isv/index.vue b/sop-admin/sop-admin-vue/src/views/isv/index.vue index 4c08fb7f..6b732348 100644 --- a/sop-admin/sop-admin-vue/src/views/isv/index.vue +++ b/sop-admin/sop-admin-vue/src/views/isv/index.vue @@ -141,10 +141,6 @@ {{ isvKeysFormData.appKey }} - - RSA - MD5 - PKCS8(JAVA适用) PKCS1(非JAVA适用) diff --git a/sop-admin/sop-admin-vue/src/views/isv/keys.vue b/sop-admin/sop-admin-vue/src/views/isv/keys.vue index 812f5857..5ea318bb 100644 --- a/sop-admin/sop-admin-vue/src/views/isv/keys.vue +++ b/sop-admin/sop-admin-vue/src/views/isv/keys.vue @@ -19,12 +19,6 @@
{{ isvKeysFormData.appKey }}
- - - RSA - MD5 - - PKCS8(JAVA适用) diff --git a/sop-admin/sop-admin-vue/src/views/service/route/index.vue b/sop-admin/sop-admin-vue/src/views/service/route/index.vue index 8ef40687..5845c8bc 100644 --- a/sop-admin/sop-admin-vue/src/views/service/route/index.vue +++ b/sop-admin/sop-admin-vue/src/views/service/route/index.vue @@ -214,8 +214,8 @@ label-width="120px" size="mini" > - - + + {{ authDialogFormData.routeId }} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/IsvRoutePermission.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/IsvRoutePermission.java index b3894f29..2836cf67 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/IsvRoutePermission.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/IsvRoutePermission.java @@ -14,5 +14,6 @@ public class IsvRoutePermission { private String appKey; private List routeIdList = Collections.emptyList(); private String routeIdListMd5; + private String listenPath; } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java index 7507e653..79c688d8 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ZookeeperContext.java @@ -28,15 +28,22 @@ public class ZookeeperContext { private static CuratorFramework client; + private static Environment environment; + public static void setEnvironment(Environment environment) { Assert.notNull(environment, "environment不能为null"); - initZookeeperClient(environment); + ZookeeperContext.environment = environment; + initZookeeperClient(); } - public synchronized static void initZookeeperClient(Environment environment) { + public synchronized static void initZookeeperClient() { if (client != null) { return; } + setClient(createClient()); + } + + public static CuratorFramework createClient() { String zookeeperServerAddr = environment.getProperty("spring.cloud.zookeeper.connect-string"); if (StringUtils.isBlank(zookeeperServerAddr)) { throw new RuntimeException("未指定spring.cloud.zookeeper.connect-string参数"); @@ -51,8 +58,7 @@ public class ZookeeperContext { .build(); client.start(); - - setClient(client); + return client; } public static String getRouteRootPath() { @@ -100,6 +106,16 @@ public class ZookeeperContext { .forPath(path, data.getBytes()); } + /** + * 更新节点 + * @param path + * @param data + * @throws Exception + */ + public static void updatePath(String path, String data) throws Exception { + getClient().setData().forPath(path, data.getBytes()); + } + /** * 创建path,如果path存在不报错,静默返回path名称 * diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java index 4a6ee0bb..8285500b 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java @@ -17,7 +17,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; -import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import javax.annotation.PostConstruct; @@ -129,7 +128,19 @@ public class DbIsvRoutePermissionManager extends DefaultIsvRoutePermissionManage switch (channelMsg.getOperation()) { case "reload": log.info("重新加载路由权限信息,isvRoutePermission:{}", isvRoutePermission); - load(); + String listenPath = isvRoutePermission.getListenPath(); + String code = "0"; + try { + load(); + } catch (Exception e) { + log.error("重新加载路由权限失败, channelMsg:{}", channelMsg, e); + code = e.getMessage(); + } + try { + ZookeeperContext.updatePath(listenPath, code); + } catch (Exception e1) { + log.error("重新加载路由权限信息, zookeeper操作失败, path: {}", listenPath, e1); + } break; case "update": log.info("更新ISV路由权限信息,isvRoutePermission:{}", isvRoutePermission); From 6c60a48e40537bb43e73f31481af5c714b7328a4 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 5 Jul 2019 09:25:55 +0800 Subject: [PATCH 37/40] =?UTF-8?q?=E4=BC=98=E5=8C=96admin=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sop/adminserver/bean/ZookeeperContext.java | 13 ++++++++----- .../adminserver/service/RoutePermissionService.java | 13 +++++-------- .../manager/DbIsvRoutePermissionManager.java | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java index 5d645ae9..1238fc29 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/ZookeeperContext.java @@ -22,7 +22,6 @@ import org.springframework.util.Assert; import java.io.Closeable; import java.util.Collections; import java.util.List; -import java.util.function.Consumer; import static com.gitee.sop.adminserver.bean.SopAdminConstants.SOP_MSG_CHANNEL_PATH; @@ -283,11 +282,11 @@ public class ZookeeperContext { * 监听一个节点 * * @param path - * @param onChange 节点修改后触发 + * @param listenCallback 回调 * @return 返回path * @throws Exception */ - public static void listenTempPath(String path, Consumer onChange) throws Exception { + public static void listenTempPath(String path, ListenCallback listenCallback) throws Exception { String initData = "{}"; CuratorFramework client = createClient(); client.create() @@ -302,8 +301,8 @@ public class ZookeeperContext { public void nodeChanged() throws Exception { byte[] nodeData = cache.getCurrentData().getData(); String data = new String(nodeData); - if (!initData.equals(data)) { - onChange.accept(data); + if (StringUtils.isNotBlank(data) && !initData.equals(data)) { + listenCallback.onError(data); new Thread(new ZKClose(cache, client)).start(); } } @@ -311,6 +310,10 @@ public class ZookeeperContext { cache.start(); } + public interface ListenCallback { + void onError(String errorMsg); + } + static class ZKClose implements Runnable { Closeable[] closes; diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java index 70fbfe31..2cf4a344 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/service/RoutePermissionService.java @@ -96,15 +96,12 @@ public class RoutePermissionService { /** * 推送所有路由权限到zookeeper */ - public synchronized void sendRoutePermissionReloadMsg(RoutePermissionParam oldRoutePermission) throws Exception { + public void sendRoutePermissionReloadMsg(RoutePermissionParam oldRoutePermission) throws Exception { String listenPath = SopAdminConstants.RELOAD_ROUTE_PERMISSION_PATH + "/" + System.currentTimeMillis(); - ZookeeperContext.listenTempPath(listenPath, code -> { - // 0成功 - if (!"0".equals(code)) { - log.error("推送所有路由权限到zookeeper失败,进行回滚,msg: {},oldRoutePermission:{}", code, JSON.toJSONString(oldRoutePermission)); - // 回滚 - this.updateRoutePermission(oldRoutePermission); - } + ZookeeperContext.listenTempPath(listenPath, errorMsg -> { + log.error("推送所有路由权限到zookeeper失败,进行回滚,errorMsg: {},oldRoutePermission:{}", errorMsg, JSON.toJSONString(oldRoutePermission)); + // 回滚 + updateRoutePermission(oldRoutePermission); }); IsvRoutePermission isvRoutePermission = new IsvRoutePermission(); isvRoutePermission.setListenPath(listenPath); diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java index 8285500b..0f8132fb 100644 --- a/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/manager/DbIsvRoutePermissionManager.java @@ -129,7 +129,7 @@ public class DbIsvRoutePermissionManager extends DefaultIsvRoutePermissionManage case "reload": log.info("重新加载路由权限信息,isvRoutePermission:{}", isvRoutePermission); String listenPath = isvRoutePermission.getListenPath(); - String code = "0"; + String code = ""; try { load(); } catch (Exception e) { From 49cd03cc6f31c949a141be423be7e37459376ed1 Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 5 Jul 2019 09:28:49 +0800 Subject: [PATCH 38/40] update --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index da66708a..54e23cba 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,10 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 - sop-test:接口调用测试用例 - sop-website:开放平台对应网站,提供文档API等内容 +## 分支说明 + +- develop:日常开发分支 +- registry-nacos:nacos作为注册中心 ## 相关文档 From 575618fe0e00b9d196322b7369dd0f8538497ef9 Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 8 Jul 2019 09:32:48 +0800 Subject: [PATCH 39/40] update --- doc/docs/files/10106_nacos注册中心.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/docs/files/10106_nacos注册中心.md b/doc/docs/files/10106_nacos注册中心.md index bf396475..315983b1 100644 --- a/doc/docs/files/10106_nacos注册中心.md +++ b/doc/docs/files/10106_nacos注册中心.md @@ -1,6 +1,8 @@ # nacos注册中心 -使用nacos作为注册中心,步骤如下: +使用nacos作为注册中心,源码在`registry-nacos`分支 + +这里演示如何将默认的eureka注册中心替换成nacos,步骤如下: - 准备工作 From ebb31433a80f0fe37f89dab7913f4153bb52d74c Mon Sep 17 00:00:00 2001 From: tanghc Date: Mon, 8 Jul 2019 09:34:45 +0800 Subject: [PATCH 40/40] update --- doc/docs/_sidebar.md | 58 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index 5a51e16b..c3fc8cb3 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,31 +1,31 @@ -* [首页](/?t=1561975674071) +* [首页](/?t=1562549680042) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1561975674073) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561975674089) - * [新增接口](files/10020_新增接口.md?t=1561975674089) - * [业务参数校验](files/10030_业务参数校验.md?t=1561975674090) - * [错误处理](files/10040_错误处理.md?t=1561975674090) - * [编写文档](files/10041_编写文档.md?t=1561975674090) - * [接口交互详解](files/10050_接口交互详解.md?t=1561975674090) - * [easyopen支持](files/10070_easyopen支持.md?t=1561975674090) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561975674090) - * [ISV管理](files/10085_ISV管理.md?t=1561975674090) - * [自定义路由](files/10086_自定义路由.md?t=1561975674090) - * [路由授权](files/10090_路由授权.md?t=1561975674090) - * [接口限流](files/10092_接口限流.md?t=1561975674090) - * [监控日志](files/10093_监控日志.md?t=1561975674091) - * [SDK开发](files/10095_SDK开发.md?t=1561975674091) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561975674091) - * [应用授权](files/10097_应用授权.md?t=1561975674091) - * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561975674091) - * [对接前端](files/10100_对接前端.md?t=1561975674091) - * [自定义过滤器](files/10102_自定义过滤器.md?t=1561975674091) - * [文件上传](files/10104_文件上传.md?t=1561975674091) - * [nacos注册中心](files/10106_nacos注册中心.md?t=1561975674091) - * [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1561975674091) + * [快速体验](files/10010_快速体验.md?t=1562549680042) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1562549680065) + * [新增接口](files/10020_新增接口.md?t=1562549680065) + * [业务参数校验](files/10030_业务参数校验.md?t=1562549680065) + * [错误处理](files/10040_错误处理.md?t=1562549680065) + * [编写文档](files/10041_编写文档.md?t=1562549680065) + * [接口交互详解](files/10050_接口交互详解.md?t=1562549680065) + * [easyopen支持](files/10070_easyopen支持.md?t=1562549680065) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1562549680066) + * [ISV管理](files/10085_ISV管理.md?t=1562549680066) + * [自定义路由](files/10086_自定义路由.md?t=1562549680066) + * [路由授权](files/10090_路由授权.md?t=1562549680066) + * [接口限流](files/10092_接口限流.md?t=1562549680066) + * [监控日志](files/10093_监控日志.md?t=1562549680066) + * [SDK开发](files/10095_SDK开发.md?t=1562549680067) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1562549680067) + * [应用授权](files/10097_应用授权.md?t=1562549680067) + * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1562549680067) + * [对接前端](files/10100_对接前端.md?t=1562549680067) + * [自定义过滤器](files/10102_自定义过滤器.md?t=1562549680067) + * [文件上传](files/10104_文件上传.md?t=1562549680068) + * [nacos注册中心](files/10106_nacos注册中心.md?t=1562549680068) + * [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1562549680069) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561975674092) - * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561975674092) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561975674092) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561975674092) - * [常见问题](files/90100_常见问题.md?t=1561975674092) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1562549680069) + * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1562549680069) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1562549680069) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1562549680069) + * [常见问题](files/90100_常见问题.md?t=1562549680069)