114 Commits

Author SHA1 Message Date
暮光:城中城
a147d389da 修改版本号 2019-06-30 21:54:38 +08:00
暮光:城中城
95ffa30c12 Merge remote-tracking branch 'origin/master' 2019-06-30 21:53:47 +08:00
暮光:城中城
17c123003f 修改版本号 2019-06-30 21:53:36 +08:00
暮光:城中城
817ae4d3fc 更新 README.md 2019-06-30 15:46:33 +08:00
暮光:城中城
0a31c4ee4b 文档优化 2019-06-30 15:41:31 +08:00
暮光:城中城
1babdb56ec 引包优化 2019-06-30 15:14:58 +08:00
暮光:城中城
4096def6b3 版本升级 2019-06-30 11:03:27 +08:00
暮光:城中城
440123aed2 版本升级 2019-06-30 10:59:39 +08:00
暮光:城中城
bdc8e7a959 调试优化 2019-06-30 10:46:23 +08:00
暮光:城中城
242ca36a7a 首页新版开发跳转 2019-06-29 23:49:20 +08:00
暮光:城中城
49c1929746 用户管理页面开发 2019-06-28 23:23:51 +08:00
暮光:城中城
9d6ab9e159 登录和首页优化 2019-06-28 22:03:52 +08:00
暮光:城中城
eb7112b956 错误优化 2019-06-27 22:56:40 +08:00
暮光:城中城
f144e77035 重构控制台首页 2019-06-27 22:42:06 +08:00
暮光:城中城
968bbb5f5a 修改swagger请求文档超时时间 2019-06-25 22:14:21 +08:00
暮光:城中城
65dd754580 修改swagger后端请求文档时带上全局参数 2019-06-25 21:47:51 +08:00
暮光:城中城
1f57b0d478 修改swagger后端请求文档时带上全局参数 2019-06-25 21:38:34 +08:00
暮光:城中城
23d4dc5ec3 权限判断 2019-06-25 12:38:21 +08:00
暮光:城中城
031ea4f199 去掉不需要的字段 2019-06-25 12:17:32 +08:00
暮光:城中城
29586f35d7 修改swagger解析报错,白名单域名默认为不限制 2019-06-24 22:43:21 +08:00
暮光:城中城
f83c27882f 修改readme 2019-06-21 21:39:09 +08:00
暮光:城中城
fbd6ef5f83 同一个页面只能一个人编辑 2019-06-21 21:05:34 +08:00
暮光:城中城
89b32304bd 空间编辑权判断 2019-06-18 22:56:51 +08:00
暮光:城中城
0f9f909d73 文件权限控制,展示下载数 2019-06-18 22:38:46 +08:00
暮光:城中城
994ced47bc 增加下载数,页面跳转、展示优化 2019-06-18 20:32:37 +08:00
暮光:城中城
40f594f1ff 开放文档排序和增加阅读数 2019-06-15 15:57:03 +08:00
暮光:城中城
8a94b6e426 wiki页面打包 2019-06-15 13:47:53 +08:00
暮光:城中城
f975e23cd8 删除页面时递归删除子页面 2019-06-15 13:13:22 +08:00
暮光:城中城
dc93ea4395 统一返回值编码 2019-06-15 10:38:57 +08:00
暮光:城中城
c1adc111a1 文档前端打包 2019-06-14 22:24:45 +08:00
暮光:城中城
5fffa51171 文档前端打包 2019-06-14 21:15:29 +08:00
暮光:城中城
a61b100768 空间首页增加列表查询,编辑查看优化 2019-06-14 20:46:53 +08:00
暮光:城中城
494149fad2 增加权限和登录跳转 2019-06-12 22:28:38 +08:00
暮光:城中城
f9d53da7fe 增加拖动改变文章顺序 2019-06-10 21:15:56 +08:00
暮光:城中城
605c97347d 权限开发,页面交互开发,增加阅读数 2019-06-05 22:53:24 +08:00
暮光:城中城
96d081fdae 文档展示和编辑,基本功能已完成 2019-06-02 22:38:36 +08:00
暮光:城中城
49189587ce 文档展示和编辑 2019-06-01 23:03:10 +08:00
暮光:城中城
48f81dc547 权限优化 2019-06-01 09:36:55 +08:00
暮光:城中城
7f4f3fd432 左侧菜单和页面内容展示 2019-05-30 22:45:22 +08:00
暮光:城中城
f5249f39e1 登录和权限处理,页面优化 2019-05-30 20:39:15 +08:00
暮光:城中城
c3b3b60d93 自己写一套权限控制,去掉spring security 2019-05-29 23:03:30 +08:00
暮光:城中城
25b4089a8f 前端拆分为单独项目来维护开发 2019-05-17 18:23:03 +08:00
暮光:城中城
13e390535d 设置dubbo超时时间 2019-04-26 18:16:01 +08:00
暮光:城中城
d406b52d6a wiki图片权限判断 2019-04-21 23:37:56 +08:00
暮光:城中城
aaa267a6c4 wiki支持粘贴图片 2019-04-21 18:13:33 +08:00
暮光:城中城
98e4f771f0 wiki文档优化 2019-04-21 17:38:33 +08:00
暮光:城中城
7c8ab60c6d wiki文档优化,系统升级信息获取和展示 2019-04-21 16:46:14 +08:00
暮光:城中城
ad739a87e0 修改数据格式 2019-04-11 20:08:22 +08:00
暮光:城中城
3bb18069ad 登录失效提示 2019-04-11 20:08:05 +08:00
暮光:城中城
a6c1360593 grpc优化 2019-04-05 21:55:18 +08:00
暮光:城中城
0e0f512571 取消grpc默认开启 2019-04-03 00:07:20 +08:00
暮光:城中城
0606099b2a Merge branch 'grpc'
# Conflicts:
#	zyplayer-doc-grpc/src/main/java/com/zyplayer/doc/grpc/framework/config/EnableDocGrpc.java
#	zyplayer-doc-grpc/src/main/resources/doc-grpc.html
#	zyplayer-doc-manage/src/main/java/com/zyplayer/doc/manage/framework/config/DocDatabaseRegistrationConfig.java
#	zyplayer-doc-manage/src/main/java/com/zyplayer/doc/manage/framework/config/DocDubboConfig.java
#	zyplayer-doc-manage/src/main/java/com/zyplayer/doc/manage/framework/config/DocWikiConfig.java
#	zyplayer-doc-manage/src/main/java/com/zyplayer/doc/manage/framework/config/SwaggerConfiguration.java
#	zyplayer-doc-manage/src/main/java/com/zyplayer/doc/manage/framework/config/ZyplayerDocConfig.java
2019-04-02 20:32:08 +08:00
暮光:城中城
6196238867 grpc开发 2019-04-02 20:31:25 +08:00
暮光:城中城
7caebe9eaf 注解优化,grpc开发 2019-04-02 20:22:18 +08:00
暮光:城中城
165d282beb grpc文档开发 2019-04-01 23:04:48 +08:00
暮光:城中城
4b1c234384 grpc开发 2019-04-01 22:01:02 +08:00
暮光:城中城
5cf08506ef grpc文档开发 2019-03-31 22:59:55 +08:00
暮光:城中城
e518957f16 grpc文档开发 2019-03-30 20:50:55 +08:00
暮光:城中城
f5e6a5998d 文件类型获取修改 2019-03-22 20:15:43 +08:00
暮光:城中城
ff91320ec8 增加grpc文档支持 2019-03-22 19:01:27 +08:00
暮光:城中城
b498a513dc wiki增加开放访问 2019-03-22 03:45:06 +08:00
暮光:城中城
42ed560750 wiki权限判断 2019-03-13 22:34:15 +08:00
暮光:城中城
5096d242fd wiki增加开放访问 2019-03-13 21:30:27 +08:00
暮光:城中城
b037af447f wiki优化 2019-03-12 22:11:10 +08:00
暮光:城中城
7bf66f3916 wiki目录预先加载 2019-03-11 23:22:57 +08:00
暮光:城中城
90ce37ec35 建库脚本 2019-03-09 23:32:36 +08:00
暮光:城中城
2cb6e39eb5 wiki文档优化,增加不可编辑实现 2019-03-09 23:30:33 +08:00
暮光:城中城
5ca5feb9e8 wiki文档优化,增加不可编辑实现 2019-03-09 22:23:30 +08:00
暮光:城中城
840f6b457b wiki空间管理,页面支持拖动管理 2019-03-08 22:40:50 +08:00
暮光:城中城
05142096f7 wiki评论和空间 2019-03-08 21:40:20 +08:00
暮光:城中城
5f7177848b wiki空间相关开发 2019-03-07 22:55:12 +08:00
暮光:城中城
73a88fb7d1 wiki评论和空间 2019-03-07 20:53:13 +08:00
暮光:城中城
c37586d596 wiki功能开发 2019-03-06 23:39:38 +08:00
暮光:城中城
3c29cac2d7 wiki评论点赞 2019-03-06 22:17:57 +08:00
暮光:城中城
7d8fa1ff82 wiki优化 2019-03-05 23:15:47 +08:00
暮光:城中城
7357058694 dubbo优化,wiki上传文件 2019-03-04 23:20:40 +08:00
暮光:城中城
6f30ef0f49 dubbo优化 2019-03-01 22:27:17 +08:00
暮光:城中城
ed8242535d wiki接口和页面 2019-02-28 22:38:56 +08:00
暮光:城中城
b14e2c5989 wiki接口 2019-02-27 21:38:25 +08:00
暮光:城中城
b930103058 框架拆分 2019-02-27 00:04:45 +08:00
暮光:城中城
c995d3a600 框架拆分 2019-02-26 23:04:24 +08:00
暮光:城中城
81435c790a 引用修改 2019-02-25 12:31:54 +08:00
暮光:城中城
aba46ff3d5 Merge remote-tracking branch 'origin/master' 2019-02-25 12:26:27 +08:00
暮光:城中城
e5f4499fa3 #IRYN4 修改参数拼接无效问题 2019-02-25 12:26:16 +08:00
暮光:城中城
caf866ded5 增加说明 2019-02-23 22:19:13 +08:00
暮光:城中城
7c3b04462a 引用优化 2019-02-21 22:14:38 +08:00
暮光:城中城
567a50d075 修改登录地址获取 2019-02-20 22:11:38 +08:00
暮光:城中城
c2968dc8d5 说明文档 2019-02-18 21:37:56 +08:00
暮光:城中城
7f78d77235 dubbo参数自动获取 2019-02-18 20:27:50 +08:00
暮光:城中城
1f4008667c 修改引用,增加搜索的位置 2019-02-18 12:18:12 +08:00
暮光:城中城
584afec6d2 Merge remote-tracking branch 'origin/master' 2019-02-17 20:53:20 +08:00
暮光:城中城
be452f68b9 增加wiki模块 2019-02-17 20:20:39 +08:00
暮光:城中城
2b8c190964 更新 README.md 2019-02-16 22:51:42 +08:00
暮光:城中城
b5a08d080c 增加关于页面 2019-02-15 21:23:42 +08:00
暮光:城中城
4d51b48429 dubbo文档操作接口和页面 2019-02-15 20:58:37 +08:00
暮光:城中城
4a7541d7e7 dubbo文档展示优化 2019-02-14 23:00:32 +08:00
暮光:城中城
705308938e 更新 README.md 2019-02-14 22:58:04 +08:00
暮光:城中城
6c936d46b4 dubbo文档操作接口和页面 2019-02-14 22:38:18 +08:00
暮光:城中城
e42ad1b3eb dubbo文档展示优化 2019-02-13 23:06:49 +08:00
暮光:城中城
a01cba771c dubbo文档操作接口和页面 2019-02-13 21:33:33 +08:00
暮光:城中城
62b6a17c21 dubbo文档操作接口和页面 2019-02-13 21:29:09 +08:00
暮光:城中城
cca2effbd2 dubbo文档优化 2019-02-12 22:33:33 +08:00
暮光:城中城
92ca7fcd4e 增加dubbo接口文档 2019-02-12 21:33:41 +08:00
暮光:城中城
619aa2e950 更新 README.md 2019-02-12 12:49:38 +08:00
暮光:城中城
e11629f77f 日志输出修改 2019-02-03 13:27:31 +08:00
暮光:城中城
fb0d78ea7a 按规范修改 2019-02-02 21:52:09 +08:00
暮光:城中城
e96418e346 各种细节打磨优化,增加提示 2019-02-02 21:17:44 +08:00
暮光:城中城
15cfa7e2d1 白名单使用正则匹配 2019-02-01 18:37:55 +08:00
暮光:城中城
620c7d02e8 开放文档逻辑修改,增加开关 2019-01-30 23:10:28 +08:00
暮光:城中城
496bb0d106 增加白名单域名,优化开放文档,优化展示 2019-01-30 22:21:52 +08:00
暮光:城中城
c8ac59e59a 开放文档逻辑修改 2019-01-28 23:12:55 +08:00
暮光:城中城
c2b64d06e4 增加开放文档逻辑,优化文档展示 2019-01-28 22:26:34 +08:00
暮光:城中城
15eecc7ee0 优化文档存储,展示文档选择 2019-01-27 22:32:14 +08:00
暮光:城中城
c32fc3f05d 优化文档存储,展示文档选择 2019-01-27 22:28:35 +08:00
364 changed files with 83810 additions and 2298 deletions

5
.gitignore vendored Normal file
View File

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

View File

@@ -1,7 +1,13 @@
# zyplayer-doc
#### 项目介绍
定位为所有文档的管理项目swagger文档、数据库文档....等,提供一整套的解决方案,欢迎有想法的一起来写
定位为所有文档的管理项目swagger文档、dubbo文档、数据库文档、wiki文档....等,提供一整套的解决方案,为开发者服务,欢迎有想法的一起来写给个Star鼓励下呗您的一个Star是快速迭代的动力源泉
欢迎加群讨论QQ群号466363173
体验地址:[http://doc.zyplayer.com](http://doc.zyplayer.com/zyplayer-doc-manage/) 需登录 账号zyplayer 密码123456 未运行dubbo服务不能体验dubbo文档调试
各模块的详细使用文档地址,部署必看:
[http://doc.zyplayer.com/zyplayer-doc-manage/open-wiki.html?pageId=1&space=23f3f59a60824d21af9f7c3bbc9bc3cb](http://doc.zyplayer.com/zyplayer-doc-manage/open-wiki.html?pageId=1&space=23f3f59a60824d21af9f7c3bbc9bc3cb)
#### 软件架构
##### 一、zyplayer-doc-core 一些核心、公用的类
@@ -10,28 +16,35 @@
> 原[zyplayer-doc-db](https://gitee.com/zyplayer/zyplayer-doc-db),具有数据库文档的查看、管理、导出等功能
##### 三、zyplayer-doc-manage 可以单独部署的文档管理后台
> 后端使用spring-boot、mybatis-plus、springfox-swagger等框架前端使用[zui](http://zui.sexy/)、[Vue](https://cn.vuejs.org/)等框架
> 后端使用spring-boot、mybatis-plus、springfox-swagger等框架前端使用[zui](http://zui.sexy/)、[Vue](https://cn.vuejs.org/)、[element-ui](http://element-cn.eleme.io)等框架
> 已集成三套优秀swagger文档前端[zyplayer-doc-swagger](https://gitee.com/zyplayer/zyplayer-doc)、[swagger-bootstrap-ui](https://gitee.com/xiaoym/swagger-bootstrap-ui)、[springfox-swagger-ui](https://github.com/springfox/springfox/tree/master/springfox-swagger-ui)
> 已集成[zyplayer-doc-db](https://gitee.com/zyplayer/zyplayer-doc)数据库文档
> 已集成本项目内的各子模块,可直接使用
##### 四、zyplayer-doc-swagger 原[swagger-mg-ui](https://gitee.com/zyplayer/swagger-mg-ui)swagger的UI及整套解决方案
> 具有 后端存储、代理请求、模拟返回、所有文档管理 等一系列原创功能不止UI
##### 五、zyplayer-doc-dubbo 将dubbo的文档在线化管理
> 支持zookeeper、nacos的注册中心文档获取支持在线调试接口
##### 六、zyplayer-doc-wiki wiki文档工具
> 支持文档创建、展示,文件上传、下载,空间隔离,开放文档访问等
##### 七、zyplayer-doc-grpc grpc文档工具
> 用比较变态的方式实现了grpc的文档和在线调试功能通过http的方式来请求grpc的接口
> 默认未开启此功能如需使用需要在zyplayer-doc-manage项目中开启@EnableDocGrpc注解
#### 运行方式
1. 创建数据库zyplayer_doc_manage执行脚本[zyplayer_doc_manage.sql](https://gitee.com/zyplayer/zyplayer-doc/blob/master/zyplayer-doc-manage/src/main/resources/sql/zyplayer_doc_manage.sql)
1. 创建数据库zyplayer_doc_manage执行脚本[zyplayer_doc_manage.1.0.2.sql](https://gitee.com/zyplayer/zyplayer-doc/blob/master/zyplayer-doc-manage/src/main/resources/sql/zyplayer_doc_manage.1.0.2.sql)
2. 修改zyplayer-doc-manage项目的application.yml配置文件里面的数据库账号密码
3. 启动zyplayer-doc-manage项目访问地址
http://127.0.0.1:8082/zyplayer-doc-manage/statics/manage/home.html
未登录会进入登录页面登陆后自动跳回默认账号zyplayer 密码:123456
> 项目页面全是静态的html如果使用idea启动有可能访问不了静态页面需要在这里配置下工作目录然后重新启动即可
![](https://images.gitee.com/uploads/images/2019/0125/094619_7f8963bf_596905.png "配置工作目录")
3. 启动zyplayer-doc-manage项目访问地址http://127.0.0.1:8083/zyplayer-doc-manage/
#### 功能介绍
#### 模块介绍
##### 一、zyplayer-doc-swagger
1.`zyplayer-doc-swagger`->`文档管理`->`文档地址管理` 页可以管理`任意地址`的文档在集成的三套UI中都可以直接查看和调试这里配置的文档不用对UI做任何调整只要标准的UI集成进来也可以直接用
@@ -55,33 +68,26 @@ http://127.0.0.1:8082/zyplayer-doc-manage/statics/manage/home.html
2. 支持多数据源,在`zyplayer-doc-manage` -> `application.yml` -> `zyplayer.doc.db.dbConfigList` 处配置多个数据库连接即可
##### 三、zyplayer-doc-manage
##### 三、zyplayer-doc-dubbo
1. `zyplayer-doc-manage` -> `application.yml` -> `zyplayer.dubbo.zookeeper.url` 配置zookeeper地址
2. `zyplayer-doc-manage` -> `application.yml` -> `zyplayer.dubbo.nacos.url` 配置nacos服务地址
3. 默认找zookeeper未配置再找nacos的配置
4. 支持文档查找、文档编辑、在线调试接口
5. 自动获取参数列表需要指定的类存在,所以请在 pom.xml -> dependencies 最后加上服务所在的包后端才能通过Class.forName("xx");来找到参数列表,减少录入成本
6. 数组或List参数调试参数录入格式例[1,2] 后端通过JSON工具转成指定类型有不支持的类型时欢迎反馈
##### 四、zyplayer-doc-manage
1. 整合了上面两个功能到此项目,较少熟悉成本,`git clone`下来即可运行
2. 具有简单的`权限管理``人员管理`功能(还没想好具体怎么控制,没需求)
3. 使用最新的一些技术框架,很简单,初学者拿来学习也是很不错的
#### 界面展示
权限和用户管理:
![](https://images.gitee.com/uploads/images/2018/1216/224050_3f93dd4a_596905.png "屏幕截图.png")
数据库文档:
![](https://images.gitee.com/uploads/images/2018/1219/231332_0a95e458_596905.png "屏幕截图.png")
增加文档处:
![](https://images.gitee.com/uploads/images/2019/0108/225208_6f4a9a64_596905.png "屏幕截图.png")
使用springfox-swagger-ui访问增加的文档
![](https://images.gitee.com/uploads/images/2019/0108/225313_76ab6962_596905.png "屏幕截图.png")
文档展示:
![](https://images.gitee.com/uploads/images/2019/0108/224850_6940f92e_596905.png "屏幕截图.png")
在线调试:
![](https://images.gitee.com/uploads/images/2019/0108/224934_cb4cedea_596905.png "屏幕截图.png")
模拟返回:
![](https://images.gitee.com/uploads/images/2019/0108/224958_1f20b45d_596905.png "屏幕截图.png")
文档配置:
![](https://images.gitee.com/uploads/images/2019/0108/225024_1c8b2526_596905.png "屏幕截图.png")
全局参数管理:
![](https://images.gitee.com/uploads/images/2019/0108/225056_d2e861df_596905.png "屏幕截图.png")
更多详细的使用部署文档http://doc.zyplayer.com/zyplayer-doc-manage/open-wiki.html?pageId=1&space=23f3f59a60824d21af9f7c3bbc9bc3cb
如果觉得此项目对您有帮助,就捐赠一个吧!无关金额,主要是对作者的认可。

35
pom.xml
View File

@@ -4,7 +4,7 @@
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc</artifactId>
<version>1.0.0</version>
<version>1.0.2</version>
<packaging>pom</packaging>
<name>zyplayer-doc</name>
@@ -17,36 +17,15 @@
<fastjson.version>1.2.53</fastjson.version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<modules>
<module>zyplayer-doc-db</module>
<module>zyplayer-doc-manage</module>
<module>zyplayer-doc-swagger</module>
<module>zyplayer-doc-core</module>
<module>zyplayer-doc-dubbo</module>
<module>zyplayer-doc-wiki</module>
<module>zyplayer-doc-data</module>
<module>zyplayer-doc-grpc</module>
<module>zyplayer-doc-page</module>
</modules>
</project>
</project>

16
upgrade.properties Normal file
View File

@@ -0,0 +1,16 @@
# 本文件用于已部署好的系统检测自己是否需要升级使用
lastVersion=1.0.2
upgradeContent=1、移除spring security重构权限和登录逻辑\
2、wiki文档页面增加权限控制分为文章删除、上传附件删除附件、文章修改、权限管理\
3、使用vue重构wiki前端使得页面分离更好维护\
4、wiki文档增加阅读数\
5、wiki文档支持拖动改变文章顺序\
6、wiki删除时使用递归删除子页面\
7、wiki文档增加首页的文章列表支持更新时间、创建时间、阅读数和点赞数等排序方式\
8、重构首页用户管理页增加重置密码、停用用户等功能更加简洁、美观\
9、swagger和dubbo部分问题修改
upgradeUrl=https://gitee.com/zyplayer/zyplayer-doc/releases
nextStep=1、数据库文档使用vue重构前端页面采用左右结构方式展示\
2、数据库文档数据源支持页面上动态增加、删除\
3、dubbo着重优化文档查看和nacos文档获取优化

View File

@@ -0,0 +1,9 @@
# zyplayer-doc-core
#### 项目介绍
整个项目的公用模块
模块的详细使用文档地址,部署必看:
http://doc.zyplayer.com/zyplayer-doc-manage/open-wiki.html?pageId=1&space=23f3f59a60824d21af9f7c3bbc9bc3cb

View File

@@ -3,14 +3,10 @@
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc-core</artifactId>
<version>1.0.0</version>
<version>1.0.2</version>
<name>zyplayer-doc-core</name>
<url>http://maven.apache.org</url>
@@ -18,9 +14,33 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<fastjson.version>1.2.53</fastjson.version>
<pagehelper.version>4.1.6</pagehelper.version>
<springfox.swagger.version>2.9.2</springfox.swagger.version>
</properties>
<dependencies>
</dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.swagger.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${pagehelper.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,12 @@
package com.zyplayer.doc.core.annotation;
import java.lang.annotation.*;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthMan {
String[] value() default {};
String authUrl() default "common/authfailed";
boolean all() default false;
}

View File

@@ -1,16 +1,15 @@
package com.zyplayer.doc.core.json;
import java.io.IOException;
import java.util.Date;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiModelProperty;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* 文档返回数据格式
*
@@ -27,13 +26,21 @@ public class DocResponseJson<T> implements ResponseJson<T> {
@ApiModelProperty(value = "返回值说明")
private String errMsg;
@ApiModelProperty(value = "返回数据")
private T data;
private Object data;
@ApiModelProperty(value = "总数")
private Long total;
@ApiModelProperty(value = "当前页数")
private Integer pageNum;
@ApiModelProperty(value = "每页条数")
private Integer pageSize;
@ApiModelProperty(value = "总页数")
private Integer totalPage;
public DocResponseJson() {
this.errCode = 200;
}
public DocResponseJson(T data) {
public DocResponseJson(Object data) {
this.setData(data);
this.errCode = 200;
}
@@ -44,7 +51,7 @@ public class DocResponseJson<T> implements ResponseJson<T> {
this.errMsg = errMsg;
}
public DocResponseJson(int errCode, String errMsg, T data) {
public DocResponseJson(int errCode, String errMsg, Object data) {
super();
this.setData(data);
this.errCode = errCode;
@@ -71,13 +78,56 @@ public class DocResponseJson<T> implements ResponseJson<T> {
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public T getData() {
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getTotalPage() {
return totalPage;
}
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
public Object getData() {
return data;
}
public void setData(T data) {
this.data = data;
public void setData(Object data) {
if (null != data) {
if (data instanceof PageInfo) {
PageInfo<?> pageInfo = (PageInfo<?>) data;
this.data = pageInfo.getList();
this.total = pageInfo.getTotal();
this.pageNum = pageInfo.getPageNum();
this.pageSize = pageInfo.getPageSize();
this.totalPage = pageInfo.getPages();
} else {
this.data = data;
}
}
}
/**
@@ -101,16 +151,16 @@ public class DocResponseJson<T> implements ResponseJson<T> {
public static <T> DocResponseJson<T> error(String errMsg) {
return new DocResponseJson<T>(500, errMsg);
}
/**
* 成功的返回方法
*
* 失败
*
* @author 暮光:城中城
* @since 2018年8月7日
* @return
*/
public static <T> DocResponseJson<T> ok() {
return new DocResponseJson<T>();
public static <T> DocResponseJson<T> failure(int errCode, String errMsg) {
return new DocResponseJson<T>(errCode, errMsg);
}
/**
@@ -120,11 +170,22 @@ public class DocResponseJson<T> implements ResponseJson<T> {
* @since 2018年8月7日
* @return
*/
public static <T> DocResponseJson<T> ok(T data) {
public static <T> DocResponseJson<T> ok() {
return new DocResponseJson<>();
}
/**
* 成功的返回方法
*
* @author 暮光:城中城
* @since 2018年8月7日
* @return
*/
public static <T> DocResponseJson<T> ok(Object data) {
if (data == null) {
return DocResponseJson.ok();
}
DocResponseJson<T> responseJson = new DocResponseJson<T>();
DocResponseJson<T> responseJson = new DocResponseJson<>();
responseJson.setData(data);
return responseJson;
}

View File

@@ -0,0 +1,67 @@
package com.zyplayer.doc.core.json;
public class HttpConst {
/** 每页显示条数 **/
public static final int PAGE_NUMBER = 50;
/** 默认当前页 **/
public static final int CURRENT_PAGE = 1;
/** 图片验证码 **/
public static final String SESSION_VERIFY_CODE = "SESSION_VERIFY_CODE";
/** 邮箱验证码 **/
public static final String SESSION_EMAIL_CODE = "SESSION_EMAIL_CODE";
/** 请求失败的原因 **/
public static final String SESSION_FAIL_REASON = "SESSION_FAIL_REASON";
/** operator */
public static final String OPERATOR = "OPERATOR";
/** 分页-总条数 */
public static final String PAGE_TOTAL = "PAGE_TOTAL";
/** 分页-当前页数 */
public static final String PAGE_NOWPAGE = "PAGE_NOWPAGE";
/** 分页-总页数 */
public static final String PAGE_PAGECOUNT = "PAGE_PAGECOUNT";
/** 分页-每页多少条 */
public static final String PAGE_SIZE = "PAGE_SIZE";
/** 会话连接 */
public static final String ACCESS_TOKEN = "accessToken";
/** 存在于ThreadLocal的http request */
public static final String HTTP_SERVLET_REQUEST = "HTTP_SERVLET_REQUEST";
/** 存在于ThreadLocal的HTTP_SESSION */
public static final String HTTP_SESSION = "HTTP_SESSION";
/** 存于operator中权限的缓存头 **/
public static final String AUTH_CACHE_HEAD = "AUTH_CACHE_HEAD_";
/** 存于operator中的用户信息 **/
public static final String CACHE_OPERATOR_USER_INFO = "USER_INFO";
/** 存于operator中的城市信息 **/
public static final String CACHE_OPERATOR_CITY_ID = "CITY_ID";
/** 存于operator中的token绑定的访问信息使得换一台电脑不能使用此token **/
public static final String CACHE_OPERATOR_ACCESS_TOKEN_VALIDATE = "ACCESS_TOKEN_VALIDATE";
/** 存于operator中的token信息 **/
public static final String CACHE_OPERATOR_ACCESS_TOKEN = "accessToken";
/** 存于operator中的微信sessionKey信息 **/
public static final String CACHE_OPERATOR_SESSION_KEY = "sessionKey";
// 新版本使用的错误码
/** 成功 **/
public static final int SUCCESS = 200;
/** 提示性状态 需要客户端配合展示 **/
public static final int CONFIRM_CODE = 300;
/** accessToken非法或过期需要重新登录 **/
public static final int TOKEN_TIMEOUT = 400;
/** 业务接口缺少参数errMsg会返回错误信息 **/
public static final int MISSING_PARAMETER = 401;
/** API 未授权 **/
public static final int UNAUTHORIZED = 402;
/** 接口调用频率超限 **/
public static final int CALL_FREQUENCY_GAUGE = 403;
/** 微信未扫码登录异常 **/
public static final int WX_NOT_LOGIN = 404;
/** 请升级至新版使用此功能 **/
public static final int NEED_UPGRADE = 405;
/** 服务器端未知错误 **/
public static final int OTHER_FAIL = 500;
}

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.core.util;
import javax.servlet.http.HttpServletRequest;
public class ThreadLocalUtil {
private static ThreadLocal<HttpServletRequest> request = new ThreadLocal<>();
public static void setHttpServletRequest(HttpServletRequest request) {
ThreadLocalUtil.request.set(request);
}
public static HttpServletRequest getHttpServletRequest() {
return ThreadLocalUtil.request.get();
}
public static void clean() {
ThreadLocalUtil.request.remove();
}
}

View File

@@ -0,0 +1,9 @@
# zyplayer-doc-data
#### 项目介绍
整个项目的数据核心,操作数据库、登录拦截、权限拦截等
模块的详细使用文档地址,部署必看:
http://doc.zyplayer.com/zyplayer-doc-manage/open-wiki.html?pageId=1&space=23f3f59a60824d21af9f7c3bbc9bc3cb

107
zyplayer-doc-data/pom.xml Normal file
View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc-data</artifactId>
<version>1.0.2</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mybatis.plus.boot.starter.version>3.0.6</mybatis.plus.boot.starter.version>
<fastjson.version>1.2.53</fastjson.version>
<velocity.engine.core.version>2.0</velocity.engine.core.version>
<dozer.core.version>6.1.0</dozer.core.version>
<alibaba.druid.version>1.1.9</alibaba.druid.version>
<zyplayer.doc.version>1.0.2</zyplayer.doc.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.boot.starter.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${alibaba.druid.version}</version>
</dependency>
<!-- json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.github.dozermapper</groupId>
<artifactId>dozer-core</artifactId>
<version>${dozer.core.version}</version>
</dependency>
<!-- 在线文档解析页面 -->
<!--zyplayer-doc-core-->
<dependency>
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc-core</artifactId>
<version>${zyplayer.doc.version}</version>
</dependency>
<!-- velocity 模板引擎, 默认 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity.engine.core.version}</version>
</dependency>
<!-- freemarker 模板引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!-- 整合spring security -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-security</artifactId>-->
<!-- </dependency>-->
<!-- aspectj -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,78 @@
package com.zyplayer.doc.data.aspect;
import com.google.common.collect.Maps;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.HttpConst;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.core.util.ThreadLocalUtil;
import com.zyplayer.doc.data.config.security.DocUserDetails;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import com.zyplayer.doc.data.service.manage.UserAuthService;
import com.zyplayer.doc.data.utils.BeanUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.Map;
@Aspect
@Component
public class AuthAspect {
@Resource
private UserAuthService userAuthService;
@Around(value = "@annotation(com.zyplayer.doc.core.annotation.AuthMan) || @within(com.zyplayer.doc.core.annotation.AuthMan)")
public Object authController(ProceedingJoinPoint pjp) throws Throwable {
AuthMan authMan = BeanUtil.getAnnotation(pjp, AuthMan.class);
ResponseBody responseBody = BeanUtil.getAnnotation(pjp, ResponseBody.class);
RestController restController = BeanUtil.getAnnotation(pjp, RestController.class);
boolean isResponseBody = (restController != null || responseBody != null);
Class<?> returnType = ((MethodSignature) pjp.getSignature()).getMethod().getReturnType();
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
if (currentUser == null) {
String reason = "你访问的内容需要登录,请登录后再试";
if (isResponseBody) {
return DocResponseJson.failure(HttpConst.TOKEN_TIMEOUT, reason);
} else if (returnType.isAssignableFrom(ModelAndView.class)) {
HttpServletRequest request = ThreadLocalUtil.getHttpServletRequest();
StringBuffer requestURL = request.getRequestURL();
String requestURLStr = URLEncoder.encode(requestURL.toString(), "utf-8");
return new ModelAndView("redirect:#/user/login?redirect=" + requestURLStr);
} else if (returnType.isAssignableFrom(Map.class)) {
return Maps.newHashMap();
}
}
// 判断权限是否足够
boolean haveAuth = DocUserUtil.haveAuth(authMan.value());
if (haveAuth) {
return pjp.proceed();
}
String reasonStr = "没有操作权限,请联系管理员";
if (isResponseBody) {
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
if (method.getReturnType().equals(ResponseJson.class)) {
return DocResponseJson.warn(reasonStr);
} else {
try {
return Class.forName(method.getReturnType().getName()).newInstance();
} catch (Exception e) {
return null;
}
}
} else {
return authMan.authUrl();
}
}
}

View File

@@ -0,0 +1,91 @@
package com.zyplayer.doc.data.config;
import com.zyplayer.doc.core.json.HttpConst;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 登录和跨域拦截器
* @author 暮光:城中城
* @since 2019年05月25日
*/
@Component
public class DocLoginOriginInterceptor implements HandlerInterceptor {
@Value("${zyplayer.doc.manage.originDomainRegex:''}")
private String originDomainRegex;
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3) {
// 清理用户信息
DocUserUtil.clean();
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object haddler, ModelAndView modelAndView) {
}
/**
* 记录请求信息
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) {
// 指定域名可跨域访问
if (StringUtils.isNotBlank(originDomainRegex)) {
String origin = request.getHeader("Origin");
if (StringUtils.isNotBlank(origin) && origin.toLowerCase().matches(originDomainRegex)) {
response.setHeader("Access-Control-Allow-Origin", origin); // 允许访问的域
response.setHeader("Access-Control-Allow-Methods", "HEAD,GET,POST,PUT,DELETE");// 允许GET、POST的外域请求
response.setHeader("Access-Control-Allow-Credentials", "true"); // 允许请求带cookie到服务器
response.setContentType("application/json; charset=utf-8"); // 设定JSON格式标准输出、及编码
}
}
// 清理用户信息
DocUserUtil.clean();
// 设置token
String accessToken = getCookieValueByRequest(request, HttpConst.ACCESS_TOKEN);
DocUserUtil.setAccessToken(accessToken);
return true;
}
/**
* 获取cookie
*
* @param request
* @param name
* @return
*/
public static Cookie getCookieByRequest(HttpServletRequest request, String name) {
if (StringUtils.isEmpty(name)) {
return null;
}
Cookie[] cookies = request.getCookies();
for (int i = 0; (cookies != null) && (i < cookies.length); i++) {
Cookie cookie = cookies[i];
if (name.equals(cookie.getName())) {
return cookie;
}
}
return null;
}
/**
* 获取cookie值
*
* @param request
* @param name
* @return
*/
public static String getCookieValueByRequest(HttpServletRequest request, String name) {
Cookie cookie = getCookieByRequest(request, name);
return cookie == null ? null : cookie.getValue();
}
}

View File

@@ -1,11 +1,12 @@
package com.zyplayer.doc.manage.framework.config;
package com.zyplayer.doc.data.config;
import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zyplayer.doc.manage.repository.support.interceptor.SqlLogInterceptor;
import com.github.pagehelper.PageHelper;
import com.zyplayer.doc.data.repository.support.interceptor.SqlLogInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
@@ -27,60 +28,72 @@ import java.util.Properties;
*/
@Configuration
public class MybatisPlusConfig {
/**
* sql日志
**/
private static final SqlLogInterceptor SQL_LOG_INTERCEPTOR;
/**
* MYSQL 分页
**/
private static final PageHelper MYSQL_PAGE_HELPER;
static {
SQL_LOG_INTERCEPTOR = new SqlLogInterceptor();
Properties properties = new Properties();
SQL_LOG_INTERCEPTOR.setProperties(properties);
{
MYSQL_PAGE_HELPER = new PageHelper();
Properties properties = new Properties();
properties.setProperty("dialect", "mysql");
MYSQL_PAGE_HELPER.setProperties(properties);
}
{
SQL_LOG_INTERCEPTOR = new SqlLogInterceptor();
Properties properties = new Properties();
SQL_LOG_INTERCEPTOR.setProperties(properties);
}
}
/**
* 分布式事务配置
*/
@Configuration
static class JTATransactionManagerConfig {
@Bean(name = "userTransaction")
public UserTransaction userTransaction() throws Throwable {
UserTransactionImp userTransactionImp = new UserTransactionImp();
userTransactionImp.setTransactionTimeout(300);
return userTransactionImp;
}
@Bean(name = "atomikosTransactionManager")
public TransactionManager atomikosTransactionManager() {
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(true);
return userTransactionManager;
}
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager() throws Throwable {
UserTransaction userTransaction = userTransaction();
TransactionManager atomikosTransactionManager = atomikosTransactionManager();
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(userTransaction, atomikosTransactionManager);
jtaTransactionManager.setAllowCustomIsolationLevels(true);
jtaTransactionManager.setGlobalRollbackOnParticipationFailure(true);
jtaTransactionManager.setDefaultTimeout(30);
return jtaTransactionManager;
}
}
/**
* 数据库配置
*/
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.zyplayer.doc.manage.repository.manage.mapper", sqlSessionFactoryRef = "manageSqlSessionFactory")
@MapperScan(value = "com.zyplayer.doc.data.repository.manage.mapper", sqlSessionFactoryRef = "manageSqlSessionFactory")
static class ManageMybatisDbConfig {
@Value("${zyplayer.doc.manage.datasource.driverClassName}")
private String driverClassName;
@Value("${zyplayer.doc.manage.datasource.url}")
@@ -89,7 +102,7 @@ public class MybatisPlusConfig {
private String username;
@Value("${zyplayer.doc.manage.datasource.password}")
private String password;
@Bean(name = "manageDatasource")
public DataSource manageDatasource() {
Properties xaProperties = new Properties();
@@ -101,7 +114,7 @@ public class MybatisPlusConfig {
xaProperties.setProperty("testOnBorrow", "true");
xaProperties.setProperty("testWhileIdle", "true");
xaProperties.setProperty("validationQuery", "select 'x'");
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaProperties(xaProperties);
xaDataSource.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
@@ -111,19 +124,19 @@ public class MybatisPlusConfig {
xaDataSource.setMaxLifetime(60);
return xaDataSource;
}
@Bean(name = "manageSqlSessionFactory")
public MybatisSqlSessionFactoryBean manageSqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(manageDatasource());
sqlSessionFactoryBean.setPlugins(new Interceptor[]{SQL_LOG_INTERCEPTOR});
sqlSessionFactoryBean.setPlugins(new Interceptor[]{SQL_LOG_INTERCEPTOR, MYSQL_PAGE_HELPER});
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mapper/manage/*Mapper.xml"));
return sqlSessionFactoryBean;
}
}
@Bean
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
@@ -133,9 +146,9 @@ public class MybatisPlusConfig {
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
}

View File

@@ -0,0 +1,84 @@
package com.zyplayer.doc.data.config.security;
import java.util.Set;
public class DocUserDetails {
private Long userId;
private String username;
private String password;
private boolean enabled;
private Set<String> authorities;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Set<String> getAuthorities() {
return authorities;
}
public void setAuthorities(Set<String> authorities) {
this.authorities = authorities;
}
public DocUserDetails(Long userId, String username) {
this.userId = userId;
this.username = username;
}
public DocUserDetails(Long userId, String username, String password, boolean enabled) {
super();
this.userId = userId;
this.username = username;
this.password = password;
this.enabled = enabled;
}
public DocUserDetails(Long userId, String username, String password, boolean enabled, Set<String> authorities) {
super();
this.userId = userId;
this.username = username;
this.password = password;
this.enabled = enabled;
this.authorities = authorities;
}
@Override
public String toString() {
return "DocUserDetails{" +
"userId=" + userId +
", username='" + username + '\'' +
", password='" + password + '\'' +
", enabled=" + enabled +
", authorities=" + authorities +
'}';
}
}

View File

@@ -0,0 +1,70 @@
package com.zyplayer.doc.data.config.security;
import com.zyplayer.doc.data.utils.CacheUtil;
/**
* 用户工具类
* @author 暮光:城中城
* @since 2019年05月25日
*/
public class DocUserUtil {
private static ThreadLocal<DocUserDetails> DOC_USER_DETAILS = new ThreadLocal<>();
private static ThreadLocal<String> ACCESS_TOKEN = new ThreadLocal<>();
public static void setAccessToken(String accessToken) {
DocUserUtil.ACCESS_TOKEN.set(accessToken);
}
public static boolean havePageAuth(String authName, Long pageId) {
return haveAuth(authName + pageId);
}
public static boolean haveAuth(String... authNames) {
DocUserDetails currentUser = getCurrentUser();
if (currentUser == null) {
return false;
}
for (String authName : authNames) {
if (!currentUser.getAuthorities().contains(authName)) {
return false;
}
}
return true;
}
/**
* 获取当前用户
*
* @return 用户信息
*/
public static DocUserDetails getCurrentUser() {
DocUserDetails docUser = DOC_USER_DETAILS.get();
if (docUser == null) {
docUser = CacheUtil.get(ACCESS_TOKEN.get());
if (docUser != null) {
DOC_USER_DETAILS.set(docUser);
}
}
return docUser;
}
/**
* 设置当前用户
*/
public static void setCurrentUser(String accessToken, DocUserDetails docUser) {
DOC_USER_DETAILS.set(docUser);
CacheUtil.put(accessToken, docUser);
}
/**
* 退出登录
*/
public static void logout() {
CacheUtil.remove(ACCESS_TOKEN.get());
}
public static void clean() {
DocUserUtil.DOC_USER_DETAILS.remove();
DocUserUtil.ACCESS_TOKEN.remove();
}
}

View File

@@ -1,13 +1,14 @@
package com.zyplayer.doc.manage.repository.manage.entity;
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
*
* </p>
*
* @author 暮光城中城

View File

@@ -1,4 +1,4 @@
package com.zyplayer.doc.manage.repository.manage.entity;
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
@@ -7,11 +7,11 @@ import java.io.Serializable;
/**
* <p>
*
* 用户权限表
* </p>
*
* @author 暮光城中城
* @since 2018-12-05
* @since 2019-05-31
*/
public class UserAuth implements Serializable {
@@ -58,6 +58,11 @@ public class UserAuth implements Serializable {
*/
private Date updateTime;
/**
* 自定义权限结尾
*/
private String authCustomSuffix;
public Long getId() {
return id;
}
@@ -114,6 +119,13 @@ public class UserAuth implements Serializable {
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getAuthCustomSuffix() {
return authCustomSuffix;
}
public void setAuthCustomSuffix(String authCustomSuffix) {
this.authCustomSuffix = authCustomSuffix;
}
@Override
public String toString() {
@@ -126,6 +138,7 @@ public class UserAuth implements Serializable {
", delFlag=" + delFlag +
", creationTime=" + creationTime +
", updateTime=" + updateTime +
", authCustomSuffix=" + authCustomSuffix +
"}";
}
}

View File

@@ -1,13 +1,14 @@
package com.zyplayer.doc.manage.repository.manage.entity;
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
*
* </p>
*
* @author 暮光城中城
@@ -68,6 +69,16 @@ public class UserInfo implements Serializable {
*/
private Date updateTime;
/**
* 手机号
*/
private String phone;
/**
* 性别 0= 1=
*/
private Integer sex;
public Long getId() {
return id;
}
@@ -154,4 +165,20 @@ public class UserInfo implements Serializable {
", updateTime=" + updateTime +
"}";
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
}

View File

@@ -0,0 +1,236 @@
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author 暮光:城中城
* @since 2019-06-06
*/
public class WikiPage implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键自增ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 空间ID
*/
private Long spaceId;
/**
* 名字
*/
private String name;
/**
* 父ID
*/
private Long parentId;
/**
* 节点类型 0=有子节点 1=终节点
*/
private Integer nodeType;
/**
* 赞的数量
*/
private Integer zanNum;
/**
* 编辑类型 0=可编辑 1=不允许编辑
*/
private Integer editType;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人名字
*/
private String createUserName;
/**
* 创建时间
*/
private Date createTime;
/**
* 修改人ID
*/
private Long updateUserId;
/**
* 修改人名字
*/
private String updateUserName;
/**
* 修改时间
*/
private Date updateTime;
/**
* 0=有效 1=删除
*/
private Integer delFlag;
/**
* 阅读数
*/
private Integer viewNum;
/**
* 顺序
*/
private Integer seqNo;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getSpaceId() {
return spaceId;
}
public void setSpaceId(Long spaceId) {
this.spaceId = spaceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public Integer getNodeType() {
return nodeType;
}
public void setNodeType(Integer nodeType) {
this.nodeType = nodeType;
}
public Integer getZanNum() {
return zanNum;
}
public void setZanNum(Integer zanNum) {
this.zanNum = zanNum;
}
public Integer getEditType() {
return editType;
}
public void setEditType(Integer editType) {
this.editType = editType;
}
public Long getCreateUserId() {
return createUserId;
}
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
public String getCreateUserName() {
return createUserName;
}
public void setCreateUserName(String createUserName) {
this.createUserName = createUserName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Long getUpdateUserId() {
return updateUserId;
}
public void setUpdateUserId(Long updateUserId) {
this.updateUserId = updateUserId;
}
public String getUpdateUserName() {
return updateUserName;
}
public void setUpdateUserName(String updateUserName) {
this.updateUserName = updateUserName;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public Integer getDelFlag() {
return delFlag;
}
public void setDelFlag(Integer delFlag) {
this.delFlag = delFlag;
}
public Integer getViewNum() {
return viewNum;
}
public void setViewNum(Integer viewNum) {
this.viewNum = viewNum;
}
public Integer getSeqNo() {
return seqNo;
}
public void setSeqNo(Integer seqNo) {
this.seqNo = seqNo;
}
@Override
public String toString() {
return "WikiPage{" +
"id=" + id +
", spaceId=" + spaceId +
", name=" + name +
", parentId=" + parentId +
", nodeType=" + nodeType +
", zanNum=" + zanNum +
", editType=" + editType +
", createUserId=" + createUserId +
", createUserName=" + createUserName +
", createTime=" + createTime +
", updateUserId=" + updateUserId +
", updateUserName=" + updateUserName +
", updateTime=" + updateTime +
", delFlag=" + delFlag +
", viewNum=" + viewNum +
", seqNo=" + seqNo +
"}";
}
}

View File

@@ -0,0 +1,131 @@
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author 暮光:城中城
* @since 2019-02-24
*/
public class WikiPageComment implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键自增ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 页面ID
*/
private Long pageId;
/**
* 父评论ID
*/
private Long parentId;
/**
* 评论内容
*/
private String content;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人名字
*/
private String createUserName;
/**
* 创建时间
*/
private Date createTime;
/**
* 0=有效 1=删除
*/
private Integer delFlag;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPageId() {
return pageId;
}
public void setPageId(Long pageId) {
this.pageId = pageId;
}
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Long getCreateUserId() {
return createUserId;
}
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
public String getCreateUserName() {
return createUserName;
}
public void setCreateUserName(String createUserName) {
this.createUserName = createUserName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Integer getDelFlag() {
return delFlag;
}
public void setDelFlag(Integer delFlag) {
this.delFlag = delFlag;
}
@Override
public String toString() {
return "WikiPageComment{" +
"id=" + id +
", pageId=" + pageId +
", parentId=" + parentId +
", content=" + content +
", createUserId=" + createUserId +
", createUserName=" + createUserName +
", createTime=" + createTime +
", delFlag=" + delFlag +
"}";
}
}

View File

@@ -0,0 +1,158 @@
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author 暮光:城中城
* @since 2019-02-24
*/
public class WikiPageContent implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键自增ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 页面ID
*/
private Long pageId;
/**
* 内容
*/
private String content;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人名字
*/
private String createUserName;
/**
* 创建时间
*/
private Date createTime;
/**
* 修改人ID
*/
private Long updateUserId;
/**
* 修改人名字
*/
private String updateUserName;
/**
* 修改时间
*/
private Date updateTime;
/**
* 预览内容
*/
private String preview;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPageId() {
return pageId;
}
public void setPageId(Long pageId) {
this.pageId = pageId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Long getCreateUserId() {
return createUserId;
}
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
public String getCreateUserName() {
return createUserName;
}
public void setCreateUserName(String createUserName) {
this.createUserName = createUserName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Long getUpdateUserId() {
return updateUserId;
}
public void setUpdateUserId(Long updateUserId) {
this.updateUserId = updateUserId;
}
public String getUpdateUserName() {
return updateUserName;
}
public void setUpdateUserName(String updateUserName) {
this.updateUserName = updateUserName;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "WikiPageContent{" +
"id=" + id +
", pageId=" + pageId +
", content=" + content +
", createUserId=" + createUserId +
", createUserName=" + createUserName +
", createTime=" + createTime +
", updateUserId=" + updateUserId +
", updateUserName=" + updateUserName +
", updateTime=" + updateTime +
"}";
}
public String getPreview() {
return preview;
}
public void setPreview(String preview) {
this.preview = preview;
}
}

View File

@@ -0,0 +1,197 @@
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author 暮光:城中城
* @since 2019-03-06
*/
public class WikiPageFile implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键自增ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 页面ID
*/
private Long pageId;
/**
* 文件名
*/
private String fileName;
/**
* 文件URL
*/
private String fileUrl;
/**
* 文件UUID
*/
private String uuid;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人名字
*/
private String createUserName;
/**
* 创建时间
*/
private Date createTime;
/**
* 修改人ID
*/
private Long updateUserId;
/**
* 修改人名字
*/
private String updateUserName;
/**
* 修改时间
*/
private Date updateTime;
/**
* 0=有效 1=删除
*/
private Integer delFlag;
/**
* 下载次数
*/
private Integer downloadNum;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPageId() {
return pageId;
}
public void setPageId(Long pageId) {
this.pageId = pageId;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileUrl() {
return fileUrl;
}
public void setFileUrl(String fileUrl) {
this.fileUrl = fileUrl;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public Long getCreateUserId() {
return createUserId;
}
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
public String getCreateUserName() {
return createUserName;
}
public void setCreateUserName(String createUserName) {
this.createUserName = createUserName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Long getUpdateUserId() {
return updateUserId;
}
public void setUpdateUserId(Long updateUserId) {
this.updateUserId = updateUserId;
}
public String getUpdateUserName() {
return updateUserName;
}
public void setUpdateUserName(String updateUserName) {
this.updateUserName = updateUserName;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public Integer getDelFlag() {
return delFlag;
}
public void setDelFlag(Integer delFlag) {
this.delFlag = delFlag;
}
@Override
public String toString() {
return "WikiPageFile{" +
"id=" + id +
", pageId=" + pageId +
", fileName=" + fileName +
", fileUrl=" + fileUrl +
", uuid=" + uuid +
", createUserId=" + createUserId +
", createUserName=" + createUserName +
", createTime=" + createTime +
", updateUserId=" + updateUserId +
", updateUserName=" + updateUserName +
", updateTime=" + updateTime +
", delFlag=" + delFlag +
"}";
}
public Integer getDownloadNum() {
return downloadNum;
}
public void setDownloadNum(Integer downloadNum) {
this.downloadNum = downloadNum;
}
}

View File

@@ -0,0 +1,119 @@
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author 暮光:城中城
* @since 2019-03-05
*/
public class WikiPageZan implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键自增ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 页面ID
*/
private Long pageId;
/**
* 评论ID
*/
private Long commentId;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人名字
*/
private String createUserName;
/**
* 创建时间
*/
private Date createTime;
/**
* 是否有效 0=无效 1=有效
*/
private Integer yn;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPageId() {
return pageId;
}
public void setPageId(Long pageId) {
this.pageId = pageId;
}
public Long getCommentId() {
return commentId;
}
public void setCommentId(Long commentId) {
this.commentId = commentId;
}
public Long getCreateUserId() {
return createUserId;
}
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
public String getCreateUserName() {
return createUserName;
}
public void setCreateUserName(String createUserName) {
this.createUserName = createUserName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Integer getYn() {
return yn;
}
public void setYn(Integer yn) {
this.yn = yn;
}
@Override
public String toString() {
return "WikiPageZan{" +
"id=" + id +
", pageId=" + pageId +
", commentId=" + commentId +
", createUserId=" + createUserId +
", createUserName=" + createUserName +
", createTime=" + createTime +
", yn=" + yn +
"}";
}
}

View File

@@ -0,0 +1,184 @@
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author 暮光:城中城
* @since 2019-03-11
*/
public class WikiSpace implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键自增ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 空间名
*/
private String name;
/**
* 空间类型 1=公司 2=个人 3=私人
*/
private Integer type;
/**
* 描述
*/
private String spaceExplain;
/**
* 编辑类型 0=可编辑 1=不允许编辑
*/
private Integer editType;
/**
* 目录延迟加载 0=否 1=是
*/
private Integer treeLazyLoad;
/**
* 是否是开放文档 0=否 1=是
*/
private Integer openDoc;
/**
* 唯一UUID
*/
private String uuid;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人名字
*/
private String createUserName;
/**
* 创建时间
*/
private Date createTime;
/**
* 删除标记 0=正常 1=已删除
*/
private Integer delFlag;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getSpaceExplain() {
return spaceExplain;
}
public void setSpaceExplain(String spaceExplain) {
this.spaceExplain = spaceExplain;
}
public Integer getEditType() {
return editType;
}
public void setEditType(Integer editType) {
this.editType = editType;
}
public Integer getTreeLazyLoad() {
return treeLazyLoad;
}
public void setTreeLazyLoad(Integer treeLazyLoad) {
this.treeLazyLoad = treeLazyLoad;
}
public Integer getOpenDoc() {
return openDoc;
}
public void setOpenDoc(Integer openDoc) {
this.openDoc = openDoc;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public Long getCreateUserId() {
return createUserId;
}
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
public String getCreateUserName() {
return createUserName;
}
public void setCreateUserName(String createUserName) {
this.createUserName = createUserName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Integer getDelFlag() {
return delFlag;
}
public void setDelFlag(Integer delFlag) {
this.delFlag = delFlag;
}
@Override
public String toString() {
return "WikiSpace{" +
"id=" + id +
", name=" + name +
", type=" + type +
", spaceExplain=" + spaceExplain +
", editType=" + editType +
", treeLazyLoad=" + treeLazyLoad +
", openDoc=" + openDoc +
", uuid=" + uuid +
", createUserId=" + createUserId +
", createUserName=" + createUserName +
", createTime=" + createTime +
", delFlag=" + delFlag +
"}";
}
}

View File

@@ -1,13 +1,14 @@
package com.zyplayer.doc.manage.repository.manage.entity;
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
*
* </p>
*
* @author 暮光城中城

View File

@@ -1,7 +1,7 @@
package com.zyplayer.doc.manage.repository.manage.mapper;
package com.zyplayer.doc.data.repository.manage.mapper;
import com.zyplayer.doc.manage.repository.manage.entity.AuthInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zyplayer.doc.data.repository.manage.entity.AuthInfo;
/**
* <p>

View File

@@ -1,15 +1,15 @@
package com.zyplayer.doc.manage.repository.manage.mapper;
package com.zyplayer.doc.data.repository.manage.mapper;
import com.zyplayer.doc.manage.repository.manage.entity.UserAuth;
import com.zyplayer.doc.data.repository.manage.entity.UserAuth;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* 用户权限表 Mapper 接口
* </p>
*
* @author 暮光城中城
* @since 2018-12-03
* @since 2019-05-31
*/
public interface UserAuthMapper extends BaseMapper<UserAuth> {

View File

@@ -1,7 +1,7 @@
package com.zyplayer.doc.manage.repository.manage.mapper;
package com.zyplayer.doc.data.repository.manage.mapper;
import com.zyplayer.doc.manage.repository.manage.entity.UserInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zyplayer.doc.data.repository.manage.entity.UserInfo;
/**
* <p>

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.data.repository.manage.mapper;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageComment;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 暮光:城中城
* @since 2019-02-24
*/
public interface WikiPageCommentMapper extends BaseMapper<WikiPageComment> {
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.data.repository.manage.mapper;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageContent;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 暮光:城中城
* @since 2019-02-24
*/
public interface WikiPageContentMapper extends BaseMapper<WikiPageContent> {
}

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.data.repository.manage.mapper;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageFile;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 暮光:城中城
* @since 2019-03-06
*/
public interface WikiPageFileMapper extends BaseMapper<WikiPageFile> {
@Update("update wiki_page_file set download_num=download_num+1 where id=#{id}")
void addDownloadNum(@Param("id") Long id);
}

View File

@@ -0,0 +1,27 @@
package com.zyplayer.doc.data.repository.manage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zyplayer.doc.data.repository.manage.entity.WikiPage;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 暮光:城中城
* @since 2019-03-09
*/
public interface WikiPageMapper extends BaseMapper<WikiPage> {
@Update("update wiki_page set zan_num=zan_num + #{numAdd} where id=#{id}")
void updateZanNum(@Param("id") Long id, @Param("numAdd") Integer numAdd);
@Update("update wiki_page set seq_no=seq_no + 1 where parent_id=#{parentId} and seq_no >= #{afterSeq} and del_flag=0")
void updateAfterSeq(@Param("parentId") Long parentId, @Param("afterSeq") Integer afterSeq);
@Select("select max(seq_no) from wiki_page where parent_id=#{parentId} and del_flag=0")
Integer getLastSeq(@Param("parentId") Long parentId);
}

View File

@@ -0,0 +1,18 @@
package com.zyplayer.doc.data.repository.manage.mapper;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageZan;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 暮光:城中城
* @since 2019-03-05
*/
public interface WikiPageZanMapper extends BaseMapper<WikiPageZan> {
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.data.repository.manage.mapper;
import com.zyplayer.doc.data.repository.manage.entity.WikiSpace;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 暮光:城中城
* @since 2019-03-13
*/
public interface WikiSpaceMapper extends BaseMapper<WikiSpace> {
}

View File

@@ -1,7 +1,7 @@
package com.zyplayer.doc.manage.repository.manage.mapper;
package com.zyplayer.doc.data.repository.manage.mapper;
import com.zyplayer.doc.manage.repository.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zyplayer.doc.data.repository.manage.entity.ZyplayerStorage;
/**
* <p>

View File

@@ -1,96 +1,93 @@
package com.zyplayer.doc.manage.repository.support.generator;
import java.util.ArrayList;
import java.util.List;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
public class CodeGenerator {
public static void main(String[] args) {
final String moduleName = "manage";
final String[] tableName = { "zyplayer_storage", "auth_info", "user_auth", "user_info" };
// final String[] tableName = { "zyplayer_storage" };
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
final String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("暮光:城中城");
gc.setOpen(false);
gc.setDateType(DateType.ONLY_DATE);
gc.setServiceName("%sService");
gc.setControllerName("Generator%sController");
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/zyplayer-doc-manage?useUnicode=true&useSSL=false&characterEncoding=utf8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
mpg.setDataSource(dsc);
// 包配置
final PackageConfig pc = new PackageConfig();
pc.setModuleName(null);
pc.setParent("com.zyplayer.doc.manage");
pc.setController("web.generator");
pc.setEntity("repository.manage.entity");
pc.setMapper("repository.manage.mapper");
pc.setService("service.manage");
pc.setServiceImpl("service.manage.impl");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
return projectPath + "/src/main/resources/mapper/" + moduleName + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
mpg.setTemplate(new TemplateConfig().setXml(null));
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// strategy.setSuperEntityClass("com.baomidou.ant.common.BaseEntity");
strategy.setEntityLombokModel(false);
strategy.setRestControllerStyle(true);
// strategy.setSuperControllerClass("com.baomidou.ant.common.BaseController");
// strategy.setSuperEntityColumns("id");
strategy.setInclude(tableName);// 表名
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
package com.zyplayer.doc.data.repository.support.generator;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
public class CodeGenerator {
public static void main(String[] args) {
final String moduleName = "manage";
// final String[] tableName = { "zyplayer_storage", "auth_info", "user_auth", "user_info" };
// final String[] tableName = { "wiki_space", "wiki_page", "wiki_page_content", "wiki_page_file", "wiki_page_comment", "wiki_page_zan" };
final String[] tableName = { "wiki_page" };
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
final String projectPath = System.getProperty("user.dir") + "/zyplayer-doc-data";
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("暮光:城中城");
gc.setOpen(false);
gc.setFileOverride(true);// 是否覆盖
gc.setDateType(DateType.ONLY_DATE);
gc.setServiceName("%sService");
gc.setControllerName("Generator%sController");
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/zyplayer_doc_manage?useUnicode=true&useSSL=false&characterEncoding=utf8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
mpg.setDataSource(dsc);
// 包配置
final PackageConfig pc = new PackageConfig();
pc.setModuleName(null);
pc.setParent("com.zyplayer.doc.data");
pc.setController("web.generator");
pc.setEntity("repository.manage.entity");
pc.setMapper("repository.manage.mapper");
pc.setService("service.manage");
pc.setServiceImpl("service.manage.impl");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
return projectPath + "/src/main/resources/mapper/" + moduleName + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
mpg.setTemplate(new TemplateConfig().setXml(null));
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// strategy.setSuperEntityClass("com.baomidou.ant.common.BaseEntity");
strategy.setEntityLombokModel(false);
strategy.setRestControllerStyle(true);
// strategy.setSuperControllerClass("com.baomidou.ant.common.BaseController");
// strategy.setSuperEntityColumns("id");
strategy.setInclude(tableName);// 表名
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}

View File

@@ -1,127 +1,123 @@
package com.zyplayer.doc.manage.repository.support.interceptor;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Intercepts({
@Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }),
@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class })
})
public class SqlLogInterceptor implements Interceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SqlLogInterceptor.class);
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
Object parameter = null;
if (invocation.getArgs().length > 1) {
parameter = invocation.getArgs()[1];
}
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
Configuration configuration = mappedStatement.getConfiguration();
// 获取sql语句
String sql = getSqlString(configuration, boundSql);
LOGGER.info(sql);
// 执行结果
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
if (target instanceof Executor) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
@Override
public void setProperties(Properties properties) {
}
private String getParameterValue(Object obj) {
String value = null;
if (obj instanceof String) {
value = "'" + obj.toString() + "'";
} else if (obj instanceof Date) {
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
value = "'" + formatter.format(obj) + "'";
//System.out.println(value);
} else {
if (obj != null) {
value = obj.toString();
} else {
value = "'null'";
}
}
return value;
}
public String getSqlString(Configuration configuration, BoundSql boundSql) {
Object parameterObject = boundSql.getParameterObject();
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
StringBuilder sqlSb = new StringBuilder(boundSql.getSql().replaceAll("[\\s]+", " "));
int fromIndex = 0;
if (parameterMappings.size() > 0 && parameterObject != null) {
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
//sqlSb = sqlSb.replaceFirst("\\?", getParameterValue(parameterObject));
fromIndex = replacePlaceholder(sqlSb, fromIndex, getParameterValue(parameterObject));
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
for (ParameterMapping parameterMapping : parameterMappings) {
String propertyName = parameterMapping.getProperty();
if (metaObject.hasGetter(propertyName)) {
Object obj = metaObject.getValue(propertyName);
//sqlSb = sqlSb.replaceFirst("\\?", getParameterValue(obj));
fromIndex = replacePlaceholder(sqlSb, fromIndex, getParameterValue(obj));
} else if (boundSql.hasAdditionalParameter(propertyName)) {
Object obj = boundSql.getAdditionalParameter(propertyName);
//sqlSb = sqlSb.replaceFirst("\\?", getParameterValue(obj));
fromIndex = replacePlaceholder(sqlSb, fromIndex, getParameterValue(obj));
}
}
}
}
return sqlSb.toString();
}
/**
* 替换占位符
* @author 暮光城中城
* @since 2018年10月27日
* @param sql
* @param fromIndex
* @param replaceStr
* @return
*/
private int replacePlaceholder(StringBuilder sql, int fromIndex, String replaceStr) {
int index = sql.indexOf("?", fromIndex);
if (index >= 0) {
sql.replace(index, index + 1, replaceStr);
}
return index + replaceStr.length();
}
}
package com.zyplayer.doc.data.repository.support.interceptor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
@Intercepts({
@Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }),
@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class })
})
public class SqlLogInterceptor implements Interceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SqlLogInterceptor.class);
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
Object parameter = null;
if (invocation.getArgs().length > 1) {
parameter = invocation.getArgs()[1];
}
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
Configuration configuration = mappedStatement.getConfiguration();
// 获取sql语句
String sql = getSqlString(configuration, boundSql);
LOGGER.info(sql);
// 执行结果
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
if (target instanceof Executor) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
@Override
public void setProperties(Properties properties) {
}
private String getParameterValue(Object obj) {
String value = null;
if (obj instanceof String) {
value = "'" + obj.toString() + "'";
} else if (obj instanceof Date) {
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
value = "'" + formatter.format(obj) + "'";
//System.out.println(value);
} else {
if (obj != null) {
value = obj.toString();
} else {
value = "'null'";
}
}
return value;
}
public String getSqlString(Configuration configuration, BoundSql boundSql) {
Object parameterObject = boundSql.getParameterObject();
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
StringBuilder sqlSb = new StringBuilder(boundSql.getSql().replaceAll("[\\s]+", " "));
int fromIndex = 0;
if (parameterMappings.size() > 0 && parameterObject != null) {
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
//sqlSb = sqlSb.replaceFirst("\\?", getParameterValue(parameterObject));
fromIndex = replacePlaceholder(sqlSb, fromIndex, getParameterValue(parameterObject));
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
for (ParameterMapping parameterMapping : parameterMappings) {
String propertyName = parameterMapping.getProperty();
if (metaObject.hasGetter(propertyName)) {
Object obj = metaObject.getValue(propertyName);
//sqlSb = sqlSb.replaceFirst("\\?", getParameterValue(obj));
fromIndex = replacePlaceholder(sqlSb, fromIndex, getParameterValue(obj));
} else if (boundSql.hasAdditionalParameter(propertyName)) {
Object obj = boundSql.getAdditionalParameter(propertyName);
//sqlSb = sqlSb.replaceFirst("\\?", getParameterValue(obj));
fromIndex = replacePlaceholder(sqlSb, fromIndex, getParameterValue(obj));
}
}
}
}
return sqlSb.toString();
}
/**
* 替换占位符
* @author 暮光城中城
* @since 2018年10月27日
* @param sql
* @param fromIndex
* @param replaceStr
* @return
*/
private int replacePlaceholder(StringBuilder sql, int fromIndex, String replaceStr) {
int index = sql.indexOf("?", fromIndex);
if (index >= 0) {
sql.replace(index, index + 1, replaceStr);
}
return index + replaceStr.length();
}
}

View File

@@ -1,7 +1,7 @@
package com.zyplayer.doc.manage.service.manage;
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.manage.repository.manage.entity.AuthInfo;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zyplayer.doc.data.repository.manage.entity.AuthInfo;
/**
* <p>

View File

@@ -1,15 +1,15 @@
package com.zyplayer.doc.manage.service.manage;
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.manage.repository.manage.entity.UserAuth;
import com.zyplayer.doc.data.repository.manage.entity.UserAuth;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* 用户权限表 服务类
* </p>
*
* @author 暮光城中城
* @since 2018-12-03
* @since 2019-05-31
*/
public interface UserAuthService extends IService<UserAuth> {

View File

@@ -1,7 +1,7 @@
package com.zyplayer.doc.manage.service.manage;
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.manage.repository.manage.entity.UserInfo;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zyplayer.doc.data.repository.manage.entity.UserInfo;
/**
* <p>

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageComment;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author 暮光:城中城
* @since 2019-02-24
*/
public interface WikiPageCommentService extends IService<WikiPageComment> {
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageContent;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author 暮光:城中城
* @since 2019-02-24
*/
public interface WikiPageContentService extends IService<WikiPageContent> {
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageFile;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author 暮光:城中城
* @since 2019-03-06
*/
public interface WikiPageFileService extends IService<WikiPageFile> {
}

View File

@@ -0,0 +1,19 @@
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.data.repository.manage.entity.WikiPage;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author 暮光:城中城
* @since 2019-03-09
*/
public interface WikiPageService extends IService<WikiPage> {
void changeParent(WikiPage wikiPage, Integer beforeSeq, Integer afterSeq);
void deletePage(WikiPage wikiPage);
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageZan;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author 暮光:城中城
* @since 2019-03-05
*/
public interface WikiPageZanService extends IService<WikiPageZan> {
void zanPage(WikiPageZan wikiPageZan);
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.data.repository.manage.entity.WikiSpace;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author 暮光:城中城
* @since 2019-03-13
*/
public interface WikiSpaceService extends IService<WikiSpace> {
}

View File

@@ -1,7 +1,7 @@
package com.zyplayer.doc.manage.service.manage;
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.manage.repository.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zyplayer.doc.data.repository.manage.entity.ZyplayerStorage;
/**
* <p>

View File

@@ -1,9 +1,9 @@
package com.zyplayer.doc.manage.service.manage.impl;
package com.zyplayer.doc.data.service.manage.impl;
import com.zyplayer.doc.manage.repository.manage.entity.AuthInfo;
import com.zyplayer.doc.manage.repository.manage.mapper.AuthInfoMapper;
import com.zyplayer.doc.manage.service.manage.AuthInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyplayer.doc.data.repository.manage.entity.AuthInfo;
import com.zyplayer.doc.data.repository.manage.mapper.AuthInfoMapper;
import com.zyplayer.doc.data.service.manage.AuthInfoService;
import org.springframework.stereotype.Service;
/**

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.data.service.manage.impl;
import com.zyplayer.doc.data.repository.manage.entity.UserAuth;
import com.zyplayer.doc.data.repository.manage.mapper.UserAuthMapper;
import com.zyplayer.doc.data.service.manage.UserAuthService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 用户权限表 服务实现类
* </p>
*
* @author 暮光:城中城
* @since 2019-05-31
*/
@Service
public class UserAuthServiceImpl extends ServiceImpl<UserAuthMapper, UserAuth> implements UserAuthService {
}

View File

@@ -1,9 +1,9 @@
package com.zyplayer.doc.manage.service.manage.impl;
package com.zyplayer.doc.data.service.manage.impl;
import com.zyplayer.doc.manage.repository.manage.entity.UserInfo;
import com.zyplayer.doc.manage.repository.manage.mapper.UserInfoMapper;
import com.zyplayer.doc.manage.service.manage.UserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyplayer.doc.data.repository.manage.entity.UserInfo;
import com.zyplayer.doc.data.repository.manage.mapper.UserInfoMapper;
import com.zyplayer.doc.data.service.manage.UserInfoService;
import org.springframework.stereotype.Service;
/**

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.data.service.manage.impl;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageComment;
import com.zyplayer.doc.data.repository.manage.mapper.WikiPageCommentMapper;
import com.zyplayer.doc.data.service.manage.WikiPageCommentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author 暮光:城中城
* @since 2019-02-24
*/
@Service
public class WikiPageCommentServiceImpl extends ServiceImpl<WikiPageCommentMapper, WikiPageComment> implements WikiPageCommentService {
}

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.data.service.manage.impl;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageContent;
import com.zyplayer.doc.data.repository.manage.mapper.WikiPageContentMapper;
import com.zyplayer.doc.data.service.manage.WikiPageContentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author 暮光:城中城
* @since 2019-02-24
*/
@Service
public class WikiPageContentServiceImpl extends ServiceImpl<WikiPageContentMapper, WikiPageContent> implements WikiPageContentService {
}

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.data.service.manage.impl;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageFile;
import com.zyplayer.doc.data.repository.manage.mapper.WikiPageFileMapper;
import com.zyplayer.doc.data.service.manage.WikiPageFileService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author 暮光:城中城
* @since 2019-03-06
*/
@Service
public class WikiPageFileServiceImpl extends ServiceImpl<WikiPageFileMapper, WikiPageFile> implements WikiPageFileService {
}

View File

@@ -0,0 +1,66 @@
package com.zyplayer.doc.data.service.manage.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyplayer.doc.data.repository.manage.entity.WikiPage;
import com.zyplayer.doc.data.repository.manage.mapper.WikiPageMapper;
import com.zyplayer.doc.data.service.manage.WikiPageService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
/**
* <p>
* 服务实现类
* </p>
*
* @author 暮光:城中城
* @since 2019-06-05
*/
@Service
public class WikiPageServiceImpl extends ServiceImpl<WikiPageMapper, WikiPage> implements WikiPageService {
@Resource
WikiPageMapper wikiPageMapper;
@Override
public void changeParent(WikiPage wikiPage, Integer beforeSeq, Integer afterSeq) {
if (beforeSeq != null && beforeSeq >= 0) {
// 在此seq之前
wikiPageMapper.updateAfterSeq(wikiPage.getParentId(), beforeSeq);
wikiPage.setSeqNo(beforeSeq);
} else if (afterSeq != null && afterSeq >= 0) {
// 在此seq之后
wikiPageMapper.updateAfterSeq(wikiPage.getParentId(), afterSeq + 1);
wikiPage.setSeqNo(afterSeq + 1);
} else {
// 放在末尾
Integer lastSeq = wikiPageMapper.getLastSeq(wikiPage.getParentId());
lastSeq = Optional.ofNullable(lastSeq).orElse(0);
wikiPage.setSeqNo(lastSeq + 1);
}
this.updateById(wikiPage);
}
@Override
public void deletePage(WikiPage wikiPage) {
wikiPage.setDelFlag(1);
this.updateById(wikiPage);
QueryWrapper<WikiPage> wrapper = new QueryWrapper<>();
wrapper.eq("del_flag", 0);
wrapper.eq("parent_id", wikiPage.getId());
List<WikiPage> wikiPageList = this.list(wrapper);
if (CollectionUtils.isEmpty(wikiPageList)) {
return;
}
// 递归删除子页面
for (WikiPage page : wikiPageList) {
wikiPage.setId(page.getId());
this.deletePage(wikiPage);
}
}
}

View File

@@ -0,0 +1,56 @@
package com.zyplayer.doc.data.service.manage.impl;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyplayer.doc.data.config.security.DocUserDetails;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageZan;
import com.zyplayer.doc.data.repository.manage.mapper.WikiPageMapper;
import com.zyplayer.doc.data.repository.manage.mapper.WikiPageZanMapper;
import com.zyplayer.doc.data.service.manage.WikiPageZanService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;
/**
* <p>
* 服务实现类
* </p>
*
* @author 暮光:城中城
* @since 2019-03-05
*/
@Service
public class WikiPageZanServiceImpl extends ServiceImpl<WikiPageZanMapper, WikiPageZan> implements WikiPageZanService {
@Resource
WikiPageMapper wikiPageMapper;
@Override
@Transactional
public void zanPage(WikiPageZan wikiPageZan) {
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
UpdateWrapper<WikiPageZan> wrapper = new UpdateWrapper<>();
wrapper.eq("create_user_id", currentUser.getUserId());
wrapper.eq("page_id", wikiPageZan.getPageId());
wrapper.eq(wikiPageZan.getCommentId() != null, "comment_id", wikiPageZan.getCommentId());
WikiPageZan pageZan = this.getOne(wrapper);
if (pageZan != null) {
if (Objects.equals(wikiPageZan.getYn(), pageZan.getYn())) {
return;
}
wikiPageZan.setId(pageZan.getId());
this.updateById(wikiPageZan);
} else {
wikiPageZan.setCreateTime(new Date());
wikiPageZan.setCreateUserId(currentUser.getUserId());
wikiPageZan.setCreateUserName(currentUser.getUsername());
this.save(wikiPageZan);
}
int numAdd = wikiPageZan.getYn() == 1 ? 1 : -1;
wikiPageMapper.updateZanNum(wikiPageZan.getPageId(), numAdd);
}
}

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.data.service.manage.impl;
import com.zyplayer.doc.data.repository.manage.entity.WikiSpace;
import com.zyplayer.doc.data.repository.manage.mapper.WikiSpaceMapper;
import com.zyplayer.doc.data.service.manage.WikiSpaceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author 暮光:城中城
* @since 2019-03-13
*/
@Service
public class WikiSpaceServiceImpl extends ServiceImpl<WikiSpaceMapper, WikiSpace> implements WikiSpaceService {
}

View File

@@ -1,9 +1,9 @@
package com.zyplayer.doc.manage.service.manage.impl;
package com.zyplayer.doc.data.service.manage.impl;
import com.zyplayer.doc.manage.repository.manage.entity.ZyplayerStorage;
import com.zyplayer.doc.manage.repository.manage.mapper.ZyplayerStorageMapper;
import com.zyplayer.doc.manage.service.manage.ZyplayerStorageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyplayer.doc.data.repository.manage.entity.ZyplayerStorage;
import com.zyplayer.doc.data.repository.manage.mapper.ZyplayerStorageMapper;
import com.zyplayer.doc.data.service.manage.ZyplayerStorageService;
import org.springframework.stereotype.Service;
/**

View File

@@ -0,0 +1,33 @@
package com.zyplayer.doc.data.utils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class BeanUtil {
@SuppressWarnings({"unchecked"})
public static <T extends Annotation> T getAnnotation(JoinPoint pjp, Class<T> t) throws Exception {
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
T annotation = method.getAnnotation(t);// 方法上定义的
if (annotation == null) {
annotation = (T) pjp.getSignature().getDeclaringType().getAnnotation(t);// 类上定义的
if (annotation == null) {
Object target = pjp.getTarget();
annotation = target.getClass().getAnnotation(t);// 实现类上定义的
if (annotation == null) {
Signature sig = pjp.getSignature();
if (sig instanceof MethodSignature) {
MethodSignature msig = (MethodSignature) sig;
Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
annotation = currentMethod.getAnnotation(t);// 实现类的方法上定义的
}
}
}
}
return annotation;
}
}

View File

@@ -0,0 +1,96 @@
package com.zyplayer.doc.data.utils;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
/**
* 缓存工具类
*
* @author 暮光:城中城
* @since 2019年05月25日
*/
public class CacheUtil {
// 定期清除过期的key
static {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
long currentTimeMillis = System.currentTimeMillis();
for (Map.Entry<String, CacheTime> entry : cacheTimeMap.entrySet()) {
CacheTime cacheTime = entry.getValue();
if (currentTimeMillis - cacheTime.getLastVisitTime() < (cacheTime.getSecond() * 1000)) {
continue;
}
cacheMap.remove(entry.getKey());
}
}
}, 0, 1000);
}
// 现在是内存缓存不支持分布式部署后期考虑放到redis但感觉也没必要。。
private static Map<String, Object> cacheMap = new ConcurrentHashMap<>();
private static Map<String, CacheTime> cacheTimeMap = new ConcurrentHashMap<>();
public static void put(String key, Object value) {
put(key, value, (long) (60 * 60 * 12));
}
public static void put(String key, Object value, Long second) {
if (StringUtils.isBlank(key) || value == null) {
return;
}
cacheMap.put(key, value);
cacheTimeMap.put(key, new CacheTime(second));
}
public static void remove(String key) {
if (StringUtils.isBlank(key)) {
return;
}
cacheMap.remove(key);
cacheTimeMap.remove(key);
}
public static <T> T get(String key) {
if (StringUtils.isBlank(key)) {
return null;
}
CacheTime cacheTime = cacheTimeMap.get(key);
if (cacheTime != null) {
cacheTime.setLastVisitTime(System.currentTimeMillis());
cacheTimeMap.put(key, cacheTime);
}
return (T) cacheMap.get(key);
}
private static class CacheTime {
private Long second;
private Long lastVisitTime;
public CacheTime(Long second) {
this.second = second;
this.lastVisitTime = System.currentTimeMillis();
}
public Long getSecond() {
return second;
}
public void setSecond(Long second) {
this.second = second;
}
public Long getLastVisitTime() {
return lastVisitTime;
}
public void setLastVisitTime(Long lastVisitTime) {
this.lastVisitTime = lastVisitTime;
}
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zyplayer.doc.manage.repository.manage.mapper.UserAuthMapper">
<mapper namespace="com.zyplayer.doc.data.repository.manage.mapper.UserAuthMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zyplayer.doc.data.repository.manage.mapper.WikiPageCommentMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zyplayer.doc.data.repository.manage.mapper.WikiPageContentMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zyplayer.doc.data.repository.manage.mapper.WikiPageFileMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zyplayer.doc.data.repository.manage.mapper.WikiPageMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zyplayer.doc.data.repository.manage.mapper.WikiPageZanMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zyplayer.doc.data.repository.manage.mapper.WikiSpaceMapper">
</mapper>

View File

@@ -5,7 +5,7 @@
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc-db</artifactId>
<version>1.0.1</version>
<version>1.0.2</version>
<packaging>jar</packaging>
<name>zyplayer-doc-db</name>
<description>数据库文档工具</description>
@@ -21,7 +21,7 @@
<timezone>2018-05-22 16:06:06</timezone>
</developer>
</developers>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
@@ -51,11 +51,6 @@
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
@@ -71,12 +66,18 @@
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
<dependency>
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc-core</artifactId>
<version>${zyplayer.doc.version}</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<zyplayer.doc.version>1.0.2</zyplayer.doc.version>
<!-- 打包跳过单元测试 -->
<skipTests>true</skipTests>
<destDir>${project.build.outputDirectory}/META-INF/resources/webjars/${project.artifactId}/${project.version}</destDir>
@@ -227,4 +228,4 @@
</build>
</profile>
</profiles>
</project>
</project>

View File

@@ -1,16 +1,20 @@
package com.zyplayer.doc.db.controller;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson.JSON;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.db.controller.vo.DatabaseExportVo;
import com.zyplayer.doc.db.controller.vo.TableColumnVo;
import com.zyplayer.doc.db.controller.vo.TableColumnVo.TableInfoVo;
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean;
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean.DatabaseProduct;
import com.zyplayer.doc.db.framework.db.bean.DatabaseRegistrationBean;
import com.zyplayer.doc.db.framework.db.dto.*;
import com.zyplayer.doc.db.framework.db.mapper.base.BaseMapper;
import com.zyplayer.doc.db.framework.db.mapper.mysql.MysqlMapper;
import com.zyplayer.doc.db.framework.json.DocDbResponseJson;
import com.zyplayer.doc.db.framework.json.ResponseJson;
import org.apache.commons.lang.StringUtils;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
@@ -19,26 +23,10 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSON;
import com.zyplayer.doc.db.controller.vo.DatabaseExportVo;
import com.zyplayer.doc.db.controller.vo.TableColumnVo;
import com.zyplayer.doc.db.controller.vo.TableColumnVo.TableInfoVo;
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean;
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean.DatabaseProduct;
import com.zyplayer.doc.db.framework.db.bean.DatabaseRegistrationBean;
import com.zyplayer.doc.db.framework.db.dto.ColumnInfoDto;
import com.zyplayer.doc.db.framework.db.dto.DatabaseInfoDto;
import com.zyplayer.doc.db.framework.db.dto.QueryTableColumnDescDto;
import com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto;
import com.zyplayer.doc.db.framework.db.dto.TableDescDto;
import com.zyplayer.doc.db.framework.db.dto.TableInfoDto;
import com.zyplayer.doc.db.framework.db.mapper.base.BaseMapper;
import com.zyplayer.doc.db.framework.db.mapper.mysql.MysqlMapper;
import com.zyplayer.doc.db.framework.json.DocDbResponseJson;
import com.zyplayer.doc.db.framework.json.ResponseJson;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ZipUtil;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
/**
* 文档控制器
@@ -46,6 +34,7 @@ import cn.hutool.core.util.ZipUtil;
* @author 暮光:城中城
* @since 2018年8月8日
*/
@AuthMan
@RestController
@RequestMapping("/zyplayer-doc-db/doc-db")
public class DatabaseDocController {

View File

@@ -1,14 +1,14 @@
package com.zyplayer.doc.db.framework.configuration;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@ComponentScan(basePackages = {
"com.zyplayer.doc.db",
})

View File

@@ -3,6 +3,8 @@
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<!--无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢-->
<meta name="author" content="开发者列表暮光城中城项目地址https://gitee.com/zyplayer/zyplayer-doc" />
<title>数据库文档</title>
<link rel="shortcut icon" href="webjars/doc-db/img/api.ico"/>
<link rel="stylesheet" href="webjars/zui/css/zui.min.css" />
@@ -35,7 +37,10 @@
</div>
</div>
<div class="table-info">
<div>表名:<span class="table-name"></span></div>
<div style="height: 35px;line-height: 35px;">
表名:<span class="table-name"></span>
<button class="btn pull-right" type="button" id="aboutBtn" style="margin-right: 30px;">关于</button>
</div>
<div class="desc">
<div id="tableDescShow">
<span class="table-desc"></span>
@@ -146,6 +151,57 @@
</div>
</div>
</div>
<!-- 关于弹出框 -->
<div class="modal fade" id="aboutModal">
<div class="modal-dialog modal-lg" style="width: 600px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span><span class="sr-only">关闭</span>
</button>
<h4 class="modal-title">关于zyplayer-doc-db</h4>
</div>
<div class="modal-body">
<form class="form-horizontal" style="line-height: 30px;">
<div class="form-group">
<label class="col-sm-2 no-padding">项目地址:</label>
<div class="col-md-6 col-sm-10">
<a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc">zyplayer-doc</a>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 no-padding">开发人员:</label>
<div class="col-md-6 col-sm-10">
<a target="_blank" href="http://zyplayer.com">暮光:城中城</a>
</div>
</div>
<div class="form-group upgrade-info">
<label class="col-sm-2 no-padding">当前版本:</label>
<div class="col-md-10 col-sm-10" id="upgradeNowVersion"></div>
</div>
<div class="form-group upgrade-info">
<label class="col-sm-2 no-padding">最新版本:</label>
<div class="col-md-10 col-sm-10" id="upgradeLastVersion"></div>
</div>
<div class="form-group upgrade-info">
<label class="col-sm-2 no-padding">升级地址:</label>
<div class="col-md-10 col-sm-10" id="upgradeUrl"></div>
</div>
<div class="form-group upgrade-info">
<label class="col-sm-2 no-padding">升级内容:</label>
<div class="col-md-10 col-sm-10" id="upgradeContent"></div>
</div>
<div class="form-group">
<div class="col-sm-2 no-padding"></div>
<div class="col-md-10 col-sm-10">
欢迎加群讨论QQ群号466363173欢迎提交需求欢迎使用和加入开发
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
<script type="text/javascript" src="webjars/doc-db/js/jquery-3.1.0.min.js"></script>

View File

@@ -27,8 +27,11 @@ function deserialize(value) {
}
function validateResult(result) {
if(result.errCode == 200) {
if (result.errCode == 200) {
return true;
} else if (result.errCode == 400) {
var href = encodeURIComponent(window.location.href);
window.location = "static/manage/login.html?redirect=" + href;
} else {
Toast.error(result.errMsg);
}
@@ -147,7 +150,10 @@ function getObjectFirstAttributeIfOnly(data) {
function postService(url, param, success=function(){}, complete=function(){}){
ajaxTemp(url, "POST", "JSON", param, function(result){
if(result.errCode != "200"){
if (result.errCode == 400) {
var href = encodeURIComponent(window.location.href);
window.location = "static/manage/login.html?redirect=" + href;
} else if (result.errCode != "200") {
Toast.warn(result.errMsg);
} else {
success(result);
@@ -178,8 +184,13 @@ function ajaxTemp(url, dataSentType, dataReceiveType, paramsStr, successFunction
data : eval(paramsStr),
contentType : "application/x-www-form-urlencoded; charset=UTF-8",
success : function(msg) {
if(typeof successFunction == "function") {
successFunction(msg,id);
if (msg.errCode == 400) {
var href = encodeURIComponent(window.location.href);
window.location = "static/manage/login.html?redirect=" + href;
} else {
if (typeof successFunction == "function") {
successFunction(msg, id);
}
}
},
beforeSend : function() {

View File

@@ -1,41 +1,43 @@
html,body{width: 100%;height: 100%;}
.container{padding-top: 20px;}
.table-info,.table-columns{margin-top: 10px;}
.table-info .desc{margin-top: 10px;}
#tableDescInput{display: none;}
#tableDescShow .icon-edit{cursor: pointer;margin-left: 20px;display: none;}
.modal-table-box{margin-top: 10px; max-height: 500px;overflow-y: auto;}
#fuzzySearchModal .table td:nth-child(3){word-break:break-all;max-width: 400px;}
#doExport{margin-right: 10px;}
#exportModal .alert{margin-top: 10px;}
#exportUl{list-style: none;}
#exportUl li{float: left; border: 1px solid #ccc;padding: 10px 15px; margin: 0 10px 10px 0; background-color: #ccc;cursor: pointer;}
#exportUl li.checked{border: 1px solid #3f51b5;background-color: #8666b8;color:#fff;}
/* S-覆盖原生样式 */
.chosen-container-single .chosen-single div b {margin-top: 8px;}
/* E-覆盖原生样式 */
/* S-JSON展示的样式 */
pre.json{margin-top:0px;margin-bottom:0px;}
pre.json .canvas{font:10pt georgia;background-color:#ececec;color:#000000;border:1px solid #cecece;}
pre.json .objectBrace{color:#00aa00;font-weight:bold;}
pre.json .arrayBrace{color:#0033ff;font-weight:bold;}
pre.json .propertyName{color:#cc0000;font-weight:bold;}
pre.json .string{color:#007777;}
pre.json .number{color:#aa00aa;}
pre.json .boolean{color:#0000ff;}
pre.json .function{color:#aa6633;text-decoration:italic;}
pre.json .null{color:#0000ff;}
pre.json .comma{color:#000000;font-weight:bold;}
pre img{cursor: pointer;}
/* E-JSON展示的样式 */
html,body{width: 100%;height: 100%;}
.container{padding-top: 20px;}
.table-info,.table-columns{margin-top: 10px;}
.table-info .desc{margin-top: 10px;}
#tableDescInput{display: none;}
#tableDescShow .icon-edit{cursor: pointer;margin-left: 20px;display: none;}
.modal-table-box{margin-top: 10px; max-height: 500px;overflow-y: auto;}
#fuzzySearchModal .table td:nth-child(3){word-break:break-all;max-width: 400px;}
#doExport{margin-right: 10px;}
#exportModal .alert{margin-top: 10px;}
#exportUl{list-style: none;}
#exportUl li{float: left; border: 1px solid #ccc;padding: 10px 15px; margin: 0 10px 10px 0; background-color: #ccc;cursor: pointer;}
#exportUl li.checked{border: 1px solid #3f51b5;background-color: #8666b8;color:#fff;}
.upgrade-info{display: none;}
/* S-覆盖原生样式 */
.chosen-container-single .chosen-single div b {margin-top: 8px;}
/* E-覆盖原生样式 */
/* S-JSON展示的样式 */
pre.json{margin-top:0px;margin-bottom:0px;}
pre.json .canvas{font:10pt georgia;background-color:#ececec;color:#000000;border:1px solid #cecece;}
pre.json .objectBrace{color:#00aa00;font-weight:bold;}
pre.json .arrayBrace{color:#0033ff;font-weight:bold;}
pre.json .propertyName{color:#cc0000;font-weight:bold;}
pre.json .string{color:#007777;}
pre.json .number{color:#aa00aa;}
pre.json .boolean{color:#0000ff;}
pre.json .function{color:#aa6633;text-decoration:italic;}
pre.json .null{color:#0000ff;}
pre.json .comma{color:#000000;font-weight:bold;}
pre img{cursor: pointer;}
/* E-JSON展示的样式 */

View File

@@ -27,8 +27,11 @@ function deserialize(value) {
}
function validateResult(result) {
if(result.errCode == 200) {
if (result.errCode == 200) {
return true;
} else if (result.errCode == 400) {
var href = encodeURIComponent(window.location.href);
window.location = "static/manage/login.html?redirect=" + href;
} else {
Toast.error(result.errMsg);
}
@@ -147,7 +150,10 @@ function getObjectFirstAttributeIfOnly(data) {
function postService(url, param, success=function(){}, complete=function(){}){
ajaxTemp(url, "POST", "JSON", param, function(result){
if(result.errCode != "200"){
if (result.errCode == 400) {
var href = encodeURIComponent(window.location.href);
window.location = "static/manage/login.html?redirect=" + href;
} else if (result.errCode != "200") {
Toast.warn(result.errMsg);
} else {
success(result);
@@ -178,14 +184,25 @@ function ajaxTemp(url, dataSentType, dataReceiveType, paramsStr, successFunction
data : eval(paramsStr),
contentType : "application/x-www-form-urlencoded; charset=UTF-8",
success : function(msg) {
if(typeof successFunction == "function") {
successFunction(msg,id);
if (msg.errCode == 400) {
var href = encodeURIComponent(window.location.href);
window.location = "static/manage/login.html?redirect=" + href;
} else {
if (typeof successFunction == "function") {
successFunction(msg, id);
}
}
},
beforeSend : function() {
},
complete : function(msg) {
if (msg.responseText.startWith("<!doctype html>")) {
if (msg.responseText.indexOf("THIS_IS_LOGIN_PAGE_FLAG") > 0) {
Toast.error('操作失败,登录已失效,请登陆后重试', 3000);
return;
}
}
if(typeof completeFunction == "function") {
completeFunction(msg,id);
}

View File

@@ -1,372 +1,395 @@
var pageConfig = {
host: '',
tableRelationDataIndex: 0,
}
// 表关系图表
var tableRelationCharts;
$(document).ready(function(){
$('select.chosen-select').chosen({
no_results_text: '没有找到', // 当检索时没有找到匹配项时显示的提示文本
disable_search_threshold: 0, // 10 个以下的选择项则不显示检索框
search_contains: true, // 从任意位置开始检索
width: '100%'
});
$('#checkAllTable').click(function(e){
$("#exportUl li").addClass("checked");
});
$('#notCheckAllTable').click(function(e){
$("#exportUl li").removeClass("checked");
});
$('#choiseExportDatabase').on('change', function(e){
var host = $('#choiseExportHost').val();
var dbName = $('#choiseExportDatabase').val();
postService("zyplayer-doc-db/doc-db/getTableList", {host: host, dbName: dbName}, function(result){
$('#exportUl').empty();
for (var i = 0; i < result.data.length; i++) {
$("#exportUl").append('<li>'+result.data[i].tableName+'</li>');
}
$('#exportModal').modal('ajustPosition', 'fit');
});
});
$('#choiseExportHost').on('change', function(e){
var host = $(this).val();
postService("zyplayer-doc-db/doc-db/getDatabaseList", {host: host}, function(result){
$('#choiseExportDatabase').empty();
$("#choiseExportDatabase").append('<option value=""></option>');
for (var i = 0; i < result.data.length; i++) {
var dbName = result.data[i].dbName;
$("#choiseExportDatabase").append('<option value="'+dbName+'">'+dbName+'</option>');
}
$('#choiseExportDatabase').trigger('chosen:updated');
});
});
$('#choiseFuzzyHost').on('change', function(e){
var host = $(this).val();
postService("zyplayer-doc-db/doc-db/getDatabaseList", {host: host}, function(result){
$('#choiseFuzzyDatabase').empty();
$("#choiseFuzzyDatabase").append('<option value=""></option>');
for (var i = 0; i < result.data.length; i++) {
var dbName = result.data[i].dbName;
$("#choiseFuzzyDatabase").append('<option value="'+dbName+'">'+dbName+'</option>');
}
$('#choiseFuzzyDatabase').trigger('chosen:updated');
});
});
$('#choiseHost').on('change', function(e){
pageConfig.host = $(this).val();
postService("zyplayer-doc-db/doc-db/getDatabaseList", {host: pageConfig.host}, function(result){
$('#choiseDatabase').empty();
$('#choiseTable').empty();
$("#choiseDatabase").append('<option value=""></option>');
$("#choiseTable").append('<option value=""></option>');
for (var i = 0; i < result.data.length; i++) {
var dbName = result.data[i].dbName;
$("#choiseDatabase").append('<option value="'+dbName+'">'+dbName+'</option>');
}
$('#choiseDatabase').trigger('chosen:updated');
$('#choiseTable').trigger('chosen:updated');
});
});
$('#choiseDatabase').on('change', function(e){
var dbName = $(this).val();
var param = {host: pageConfig.host, dbName: dbName};
postService("zyplayer-doc-db/doc-db/getTableList", param, function(result){
$('#choiseTable').empty();
$("#choiseTable").append('<option value=""></option>');
for (var i = 0; i < result.data.length; i++) {
var tableName = result.data[i].tableName;
$("#choiseTable").append('<option value="'+tableName+'">'+tableName+'</option>');
}
$('#choiseTable').trigger('chosen:updated');
});
});
$('#choiseTable').on('change', function(e){
getTableColumnList();
});
$('#tableDescShow .icon-edit').click(function(e){
var nowDesc = $("#tableDescShow .table-desc").html();
$("#tableDescInput").val((nowDesc == "暂无注释") ? "" : nowDesc);
$("#tableDescShow").hide();
$("#tableDescInput").show().focus();
});
$("#tableDescInput").blur(function(){
$("#tableDescShow").show();
$("#tableDescInput").hide();
updateTableDesc();
});
$("#fuzzySearchBtn").click(function(){
$('#fuzzySearchModal').modal({moveable:true, backdrop: 'static'});
$('#choiseFuzzyHost').trigger('chosen:updated');
});
$("#exportBtn").click(function(){
$('#exportModal').modal({moveable:true, backdrop: 'static'});
});
$("#doExport").click(function(){
var host = $('#choiseExportHost').val();
var dbName = $('#choiseExportDatabase').val();
var tableNames = "";
$('#exportUl li.checked').text(function(index, value){
if(tableNames != "") {tableNames += ",";}
tableNames += value;
});
if(isEmpty(host)){
Toast.warn("请先选择库名");return;
}
if(isEmpty(dbName)){
Toast.warn("请先选择库名");return;
}
if(isEmpty(tableNames)){
Toast.warn("请输选择需要导出的表");return;
}
window.open("zyplayer-doc-db/doc-db/exportDatabase?host="+host
+"&dbName="+dbName
+"&tableNames="+tableNames);
});
$("#exportUl").on("click", "li", function(){
$(this).toggleClass("checked");
});
$("#showEchartsBtn").click(function(){
$("#tableRelationBox").toggleClass("hide");
if($("#tableRelationBox").hasClass("hide")){
$(this).text("显示表关系图");
} else {
$(this).text("隐藏表关系图");
tableRelationCharts.resize();
}
});
$("#doSearch").click(function(){
fuzzySearchByDesc();
});
$("#tableCloumnsTable tbody").on("click", ".column-desc", function(event){
$(this).find("span").hide();
$(this).find(".desc-input").show().focus();
}).on("blur", ".column-desc", function(event){
var newDesc = $(this).find(".desc-input").val();
var columnName = $(this).find(".desc-input").attr("column");
var oldDesc = $(this).find("span").text();
$(this).find("span").show();
$(this).find(".desc-input").hide();
if(newDesc != oldDesc){
var objThis = this;
var param = getChoiseDbInfo(3);
if(param == null){
return;
}
param.newDesc = newDesc;
param.columnName = columnName;
postService("zyplayer-doc-db/doc-db/updateTableColumnDesc", param, function(msg){
$(objThis).find("span").text(newDesc);
});
}
});
initData();
});
function initData(){
postService("zyplayer-doc-db/doc-db/getDataSourceList", {}, function(result){
$('#choiseHost,#choiseFuzzyHost,#choiseExportHost').empty();
if(validateResult(result)) {
$("#choiseHost,#choiseFuzzyHost,#choiseExportHost").append('<option value=""></option>');
for (var i = 0; i < result.data.length; i++) {
$("#choiseHost,#choiseFuzzyHost,#choiseExportHost").append('<option value="'+result.data[i]+'">'+result.data[i]+'</option>');
}
}
$('#choiseHost').trigger('chosen:updated');
$('#choiseFuzzyHost').trigger('chosen:updated');
$('#choiseExportHost').trigger('chosen:updated');
});
tableRelationCharts = echarts.init(document.getElementById('tableRelationCharts'));
tableRelationCharts.setOption(tableRelationOption);
tableRelationCharts.on('click', function (params) {
//console.log(params.data);
var dataIndex = params.data.index;
var description = params.data.description;
// 用户IDT:user_info.id
// 用户IDT:order_db.user_info.id
var indexOf = description.indexOf("T:");
if(indexOf < 0) {
Toast.warn("该字段未关联表");
return;
}
var dbAndTable = description.substring(indexOf + 2, description.length);
var dbNameChoise, tableNameChoise;
var tempSplit = dbAndTable.split(".");
if(tempSplit.length == 3) {
dbNameChoise = tempSplit[0];
tableNameChoise = tempSplit[1];
} else if(tempSplit.length == 2) {
tableNameChoise = tempSplit[0];
} else {
tableNameChoise = dbAndTable;
}
var children = findChildren(tableRelationData, dataIndex);
if(children != null && children.children.length <= 0) {
// 查询表字段
var param = getChoiseDbInfo(2);
if(param == null){
return;
}
if(isNotEmpty(dbNameChoise)){
param.dbName = dbNameChoise;
}
param.tableName = tableNameChoise;
postService("zyplayer-doc-db/doc-db/getTableColumnList", param, function(msg){
var columnList = msg.data.columnList
if(!columnList || columnList.length <= 0) {
Toast.warn("未找到该字段关联的表信息");return;
}
changetableRelationOption(children, columnList);
tableRelationCharts.setOption(tableRelationOption);
var height = pageConfig.tableRelationDataIndex * 25;
$("#tableRelationBox").css("height", height + "px");
tableRelationCharts.resize();
});
}
});
}
function changetableRelationOption(data, columnList){
var childrenArr = [];
for (var i = 0; i < columnList.length; i++) {
var item = columnList[i];
var description = getNotEmptyStr(item.description);
var indexOf = description.indexOf("T:");
var dbAndTable = "";
if(indexOf >= 0) {
dbAndTable = " " + description.substring(indexOf + 2, description.length);
}
childrenArr.push({
name: item.name + " " + item.type + dbAndTable,
children: [],
collapsed: false,
index: pageConfig.tableRelationDataIndex++,
description: getNotEmptyStr(item.description),
length: item.length
});
}
data.children = childrenArr;
}
function findChildren(source, dataIndex){
var result = null;
echarts.util.each(source.children, function (datum, index) {
if(result != null) {
return;
}
if(datum.index == dataIndex) {
result = datum;
} else if(datum.children && datum.children.length > 0) {
result = findChildren(datum, dataIndex);
}
});
if(result != null) {
return result;
}
}
function getTableColumnList(){
var param = getChoiseDbInfo(3);
if(param == null){
return;
}
$("#tableDescShow .icon-edit").hide();
$("#tableCloumnsTable tbody").empty();
$(".table-name").text(param.tableName);
$(".table-desc").text("暂无注释");
postService("zyplayer-doc-db/doc-db/getTableColumnList", param, function(msg){
var columnList = msg.data.columnList
for (var i = 0; i < columnList.length; i++) {
var item = columnList[i];
//var isidentity = isNull(item.isidentity) ? '-' : (1 == item.isidentity ? '是' : '否');
$("#tableCloumnsTable tbody").append(
'<tr>'
+'<td>' + item.name + '</td>'
+'<td>' + (1 == item.isidentity ? '是' : '否') + '</td>'
+'<td>' + getNotEmptyStr(item.type) + '</td>'
+'<td>' + getNotEmptyStr(item.length) + '</td>'
+'<td>' + (1 == item.nullable ? '允许' : '不允许') + '</td>'
+'<td>' + ("true" == item.ispramary ? '是' : '否') + '</td>'
+'<td class="column-desc"><span>' + getNotEmptyStr(item.description) + '</span>'
+'<input type="text" class="desc-input form-control" style="display:none;width: 100%;" column="' + item.name + '" value="' + (isEmpty(item.description)?'':item.description) + '">'
+'</tr>'
);
}
var tableInfo = msg.data.tableInfo;
if (!!tableInfo && isNotEmpty(tableInfo.description)) {
$(".table-desc").text(getNotEmptyStr(tableInfo.description));
}
$("#tableDescShow .icon-edit").show();
pageConfig.tableRelationDataIndex = 0;
changetableRelationOption(tableRelationData, columnList);
tableRelationData.name = tableInfo.tableName;
tableRelationCharts.setOption(tableRelationOption);
var height = pageConfig.tableRelationDataIndex * 25;
$("#tableRelationBox").css("height", height + "px");
tableRelationCharts.resize();
});
}
function updateTableDesc(){
var tableDescInput = $("#tableDescInput").val();
var param = getChoiseDbInfo(3);
if(param == null){
return;
}
param.newDesc = tableDescInput;
postService("zyplayer-doc-db/doc-db/updateTableDesc", param, function(msg){
$("#tableDescShow .table-desc").text(tableDescInput);
});
}
function getChoiseDbInfo(type) {
var host = $("#choiseHost").val();
var dbName = $("#choiseDatabase").val();
var tableName = $("#choiseTable").val();
if(type >= 1 && isEmpty(host)){
Toast.warn("请先选择连接");return null;
}
if(type >= 2 && isEmpty(dbName)){
Toast.warn("请先选择库名");return null;
}
if(type >= 3 && isEmpty(tableName)){
Toast.warn("请先选择表名");return null;
}
return {host: host, dbName: dbName, tableName: tableName};
}
function fuzzySearchByDesc(){
var host = $("#choiseFuzzyHost").val();
var dbName = $("#choiseFuzzyDatabase").val();
var searchText = $("#searchText").val();
if(isEmpty(host)){
Toast.warn("请先选择库名");return;
}
if(isEmpty(dbName)){
Toast.warn("请先选择库名");return;
}
if(isEmpty(searchText)){
Toast.warn("请输入模糊匹配的内容");return;
}
$("#doSearch .icon").removeClass("hidden");
var param = {host: host, dbName: dbName, searchText: searchText};
postService("zyplayer-doc-db/doc-db/getTableAndColumnBySearch", param, function(msg){
$("#fuzzySearchTable tbody").empty();
for (var i = 0; i < msg.data.length; i++) {
var item = msg.data[i];
$("#fuzzySearchTable tbody").append(
'<tr>'
+'<td>' + item.tableName + '</td>'
+'<td>' + item.columnName + '</td>'
+'<td>' + getNotEmptyStr(item.description) + '</td>'
+'</tr>'
);
}
$('#fuzzySearchModal').modal('ajustPosition', 'fit');
}, function(){
$("#doSearch .icon").addClass("hidden");
});
}
var pageConfig = {
host: '',
tableRelationDataIndex: 0,
}
// 表关系图表
var tableRelationCharts;
$(document).ready(function(){
// 无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢
console.log("%c项目信息\n开发者列表暮光城中城\n项目地址https://gitee.com/zyplayer/zyplayer-doc","color:red");
$('select.chosen-select').chosen({
no_results_text: '没有找到', // 当检索时没有找到匹配项时显示的提示文本
disable_search_threshold: 0, // 10 个以下的选择项则不显示检索框
search_contains: true, // 从任意位置开始检索
width: '100%'
});
$('#checkAllTable').click(function(e){
$("#exportUl li").addClass("checked");
});
$('#notCheckAllTable').click(function(e){
$("#exportUl li").removeClass("checked");
});
$('#choiseExportDatabase').on('change', function(e){
var host = $('#choiseExportHost').val();
var dbName = $('#choiseExportDatabase').val();
postService("zyplayer-doc-db/doc-db/getTableList", {host: host, dbName: dbName}, function(result){
$('#exportUl').empty();
for (var i = 0; i < result.data.length; i++) {
$("#exportUl").append('<li>'+result.data[i].tableName+'</li>');
}
$('#exportModal').modal('ajustPosition', 'fit');
});
});
$('#choiseExportHost').on('change', function(e){
var host = $(this).val();
postService("zyplayer-doc-db/doc-db/getDatabaseList", {host: host}, function(result){
$('#choiseExportDatabase').empty();
$("#choiseExportDatabase").append('<option value=""></option>');
for (var i = 0; i < result.data.length; i++) {
var dbName = result.data[i].dbName;
$("#choiseExportDatabase").append('<option value="'+dbName+'">'+dbName+'</option>');
}
$('#choiseExportDatabase').trigger('chosen:updated');
});
});
$('#choiseFuzzyHost').on('change', function(e){
var host = $(this).val();
postService("zyplayer-doc-db/doc-db/getDatabaseList", {host: host}, function(result){
$('#choiseFuzzyDatabase').empty();
$("#choiseFuzzyDatabase").append('<option value=""></option>');
for (var i = 0; i < result.data.length; i++) {
var dbName = result.data[i].dbName;
$("#choiseFuzzyDatabase").append('<option value="'+dbName+'">'+dbName+'</option>');
}
$('#choiseFuzzyDatabase').trigger('chosen:updated');
});
});
$('#choiseHost').on('change', function(e){
pageConfig.host = $(this).val();
postService("zyplayer-doc-db/doc-db/getDatabaseList", {host: pageConfig.host}, function(result){
$('#choiseDatabase').empty();
$('#choiseTable').empty();
$("#choiseDatabase").append('<option value=""></option>');
$("#choiseTable").append('<option value=""></option>');
for (var i = 0; i < result.data.length; i++) {
var dbName = result.data[i].dbName;
$("#choiseDatabase").append('<option value="'+dbName+'">'+dbName+'</option>');
}
$('#choiseDatabase').trigger('chosen:updated');
$('#choiseTable').trigger('chosen:updated');
});
});
$('#choiseDatabase').on('change', function(e){
var dbName = $(this).val();
var param = {host: pageConfig.host, dbName: dbName};
postService("zyplayer-doc-db/doc-db/getTableList", param, function(result){
$('#choiseTable').empty();
$("#choiseTable").append('<option value=""></option>');
for (var i = 0; i < result.data.length; i++) {
var tableName = result.data[i].tableName;
$("#choiseTable").append('<option value="'+tableName+'">'+tableName+'</option>');
}
$('#choiseTable').trigger('chosen:updated');
});
});
$('#choiseTable').on('change', function(e){
getTableColumnList();
});
$('#tableDescShow .icon-edit').click(function(e){
var nowDesc = $("#tableDescShow .table-desc").html();
$("#tableDescInput").val((nowDesc == "暂无注释") ? "" : nowDesc);
$("#tableDescShow").hide();
$("#tableDescInput").show().focus();
});
$("#tableDescInput").blur(function(){
$("#tableDescShow").show();
$("#tableDescInput").hide();
updateTableDesc();
});
$("#fuzzySearchBtn").click(function(){
$('#fuzzySearchModal').modal({moveable:true, backdrop: 'static'});
$('#choiseFuzzyHost').trigger('chosen:updated');
});
$("#exportBtn").click(function(){
$('#exportModal').modal({moveable:true, backdrop: 'static'});
});
$("#doExport").click(function(){
var host = $('#choiseExportHost').val();
var dbName = $('#choiseExportDatabase').val();
var tableNames = "";
$('#exportUl li.checked').text(function(index, value){
if(tableNames != "") {tableNames += ",";}
tableNames += value;
});
if(isEmpty(host)){
Toast.warn("请先选择库名");return;
}
if(isEmpty(dbName)){
Toast.warn("请先选择库名");return;
}
if(isEmpty(tableNames)){
Toast.warn("请输选择需要导出的表");return;
}
window.open("zyplayer-doc-db/doc-db/exportDatabase?host="+host
+"&dbName="+dbName
+"&tableNames="+tableNames);
});
$("#exportUl").on("click", "li", function(){
$(this).toggleClass("checked");
});
$("#showEchartsBtn").click(function(){
$("#tableRelationBox").toggleClass("hide");
if($("#tableRelationBox").hasClass("hide")){
$(this).text("显示表关系图");
} else {
$(this).text("隐藏表关系图");
tableRelationCharts.resize();
}
});
$("#doSearch").click(function(){
fuzzySearchByDesc();
});
$("#aboutBtn").click(function(){
$('#aboutModal').modal({moveable:true, backdrop: 'static'});
});
$("#tableCloumnsTable tbody").on("click", ".column-desc", function(event){
$(this).find("span").hide();
$(this).find(".desc-input").show().focus();
}).on("blur", ".column-desc", function(event){
var newDesc = $(this).find(".desc-input").val();
var columnName = $(this).find(".desc-input").attr("column");
var oldDesc = $(this).find("span").text();
$(this).find("span").show();
$(this).find(".desc-input").hide();
if(newDesc != oldDesc){
var objThis = this;
var param = getChoiseDbInfo(3);
if(param == null){
return;
}
param.newDesc = newDesc;
param.columnName = columnName;
postService("zyplayer-doc-db/doc-db/updateTableColumnDesc", param, function(msg){
$(objThis).find("span").text(newDesc);
});
}
});
initData();
checkSystemUpgrade();
});
function initData(){
postService("zyplayer-doc-db/doc-db/getDataSourceList", {}, function(result){
$('#choiseHost,#choiseFuzzyHost,#choiseExportHost').empty();
if(validateResult(result)) {
$("#choiseHost,#choiseFuzzyHost,#choiseExportHost").append('<option value=""></option>');
for (var i = 0; i < result.data.length; i++) {
$("#choiseHost,#choiseFuzzyHost,#choiseExportHost").append('<option value="'+result.data[i]+'">'+result.data[i]+'</option>');
}
}
$('#choiseHost').trigger('chosen:updated');
$('#choiseFuzzyHost').trigger('chosen:updated');
$('#choiseExportHost').trigger('chosen:updated');
});
tableRelationCharts = echarts.init(document.getElementById('tableRelationCharts'));
tableRelationCharts.setOption(tableRelationOption);
tableRelationCharts.on('click', function (params) {
//console.log(params.data);
var dataIndex = params.data.index;
var description = params.data.description;
// 用户IDT:user_info.id
// 用户IDT:order_db.user_info.id
var indexOf = description.indexOf("T:");
if(indexOf < 0) {
Toast.warn("该字段未关联表");
return;
}
var dbAndTable = description.substring(indexOf + 2, description.length);
var dbNameChoise, tableNameChoise;
var tempSplit = dbAndTable.split(".");
if(tempSplit.length == 3) {
dbNameChoise = tempSplit[0];
tableNameChoise = tempSplit[1];
} else if(tempSplit.length == 2) {
tableNameChoise = tempSplit[0];
} else {
tableNameChoise = dbAndTable;
}
var children = findChildren(tableRelationData, dataIndex);
if(children != null && children.children.length <= 0) {
// 查询表字段
var param = getChoiseDbInfo(2);
if(param == null){
return;
}
if(isNotEmpty(dbNameChoise)){
param.dbName = dbNameChoise;
}
param.tableName = tableNameChoise;
postService("zyplayer-doc-db/doc-db/getTableColumnList", param, function(msg){
var columnList = msg.data.columnList
if(!columnList || columnList.length <= 0) {
Toast.warn("未找到该字段关联的表信息");return;
}
changetableRelationOption(children, columnList);
tableRelationCharts.setOption(tableRelationOption);
var height = pageConfig.tableRelationDataIndex * 25;
$("#tableRelationBox").css("height", height + "px");
tableRelationCharts.resize();
});
}
});
}
function changetableRelationOption(data, columnList){
var childrenArr = [];
for (var i = 0; i < columnList.length; i++) {
var item = columnList[i];
var description = getNotEmptyStr(item.description);
var indexOf = description.indexOf("T:");
var dbAndTable = "";
if(indexOf >= 0) {
dbAndTable = " " + description.substring(indexOf + 2, description.length);
}
childrenArr.push({
name: item.name + " " + item.type + dbAndTable,
children: [],
collapsed: false,
index: pageConfig.tableRelationDataIndex++,
description: getNotEmptyStr(item.description),
length: item.length
});
}
data.children = childrenArr;
}
function findChildren(source, dataIndex){
var result = null;
echarts.util.each(source.children, function (datum, index) {
if(result != null) {
return;
}
if(datum.index == dataIndex) {
result = datum;
} else if(datum.children && datum.children.length > 0) {
result = findChildren(datum, dataIndex);
}
});
if(result != null) {
return result;
}
}
function getTableColumnList(){
var param = getChoiseDbInfo(3);
if(param == null){
return;
}
$("#tableDescShow .icon-edit").hide();
$("#tableCloumnsTable tbody").empty();
$(".table-name").text(param.tableName);
$(".table-desc").text("暂无注释");
postService("zyplayer-doc-db/doc-db/getTableColumnList", param, function(msg){
var columnList = msg.data.columnList
for (var i = 0; i < columnList.length; i++) {
var item = columnList[i];
//var isidentity = isNull(item.isidentity) ? '-' : (1 == item.isidentity ? '是' : '否');
$("#tableCloumnsTable tbody").append(
'<tr>'
+'<td>' + item.name + '</td>'
+'<td>' + (1 == item.isidentity ? '' : '否') + '</td>'
+'<td>' + getNotEmptyStr(item.type) + '</td>'
+'<td>' + getNotEmptyStr(item.length) + '</td>'
+'<td>' + (1 == item.nullable ? '允许' : '不允许') + '</td>'
+'<td>' + ("true" == item.ispramary ? '是' : '否') + '</td>'
+'<td class="column-desc"><span>' + getNotEmptyStr(item.description) + '</span>'
+'<input type="text" class="desc-input form-control" style="display:none;width: 100%;" column="' + item.name + '" value="' + (isEmpty(item.description)?'':item.description) + '">'
+'</tr>'
);
}
var tableInfo = msg.data.tableInfo;
if (!!tableInfo && isNotEmpty(tableInfo.description)) {
$(".table-desc").text(getNotEmptyStr(tableInfo.description));
}
$("#tableDescShow .icon-edit").show();
pageConfig.tableRelationDataIndex = 0;
changetableRelationOption(tableRelationData, columnList);
tableRelationData.name = tableInfo.tableName;
tableRelationCharts.setOption(tableRelationOption);
var height = pageConfig.tableRelationDataIndex * 25;
$("#tableRelationBox").css("height", height + "px");
tableRelationCharts.resize();
});
}
function updateTableDesc(){
var tableDescInput = $("#tableDescInput").val();
var param = getChoiseDbInfo(3);
if(param == null){
return;
}
param.newDesc = tableDescInput;
postService("zyplayer-doc-db/doc-db/updateTableDesc", param, function(msg){
$("#tableDescShow .table-desc").text(tableDescInput);
});
}
function getChoiseDbInfo(type) {
var host = $("#choiseHost").val();
var dbName = $("#choiseDatabase").val();
var tableName = $("#choiseTable").val();
if(type >= 1 && isEmpty(host)){
Toast.warn("请先选择连接");return null;
}
if(type >= 2 && isEmpty(dbName)){
Toast.warn("请先选择库名");return null;
}
if(type >= 3 && isEmpty(tableName)){
Toast.warn("请先选择表名");return null;
}
return {host: host, dbName: dbName, tableName: tableName};
}
function fuzzySearchByDesc(){
var host = $("#choiseFuzzyHost").val();
var dbName = $("#choiseFuzzyDatabase").val();
var searchText = $("#searchText").val();
if(isEmpty(host)){
Toast.warn("请先选择库名");return;
}
if(isEmpty(dbName)){
Toast.warn("请先选择库名");return;
}
if(isEmpty(searchText)){
Toast.warn("请输入模糊匹配的内容");return;
}
$("#doSearch .icon").removeClass("hidden");
var param = {host: host, dbName: dbName, searchText: searchText};
postService("zyplayer-doc-db/doc-db/getTableAndColumnBySearch", param, function(msg){
$("#fuzzySearchTable tbody").empty();
for (var i = 0; i < msg.data.length; i++) {
var item = msg.data[i];
$("#fuzzySearchTable tbody").append(
'<tr>'
+'<td>' + item.tableName + '</td>'
+'<td>' + item.columnName + '</td>'
+'<td>' + getNotEmptyStr(item.description) + '</td>'
+'</tr>'
);
}
$('#fuzzySearchModal').modal('ajustPosition', 'fit');
}, function(){
$("#doSearch .icon").addClass("hidden");
});
}
function checkSystemUpgrade() {
ajaxTemp("system/info/upgrade", "post", "json", {}, function (json) {
if (json.errCode == 200 && !!json.data) {
$(".upgrade-info").show();
$("#upgradeNowVersion").html(json.data.nowVersion);
$("#upgradeLastVersion").html(json.data.lastVersion);
$("#upgradeUrl").html("<a target='_blank' href='" + json.data.upgradeUrl + "'>" + json.data.upgradeUrl + "</a>");
$("#upgradeContent").html(json.data.upgradeContent);
console.log("zyplayer-doc发现新版本"
+ "\n升级地址" + json.data.upgradeUrl
+ "\n当前版本" + json.data.nowVersion
+ "\n最新版本" + json.data.lastVersion
+ "\n升级内容" + json.data.upgradeContent
);
}
});
}

View File

@@ -0,0 +1,23 @@
# zyplayer-doc-dubbo
#### 项目介绍
dubbo文档的管理项目支持文档自动扫描文档展示和修改支持参数自动扫描获取接口在线调试
#### 软件架构
后端使用spring boot前端使用vue、element-ui、JQuery等
#### 安装教程
1. `zyplayer-doc-manage` -> `application.yml` -> `zyplayer.dubbo.zookeeper.url` 配置zookeeper地址
2. `zyplayer-doc-manage` -> `application.yml` -> `zyplayer.dubbo.nacos.url` 配置nacos服务地址
3. 默认找zookeeper未配置再找nacos的配置访问地址http://127.0.0.1:8082/zyplayer-doc-manage/doc-dubbo.html
4. 支持文档查找、文档编辑、在线调试接口
5. 自动获取参数列表需要指定的类存在,所以请在 pom.xml -> dependencies 最后加上服务所在的包后端才能通过Class.forName("xx");来找到参数列表,减少录入成本
6. 数组或List参数调试参数录入格式例[1,2] 后端通过JSON工具转成指定类型有不支持的类型时欢迎反馈

226
zyplayer-doc-dubbo/pom.xml Normal file
View File

@@ -0,0 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc-dubbo</artifactId>
<version>1.0.2</version>
<packaging>jar</packaging>
<name>zyplayer-doc-dubbo</name>
<description>dubbo文档工具</description>
<url>https://gitee.com/zyplayer/zyplayer-doc/zyplayer-doc-dubbo</url>
<developers>
<developer>
<id>zyplayer</id>
<name>暮光:城中城</name>
<email>806783409@qq.com</email>
<roles>
<role>Java Development Engineer</role>
</roles>
<timezone>2018-05-22 16:06:06</timezone>
</developer>
</developers>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<!-- 打包跳过单元测试 -->
<skipTests>true</skipTests>
<destDir>${project.build.outputDirectory}/META-INF/resources/webjars/${project.artifactId}/${project.version}</destDir>
<zyplayer.doc.version>1.0.2</zyplayer.doc.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.44</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
<version>4.1.8</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc-core</artifactId>
<version>${zyplayer.doc.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.0</version>
</dependency>
<!-- 业务包 -->
</dependencies>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<scm>
<connection>scm:git@git.oschina.net:zyplayer/zyplayer-doc.git</connection>
<developerConnection>scm:git@git.oschina.net:zyplayer/zyplayer-doc.git</developerConnection>
<url>git@git.oschina.net:zyplayer/zyplayer-doc.git</url>
</scm>
<distributionManagement>
<snapshotRepository>
<id>snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>snapshots</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>META-INF/resources/</targetPath>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/webapp</directory>
<includes>
<include>**/*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.2</version>
<configuration>
<aggregate>true</aggregate>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<skipTests>${skipTests}</skipTests>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.2</version>
<configuration>
<aggregate>true</aggregate>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -0,0 +1,459 @@
package com.zyplayer.doc.dubbo.controller;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.dubbo.controller.param.DubboRequestParam;
import com.zyplayer.doc.dubbo.controller.vo.DubboInfoVo;
import com.zyplayer.doc.dubbo.framework.bean.DubboDocInfo;
import com.zyplayer.doc.dubbo.framework.bean.DubboInfo;
import com.zyplayer.doc.dubbo.framework.bean.NacosDubboInfo;
import com.zyplayer.doc.dubbo.framework.bean.ReferenceConfigHolder;
import com.zyplayer.doc.dubbo.framework.constant.StorageKeys;
import com.zyplayer.doc.dubbo.framework.service.MgDubboStorageService;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.UrlUtils;
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.definition.model.MethodDefinition;
import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
import org.apache.dubbo.rpc.service.GenericService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* 文档控制器
*
* @author 暮光:城中城
* @since 2019年2月10日
*/
@AuthMan
@RestController
@RequestMapping("/zyplayer-doc-dubbo/doc-dubbo")
public class DubboController {
private static Logger logger = LoggerFactory.getLogger(DubboController.class);
private final static String DEFAULT_ROOT = "dubbo";
private final static String METADATA_NODE_NAME = "service.data";
private String root;
@Value("${zyplayer.doc.dubbo.zookeeper.url:}")
private String serviceZookeeperUrl;
@Value("${zyplayer.doc.dubbo.zookeeper.metadata-url:}")
private String metadataZookeeperUrl;
@Value("${zyplayer.doc.dubbo.nacos.url:}")
private String nacosUrl;
@Value("${zyplayer.doc.dubbo.nacos.service:}")
private String nacosService;
@Resource
private MgDubboStorageService mgDubboStorageService;
private CuratorFramework serverClient;
private CuratorFramework metadataClient;
private void initServerClient() {
if (serverClient == null && StringUtils.isNotBlank(serviceZookeeperUrl)) {
synchronized (DEFAULT_ROOT) {
if (serverClient == null) {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
serverClient = CuratorFrameworkFactory.newClient(serviceZookeeperUrl, retryPolicy);
serverClient.start();
}
}
}
}
private void initMetadataClient() {
if (metadataClient == null && StringUtils.isNotBlank(metadataZookeeperUrl)) {
synchronized (DEFAULT_ROOT) {
if (metadataClient == null) {
URL url = UrlUtils.parseURL(metadataZookeeperUrl, Collections.emptyMap());
String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
if (!group.startsWith(Constants.PATH_SEPARATOR)) {
group = Constants.PATH_SEPARATOR + group;
}
this.root = group;
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
metadataClient = CuratorFrameworkFactory.newClient(metadataZookeeperUrl, retryPolicy);
metadataClient.start();
}
}
}
}
/**
* 重新获取所有的服务列表
*
* @author 暮光:城中城
* @since 2019年2月10日
**/
@PostMapping(value = "/reloadService")
public DocResponseJson loadService() throws Exception {
List<DubboInfo> providerList;
try {
if (StringUtils.isBlank(serviceZookeeperUrl)) {
if (StringUtils.isBlank(nacosUrl) || StringUtils.isBlank(nacosService)) {
return DocResponseJson.warn("zyplayer.doc.dubbo.zookeeper.url、zyplayer.doc.dubbo.nacos.url 参数均未配置");
}
logger.info("zookeeper参数未配置使用nacos配置");
providerList = this.getDubboInfoByNacos();
} else {
providerList = this.getDubboInfoByZookeeper();
}
mgDubboStorageService.put(StorageKeys.DUBBO_SERVICE_LIST, JSON.toJSONString(providerList));
} catch (Exception e) {
e.printStackTrace();
return DocResponseJson.warn("获取服务列表失败");
}
return DocResponseJson.ok();
}
/**
* 请求执行服务
*
* @author 暮光:城中城
* @since 2019年2月10日
**/
@PostMapping(value = "/request")
public DocResponseJson request(DubboRequestParam param) {
DubboInfo.DubboNodeInfo dubboNodeInfo = new DubboInfo.DubboNodeInfo();
dubboNodeInfo.setIp(param.getIp());
dubboNodeInfo.setPort(param.getPort());
dubboNodeInfo.setInterfaceX(param.getService());
String paramTypeStr = Optional.ofNullable(param.getParamTypes()).orElse("");
String paramsStr = Optional.ofNullable(param.getParams()).orElse("");
List<String> typeList = JSON.parseArray(paramTypeStr, String.class);
List<String> paramList = JSON.parseArray(paramsStr, String.class);
List<String> queryTypeList = new LinkedList<>();
List<Object> queryParamList = new LinkedList<>();
for (int i = 0; i < paramList.size(); i++) {
String typeStr = typeList.get(i);
String paramStr = paramList.get(i);
try {
if (typeStr.endsWith("[]")) {
String type = typeStr.substring(0, typeStr.length() - 2);
Class<?> aClass = Class.forName(type);
List<?> objects = JSON.parseArray(paramStr, aClass);
queryTypeList.add(typeStr);
queryParamList.add(objects);
} else if (typeStr.matches("java\\.util\\.List<.+>")) {
Pattern pattern = Pattern.compile("java\\.util\\.List<(.+)>");
Matcher matcher = pattern.matcher(typeStr);
if (matcher.find()) {
String group = matcher.group(1);
Class<?> aClass = Class.forName(group);
List<?> objects = JSON.parseArray(paramStr, aClass);
queryParamList.add(objects);
queryTypeList.add("java.util.List");
}
} else {
Class<?> aClass = Class.forName(typeStr);
Object object = JSON.parseObject(paramStr, aClass);
queryParamList.add(object);
queryTypeList.add(typeStr);
}
} catch (Exception e) {
// 未找到对应类型,请手动引入项目包
logger.warn("未找到对应类型,请手动引入项目包:{}", typeStr);
queryParamList.add(paramStr);
queryTypeList.add(typeStr);
}
}
GenericService bean = ReferenceConfigHolder.getBean(dubboNodeInfo);
try {
Object result = bean.$invoke(param.getMethod(), queryTypeList.toArray(new String[]{}), queryParamList.toArray());
return DocResponseJson.ok(result);
} catch (Exception e) {
e.printStackTrace();
return DocResponseJson.warn("请求失败:" + e.getMessage());
}
}
/**
* 获取文档列表
*
* @author 暮光:城中城
* @since 2019年2月10日
**/
@PostMapping(value = "/getDocList")
public DocResponseJson getDocList() {
String dubboServiceList = mgDubboStorageService.get(StorageKeys.DUBBO_SERVICE_LIST);
String dubboServiceDoc = mgDubboStorageService.get(StorageKeys.DUBBO_SERVICE_DOC);
if (StringUtils.isBlank(dubboServiceList)) {
return DocResponseJson.ok();
}
DubboInfoVo dubboInfoVo = new DubboInfoVo();
List<DubboInfo> providerList = JSON.parseArray(dubboServiceList, DubboInfo.class);
dubboInfoVo.setServerList(providerList);
if (StringUtils.isNotBlank(dubboServiceDoc)) {
List<DubboDocInfo> docInfoList = JSON.parseArray(dubboServiceDoc, DubboDocInfo.class);
Map<String, DubboDocInfo> docInfoMap = docInfoList.stream().collect(Collectors.toMap(DubboDocInfo::getFunction, val -> val));
dubboInfoVo.setDocMap(docInfoMap);
}
return DocResponseJson.ok(dubboInfoVo);
}
/**
* 获取文档详情,依据类名生成
*
* @author 暮光:城中城
* @since 2019年2月10日
**/
@PostMapping(value = "/findDocInfo")
public DocResponseJson findDocInfo(DubboRequestParam param) {
DubboDocInfo definition = this.getDefinitionByJar(param);
if (definition == null) {
definition = this.getDefinitionByMetadata(param);
}
if (definition == null) {
return DocResponseJson.warn("未找到指定类请引入相关包或开启metadata类名" + param.getService());
}
Map<String, DubboDocInfo> docInfoMap = new HashMap<>();
String dubboServiceDoc = mgDubboStorageService.get(StorageKeys.DUBBO_SERVICE_DOC);
if (StringUtils.isNotBlank(dubboServiceDoc)) {
List<DubboDocInfo> docInfoList = JSON.parseArray(dubboServiceDoc, DubboDocInfo.class);
docInfoMap = docInfoList.stream().collect(Collectors.toMap(DubboDocInfo::getFunction, val -> val));
}
String function = param.getService() + "." + param.getMethod();
DubboDocInfo dubboDocInfo = docInfoMap.get(function);
if (dubboDocInfo == null) {
dubboDocInfo = new DubboDocInfo();
dubboDocInfo.setParams(definition.getParams());
dubboDocInfo.setFunction(function);
dubboDocInfo.setVersion(1);
dubboDocInfo.setResultType(definition.getResultType());
dubboDocInfo.setService(param.getService());
dubboDocInfo.setMethod(param.getMethod());
docInfoMap.put(function, dubboDocInfo);
List<DubboDocInfo> docInfoList = new ArrayList<>(docInfoMap.values());
mgDubboStorageService.put(StorageKeys.DUBBO_SERVICE_DOC, JSON.toJSONString(docInfoList));
}
return DocResponseJson.ok(dubboDocInfo);
}
/**
* 保存文档
*
* @author 暮光:城中城
* @since 2019年2月10日
**/
@PostMapping(value = "/saveDoc")
public DocResponseJson saveDoc(DubboDocInfo param, String paramsJson) {
String dubboServiceDoc = mgDubboStorageService.get(StorageKeys.DUBBO_SERVICE_DOC);
Map<String, DubboDocInfo> docInfoMap = new HashMap<>();
if (StringUtils.isNotBlank(dubboServiceDoc)) {
List<DubboDocInfo> docInfoList = JSON.parseArray(dubboServiceDoc, DubboDocInfo.class);
docInfoMap = docInfoList.stream().collect(Collectors.toMap(DubboDocInfo::getFunction, val -> val));
}
String function = param.getService() + "." + param.getMethod();
DubboDocInfo dubboDocInfo = docInfoMap.get(function);
if (dubboDocInfo != null) {
Integer newVersion = Optional.ofNullable(param.getVersion()).orElse(1);
Integer oldVersion = Optional.ofNullable(dubboDocInfo.getVersion()).orElse(1);
if (oldVersion > newVersion) {
return DocResponseJson.warn("已有用户在您之前修改过文档,请刷新后再修改");
}
param.setVersion(oldVersion + 1);
if (StringUtils.isEmpty(param.getExplain())) {
param.setExplain(dubboDocInfo.getExplain());
}
if (StringUtils.isEmpty(param.getResult())) {
param.setResult(dubboDocInfo.getResult());
}
param.setParams(dubboDocInfo.getParams());
} else {
param.setVersion(1);
}
if (StringUtils.isNotBlank(paramsJson)) {
param.setParams(JSON.parseArray(paramsJson, DubboDocInfo.DubboDocParam.class));
}
param.setFunction(function);
docInfoMap.put(function, param);
List<DubboDocInfo> docInfoList = new ArrayList<>(docInfoMap.values());
mgDubboStorageService.put(StorageKeys.DUBBO_SERVICE_DOC, JSON.toJSONString(docInfoList));
return DocResponseJson.ok(param);
}
/**
* 通过nacos方式获取所有服务
*
* @author 暮光:城中城
* @since 2019年2月10日
**/
private List<DubboInfo> getDubboInfoByNacos() {
List<DubboInfo> providerList = new LinkedList<>();
String[] nacosServiceArr = nacosService.split(";");
for (String service : nacosServiceArr) {
String resultStr = HttpUtil.get(nacosUrl + "/v1/ns/instance/list?serviceName=providers:" + service);
NacosDubboInfo dubboInstance = JSON.parseObject(resultStr, NacosDubboInfo.class);
List<NacosDubboInfo.HostsBean> hosts = dubboInstance.getHosts();
DubboInfo dubboInfo = new DubboInfo();
List<DubboInfo.DubboNodeInfo> nodeList = new LinkedList<>();
for (NacosDubboInfo.HostsBean host : hosts) {
DubboInfo.DubboNodeInfo dubboNodeInfo = new DubboInfo.DubboNodeInfo();
dubboNodeInfo.setIp(host.getIp());
dubboNodeInfo.setPort(host.getPort());
dubboNodeInfo.setInterfaceX(host.getMetadata().getInterfaceX());
dubboNodeInfo.setMethods(host.getMetadata().getMethods().split(","));
dubboNodeInfo.setApplication(host.getMetadata().getApplication());
nodeList.add(dubboNodeInfo);
}
dubboInfo.setInterfaceX(service);
dubboInfo.setNodeList(nodeList);
providerList.add(dubboInfo);
}
return providerList;
}
/**
* 通过Zookeeper方式获取所有服务
*
* @author 暮光:城中城
* @since 2019年2月10日
**/
private List<DubboInfo> getDubboInfoByZookeeper() throws Exception {
this.initServerClient();
List<String> dubboList = serverClient.getChildren().forPath("/dubbo");
if (dubboList == null || dubboList.isEmpty()) {
return Collections.emptyList();
}
List<DubboInfo> providerList = new LinkedList<>();
for (String dubboStr : dubboList) {
String path = "/dubbo/" + dubboStr + "/providers";
if (serverClient.checkExists().forPath(path) == null) {
continue;
}
List<String> providers = serverClient.getChildren().forPath(path);
List<DubboInfo.DubboNodeInfo> nodeList = providers.stream().map(val -> {
String tempStr = val;
try {
tempStr = URLDecoder.decode(val, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
// IP和端口
String ipPort = tempStr.substring(tempStr.indexOf("://") + 3);
ipPort = ipPort.substring(0, ipPort.indexOf("/"));
String[] ipPortArr = ipPort.split(":");
// 参数
Map<String, String> paramMap = new HashMap<>();
String params = tempStr.substring(tempStr.indexOf("?"));
String[] paramsArr = params.split("&");
for (String param : paramsArr) {
String[] split = param.split("=");
paramMap.put(split[0], split[1]);
}
DubboInfo.DubboNodeInfo dubboNodeInfo = new DubboInfo.DubboNodeInfo();
dubboNodeInfo.setIp(ipPortArr[0]);
dubboNodeInfo.setPort(NumberUtils.toInt(ipPortArr[1]));
dubboNodeInfo.setInterfaceX(paramMap.get("interface"));
dubboNodeInfo.setMethods(paramMap.get("methods").split(","));
dubboNodeInfo.setApplication(paramMap.get("application"));
return dubboNodeInfo;
}).collect(Collectors.toList());
DubboInfo dubboInfo = new DubboInfo();
dubboInfo.setInterfaceX(dubboStr);
dubboInfo.setNodeList(nodeList);
providerList.add(dubboInfo);
}
return providerList;
}
private DubboDocInfo getDefinitionByMetadata(DubboRequestParam param) {
try {
this.initMetadataClient();
String path = getNodePath(param.getService(), null, null, param.getApplication());
if (metadataClient.checkExists().forPath(path) == null) {
return null;
}
String resultType = null;
String metadata = new String(metadataClient.getData().forPath(path));
FullServiceDefinition definition = JSON.parseObject(metadata, FullServiceDefinition.class);
List<DubboDocInfo.DubboDocParam> paramList = new LinkedList<>();
for (MethodDefinition method : definition.getMethods()) {
if (Objects.equals(method.getName(), param.getMethod())) {
String[] parameterTypes = method.getParameterTypes();
resultType = method.getReturnType();
for (int i = 0; i < parameterTypes.length; i++) {
DubboDocInfo.DubboDocParam docParam = new DubboDocInfo.DubboDocParam();
docParam.setParamType(parameterTypes[i]);
docParam.setParamName("arg" + i);
paramList.add(docParam);
}
}
}
DubboDocInfo dubboDocInfo = new DubboDocInfo();
dubboDocInfo.setParams(paramList);
dubboDocInfo.setResultType(resultType);
return dubboDocInfo;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private DubboDocInfo getDefinitionByJar(DubboRequestParam param) {
String resultType = null;
List<DubboDocInfo.DubboDocParam> paramList = new LinkedList<>();
try {
Class clazz = Class.forName(param.getService());
Method[] methods = clazz.getMethods();
for (Method method : methods) {
String methodName = method.getName();
if (methodName.equals(param.getMethod())) {
resultType = method.getGenericReturnType().getTypeName();
Type[] parameterTypes = method.getGenericParameterTypes();
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameterTypes.length; i++) {
DubboDocInfo.DubboDocParam docParam = new DubboDocInfo.DubboDocParam();
docParam.setParamName(parameters[i].getName());
docParam.setParamType(parameterTypes[i].getTypeName());
paramList.add(docParam);
}
}
}
} catch (Exception e) {
return null;
}
DubboDocInfo dubboDocInfo = new DubboDocInfo();
dubboDocInfo.setParams(paramList);
dubboDocInfo.setResultType(resultType);
return dubboDocInfo;
}
String toRootDir() {
if (root.equals(Constants.PATH_SEPARATOR)) {
return root;
}
return root + Constants.PATH_SEPARATOR;
}
String getNodePath(String serviceInterface, String version, String group, String application) {
MetadataIdentifier metadataIdentifier = new MetadataIdentifier(serviceInterface, version, group, Constants.PROVIDER_SIDE, application);
return toRootDir() + metadataIdentifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.PATH) + Constants.PATH_SEPARATOR + METADATA_NODE_NAME;
}
}

View File

@@ -0,0 +1,73 @@
package com.zyplayer.doc.dubbo.controller.param;
/**
* 请求参数对象
*
* @author 暮光:城中城
* @since 2019年2月10日
*/
public class DubboRequestParam {
private String application;
private String service;
private String method;
private String ip;
private Integer port;
private String paramTypes;
private String params;
public String getParamTypes() {
return paramTypes;
}
public void setParamTypes(String paramTypes) {
this.paramTypes = paramTypes;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public String getApplication() {
return application;
}
public void setApplication(String application) {
this.application = application;
}
}

View File

@@ -0,0 +1,32 @@
package com.zyplayer.doc.dubbo.controller.vo;
import com.zyplayer.doc.dubbo.framework.bean.DubboDocInfo;
import com.zyplayer.doc.dubbo.framework.bean.DubboInfo;
import java.util.List;
import java.util.Map;
/**
* @author 暮光:城中城
* @since 2019年1月10日
**/
public class DubboInfoVo {
private List<DubboInfo> serverList;
private Map<String, DubboDocInfo> docMap;
public List<DubboInfo> getServerList() {
return serverList;
}
public void setServerList(List<DubboInfo> serverList) {
this.serverList = serverList;
}
public Map<String, DubboDocInfo> getDocMap() {
return docMap;
}
public void setDocMap(Map<String, DubboDocInfo> docMap) {
this.docMap = docMap;
}
}

View File

@@ -0,0 +1,131 @@
package com.zyplayer.doc.dubbo.framework.bean;
import java.util.List;
/**
* 请求参数对象
*
* @author 暮光:城中城
* @since 2019年2月10日
*/
public class DubboDocInfo {
private String service;
private String method;
private String function;
private String explain;
private String result;
private String resultType;
private Integer version;
private List<DubboDocParam> params;
public static class DubboDocParam {
private String paramName;
private String paramType;
private String paramDesc;
private Object paramValue;
private Integer required;
public String getParamName() {
return paramName;
}
public void setParamName(String paramName) {
this.paramName = paramName;
}
public String getParamType() {
return paramType;
}
public void setParamType(String paramType) {
this.paramType = paramType;
}
public String getParamDesc() {
return paramDesc;
}
public void setParamDesc(String paramDesc) {
this.paramDesc = paramDesc;
}
public Object getParamValue() {
return paramValue;
}
public void setParamValue(Object paramValue) {
this.paramValue = paramValue;
}
public Integer getRequired() {
return required;
}
public void setRequired(Integer required) {
this.required = required;
}
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getExplain() {
return explain;
}
public void setExplain(String explain) {
this.explain = explain;
}
public List<DubboDocParam> getParams() {
return params;
}
public void setParams(List<DubboDocParam> params) {
this.params = params;
}
public String getFunction() {
return function;
}
public void setFunction(String function) {
this.function = function;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
}

View File

@@ -0,0 +1,81 @@
package com.zyplayer.doc.dubbo.framework.bean;
import com.alibaba.fastjson.annotation.JSONField;
import java.util.List;
/**
* @author 暮光:城中城
* @since 2019年1月10日
**/
public class DubboInfo {
@JSONField(name = "interface")
private String interfaceX;
private List<DubboNodeInfo> nodeList;
public static class DubboNodeInfo {
private Integer port;
private String ip;
@JSONField(name = "interface")
private String interfaceX;
private String[] methods;
private String application;
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getInterfaceX() {
return interfaceX;
}
public void setInterfaceX(String interfaceX) {
this.interfaceX = interfaceX;
}
public String[] getMethods() {
return methods;
}
public void setMethods(String[] methods) {
this.methods = methods;
}
public String getApplication() {
return application;
}
public void setApplication(String application) {
this.application = application;
}
}
public List<DubboNodeInfo> getNodeList() {
return nodeList;
}
public void setNodeList(List<DubboNodeInfo> nodeList) {
this.nodeList = nodeList;
}
public String getInterfaceX() {
return interfaceX;
}
public void setInterfaceX(String interfaceX) {
this.interfaceX = interfaceX;
}
}

View File

@@ -0,0 +1,333 @@
package com.zyplayer.doc.dubbo.framework.bean;
import com.alibaba.fastjson.annotation.JSONField;
import java.util.List;
/**
* @author 暮光:城中城
* @since 2019年1月10日
**/
public class NacosDubboInfo {
/**
* metadata : {}
* dom : providers:com.zyplayer.dubbo.service.UserService
* cacheMillis : 10000
* useSpecifiedURL : false
* hosts : [{"valid":true,"marked":false,"metadata":{"side":"provider","protocol":"dubbo","application":"dubbo-provider","methods":"getUserDetail,getUserList","dubbo":"2.0.2","pid":"8164","interface":"com.zyplayer.dubbo.service.UserService","category":"providers","generic":"false","anyhost":"true","bean.name":"ServiceBean:com.zyplayer.dubbo.service.UserService","timestamp":"1549953970871"},"instanceId":"127.0.0.1#22223#DEFAULT#providers:com.zyplayer.dubbo.service.UserService","port":22223,"ip":"127.0.0.1","clusterName":"DEFAULT","weight":1,"serviceName":"providers:com.zyplayer.dubbo.service.UserService","enabled":true}]
* checksum : 2489ae2874f2f490caf7d6195192d6c71549954548862
* lastRefTime : 1549954548862
* env :
* clusters :
*/
private MetadataBean metadata;
private String dom;
private int cacheMillis;
private boolean useSpecifiedURL;
private String checksum;
private long lastRefTime;
private String env;
private String clusters;
private List<HostsBean> hosts;
public MetadataBean getMetadata() {
return metadata;
}
public void setMetadata(MetadataBean metadata) {
this.metadata = metadata;
}
public String getDom() {
return dom;
}
public void setDom(String dom) {
this.dom = dom;
}
public int getCacheMillis() {
return cacheMillis;
}
public void setCacheMillis(int cacheMillis) {
this.cacheMillis = cacheMillis;
}
public boolean isUseSpecifiedURL() {
return useSpecifiedURL;
}
public void setUseSpecifiedURL(boolean useSpecifiedURL) {
this.useSpecifiedURL = useSpecifiedURL;
}
public String getChecksum() {
return checksum;
}
public void setChecksum(String checksum) {
this.checksum = checksum;
}
public long getLastRefTime() {
return lastRefTime;
}
public void setLastRefTime(long lastRefTime) {
this.lastRefTime = lastRefTime;
}
public String getEnv() {
return env;
}
public void setEnv(String env) {
this.env = env;
}
public String getClusters() {
return clusters;
}
public void setClusters(String clusters) {
this.clusters = clusters;
}
public List<HostsBean> getHosts() {
return hosts;
}
public void setHosts(List<HostsBean> hosts) {
this.hosts = hosts;
}
public static class MetadataBean {
}
public static class HostsBean {
/**
* valid : true
* marked : false
* metadata : {"side":"provider","protocol":"dubbo","application":"dubbo-provider","methods":"getUserDetail,getUserList","dubbo":"2.0.2","pid":"8164","interface":"com.zyplayer.dubbo.service.UserService","category":"providers","generic":"false","anyhost":"true","bean.name":"ServiceBean:com.zyplayer.dubbo.service.UserService","timestamp":"1549953970871"}
* instanceId : 127.0.0.1#22223#DEFAULT#providers:com.zyplayer.dubbo.service.UserService
* port : 22223
* ip : 127.0.0.1
* clusterName : DEFAULT
* weight : 1
* serviceName : providers:com.zyplayer.dubbo.service.UserService
* enabled : true
*/
private boolean valid;
private boolean marked;
private MetadataBeanX metadata;
private String instanceId;
private int port;
private String ip;
private String clusterName;
private int weight;
private String serviceName;
private boolean enabled;
public boolean isValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
public boolean isMarked() {
return marked;
}
public void setMarked(boolean marked) {
this.marked = marked;
}
public MetadataBeanX getMetadata() {
return metadata;
}
public void setMetadata(MetadataBeanX metadata) {
this.metadata = metadata;
}
public String getInstanceId() {
return instanceId;
}
public void setInstanceId(String instanceId) {
this.instanceId = instanceId;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public static class MetadataBeanX {
/**
* side : provider
* protocol : dubbo
* application : dubbo-provider
* methods : getUserDetail,getUserList
* dubbo : 2.0.2
* pid : 8164
* interface : com.zyplayer.dubbo.service.UserService
* category : providers
* generic : false
* anyhost : true
* bean.name : ServiceBean:com.zyplayer.dubbo.service.UserService
* timestamp : 1549953970871
*/
private String side;
private String protocol;
private String application;
private String methods;
private String dubbo;
private String pid;
@JSONField(name = "interface")
private String interfaceX;
private String category;
private String generic;
private String anyhost;
private String timestamp;
public String getSide() {
return side;
}
public void setSide(String side) {
this.side = side;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getApplication() {
return application;
}
public void setApplication(String application) {
this.application = application;
}
public String getMethods() {
return methods;
}
public void setMethods(String methods) {
this.methods = methods;
}
public String getDubbo() {
return dubbo;
}
public void setDubbo(String dubbo) {
this.dubbo = dubbo;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getInterfaceX() {
return interfaceX;
}
public void setInterfaceX(String interfaceX) {
this.interfaceX = interfaceX;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getGeneric() {
return generic;
}
public void setGeneric(String generic) {
this.generic = generic;
}
public String getAnyhost() {
return anyhost;
}
public void setAnyhost(String anyhost) {
this.anyhost = anyhost;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
}
}
}

View File

@@ -0,0 +1,42 @@
package com.zyplayer.doc.dubbo.framework.bean;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.rpc.service.GenericService;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author 暮光:城中城
* @since 2019年1月10日
**/
public class ReferenceConfigHolder {
private static Map<String, ReferenceConfig> referenceConfigMap = new ConcurrentHashMap<>();
public static GenericService getBean(DubboInfo.DubboNodeInfo dubboNodeInfo) {
String name = dubboNodeInfo.getInterfaceX();
String url = "dubbo://" + dubboNodeInfo.getIp() + ":" + dubboNodeInfo.getPort() + "/" + dubboNodeInfo.getInterfaceX();
ReferenceConfig referenceConfig = referenceConfigMap.get(url);
if (referenceConfig == null) {
ApplicationConfig application = new ApplicationConfig();
application.setName("zyplayer-doc-consume");
// 参考http://dubbo.apache.org/zh-cn/docs/user/configuration/api.html
// 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
referenceConfig = new ReferenceConfig<>();
// 如果点对点直连可以用reference.setUrl()指定目标地址设置url后将绕过注册中心
// 其中协议对应provider.setProtocol()的值端口对应provider.setPort()的值,
// 路径对应service.setPath()的值如果未设置path缺省path为接口名
referenceConfig.setUrl(url);
referenceConfig.setInterface(name.substring(name.lastIndexOf(".") + 1));
referenceConfig.setGeneric(true);
referenceConfig.setApplication(application);
referenceConfig.setTimeout(5000);
referenceConfigMap.put(url, referenceConfig);
}
// 本项目没有dubbo里面申明的类快放弃时看源码发现可以设置generic返回一个GenericService对象通过$invoke去操作具体方法感觉又打开了一扇大门
// 本项目选择的不入侵的方式管理文档,所以文档里面就必须手动加参数,写文档那些了
return (GenericService) referenceConfig.get();
}
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.dubbo.framework.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@ComponentScan(basePackages = {
"com.zyplayer.doc.dubbo",
})
public @interface EnableDocDubbo {
}

View File

@@ -0,0 +1,13 @@
package com.zyplayer.doc.dubbo.framework.constant;
/**
* 存储数据的KEY常量类
*
* @author 暮光:城中城
* @since 2018年8月21日
*/
public class StorageKeys {
// 所有文档地址
public static final String DUBBO_SERVICE_DOC = "dubbo-service-doc";
public static final String DUBBO_SERVICE_LIST = "dubbo-service-list";
}

View File

@@ -0,0 +1,47 @@
package com.zyplayer.doc.dubbo.framework.service;
import java.io.Serializable;
/**
* 数据类型
* @author 暮光:城中城
* @since 2018-11-27
*/
public class MgDubboStorage implements Serializable {
private static final long serialVersionUID = 1L;
private String key;
private String value;
public MgDubboStorage() {
}
public MgDubboStorage(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}

View File

@@ -0,0 +1,48 @@
package com.zyplayer.doc.dubbo.framework.service;
import java.util.List;
/**
* 实现此类才能使用服务器端的存贮功能
* dubbo的文档需要手动写的比较重要所以重起一个存储service实现类尽量操作另外的库
* @author 暮光:城中城
* @since 2018年8月19日
*/
public interface MgDubboStorageService {
/**
* 获取存储的值
* @author 暮光:城中城
* @since 2018年8月19日
* @param key 参数
* @return 值
*/
String get(String key);
/**
* 模糊获取存储的值
* @author 暮光:城中城
* @since 2018年8月19日
* @param key 参数
* @param value 值
* @return 值
*/
List<MgDubboStorage> like(String key, String value);
/**
* 存储数据
* @author 暮光:城中城
* @since 2018年8月19日
* @param key 参数
* @param value 值
*/
void put(String key, String value);
/**
* 删除数据
* @author 暮光:城中城
* @since 2018年8月19日
* @param key 参数
*/
void remove(String key);
}

View File

@@ -0,0 +1,62 @@
一些地址:
http://127.0.0.1:8082/zyplayer-doc-manage/zyplayer-doc-dubbo/doc-dubbo/getList
http://127.0.0.1.56:8848/nacos/index.html
zookeeper 格式:
路劲ls /dubbo/com.zyplayer.dubbo.service.UserService/providers
格式:
dubbo://127.0.0.1:22223/com.zyplayer.dubbo.service.UserService
?anyhost=true
&application=dubbo-provider
&bean.name=ServiceBean:com.zyplayer.dubbo.service.UserService
&dubbo=2.0.2
&generic=false
&interface=com.zyplayer.dubbo.service.UserService
&methods=getUserDetail,getUserList
&pid=36580
&side=provider
&timestamp=1549955979708
nacos 格式:
文档https://nacos.io/zh-cn/docs/open-API.html
请求地址http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=providers:com.zyplayer.dubbo.service.UserService
格式:
{
"metadata": {},
"dom": "providers:com.zyplayer.dubbo.service.UserService",
"cacheMillis": 10000,
"useSpecifiedURL": false,
"hosts": [{
"valid": true,
"marked": false,
"metadata": {
"side": "provider",
"protocol": "dubbo",
"application": "dubbo-provider",
"methods": "getUserDetail,getUserList",
"dubbo": "2.0.2",
"pid": "8164",
"interface": "com.zyplayer.dubbo.service.UserService",
"category": "providers",
"generic": "false",
"anyhost": "true",
"bean.name": "ServiceBean:com.zyplayer.dubbo.service.UserService",
"timestamp": "1549953970871"
},
"instanceId": "127.0.0.1#22223#DEFAULT#providers:com.zyplayer.dubbo.service.UserService",
"port": 22223,
"ip": "127.0.0.1",
"clusterName": "DEFAULT",
"weight": 1.0,
"serviceName": "providers:com.zyplayer.dubbo.service.UserService",
"enabled": true
}],
"checksum": "2489ae2874f2f490caf7d6195192d6c71549955797122",
"lastRefTime": 1549955797122,
"env": "",
"clusters": ""
}

View File

@@ -0,0 +1,482 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<!--无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢-->
<meta name="author" content="开发者列表暮光城中城项目地址https://gitee.com/zyplayer/zyplayer-doc" />
<title>dubbo文档管理系统</title>
<link rel="shortcut icon" href="webjars/doc-dubbo/img/dubbo.ico"/>
<link rel="stylesheet" href="webjars/doc-dubbo/css/element-ui.css">
<link rel="stylesheet" href="webjars/doc-dubbo/css/doc-dubbo.css" />
</head>
<body>
<div id="app">
<el-container style="height: 100%;">
<el-aside width="auto" style="height: 100%;">
<div class="logo" @click="aboutDialogVisible = true">zyplayer-doc-dubbo</div>
<div style="padding: 10px;">
<div align="center"><el-button type="primary" v-on:click="reloadService" icon="el-icon-refresh" style="width: 100%;">重新加载服务列表</el-button></div>
<!--<el-row><el-switch v-model="isCollapse"></el-switch></el-row>-->
<el-input v-model="searchKeywords" placeholder="搜索文档" style="margin: 10px 0;">
<el-button slot="append" icon="el-icon-search" v-on:click="searchByKeywords"></el-button>
</el-input>
<!--<el-menu default-active="" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose" :collapse="isCollapse">-->
<!--<el-submenu index="1">-->
<!--<template slot="title">-->
<!--<i class="el-icon-setting"></i>-->
<!--<span slot="title">文档管理</span>-->
<!--</template>-->
<!--<el-menu-item index="1-1">管理服务列表</el-menu-item>-->
<!--</el-submenu>-->
<!--</el-menu>-->
<el-tree :data="pathIndex" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
</div>
</el-aside>
<el-container>
<el-tabs type="border-card" style="width: 100%;">
<el-tab-pane label="接口说明">
<div v-if="!dubboInfo.interface">
请先选择服务
</div>
<el-form v-else label-width="80px">
<el-form-item label="服务:">
{{dubboInfo.interface}}
</el-form-item>
<el-form-item label="方法:">
{{dubboInfo.method}}
</el-form-item>
<el-form-item label="说明:">
<div v-if="dubboInfoExplainShow">
<pre>{{dubboInfo.docInfo.explain}}<el-button @click.prevent="dubboInfoExplainShow = false;" style="float: right;">编辑</el-button></pre>
</div>
<div v-else>
<el-input type="textarea" :rows="4" placeholder="维护人员、使用说明、便于搜索的信息" v-model="docInfoExplainInput"></el-input>
<el-button @click.prevent="dubboInfoExplainShow = true;" style="float: right;margin: 5px;">取消</el-button>
<el-button type="primary" @click.prevent="saveDocInfoExplain" style="float: right;margin: 5px;">保存</el-button>
</div>
</el-form-item>
<el-form-item label="节点:">
<el-table :data="dubboInfo.nodeList" border style="width: 100%">
<el-table-column prop="application" label="应用"></el-table-column>
<el-table-column prop="ip" label="IP"></el-table-column>
<el-table-column prop="port" label="端口"></el-table-column>
</el-table>
</el-form-item>
<el-form-item label="参数:">
<!--<div slot="label">-->
<!--<el-tooltip placement="top">-->
<!--<div slot="content">1. 顺序必须和参数的顺序一致<br/>2. 参数名意义不大,可不填</div>-->
<!--<i class="el-icon-info" style="color: #aaa;"></i>-->
<!--</el-tooltip>-->
<!--参数:-->
<!--</div>-->
<el-table :data="docParamList" border style="width: 100%; margin-bottom: 5px;">
<el-table-column label="顺序" width="100">
<template slot-scope="scope">{{scope.$index}}</template>
</el-table-column>
<el-table-column label="参数名" width="200">
<template slot-scope="scope">
<el-input v-model="scope.row.paramName"></el-input>
</template>
</el-table-column>
<el-table-column label="类型" width="300">
<template slot-scope="scope">{{scope.row.paramType}}</template>
<!--<template slot-scope="scope">-->
<!--<el-select v-model="scope.row.paramType" filterable allow-create clearable placeholder="请选择" style="width: 100%;">-->
<!--<el-option v-for="item in paramTypeOptions" :key="item.value" :label="item.value" :value="item.value"></el-option>-->
<!--</el-select>-->
<!--</template>-->
</el-table-column>
<el-table-column label="说明">
<template slot-scope="scope">
<el-input v-model="scope.row.paramDesc"></el-input>
</template>
</el-table-column>
</el-table>
<el-button @click.prevent="saveDocInfoParam" type="primary" style="float: right;margin: 5px;">保存</el-button>
<!--<el-button @click.prevent="addDocParam" style="float: right;margin: 5px;">添加</el-button>-->
</el-form-item>
<el-form-item label="返回值:">
{{dubboInfo.docInfo.resultType}}
</el-form-item>
<el-form-item label="结果:">
<div v-if="dubboInfoResultShow">
<pre>{{dubboInfo.docInfo.result}}<el-button @click.prevent="dubboInfoResultShow = false;" style="float: right;">编辑</el-button></pre>
</div>
<div v-else>
<el-input type="textarea" :rows="4" placeholder="结果集说明等" v-model="docInfoResultInput"></el-input>
<el-button @click.prevent="dubboInfoResultShow = true;" style="float: right;margin: 5px;">取消</el-button>
<el-button type="primary" @click.prevent="saveDocInfoResult" style="float: right;margin: 5px;">保存</el-button>
</div>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="在线调试">
<div v-if="!dubboInfo.interface">
请先选择服务
</div>
<div v-loading="onlineDebugLoading" v-else>
<el-input placeholder="请输入内容" v-model="dubboInfo.function" class="input-with-select">
<el-select v-model="requestHostValue" slot="prepend" placeholder="请选择" style="width: 200px;">
<el-option v-for="item in requestHostOptions" :key="item.value" :label="item.value" :value="item.value"></el-option>
</el-select>
<el-button slot="append" @click.prevent="requestExecute">执行</el-button>
</el-input>
<el-form label-width="100px" label-position="top">
<el-form-item label="请求参数:">
<el-table :data="docParamRequestList" border style="width: 100%; margin: 10px 0;">
<el-table-column label="顺序" width="100">
<template slot-scope="scope">{{scope.$index}}</template>
</el-table-column>
<el-table-column label="参数名">
<template slot-scope="scope">{{scope.row.paramName}}</template>
</el-table-column>
<el-table-column label="类型">
<template slot-scope="scope">{{scope.row.paramType}}</template>
</el-table-column>
<el-table-column label="参数值">
<template slot-scope="scope">
<el-input v-model="scope.row.paramValue"></el-input>
</template>
</el-table-column>
<el-table-column label="说明">
<template slot-scope="scope">{{scope.row.paramDesc}}</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item label="请求结果:">
<div v-html="requestResult"></div>
</el-form-item>
</el-form>
</div>
</el-tab-pane>
</el-tabs>
</el-container>
</el-container>
<el-dialog title="关于zyplayer-doc-dubbo" :visible.sync="aboutDialogVisible" width="600px">
<el-form>
<el-form-item label="项目地址:">
<a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc">zyplayer-doc</a>
</el-form-item>
<el-form-item label="开发人员:">
<a target="_blank" href="http://zyplayer.com">暮光:城中城</a>
</el-form-item>
<template v-if="upgradeInfo.lastVersion">
<el-form-item label="当前版本:">{{upgradeInfo.nowVersion}}</el-form-item>
<el-form-item label="最新版本:">{{upgradeInfo.lastVersion}}</el-form-item>
<el-form-item label="升级地址:">
<a target="_blank" :href="upgradeInfo.upgradeUrl">{{upgradeInfo.upgradeUrl}}</a>
</el-form-item>
<el-form-item label="升级内容:">{{upgradeInfo.upgradeContent}}</el-form-item>
</template>
<el-form-item label="">
欢迎加群讨论QQ群号466363173欢迎提交需求欢迎使用和加入开发
</el-form-item>
</el-form>
</el-dialog>
</div>
</body>
<script type="text/javascript" src="webjars/doc-dubbo/vue/vue.js"></script>
<script type="text/javascript" src="webjars/doc-dubbo/js/element-ui.js"></script>
<!-- ajax 用到了jquery -->
<script type="text/javascript" src="webjars/doc-dubbo/js/jquery-3.1.0.min.js"></script>
<script type="text/javascript" src="webjars/doc-dubbo/js/common.js"></script>
<script type="text/javascript" src="webjars/doc-dubbo/js/toast.js"></script>
<script type="text/javascript" src="webjars/doc-dubbo/js/formatjson.js"></script>
<script type="text/javascript" src="webjars/doc-dubbo/js/doc-dubbo-tree.js"></script>
<script>
var app = new Vue({
el: '#app',
data() {
return {
isCollapse: false,
aboutDialogVisible: false,
onlineDebugLoading: false,
pathIndex: [],
defaultProps: {
children: 'children',
label: 'label'
},
// 展示的信息
dubboInfo: {},
dubboInfoExplainShow: true,
docInfoExplainInput: "",
dubboInfoResultShow: true,
docInfoResultInput: "",
// 请求的IP端口下拉选项
requestHostOptions: [],
requestHostValue: "",
requestResult: "",
// 依据目录树存储的map全局对象
treePathDataMap: new Map(),
// dubbo列表
dubboDocList: [],
dubboDocMap: [],
// 搜索的输入内容
searchKeywords: "",
docParamList: [],
docParamRequestList: [],
// 参数类型选项
paramTypeOptions: [{
value: 'java.lang.String'
}, {
value: 'java.lang.Long'
}, {
value: 'java.lang.Integer'
}],
paramTypeValue: "java.lang.String",
// 升级信息
upgradeInfo: {},
}
},
watch: {
},
mounted: function () {
// 无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢
console.log("%c项目信息\n开发者列表暮光城中城\n项目地址https://gitee.com/zyplayer/zyplayer-doc", "color:red");
this.doGetServiceList();
this.checkSystemUpgrade();
},
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
handleNodeClick(data) {
if (data.children == null) {
console.log(data);
var path = data.interface;
var application = data.application;
var docInfo = app.dubboDocMap[path];
if (!!docInfo) {
this.createDocInfo(path, data.method);
} else {
var service = path.substring(0, path.lastIndexOf("."));
var method = path.substring(path.lastIndexOf(".") + 1, path.length);
var param = {service: service, method: method, application: application};
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/findDocInfo", "post", "json", param, function (json) {
if (validateResult(json)) {
if (!!json.data) {
app.dubboDocMap[json.data.function] = json.data;
}
app.createDocInfo(path, method);
}
});
}
//console.log(app.dubboInfo);
}
},
createDocInfo(path, method) {
var docInfo = app.dubboDocMap[path];
var dubboInfo = app.treePathDataMap.get(path);
dubboInfo.method = method;
dubboInfo.function = path;
dubboInfo.docInfo = docInfo || {};
// 清空再赋值才会重新渲染
app.dubboInfo = {};
app.dubboInfo = dubboInfo;
app.docInfoExplainInput = dubboInfo.docInfo.explain;
app.docParamList = [];
app.docParamList = dubboInfo.docInfo.params || [];
this.createDocParamRequestList();
// 请求相关
app.requestResult = "";
app.requestHostValue = "";
app.requestHostOptions = [];
for (var i = 0; i < dubboInfo.nodeList.length; i++) {
var item = dubboInfo.nodeList[i];
app.requestHostOptions.push({
value: item.ip + ":" + item.port
});
}
if (app.requestHostOptions.length > 0) {
app.requestHostValue = app.requestHostOptions[0].value;
}
},
reloadService(){
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/reloadService", "post", "json", {}, function (json) {
if (validateResult(json)) {
app.$message({
message: '加载成功!',
type: 'success'
});
app.doGetServiceList();
}
});
},
searchByKeywords() {
app.pathIndex = createTreeViewByTreeWithMerge(app.dubboDocList, app.searchKeywords);
},
doGetServiceList() {
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/getDocList", "post", "json", {}, function (json) {
if (validateResult(json)) {
app.dubboDocList = json.data.serverList || [];
app.dubboDocMap = json.data.docMap || {};
app.pathIndex = createTreeViewByTreeWithMerge(app.dubboDocList);
}
});
},
saveDocInfoExplain(){
this.doSaveDocInfo(app.docInfoExplainInput, null, null, true);
},
saveDocInfoResult(){
this.doSaveDocInfo(null, null, app.docInfoResultInput, true);
},
saveDocInfoParam() {
var docParamList = [];
for (var i = 0; i < app.docParamList.length; i++) {
var item = app.docParamList[i];
if (isNotEmpty(item.paramType)) {
docParamList.push(item);
}
}
var paramsJson = JSON.stringify(docParamList);
this.doSaveDocInfo(null, paramsJson, null, true);
},
createDocParamRequestList() {
var docParamList = [];
for (var i = 0; i < app.docParamList.length; i++) {
var item = app.docParamList[i];
if (isNotEmpty(item.paramType) || isNotEmpty(item.paramDesc)) {
docParamList.push(item);
}
}
app.docParamRequestList = docParamList;
},
doSaveDocInfo(explain, params, result, showSuccess){
var param = {
service: app.dubboInfo.interface,
method: app.dubboInfo.method,
resultType: app.dubboInfo.resultType,
paramValue: app.dubboInfo.paramValue,
version: app.dubboInfo.docInfo.version || 0,
explain: explain,
result: result,
paramsJson: params,
};
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/saveDoc", "post", "json", param, function (json) {
if (validateResult(json)) {
app.dubboDocMap[json.data.function] = json.data;
app.dubboInfo.docInfo = json.data;
app.dubboInfoExplainShow = true;
app.dubboInfoResultShow = true;
app.docParamList = json.data.params || [];
app.createDocParamRequestList();
if (showSuccess) {
Toast.success("保存成功!");
}
}
});
},
addDocParam() {
var leadAdd = app.docParamList.length <= 0;
if (!leadAdd) {
var last = app.docParamList[app.docParamList.length - 1];
if (isNotEmpty(last.paramType) || isNotEmpty(last.paramDesc)) {
leadAdd = true;
}
}
if (leadAdd) {
app.docParamList.push({
paramName: '',
paramType: '',
paramDesc: '',
paramValue: '',
});
}
},
requestExecute() {
var fuc = app.dubboInfo.function;
var hostValue = app.requestHostValue;
var service = fuc.substring(0, fuc.lastIndexOf("."));
var method = fuc.substring(fuc.lastIndexOf(".") + 1, fuc.length);
var ip = hostValue.substring(0, hostValue.lastIndexOf(":"));
var port = hostValue.substring(hostValue.lastIndexOf(":") + 1, hostValue.length);
var paramTypes = [];
var params = [];
for (var i = 0; i < app.docParamList.length; i++) {
var item = app.docParamList[i];
if (isNotEmpty(item.paramType) && isNotEmpty(item.paramValue)) {
paramTypes.push(item.paramType);
params.push(item.paramValue);
}
}
var param = {
service: service,
method: method,
ip: ip,
port: port,
paramTypes: JSON.stringify(paramTypes),
params: JSON.stringify(params),
};
app.requestResult = "";
app.onlineDebugLoading = true;
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/request", "post", "json", param, function (json) {
app.onlineDebugLoading = false;
if (json.errCode == 200) {
try {
app.requestResult = Formatjson.processObjectToHtmlPre(JSON.parse(json.data), 0, false, false, false, false);
} catch (e) {
try {
app.requestResult = Formatjson.processObjectToHtmlPre(json.data, 0, false, false, false, false);
} catch (e) {
app.requestResult = json.data;
}
}
var paramsJson = JSON.stringify(app.docParamRequestList);
app.doSaveDocInfo(null, paramsJson, null, false);
} else {
app.requestResult = json.errMsg;
}
});
},
checkSystemUpgrade() {
ajaxTemp("system/info/upgrade", "post", "json", {}, function (json) {
if (json.errCode == 200 && !!json.data) {
app.upgradeInfo = json.data;
console.log("zyplayer-doc发现新版本"
+ "\n升级地址" + json.data.upgradeUrl
+ "\n当前版本" + json.data.nowVersion
+ "\n最新版本" + json.data.lastVersion
+ "\n升级内容" + json.data.upgradeContent
);
}
});
},
}
});
</script>
<style>
html,body,#app {
margin: 0;
padding: 0;
height: 100%;
}
pre{margin: 0;}
.el-menu {
box-sizing: border-box;
border-right: 0;
margin-right: 3px;
}
.el-tree{
margin-right: 3px;
}
.el-tree-node__content{
padding-right: 20px;
}
.el-tabs--border-card>.el-tabs__content{
height: calc(100vh - 100px);overflow-y: auto;
}
.logo{
background: linear-gradient(-90deg, #03DDE4 0%, #30AFED 51%, #8755FF 100%); cursor: pointer;
width: 100%; height:60px;line-height:60px;font-size: 25px;color: #fff;text-align: center;
}
</style>
</html>

View File

@@ -0,0 +1,29 @@
/* S-JSON展示的样式 */
pre.json {
display: block;
padding: 9.5px;
margin: 0 0 0 10px;
font-size: 12px;
line-height: 1.38461538;
color: #333;
word-break: break-all;
word-wrap: break-word;
background-color: #f5f5f5;
border: 1px solid #ccc;
border-radius: 4px;
}
pre.json .canvas{font:10pt georgia;background-color:#ececec;color:#000000;border:1px solid #cecece;}
pre.json .object-brace{color:#00aa00;font-weight:bold;}
pre.json .array-brace{color:#0033ff;font-weight:bold;}
pre.json .property-name{color:#cc0000;font-weight:bold;}
pre.json .string{color:#007777;}
pre.json .number{color:#aa00aa;}
pre.json .boolean{color:#0000ff;}
pre.json .function{color:#aa6633;text-decoration:italic;}
pre.json .null{color:#0000ff;}
pre.json .comma{color:#000000;font-weight:bold;}
pre.json .annotation{color:#aaa;}
pre img{cursor: pointer;}
/* E-JSON展示的样式 */

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Some files were not shown because too many files have changed in this diff Show More