项目导入初始化

This commit is contained in:
暮光:城中城
2018-11-27 22:19:16 +08:00
parent 9350e107f2
commit f3d2b4eeab
189 changed files with 16210 additions and 0 deletions

90
pom.xml Normal file
View File

@@ -0,0 +1,90 @@
<?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</artifactId>
<version>1.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>zyplayer-doc</name>
<description>定位为所有文档的管理项目swagger文档、数据库文档、、、、等</description>
<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>
<swagger.mg.ui.version>2.0.1</swagger.mg.ui.version>
<velocity.engine.core.version>2.0</velocity.engine.core.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>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>
<!-- json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- 在线文档解析页面 -->
<dependency>
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc-swagger</artifactId>
<version>${swagger.mg.ui.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>
</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>
</modules>
</project>

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.mapper;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
public interface ZyplayerStorageMapper extends BaseMapper<ZyplayerStorage> {
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.mapper;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
public interface ZyplayerStorageMapper extends BaseMapper<ZyplayerStorage> {
}

View File

@@ -0,0 +1,67 @@
package com.zyplayer.doc.manage.repository.support.plus.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 hongli.zhang
* @since 2018-11-27
*/
public class ZyplayerStorage implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String docKey;
private String docValue;
private Date creationTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDocKey() {
return docKey;
}
public void setDocKey(String docKey) {
this.docKey = docKey;
}
public String getDocValue() {
return docValue;
}
public void setDocValue(String docValue) {
this.docValue = docValue;
}
public Date getCreationTime() {
return creationTime;
}
public void setCreationTime(Date creationTime) {
this.creationTime = creationTime;
}
@Override
public String toString() {
return "ZyplayerStorage{" +
"id=" + id +
", docKey=" + docKey +
", docValue=" + docValue +
", creationTime=" + creationTime +
"}";
}
}

View File

@@ -0,0 +1,67 @@
package com.zyplayer.doc.manage.repository.support.plus.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 hongli.zhang
* @since 2018-11-27
*/
public class ZyplayerStorage implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String docKey;
private String docValue;
private Date creationTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDocKey() {
return docKey;
}
public void setDocKey(String docKey) {
this.docKey = docKey;
}
public String getDocValue() {
return docValue;
}
public void setDocValue(String docValue) {
this.docValue = docValue;
}
public Date getCreationTime() {
return creationTime;
}
public void setCreationTime(Date creationTime) {
this.creationTime = creationTime;
}
@Override
public String toString() {
return "ZyplayerStorage{" +
"id=" + id +
", docKey=" + docKey +
", docValue=" + docValue +
", creationTime=" + creationTime +
"}";
}
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.service;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
public interface ZyplayerStorageService extends IService<ZyplayerStorage> {
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.service;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
public interface ZyplayerStorageService extends IService<ZyplayerStorage> {
}

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.service.impl;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.zyplayer.doc.manage.repository.support.plus.manage.mapper.ZyplayerStorageMapper;
import com.zyplayer.doc.manage.repository.support.plus.manage.service.ZyplayerStorageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
@Service
public class ZyplayerStorageServiceImpl extends ServiceImpl<ZyplayerStorageMapper, ZyplayerStorage> implements ZyplayerStorageService {
}

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.service.impl;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.zyplayer.doc.manage.repository.support.plus.manage.mapper.ZyplayerStorageMapper;
import com.zyplayer.doc.manage.repository.support.plus.manage.service.ZyplayerStorageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
@Service
public class ZyplayerStorageServiceImpl extends ServiceImpl<ZyplayerStorageMapper, ZyplayerStorage> implements ZyplayerStorageService {
}

192
zyplayer-doc-db/LICENSE Normal file
View File

@@ -0,0 +1,192 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "{}" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright 2018 暮光:城中城
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

53
zyplayer-doc-db/README.md Normal file
View File

@@ -0,0 +1,53 @@
# zyplayer-doc-db
#### 项目介绍
数据库文档工具,网页方式管理,只需两步即可对表注释、字段注释进行查看、修改、导出等操作,支持字段或注释的模糊查询,只有一个单独的页面,方便集成到已有的管理系统里面,本工具不对数据源进行管理,因为后台管理系统肯定是已有的数据源,没必要再来创建,只需要注入数据源即可管理
按照指定的格式可展示表的关系图,展示样式见下图
本关系图不是通过外键生成,所以需要在字段注释最后按规则添加外键关系才能生成图表,支持的格式有:
1. T:表XXX(字段注释)T:user_info
2. T:表.关联IDXXX(字段注释)T:user_info.id
3. T:库.表.关联IDXXX(字段注释)T:order_db.user_info.id
关系图为实验功能,有更好的建议或展示方式欢迎提交建议!
当前支持SqlServer、mysql的管理后期加上oracle和其他数据库的支持
#### 使用方式
1. 添加注解:@EnableDocDb
2. 注入Bean
```
// 注入已有的数据源
@Resource DataSource orderDatasource;
@Resource DataSource userDatasource;
//....
@Bean
public DatabaseRegistrationBean databaseRegistrationBean() {
DatabaseRegistrationBean bean = new DatabaseRegistrationBean();
List<DataSource> dataSourceList = new LinkedList<>();
// 设置需要展示的数据源
dataSourceList.add(orderDatasource);
dataSourceList.add(userDatasource);
bean.setDataSourceList(dataSourceList);
return bean;
}
```
3. 打开网页访问域名地址+doc-db.html即可http://192.168.0.100:8080/doc-db.html
#### 界面展示
基本界面:
![](https://images.gitee.com/uploads/images/2018/0918/190615_af5e8cdb_596905.jpeg "31.jpg")
模糊查询:
![](https://images.gitee.com/uploads/images/2018/0918/190721_872b2d76_596905.png "03.png")
表注释修改:
![](https://images.gitee.com/uploads/images/2018/0918/190739_afe7ba53_596905.jpeg "50.jpg")
文档导出:
![](https://images.gitee.com/uploads/images/2018/0920/223122_172d1fc2_596905.png "21.png")
导出文档查看:
![](https://images.gitee.com/uploads/images/2018/0920/223223_b899b367_596905.png "54.png")
表关联关系图:
![](https://images.gitee.com/uploads/images/2018/0925/214544_14b1b6eb_596905.jpeg "08.jpg")

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

@@ -0,0 +1,226 @@
<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-db</artifactId>
<version>1.0.1</version>
<packaging>jar</packaging>
<name>zyplayer-doc-db</name>
<description>数据库文档工具</description>
<url>https://gitee.com/zyplayer/zyplayer-doc/zyplayer-doc-db</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>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<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>
<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>
</dependencies>
<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>
</properties>
<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/swagger-mg-ui.git</connection>
<developerConnection>scm:git@git.oschina.net:zyplayer/swagger-mg-ui.git</developerConnection>
<url>git@git.oschina.net:zyplayer/swagger-mg-ui.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,240 @@
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 org.apache.commons.lang.StringUtils;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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;
/**
* 文档控制器
*
* @author 暮光:城中城
* @since 2018年8月8日
*/
@RestController
@RequestMapping("/zyplayer-doc-db/doc-db")
public class DatabaseDocController {
@Autowired(required = false)
DatabaseRegistrationBean databaseRegistrationBean;
@PostMapping(value = "/getDataSourceList")
public ResponseJson getDataSourceList() {
List<DatabaseFactoryBean> factoryBeanList = databaseRegistrationBean.getDatabaseFactoryBeanList();
Set<String> dataSourceList = factoryBeanList.stream().collect(Collectors.mapping(DatabaseFactoryBean::getHost, Collectors.toSet()));
return DocDbResponseJson.ok(dataSourceList);
}
@PostMapping(value = "/getDatabaseList")
public ResponseJson getDatabaseList(String host) {
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapperByHost(host);
if (baseMapper == null) {
return DocDbResponseJson.warn("未找到对应的数据库连接");
}
List<DatabaseInfoDto> dbNameDtoList = baseMapper.getDatabaseList();
return DocDbResponseJson.ok(dbNameDtoList);
}
@PostMapping(value = "/getTableList")
public ResponseJson getTableList(String host, String dbName) {
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
if (baseMapper == null) {
return DocDbResponseJson.warn("未找到对应的数据库连接");
}
List<TableInfoDto> dbTableList = baseMapper.getTableList(dbName);
return DocDbResponseJson.ok(dbTableList);
}
@PostMapping(value = "/getTableColumnList")
public ResponseJson getTableColumnList(String host, String dbName, String tableName) {
DatabaseFactoryBean databaseFactoryBean = databaseRegistrationBean.getDatabaseFactoryBean(host, dbName);
if (databaseFactoryBean == null) {
return DocDbResponseJson.warn("未找到对应的数据库连接");
}
TableColumnVo tableColumnVo = this.getTableColumnVo(databaseFactoryBean, dbName, tableName);
return DocDbResponseJson.ok(tableColumnVo);
}
@PostMapping(value = "/getTableColumnDescList")
public ResponseJson getTableColumnDescList(String host, String dbName, String tableName) {
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
if (baseMapper == null) {
return DocDbResponseJson.warn("未找到对应的数据库连接");
}
List<TableColumnDescDto> columnDescDto = baseMapper.getTableColumnDescList(tableName);
return DocDbResponseJson.ok(columnDescDto);
}
@PostMapping(value = "/getTableAndColumnBySearch")
public ResponseJson getTableAndColumnBySearch(String host, String dbName, String tableName, String searchText) {
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
if (baseMapper == null) {
return DocDbResponseJson.warn("未找到对应的数据库连接");
}
if (StringUtils.isNotBlank(searchText)) {
searchText = "%" + searchText + "%";
}
List<QueryTableColumnDescDto> columnDescDto = baseMapper.getTableAndColumnBySearch(dbName, searchText);
return DocDbResponseJson.ok(columnDescDto);
}
@PostMapping(value = "/getTableDescList")
public ResponseJson getTableDescList(String host, String dbName, String tableName) {
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
if (baseMapper == null) {
return DocDbResponseJson.warn("未找到对应的数据库连接");
}
List<TableDescDto> columnDescDto = baseMapper.getTableDescList(tableName);
return DocDbResponseJson.ok(columnDescDto);
}
@PostMapping(value = "/updateTableDesc")
public ResponseJson updateTableDesc(String host, String dbName, String tableName, String newDesc) {
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
if (baseMapper == null) {
return DocDbResponseJson.warn("未找到对应的数据库连接");
}
baseMapper.updateTableDesc(dbName, tableName, newDesc);
return DocDbResponseJson.ok();
}
@PostMapping(value = "/updateTableColumnDesc")
public ResponseJson updateTableColumnDesc(String host, String dbName, String tableName, String columnName, String newDesc) {
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
if (baseMapper == null) {
return DocDbResponseJson.warn("未找到对应的数据库连接");
}
ColumnInfoDto columnInfo = null;
// mysql要同时修改类型默认值等所以先查出来
MysqlMapper mysqlMapper = databaseRegistrationBean.getBaseMapper(host, dbName, MysqlMapper.class);
if (mysqlMapper != null) {
columnInfo = mysqlMapper.getColumnInfo(dbName, tableName, columnName);
String isNullable = Optional.ofNullable(columnInfo.getIsNullable()).orElse("");
columnInfo.setIsNullable("yes".equalsIgnoreCase(isNullable) ? "null" : "not null");
String columnDefault = columnInfo.getColumnDefault();
if (StringUtils.isNotBlank(columnDefault)) {
columnInfo.setColumnDefault("DEFAULT " + columnDefault);
} else {
columnInfo.setColumnDefault("");
}
String extra = columnInfo.getExtra();
columnInfo.setExtra(StringUtils.isBlank(extra) ? "" : extra);
}
baseMapper.updateTableColumnDesc(dbName, tableName, columnName, newDesc, columnInfo);
return DocDbResponseJson.ok();
}
@GetMapping(value = "/exportDatabase")
public ResponseJson exportDatabase(HttpServletResponse response, String host, String dbName, String tableNames) {
if (StringUtils.isBlank(tableNames)) {
return DocDbResponseJson.warn("请选择需要导出的表");
}
DatabaseFactoryBean databaseFactoryBean = databaseRegistrationBean.getDatabaseFactoryBean(host, dbName);
if (databaseFactoryBean == null) {
return DocDbResponseJson.warn("未找到对应的数据库连接");
}
List<TableInfoVo> tableList = new LinkedList<>();
Map<String, List<TableColumnDescDto>> columnList = new HashMap<>();
String[] tableNameArr = tableNames.split(",");
for (String tableName : tableNameArr) {
if (StringUtils.isBlank(tableName)) {
continue;
}
TableColumnVo tableColumnVo = this.getTableColumnVo(databaseFactoryBean, dbName, tableName);
columnList.put(tableName, tableColumnVo.getColumnList());
tableList.add(tableColumnVo.getTableInfo());
}
DatabaseExportVo exportVo = new DatabaseExportVo();
exportVo.setColumnList(columnList);
exportVo.setTableList(tableList);
String content = JSON.toJSONString(exportVo);
content = "var database = " + content;
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition", "attachment;filename=database.js");
response.setCharacterEncoding("utf-8");
// 将文件输入流写入response的输出流中
try {
IoUtil.write(response.getOutputStream(), "utf-8", true, content);
} catch (Exception e) {
e.printStackTrace();
}
return DocDbResponseJson.ok();
}
private TableColumnVo getTableColumnVo(DatabaseFactoryBean databaseFactoryBean, String dbName, String tableName) {
SqlSessionTemplate sessionTemplate = databaseFactoryBean.getSqlSessionTemplate();
BaseMapper baseMapper = sessionTemplate.getMapper(BaseMapper.class);
List<TableColumnDescDto> columnDescDto = baseMapper.getTableColumnList(dbName, tableName);
// SQLSERVER要单独查字段注释
if (databaseFactoryBean.getDatabaseProduct() == DatabaseProduct.SQLSERVER) {
List<TableColumnDescDto> columnDescList = baseMapper.getTableColumnDescList(tableName);
Map<String, TableColumnDescDto> columnMap = columnDescDto.stream().collect(Collectors.toMap(TableColumnDescDto::getName, val -> val));
// 字段注释
for (TableColumnDescDto descDto : columnDescList) {
TableColumnDescDto tempDesc = columnMap.get(descDto.getName());
if(tempDesc != null) {
tempDesc.setDescription(descDto.getDescription());
}
}
}
TableColumnVo tableColumnVo = new TableColumnVo();
tableColumnVo.setColumnList(columnDescDto);
// 表注释
TableInfoVo tableInfoVo = new TableInfoVo();
List<TableDescDto> tableDescList = baseMapper.getTableDescList(tableName);
String description = null;
if (tableDescList.size() > 0) {
TableDescDto descDto = tableDescList.get(0);
description = descDto.getDescription();
}
description = Optional.ofNullable(description).orElse("");
tableInfoVo.setDescription(description);
tableInfoVo.setTableName(tableName);
tableColumnVo.setTableInfo(tableInfoVo);
return tableColumnVo;
}
public static void main(String[] args) {
//File zipFile = ZipUtil.zip("d:/aaa");
File zipFile = new File("d:/111.zip");
ZipUtil.zip(zipFile, true, new File("d:/111.txt"),
new File("d:/222.txt"), new File("d:/aaa"));
}
}

View File

@@ -0,0 +1,31 @@
package com.zyplayer.doc.db.controller.vo;
import java.util.List;
import java.util.Map;
import com.zyplayer.doc.db.controller.vo.TableColumnVo.TableInfoVo;
import com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto;
public class DatabaseExportVo {
private Map<String, List<TableColumnDescDto>> columnList;
private List<TableInfoVo> tableList;
public Map<String, List<TableColumnDescDto>> getColumnList() {
return columnList;
}
public void setColumnList(Map<String, List<TableColumnDescDto>> columnList) {
this.columnList = columnList;
}
public List<TableInfoVo> getTableList() {
return tableList;
}
public void setTableList(List<TableInfoVo> tableList) {
this.tableList = tableList;
}
}

View File

@@ -0,0 +1,50 @@
package com.zyplayer.doc.db.controller.vo;
import java.util.List;
import com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto;
public class TableColumnVo {
private List<TableColumnDescDto> columnList;
private TableInfoVo tableInfo;
public static class TableInfoVo {
private String tableName;
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
}
public List<TableColumnDescDto> getColumnList() {
return columnList;
}
public void setColumnList(List<TableColumnDescDto> columnList) {
this.columnList = columnList;
}
public TableInfoVo getTableInfo() {
return tableInfo;
}
public void setTableInfo(TableInfoVo tableInfo) {
this.tableInfo = tableInfo;
}
}

View File

@@ -0,0 +1,90 @@
package com.zyplayer.doc.db.framework.configuration;
import java.sql.DatabaseMetaData;
import java.util.LinkedList;
import java.util.List;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Component;
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;
@Component
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
@Autowired(required = false)
DatabaseRegistrationBean databaseRegistrationBean;
private volatile static boolean IS_INIT = false;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (databaseRegistrationBean == null || IS_INIT) {
return;
}
// 会被调用两次
IS_INIT = true;
List<DatabaseFactoryBean> databaseFactoryBeanList = new LinkedList<>();
for (DataSource dataSource : databaseRegistrationBean.getDataSourceList()) {
try {
DatabaseFactoryBean databaseFactoryBean = new DatabaseFactoryBean();
DatabaseMetaData metaData = dataSource.getConnection().getMetaData();
String productName = metaData.getDatabaseProductName().toLowerCase();
Resource[] resources = null;
String dbUrl = metaData.getURL();
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
if (productName.indexOf("mysql") >= 0) {
// jdbc:mysql://192.168.0.1:3306/user_info?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
String[] urlParamArr = dbUrl.split("\\?");
String[] urlDbNameArr = urlParamArr[0].split("/");
if (urlDbNameArr.length >= 2) {
databaseFactoryBean.setDbName(urlDbNameArr[urlDbNameArr.length - 1]);
databaseFactoryBean.setHost(urlDbNameArr[urlDbNameArr.length - 2]);
}
databaseFactoryBean.setDatabaseProduct(DatabaseProduct.MYSQL);
resources = resolver.getResources("classpath:com/zyplayer/doc/db/framework/db/mapper/mysql/*.xml");
} else if (productName.indexOf("sql server") >= 0) {
// jdbc:jtds:sqlserver://192.168.0.1:33434;socketTimeout=60;DatabaseName=user_info;
String[] urlParamArr = dbUrl.split(";");
String[] urlDbNameArr = urlParamArr[0].split("/");
databaseFactoryBean.setHost(urlDbNameArr[urlDbNameArr.length - 1]);
for (String urlParam : urlParamArr) {
String[] keyValArr = urlParam.split("=");
if (keyValArr.length >= 2 && keyValArr[0].equalsIgnoreCase("DatabaseName")) {
databaseFactoryBean.setDbName(keyValArr[1]);
}
}
databaseFactoryBean.setDatabaseProduct(DatabaseProduct.SQLSERVER);
resources = resolver.getResources("classpath:com/zyplayer/doc/db/framework/db/mapper/sqlserver/*.xml");
}
if (resources == null) {
continue;
}
// 创建sqlSessionTemplate
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(resources);
SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactoryBean.getObject());
// 组装自定义的bean
databaseFactoryBean.setDataSource(dataSource);
databaseFactoryBean.setSqlSessionTemplate(sqlSessionTemplate);
databaseFactoryBean.setUrl(dbUrl);
databaseFactoryBeanList.add(databaseFactoryBean);
} catch (Exception e) {
e.printStackTrace();
}
}
databaseRegistrationBean.setDatabaseFactoryBeanList(databaseFactoryBeanList);
}
}

View File

@@ -0,0 +1,16 @@
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;
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@ComponentScan(basePackages = {
"com.zyplayer.doc.db",
})
public @interface EnableDocDb {
}

View File

@@ -0,0 +1,72 @@
package com.zyplayer.doc.db.framework.db.bean;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionTemplate;
/**
* 描述连接信息的对象
* @author 暮光:城中城
* @since 2018年8月8日
*/
public class DatabaseFactoryBean {
private DataSource dataSource;
private SqlSessionTemplate sqlSessionTemplate;
private String url;
private String host;
private String dbName;
private DatabaseProduct databaseProduct;
public static enum DatabaseProduct {
MYSQL, SQLSERVER
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public DatabaseProduct getDatabaseProduct() {
return databaseProduct;
}
public void setDatabaseProduct(DatabaseProduct databaseProduct) {
this.databaseProduct = databaseProduct;
}
public SqlSessionTemplate getSqlSessionTemplate() {
return sqlSessionTemplate;
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
}

View File

@@ -0,0 +1,92 @@
package com.zyplayer.doc.db.framework.db.bean;
import java.util.LinkedList;
import java.util.List;
import javax.sql.DataSource;
import org.apache.commons.lang.StringUtils;
import org.mybatis.spring.SqlSessionTemplate;
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.mapper.base.BaseMapper;
/**
* 需要声明注入的对象只需要设置dataSourceList即可
* databaseFactoryBeanList是后面生成的
*
* @author 暮光:城中城
* @since 2018年8月8日
*/
public class DatabaseRegistrationBean {
private List<DataSource> dataSourceList = new LinkedList<>();
private List<DatabaseFactoryBean> databaseFactoryBeanList = new LinkedList<>();
public List<DataSource> getDataSourceList() {
return dataSourceList;
}
public void setDataSourceList(List<DataSource> dataSourceList) {
this.dataSourceList = dataSourceList;
}
public List<DatabaseFactoryBean> getDatabaseFactoryBeanList() {
return databaseFactoryBeanList;
}
public void setDatabaseFactoryBeanList(List<DatabaseFactoryBean> databaseFactoryBeanList) {
this.databaseFactoryBeanList = databaseFactoryBeanList;
}
public DatabaseFactoryBean getDatabaseFactoryBean(String host, String dbName) {
if (StringUtils.isBlank(dbName)) {
return null;
}
DatabaseFactoryBean resultBean = null;
for (DatabaseFactoryBean databaseFactoryBean : databaseFactoryBeanList) {
if (host.equalsIgnoreCase(databaseFactoryBean.getHost())) {
if (dbName.equalsIgnoreCase(databaseFactoryBean.getDbName())) {
return databaseFactoryBean;
}
if (databaseFactoryBean.getDatabaseProduct() == DatabaseProduct.MYSQL) {
resultBean = databaseFactoryBean;
}
}
}
return resultBean;
}
public BaseMapper getBaseMapper(String host, String dbName) {
return getBaseMapper(host, dbName, BaseMapper.class);
}
public <T> T getBaseMapper(String host, String dbName, Class<T> cls) {
DatabaseFactoryBean factoryBean = getDatabaseFactoryBean(host, dbName);
if (factoryBean != null) {
SqlSessionTemplate sessionTemplate = factoryBean.getSqlSessionTemplate();
try {
return sessionTemplate.getMapper(cls);
} catch (Exception e) {}
}
return null;
}
public BaseMapper getBaseMapperByHost(String host) {
if (StringUtils.isBlank(host)) {
return null;
}
for (DatabaseFactoryBean databaseFactoryBean : databaseFactoryBeanList) {
if (host.equalsIgnoreCase(databaseFactoryBean.getHost())) {
try {
SqlSessionTemplate sessionTemplate = databaseFactoryBean.getSqlSessionTemplate();
return sessionTemplate.getMapper(BaseMapper.class);
} catch (Exception e) {}
}
}
return null;
}
}

View File

@@ -0,0 +1,41 @@
package com.zyplayer.doc.db.framework.db.dto;
public class ColumnInfoDto {
private String isNullable;
private String columnType;
private String columnDefault;
private String extra;
public String getIsNullable() {
return isNullable;
}
public void setIsNullable(String isNullable) {
this.isNullable = isNullable;
}
public String getColumnDefault() {
return columnDefault;
}
public void setColumnDefault(String columnDefault) {
this.columnDefault = columnDefault;
}
public String getColumnType() {
return columnType;
}
public void setColumnType(String columnType) {
this.columnType = columnType;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
}

View File

@@ -0,0 +1,14 @@
package com.zyplayer.doc.db.framework.db.dto;
public class DatabaseInfoDto {
private String dbName;
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
}

View File

@@ -0,0 +1,31 @@
package com.zyplayer.doc.db.framework.db.dto;
public class QueryTableColumnDescDto {
private String tableName;
private String columnName;
private String description;
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@@ -0,0 +1,68 @@
package com.zyplayer.doc.db.framework.db.dto;
public class TableColumnDescDto {
private String name;
private String isidenity;
private String type;
private String nullable;
private String length;
private String ispramary;
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIsidenity() {
return isidenity;
}
public void setIsidenity(String isidenity) {
this.isidenity = isidenity;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getNullable() {
return nullable;
}
public void setNullable(String nullable) {
this.nullable = nullable;
}
public String getLength() {
return length;
}
public void setLength(String length) {
this.length = length;
}
public String getIspramary() {
return ispramary;
}
public void setIspramary(String ispramary) {
this.ispramary = ispramary;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@@ -0,0 +1,32 @@
package com.zyplayer.doc.db.framework.db.dto;
public class TableDescDto {
private String tableName;
private String description;
private String majorId;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getMajorId() {
return majorId;
}
public void setMajorId(String majorId) {
this.majorId = majorId;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
}

View File

@@ -0,0 +1,32 @@
package com.zyplayer.doc.db.framework.db.dto;
public class TableInfoDto {
private String tableName;
private String tableComment;
private String tableId;
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getTableId() {
return tableId;
}
public void setTableId(String tableId) {
this.tableId = tableId;
}
public String getTableComment() {
return tableComment;
}
public void setTableComment(String tableComment) {
this.tableComment = tableComment;
}
}

View File

@@ -0,0 +1,97 @@
package com.zyplayer.doc.db.framework.db.mapper.base;
import java.util.List;
import org.apache.ibatis.annotations.Param;
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;
/**
* 数据库的mapper持有对象接口
* @author 暮光:城中城
* @since 2018年8月8日
*/
public interface BaseMapper {
/**
* 获取库列表
* @author 暮光:城中城
* @since 2018年8月8日
* @return
*/
List<DatabaseInfoDto> getDatabaseList();
/**
* 获取表列表
* @author 暮光:城中城
* @since 2018年8月8日
* @param dbName
* @return
*/
List<TableInfoDto> getTableList(@Param("dbName")String dbName);
/**
* 获取字段列表
* @author 暮光:城中城
* @since 2018年8月8日
* @param dbName
* @param tableName
* @return
*/
List<TableColumnDescDto> getTableColumnList(@Param("dbName") String dbName, @Param("tableName") String tableName);
/**
* 获取字段注释
* @author 暮光:城中城
* @since 2018年8月8日
* @param tableName
* @return
*/
List<TableColumnDescDto> getTableColumnDescList(@Param("tableName") String tableName);
/**
* 模糊搜索表和字段
* @author 暮光:城中城
* @since 2018年8月8日
* @param searchText
* @return
*/
List<QueryTableColumnDescDto> getTableAndColumnBySearch(@Param("dbName") String dbName, @Param("searchText") String searchText);
/**
* 获取表注释
* @author 暮光:城中城
* @since 2018年8月8日
* @param tableName 可不传,传了只查询指定表的注释
* @return
*/
List<TableDescDto> getTableDescList(@Param("tableName") String tableName);
/**
* 增加表注释
* @author 暮光:城中城
* @since 2018年8月8日
* @param tableName
* @param newDesc
*/
void updateTableDesc(@Param("dbName") String dbName, @Param("tableName") String tableName, @Param("newDesc") String newDesc);
/**
* 增加字段注释
*
* @author 暮光:城中城
* @since 2018年8月8日
* @param tableName
* @param columnName
* @param newDesc
*/
void updateTableColumnDesc(@Param("dbName") String dbName, @Param("tableName") String tableName,
@Param("columnName") String columnName, @Param("newDesc") String newDesc,
@Param("columnInfo") ColumnInfoDto columnInfo);
}

View File

@@ -0,0 +1,67 @@
<?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.db.framework.db.mapper.base.BaseMapper">
<resultMap id="TableColumnDescDtoMap" type="com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto" >
<result column="NAME" property="name" jdbcType="VARCHAR" />
<result column="ISIDENITY" property="isidenity" jdbcType="VARCHAR" />
<result column="TYPE" property="type" jdbcType="VARCHAR" />
<result column="NULLABLE" property="nullable" jdbcType="VARCHAR" />
<result column="LENGTH" property="length" jdbcType="VARCHAR" />
<result column="ISPRAMARY" property="ispramary" jdbcType="VARCHAR" />
<result column="DESCRIPTION" property="description" jdbcType="VARCHAR" />
</resultMap>
<resultMap id="QueryTableColumnDescDtoMap" type="com.zyplayer.doc.db.framework.db.dto.QueryTableColumnDescDto" >
<result column="TABLE_NAME" property="tableName" jdbcType="VARCHAR" />
<result column="COLUMN_NAME" property="columnName" jdbcType="VARCHAR" />
<result column="DESCRIPTION" property="description" jdbcType="VARCHAR" />
</resultMap>
<select id="getDatabaseList" resultType="com.zyplayer.doc.db.framework.db.dto.DatabaseInfoDto">
select TABLE_SCHEMA dbName
from information_schema.tables
group by TABLE_SCHEMA
</select>
<select id="getTableList" resultType="com.zyplayer.doc.db.framework.db.dto.TableInfoDto">
select table_name tableName, table_comment as tableComment
from information_schema.tables
where table_schema=#{dbName}
</select>
<select id="getTableColumnList" resultMap="TableColumnDescDtoMap">
SELECT COLUMN_NAME NAME,column_comment DESCRIPTION,column_type TYPE,if(is_nullable='YES',1,0) NULLABLE
FROM INFORMATION_SCHEMA.Columns
WHERE table_schema=#{dbName} AND table_name=#{tableName}
</select>
<select id="getTableColumnDescList" resultMap="TableColumnDescDtoMap">
select 1
</select>
<select id="getTableAndColumnBySearch" resultMap="QueryTableColumnDescDtoMap">
SELECT TABLE_NAME, COLUMN_NAME, column_comment DESCRIPTION
FROM INFORMATION_SCHEMA.Columns
WHERE table_schema=#{dbName} AND (COLUMN_NAME like #{searchText} or column_comment like #{searchText})
</select>
<select id="getTableDescList" resultType="com.zyplayer.doc.db.framework.db.dto.TableDescDto">
select table_name tableName, table_comment as description
from information_schema.tables
<if test="tableName != null">
where table_name=#{tableName}
</if>
</select>
<insert id="updateTableDesc">
alter table ${dbName}.${tableName} comment #{newDesc}
</insert>
<insert id="updateTableColumnDesc">
alter table ${dbName}.${tableName} modify column ${columnName}
${columnInfo.columnType} ${columnInfo.isNullable} ${columnInfo.columnDefault} ${columnInfo.extra}
comment #{newDesc}
</insert>
</mapper>

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.db.framework.db.mapper.mysql;
import org.apache.ibatis.annotations.Param;
import com.zyplayer.doc.db.framework.db.dto.ColumnInfoDto;
/**
* mysql数据库的mapper持有对象
*
* @author 暮光:城中城
* @since 2018年8月8日
*/
public interface MysqlMapper {
ColumnInfoDto getColumnInfo(@Param("dbName") String dbName, @Param("tableName") String tableName, @Param("columnName") String columnName);
}

View File

@@ -0,0 +1,15 @@
<?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.db.framework.db.mapper.mysql.MysqlMapper">
<select id="getColumnInfo" resultType="com.zyplayer.doc.db.framework.db.dto.ColumnInfoDto">
select
IS_NULLABLE isNullable, COLUMN_TYPE columnType, CHARACTER_MAXIMUM_LENGTH maxLength,
COLUMN_DEFAULT columnDefault,EXTRA extra
from information_schema.columns t
where t.table_schema=#{dbName}
and t.table_name=#{tableName}
and t.column_name=#{columnName}
</select>
</mapper>

View File

@@ -0,0 +1,103 @@
<?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.db.framework.db.mapper.base.BaseMapper">
<resultMap id="TableColumnDescDtoMap" type="com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto" >
<result column="NAME" property="name" jdbcType="VARCHAR" />
<result column="ISIDENITY" property="isidenity" jdbcType="VARCHAR" />
<result column="TYPE" property="type" jdbcType="VARCHAR" />
<result column="NULLABLE" property="nullable" jdbcType="VARCHAR" />
<result column="LENGTH" property="length" jdbcType="VARCHAR" />
<result column="ISPRAMARY" property="ispramary" jdbcType="VARCHAR" />
<result column="DESCRIPTION" property="description" jdbcType="VARCHAR" />
</resultMap>
<resultMap id="QueryTableColumnDescDtoMap" type="com.zyplayer.doc.db.framework.db.dto.QueryTableColumnDescDto" >
<result column="TABLE_NAME" property="tableName" jdbcType="VARCHAR" />
<result column="COLUMN_NAME" property="columnName" jdbcType="VARCHAR" />
<result column="DESCRIPTION" property="description" jdbcType="VARCHAR" />
</resultMap>
<select id="getDatabaseList" resultType="com.zyplayer.doc.db.framework.db.dto.DatabaseInfoDto">
SELECT NAME as dbName FROM Master..SysDatabases ORDER BY NAME
</select>
<select id="getTableList" resultType="com.zyplayer.doc.db.framework.db.dto.TableInfoDto">
SELECT NAME as tableName, ID as tableId
FROM ${dbName}..SysObjects Where XType='U' ORDER BY NAME
</select>
<select id="getTableColumnList" resultMap="TableColumnDescDtoMap">
WITH PRIMARYINFO( COLUMNNAME ,ISPRAMARY) AS
(
SELECT C.NAME,'true' AS COLUMNNAME
FROM SYSINDEXES I
JOIN SYSINDEXKEYS K ON I.ID = K.ID AND I.INDID = K.INDID
JOIN SYSOBJECTS O ON I.ID = O.ID
JOIN SYSCOLUMNS C ON I.ID=C.ID AND K.COLID = C.COLID
WHERE O.XTYPE = 'U'
AND EXISTS(SELECT 1 FROM SYSOBJECTS WHERE XTYPE = 'PK' AND NAME = I.NAME)
AND O.NAME=#{tableName}
)
SELECT (
SELECT IS_IDENTITY FROM SYS.ALL_COLUMNS
WHERE SYS.ALL_COLUMNS.NAME=SYSCOLUMNS.NAME AND OBJECT_ID = OBJECT_ID(#{tableName})
) ISIDENTITY,SYSCOLUMNS.NAME NAME,SYSTYPES.NAME TYPE,SYSCOLUMNS.ISNULLABLE NULLABLE,SYSCOLUMNS.LENGTH LENGTH,PRIMARYINFO.ISPRAMARY
FROM SYSCOLUMNS
LEFT JOIN PRIMARYINFO ON PRIMARYINFO.COLUMNNAME=NAME
LEFT JOIN SYSTYPES ON SYSCOLUMNS.XUSERTYPE = SYSTYPES.XUSERTYPE
WHERE SYSCOLUMNS.ID = OBJECT_ID(#{tableName})
</select>
<select id="getTableColumnDescList" resultMap="TableColumnDescDtoMap">
SELECT B.name AS NAME,C.value AS DESCRIPTION
FROM sys.tables A
INNER JOIN sys.columns B ON B.object_id = A.object_id
LEFT JOIN sys.extended_properties C ON C.major_id = B.object_id AND C.minor_id = B.column_id
WHERE A.name = #{tableName}
</select>
<select id="getTableAndColumnBySearch" resultMap="QueryTableColumnDescDtoMap">
SELECT top 500
A.name AS TABLE_NAME,B.name AS COLUMN_NAME,C.value AS DESCRIPTION
FROM sys.tables A
INNER JOIN sys.columns B ON B.object_id = A.object_id
LEFT JOIN sys.extended_properties C ON C.major_id = B.object_id AND C.minor_id = B.column_id
WHERE convert(nvarchar(max),C.value) like #{searchText} OR B.name like #{searchText}
</select>
<select id="getTableDescList" resultType="com.zyplayer.doc.db.framework.db.dto.TableDescDto">
select 'TABLEDESC_SYS' as tableName, value as description, major_id as majorId
from sys.extended_properties
WHERE minor_id=0
<if test="tableName != null">
and major_id=object_id(#{tableName})
</if>
</select>
<insert id="updateTableDesc">
IF ((SELECT COUNT(*) from fn_listextendedproperty('MS_Description', 'SCHEMA', 'dbo', 'TABLE', #{tableName}, NULL, NULL)) > 0)
EXEC sp_updateextendedproperty @name = 'MS_Description', @value = #{newDesc}
, @level0type = 'SCHEMA', @level0name = 'dbo'
, @level1type = 'TABLE', @level1name = #{tableName}
ELSE
EXEC sp_addextendedproperty @name = 'MS_Description', @value = #{newDesc}
, @level0type = 'SCHEMA', @level0name = 'dbo'
, @level1type = 'TABLE', @level1name = #{tableName}
</insert>
<insert id="updateTableColumnDesc">
IF ((SELECT COUNT(*) from fn_listextendedproperty('MS_Description', 'SCHEMA', 'dbo', 'TABLE', #{tableName}, 'COLUMN', #{columnName})) > 0)
EXEC sp_updateextendedproperty @name = 'MS_Description', @value = #{newDesc}
, @level0type = 'SCHEMA', @level0name = 'dbo'
, @level1type = 'TABLE', @level1name = #{tableName}
, @level2type = 'COLUMN', @level2name = #{columnName}
ELSE
EXEC sp_addextendedproperty @name = 'MS_Description', @value = #{newDesc}
, @level0type = 'SCHEMA', @level0name = 'dbo'
, @level1type = 'TABLE', @level1name = #{tableName}
, @level2type = 'COLUMN', @level2name = #{columnName}
</insert>
</mapper>

View File

@@ -0,0 +1,11 @@
package com.zyplayer.doc.db.framework.db.mapper.sqlserver;
/**
* sqlserver数据库的mapper持有对象
*
* @author 暮光:城中城
* @since 2018年8月8日
*/
public interface SqlServerMapper {
}

View File

@@ -0,0 +1,19 @@
package com.zyplayer.doc.db.framework.db.support;
/**
* 动态分库使用
*/
public class DBInfoHolder {
private static final ThreadLocal<String> DB_INFO_NOW = new ThreadLocal<String>();
public static void setDbInfoNow(String dbInfo) {
DB_INFO_NOW.set(dbInfo);
}
public static String getDbInfoNow() {
return DB_INFO_NOW.get();
}
public static void clear() {
}
}

View File

@@ -0,0 +1,15 @@
package com.zyplayer.doc.db.framework.db.support;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 动态切换数据源
*/
public class ErpRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DBInfoHolder.getDbInfoNow();
}
}

View File

@@ -0,0 +1,147 @@
package com.zyplayer.doc.db.framework.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 io.swagger.annotations.ApiModelProperty;
/**
* 数据库文档返回数据格式
*
* @author 暮光:城中城
* @since 2018年8月8日
*/
public class DocDbResponseJson implements ResponseJson {
private static SerializeConfig mapping = new SerializeConfig();
static {
mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
}
@ApiModelProperty(value = "状态码")
private Integer errCode;
@ApiModelProperty(value = "返回值说明")
private String errMsg;
@ApiModelProperty(value = "返回数据")
private Object data;
public DocDbResponseJson() {
this.errCode = 200;
}
public DocDbResponseJson(Object data) {
this.setData(data);
this.errCode = 200;
}
public DocDbResponseJson(int errCode, String errMsg) {
super();
this.errCode = errCode;
this.errMsg = errMsg;
}
public DocDbResponseJson(int errCode, String errMsg, Object data) {
super();
this.setData(data);
this.errCode = errCode;
this.errMsg = errMsg;
}
public DocDbResponseJson(Integer errCode) {
super();
this.errCode = errCode;
}
public Integer getErrCode() {
return errCode;
}
public void setErrCode(Integer errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
/**
* 提示语
*
* @author 暮光:城中城
* @since 2018年8月7日
* @return
*/
public static DocDbResponseJson warn(String errMsg) {
return new DocDbResponseJson(300, errMsg);
}
/**
* 错误
*
* @author 暮光:城中城
* @since 2018年8月7日
* @return
*/
public static DocDbResponseJson error(String errMsg) {
return new DocDbResponseJson(500, errMsg);
}
/**
* 成功的返回方法
*
* @author 暮光:城中城
* @since 2018年8月7日
* @return
*/
public static DocDbResponseJson ok() {
return new DocDbResponseJson();
}
/**
* 成功的返回方法
*
* @author 暮光:城中城
* @since 2018年8月7日
* @return
*/
public static DocDbResponseJson ok(Object data) {
return new DocDbResponseJson(data);
}
public String toJson() {
return JSON.toJSONString(this, mapping);
}
public void send(HttpServletResponse response) {
try {
response.setStatus(200);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
response.getWriter().write(toJson());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return "DefaultResponseJson [errCode=" + errCode + ", errMsg=" + errMsg + ", data=" + data + "]";
}
}

View File

@@ -0,0 +1,11 @@
package com.zyplayer.doc.db.framework.json;
/**
* json视图
*
* @author 暮光:城中城
* @since 2018年8月8日
*/
public interface ResponseJson {
}

View File

@@ -0,0 +1,162 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>zyplayer-doc-db</title>
<link rel="shortcut icon" href="webjars/doc-db/img/api.ico"/>
<link rel="stylesheet" href="webjars/zui/css/zui.min.css" />
<link rel="stylesheet" href="webjars/zui/css/zui-theme.min.css">
<link rel="stylesheet" href="webjars/zui/lib/chosen/chosen.min.css" />
<link rel="stylesheet" href="webjars/doc-db/css/doc-db.css" />
</head>
<body>
<div class="container">
<div class="row choise-db">
<div class="col-md-3">
<select id="choiseHost" data-placeholder="选择一个连接" class="chosen-select form-control" tabindex="2">
<option value=""></option>
</select>
</div>
<div class="col-md-3">
<select id="choiseDatabase" data-placeholder="选择一个数据库" class="chosen-select form-control" tabindex="2">
<option value=""></option>
</select>
</div>
<div class="col-md-3">
<select id="choiseTable" data-placeholder="选择一张表" class="chosen-select form-control" tabindex="2">
<option value=""></option>
</select>
</div>
<div class="col-md-3">
<button class="btn btn-primary" type="button" id="fuzzySearchBtn">模糊查询</button>
<button class="btn btn-primary" type="button" id="exportBtn">导出</button>
<button class="btn" type="button" id="showEchartsBtn">显示表关系图</button>
</div>
</div>
<div class="table-info">
<div>表名:<span class="table-name"></span></div>
<div class="desc">
<div id="tableDescShow">
<span class="table-desc"></span>
<i class="icon icon-edit" title="编辑表注释"></i>
</div>
<textarea id="tableDescInput" rows="2" class="form-control"></textarea>
</div>
</div>
<div class="table-columns">
<table class="table table-bordered table-striped table-hover" id="tableCloumnsTable">
<thead>
<tr><th>字段名</th><th>自增</th><th>类型</th><th>长度</th><th>NULL</th><th>主键</th><th>注释</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
<div id="tableRelationBox" class="hide" style="width: 100%;height:100px;">
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<p>
Tips本关系图不是通过外键生成所以需要在字段注释最后按规则添加外键关系才能生成图表支持的格式有<br/>
1、T:表XXX(字段注释)T:user_info<br/>
2、T:表.关联IDXXX(字段注释)T:user_info.id<br/>
3、T:库.表.关联IDXXX(字段注释)T:order_db.user_info.id<br/>
实验功能,有更好的建议或展示方式欢迎<a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc-db">提交建议</a>
</p>
</div>
<div id="tableRelationCharts" style="width: 100%;height:100%;margin-bottom: 50px;"></div>
</div>
<!-- 模糊查询 -->
<div class="modal fade" id="fuzzySearchModal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span><span class="sr-only">关闭</span>
</button>
<h4 class="modal-title">通过字段名或释义模糊查询</h4>
</div>
<div class="modal-body">
<div class="row choise-db">
<div class="col-md-3">
<select id="choiseFuzzyHost" data-placeholder="选择一个连接" class="chosen-select form-control" tabindex="2">
<option value=""></option>
</select>
</div>
<div class="col-md-3">
<select id="choiseFuzzyDatabase" data-placeholder="选择一个数据库" class="chosen-select form-control" tabindex="2">
<option value=""></option>
</select>
</div>
<div class="col-md-4">
<input id="searchText" type="text" class="form-control" placeholder="搜索内容,字段名或注释">
</div>
<div class="col-md-2">
<button id="doSearch" class="btn btn-primary" type="button">查询 <i class="icon icon-spin icon-spinner-snake hidden"></i></button>
</div>
</div>
<div class="modal-table-box">
<table class="table table-bordered table-striped table-hover" id="fuzzySearchTable">
<thead>
<tr><th>表名</th><th>字段名</th><th>注释</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- 导出弹出框 -->
<div class="modal fade" id="exportModal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span><span class="sr-only">关闭</span>
</button>
<h4 class="modal-title">导出数据库文档</h4>
</div>
<div class="modal-body">
<div class="row choise-db">
<div class="col-md-3">
<select id="choiseExportHost" data-placeholder="选择一个连接" class="chosen-select form-control" tabindex="2">
<option value=""></option>
</select>
</div>
<div class="col-md-3">
<select id="choiseExportDatabase" data-placeholder="选择一个数据库" class="chosen-select form-control" tabindex="2">
<option value=""></option>
</select>
</div>
<div class="col-md-6">
<button id="doExport" class="btn btn-primary" type="button">确认导出 <i class="icon icon-spin icon-spinner-snake hidden"></i></button>
<button id="checkAllTable" class="btn" type="button">全选</button>
<button id="notCheckAllTable" class="btn" type="button">全不选</button>
</div>
</div>
<div class="alert alert-danger">
请到 <a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc-db">源码处下载</a>《对外文档模板.zip》解压
然后将“确认导出”后的文件放至/js目录下文件名必须为database.js<br/>
然后双击打开目录下的doc-db.html 即可看到导出的文档
</div>
<div class="modal-table-box">
<ul id="exportUl"></ul>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script type="text/javascript" src="webjars/doc-db/js/jquery-3.1.0.min.js"></script>
<script type="text/javascript" src="webjars/zui/js/zui.min.js"></script>
<script type="text/javascript" src="webjars/zui/lib/chosen/chosen.min.js"></script>
<script type="text/javascript" src="webjars/doc-db/js/echarts.min.js"></script>
<script type="text/javascript" src="webjars/doc-db/js/option-table-relation.js"></script>
<script type="text/javascript" src="webjars/doc-db/js/formatjson.js"></script>
<script type="text/javascript" src="webjars/doc-db/js/toast.js"></script>
<script type="text/javascript" src="webjars/doc-db/js/common.js"></script>
<script type="text/javascript" src="webjars/doc-db/js/doc-db.js"></script>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
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;}
#fuzzySearchModal .table-box{margin-top: 20px; max-height: 600px;overflow-y: auto;}
#fuzzySearchModal .table-box td:nth-child(3){word-break:break-all;max-width: 400px;}
/* 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展示的样式 */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,45 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>zyplayer-doc-db</title>
<link rel="stylesheet" href="css/zui.min.css" />
<link rel="stylesheet" href="css/zui-theme.min.css">
<link rel="stylesheet" href="css/chosen.min.css" />
<link rel="stylesheet" href="css/doc-db.css" />
</head>
<body>
<div class="container">
<div class="row choise-db">
<div class="col-md-12">
<select id="choiseTable" data-placeholder="选择一张表" class="chosen-select form-control" tabindex="2">
<option value=""></option>
</select>
</div>
</div>
<div class="table-info">
<div>表注释:<span class="table-desc"></span></div>
</div>
<div class="table-columns">
<table class="table table-bordered table-striped table-hover" id="tableCloumnsTable">
<thead>
<tr><th>字段名</th><th>自增</th><th>类型</th><th>长度</th><th>NULL</th><th>主键</th><th>注释</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</body>
<script type="text/javascript" src="js/database.js"></script>
<script type="text/javascript" src="js/jquery-3.1.0.min.js"></script>
<script type="text/javascript" src="js/zui.min.js"></script>
<script type="text/javascript" src="js/chosen.min.js"></script>
<script type="text/javascript" src="js/formatjson.js"></script>
<script type="text/javascript" src="js/toast.js"></script>
<script type="text/javascript" src="js/common.js"></script>
<script type="text/javascript" src="js/doc-db.js"></script>
</html>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 290 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,254 @@
/**
* 一些公用方法
* @author 暮光:城中城
* @since 2017年5月7日
*/
function serialize(value) {
if (typeof value === 'string') {
return value;
}
return JSON.stringify(value);
}
function deserialize(value) {
if (typeof value !== 'string' || isEmpty(value)) {
return undefined;
}
try {
return JSON.parse(value);
} catch (e) {
try {
return eval('(' + value + ')');// 处理变态的单双引号共存字符串
} catch (e) {
return value || undefined;
}
}
}
function validateResult(result) {
if(result.errCode == 200) {
return true;
} else {
Toast.error(result.errMsg);
}
return false;
}
/**
* 返回不为空的字符串为空返回def
*/
function getNotEmptyStr(str, def){
if(isEmpty(str)) {
return isEmpty(def)?"":def;
}
return str;
}
/**
* 是否是空对象
* @param obj
* @returns
*/
function isEmptyObject(obj){
return $.isEmptyObject(obj);
}
/**
* 是否是空字符串
* @param str
* @returns
*/
function isEmpty(str){
return (str == "" || str == null || str == undefined);
}
/**
* 是否是空
* @param str
* @returns
*/
function isNull(str){
return (str == null || str == undefined);
}
/**
* 是否不是空字符串
* @param str
* @returns
*/
function isNotEmpty(str){
return !isEmpty(str);
}
/**
* 数组转字符串,使用空格分隔
* @param array
* @returns
*/
function arrToString(array){
var temStr = "";
if(isEmpty(array)){
return temStr;
}
array.forEach(function(e){
if(isNotEmpty(temStr)) {
temStr += " ";
}
temStr += e;
});
return temStr;
}
/**
* 数组array中是否包含str字符串
* @param array
* @param str
* @returns
*/
function haveString(array, str){
if(isEmpty(array)) {
return false;
}
for (var i = 0; i < array.length; i++) {
if(array[i] == str) {
return true;
}
}
return false;
}
/**
* 直接返回对象的第一个属性
* @param data
* @returns
*/
function getObjectFirstAttribute(data) {
for ( var key in data) {
return data[key];
}
}
/**
* 如果对象只有一个属性则返回第一个属性否则返回null
* @param data
* @returns
*/
function getObjectFirstAttributeIfOnly(data) {
var len = 0, value = "";
for ( var key in data) {
if (++len > 1) {
return null;
}
value = data[key];
}
return value;
}
function postService(url, param, success=function(){}, complete=function(){}){
ajaxTemp(url, "POST", "JSON", param, function(result){
if(result.errCode != "200"){
Toast.warn(result.errMsg);
} else {
success(result);
}
},function(){
Toast.warn("请求数据失败");
}, function(result){
complete(result);
});
}
/**
* ajax处理事件模板
*
* @url 后台处理的url即action
* @dataSentType 数据发送的方式有postget方式
* @dataReceiveType 数据接收格式有html json text等
* @paramsStr 传入后台的参数
* @successFunction ajax成功后执行的函数名 ajaxTemp("", "GET", "html", {}, function(){},
* function(){}, "");
*/
function ajaxTemp(url, dataSentType, dataReceiveType, paramsStr, successFunction, errorFunction, completeFunction, id) {
$.ajax({
url : url, // 后台处理程序
sync : false,
type : dataSentType, // 数据发送方式
dataType : dataReceiveType, // 接受数据格式
data : eval(paramsStr),
contentType : "application/x-www-form-urlencoded; charset=UTF-8",
success : function(msg) {
if(typeof successFunction == "function") {
successFunction(msg,id);
}
},
beforeSend : function() {
},
complete : function(msg) {
if(typeof completeFunction == "function") {
completeFunction(msg,id);
}
},
error : function(msg) {
if(typeof errorFunction == "function") {
errorFunction(msg,id);
}
}
});
}
/**
* 获取cookie
* @param name
* @returns
*/
function getCookie(name) {
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg)){
return unescape(arr[2]);
}
return null;
}
/**
* 字符串格式化
*/
String.prototype.format = function(args) {
if (arguments.length > 0) {
var result = this;
if (arguments.length == 1 && typeof (args) == "object") {
for ( var key in args) {
var reg = new RegExp("({" + key + "})", "g");
result = result.replace(reg, args[key]);
}
} else {
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] == undefined) {
return "";
} else {
var reg = new RegExp("({[" + i + "]})", "g");
result = result.replace(reg, arguments[i]);
}
}
}
return result;
} else {
return this;
}
}
String.prototype.endWith = function(str) {
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
return false;
}
return (this.substring(this.length - str.length) == str);
};
String.prototype.startWith = function(str) {
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
return false;
}
return (this.substr(0, str.length) == str);
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,54 @@
$(document).ready(function(){
$('select.chosen-select').chosen({
no_results_text: '没有找到', // 当检索时没有找到匹配项时显示的提示文本
disable_search_threshold: 0, // 10 个以下的选择项则不显示检索框
search_contains: true, // 从任意位置开始检索
width: '100%'
});
$('#choiseTable').on('change', function(e){
var tableName = $("#choiseTable").val();
var columnList = database.columnList[tableName];
$("#tableCloumnsTable tbody").empty();
for (var i = 0; i < columnList.length; i++) {
var item = columnList[i];
$("#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 tableList = database.tableList;
for (var i = 0; i < tableList.length; i++) {
if(tableList[i].tableName == tableName) {
$(".table-desc").text(getNotEmptyStr(tableList[i].description));
break;
}
}
});
initData();
});
function initData(){
$('#choiseTable').empty();
$("#choiseTable").append('<option value=""></option>');
var tableList = database.tableList;
for (var i = 0; i < tableList.length; i++) {
var tableName = tableList[i].tableName;
var description = tableList[i].description;
var infoShow = tableName;
if(isNotEmpty(description)) {
infoShow += "(" + description + ")";
}
$("#choiseTable").append('<option value="'+tableName+'">' + infoShow + '</option>');
}
$('#choiseTable').trigger('chosen:updated');
}

View File

@@ -0,0 +1,115 @@
/**
* 将对象处理成json格式化和着色的html
* @author 暮光:城中城
* @since 2017年5月7日
*/
var Formatjson = {
tabStr: " ",
isArray: function(obj) {
return obj && typeof obj === 'object' && typeof obj.length === 'number'
&& !(obj.propertyIsEnumerable('length'));
},
processObjectToHtmlPre: function(obj, indent, addComma, isArray, isPropertyContent) {
var htmlStr = this.processObject(obj, indent, addComma, isArray, isPropertyContent);
htmlStr = '<pre class="json">' + htmlStr + '</pre>';
return htmlStr;
},
processObject: function(obj, indent, addComma, isArray, isPropertyContent) {
var html = "";
var comma = (addComma) ? "<span class='comma'>,</span> " : "";
var type = typeof obj;
var clpsHtml ="";
if (this.isArray(obj)) {
if (obj.length == 0) {
html += this.getRow(indent, "<span class='arrayBrace'>[ ]</span>" + comma, isPropertyContent);
} else {
clpsHtml = '<span><img class="option-img" src="webjars/mg-ui/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
html += this.getRow(indent, "<span class='arrayBrace'>[</span>"+clpsHtml, isPropertyContent);
for (var i = 0; i < obj.length; i++) {
html += this.processObject(obj[i], indent + 1, i < (obj.length - 1), true, false);
}
clpsHtml = "</span>";
html += this.getRow(indent, clpsHtml + "<span class='arrayBrace'>]</span>" + comma);
}
} else if (type == 'object' && obj == null) {
html += this.formatLiteral("null", "", comma, indent, isArray, "null");
} else if (type == 'object') {
var numProps = 0;
for ( var prop in obj) {
numProps++;
}
if (numProps == 0) {
html += this.getRow(indent, "<span class='objectBrace'>{ }</span>" + comma, isPropertyContent);
} else {
clpsHtml = '<span><img class="option-img" src="webjars/mg-ui/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
html += this.getRow(indent, "<span class='objectBrace'>{</span>"+clpsHtml, isPropertyContent);
var j = 0;
for ( var prop in obj) {
var processStr = '<span class="propertyName">"' + prop + '"</span>: ' + this.processObject(obj[prop], indent + 1, ++j < numProps, false, true);
html += this.getRow(indent + 1, processStr);
}
clpsHtml = "</span>";
html += this.getRow(indent, clpsHtml + "<span class='objectBrace'>}</span>" + comma);
}
} else if (type == 'number') {
html += this.formatLiteral(obj, "", comma, indent, isArray, "number");
} else if (type == 'boolean') {
html += this.formatLiteral(obj, "", comma, indent, isArray, "boolean");
} else if (type == 'function') {
obj = this.formatFunction(indent, obj);
html += this.formatLiteral(obj, "", comma, indent, isArray, "function");
} else if (type == 'undefined') {
html += this.formatLiteral("undefined", "", comma, indent, isArray, "null");
} else {
html += this.formatLiteral(obj, "\"", comma, indent, isArray, "string");
}
return html;
},
expImgClicked: function(img){
var container = img.parentNode.nextSibling;
if(!container) return;
var disp = "none";
var src = "webjars/mg-ui/img/collapsed.png";
if(container.style.display == "none"){
disp = "inline";
src = "webjars/mg-ui/img/expanded.png";
}
container.style.display = disp;
img.src = src;
},
formatLiteral: function(literal, quote, comma, indent, isArray, style) {
if (typeof literal == 'string') {
literal = literal.split("<").join("&lt;").split(">").join("&gt;");
}
var str = "<span class='" + style + "'>" + quote + literal + quote + comma + "</span>";
if (isArray) {
str = this.getRow(indent, str);
}
return str;
},
formatFunction: function(indent, obj) {
var tabs = "";
for (var i = 0; i < indent; i++) {
tabs += this.tabStr;
}
var funcStrArray = obj.toString().split("\n");
var str = "";
for (var i = 0; i < funcStrArray.length; i++) {
str += ((i == 0) ? "" : tabs) + funcStrArray[i] + "\n";
}
return str;
},
getRow: function(indent, data, isPropertyContent) {
var tabs = "";
for (var i = 0; i < indent && !isPropertyContent; i++) {
tabs += this.tabStr;
}
if (data != null && data.length > 0 && data.charAt(data.length - 1) != "\n") {
data = data + "\n";
}
return tabs + data;
}
}

File diff suppressed because one or more lines are too long

View File

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

View File

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,41 @@
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展示的样式 */

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

View File

@@ -0,0 +1,254 @@
/**
* 一些公用方法
* @author 暮光:城中城
* @since 2017年5月7日
*/
function serialize(value) {
if (typeof value === 'string') {
return value;
}
return JSON.stringify(value);
}
function deserialize(value) {
if (typeof value !== 'string' || isEmpty(value)) {
return undefined;
}
try {
return JSON.parse(value);
} catch (e) {
try {
return eval('(' + value + ')');// 处理变态的单双引号共存字符串
} catch (e) {
return value || undefined;
}
}
}
function validateResult(result) {
if(result.errCode == 200) {
return true;
} else {
Toast.error(result.errMsg);
}
return false;
}
/**
* 返回不为空的字符串为空返回def
*/
function getNotEmptyStr(str, def){
if(isEmpty(str)) {
return isEmpty(def)?"":def;
}
return str;
}
/**
* 是否是空对象
* @param obj
* @returns
*/
function isEmptyObject(obj){
return $.isEmptyObject(obj);
}
/**
* 是否是空字符串
* @param str
* @returns
*/
function isEmpty(str){
return (str == "" || str == null || str == undefined);
}
/**
* 是否是空
* @param str
* @returns
*/
function isNull(str){
return (str == null || str == undefined);
}
/**
* 是否不是空字符串
* @param str
* @returns
*/
function isNotEmpty(str){
return !isEmpty(str);
}
/**
* 数组转字符串,使用空格分隔
* @param array
* @returns
*/
function arrToString(array){
var temStr = "";
if(isEmpty(array)){
return temStr;
}
array.forEach(function(e){
if(isNotEmpty(temStr)) {
temStr += " ";
}
temStr += e;
});
return temStr;
}
/**
* 数组array中是否包含str字符串
* @param array
* @param str
* @returns
*/
function haveString(array, str){
if(isEmpty(array)) {
return false;
}
for (var i = 0; i < array.length; i++) {
if(array[i] == str) {
return true;
}
}
return false;
}
/**
* 直接返回对象的第一个属性
* @param data
* @returns
*/
function getObjectFirstAttribute(data) {
for ( var key in data) {
return data[key];
}
}
/**
* 如果对象只有一个属性则返回第一个属性否则返回null
* @param data
* @returns
*/
function getObjectFirstAttributeIfOnly(data) {
var len = 0, value = "";
for ( var key in data) {
if (++len > 1) {
return null;
}
value = data[key];
}
return value;
}
function postService(url, param, success=function(){}, complete=function(){}){
ajaxTemp(url, "POST", "JSON", param, function(result){
if(result.errCode != "200"){
Toast.warn(result.errMsg);
} else {
success(result);
}
},function(){
Toast.warn("请求数据失败");
}, function(result){
complete(result);
});
}
/**
* ajax处理事件模板
*
* @url 后台处理的url即action
* @dataSentType 数据发送的方式有postget方式
* @dataReceiveType 数据接收格式有html json text等
* @paramsStr 传入后台的参数
* @successFunction ajax成功后执行的函数名 ajaxTemp("", "GET", "html", {}, function(){},
* function(){}, "");
*/
function ajaxTemp(url, dataSentType, dataReceiveType, paramsStr, successFunction, errorFunction, completeFunction, id) {
$.ajax({
url : url, // 后台处理程序
sync : false,
type : dataSentType, // 数据发送方式
dataType : dataReceiveType, // 接受数据格式
data : eval(paramsStr),
contentType : "application/x-www-form-urlencoded; charset=UTF-8",
success : function(msg) {
if(typeof successFunction == "function") {
successFunction(msg,id);
}
},
beforeSend : function() {
},
complete : function(msg) {
if(typeof completeFunction == "function") {
completeFunction(msg,id);
}
},
error : function(msg) {
if(typeof errorFunction == "function") {
errorFunction(msg,id);
}
}
});
}
/**
* 获取cookie
* @param name
* @returns
*/
function getCookie(name) {
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg)){
return unescape(arr[2]);
}
return null;
}
/**
* 字符串格式化
*/
String.prototype.format = function(args) {
if (arguments.length > 0) {
var result = this;
if (arguments.length == 1 && typeof (args) == "object") {
for ( var key in args) {
var reg = new RegExp("({" + key + "})", "g");
result = result.replace(reg, args[key]);
}
} else {
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] == undefined) {
return "";
} else {
var reg = new RegExp("({[" + i + "]})", "g");
result = result.replace(reg, arguments[i]);
}
}
}
return result;
} else {
return this;
}
}
String.prototype.endWith = function(str) {
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
return false;
}
return (this.substring(this.length - str.length) == str);
};
String.prototype.startWith = function(str) {
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
return false;
}
return (this.substr(0, str.length) == str);
};

View File

@@ -0,0 +1,372 @@
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");
});
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,115 @@
/**
* 将对象处理成json格式化和着色的html
* @author 暮光:城中城
* @since 2017年5月7日
*/
var Formatjson = {
tabStr: " ",
isArray: function(obj) {
return obj && typeof obj === 'object' && typeof obj.length === 'number'
&& !(obj.propertyIsEnumerable('length'));
},
processObjectToHtmlPre: function(obj, indent, addComma, isArray, isPropertyContent) {
var htmlStr = this.processObject(obj, indent, addComma, isArray, isPropertyContent);
htmlStr = '<pre class="json">' + htmlStr + '</pre>';
return htmlStr;
},
processObject: function(obj, indent, addComma, isArray, isPropertyContent) {
var html = "";
var comma = (addComma) ? "<span class='comma'>,</span> " : "";
var type = typeof obj;
var clpsHtml ="";
if (this.isArray(obj)) {
if (obj.length == 0) {
html += this.getRow(indent, "<span class='arrayBrace'>[ ]</span>" + comma, isPropertyContent);
} else {
clpsHtml = '<span><img class="option-img" src="webjars/mg-ui/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
html += this.getRow(indent, "<span class='arrayBrace'>[</span>"+clpsHtml, isPropertyContent);
for (var i = 0; i < obj.length; i++) {
html += this.processObject(obj[i], indent + 1, i < (obj.length - 1), true, false);
}
clpsHtml = "</span>";
html += this.getRow(indent, clpsHtml + "<span class='arrayBrace'>]</span>" + comma);
}
} else if (type == 'object' && obj == null) {
html += this.formatLiteral("null", "", comma, indent, isArray, "null");
} else if (type == 'object') {
var numProps = 0;
for ( var prop in obj) {
numProps++;
}
if (numProps == 0) {
html += this.getRow(indent, "<span class='objectBrace'>{ }</span>" + comma, isPropertyContent);
} else {
clpsHtml = '<span><img class="option-img" src="webjars/mg-ui/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
html += this.getRow(indent, "<span class='objectBrace'>{</span>"+clpsHtml, isPropertyContent);
var j = 0;
for ( var prop in obj) {
var processStr = '<span class="propertyName">"' + prop + '"</span>: ' + this.processObject(obj[prop], indent + 1, ++j < numProps, false, true);
html += this.getRow(indent + 1, processStr);
}
clpsHtml = "</span>";
html += this.getRow(indent, clpsHtml + "<span class='objectBrace'>}</span>" + comma);
}
} else if (type == 'number') {
html += this.formatLiteral(obj, "", comma, indent, isArray, "number");
} else if (type == 'boolean') {
html += this.formatLiteral(obj, "", comma, indent, isArray, "boolean");
} else if (type == 'function') {
obj = this.formatFunction(indent, obj);
html += this.formatLiteral(obj, "", comma, indent, isArray, "function");
} else if (type == 'undefined') {
html += this.formatLiteral("undefined", "", comma, indent, isArray, "null");
} else {
html += this.formatLiteral(obj, "\"", comma, indent, isArray, "string");
}
return html;
},
expImgClicked: function(img){
var container = img.parentNode.nextSibling;
if(!container) return;
var disp = "none";
var src = "webjars/mg-ui/img/collapsed.png";
if(container.style.display == "none"){
disp = "inline";
src = "webjars/mg-ui/img/expanded.png";
}
container.style.display = disp;
img.src = src;
},
formatLiteral: function(literal, quote, comma, indent, isArray, style) {
if (typeof literal == 'string') {
literal = literal.split("<").join("&lt;").split(">").join("&gt;");
}
var str = "<span class='" + style + "'>" + quote + literal + quote + comma + "</span>";
if (isArray) {
str = this.getRow(indent, str);
}
return str;
},
formatFunction: function(indent, obj) {
var tabs = "";
for (var i = 0; i < indent; i++) {
tabs += this.tabStr;
}
var funcStrArray = obj.toString().split("\n");
var str = "";
for (var i = 0; i < funcStrArray.length; i++) {
str += ((i == 0) ? "" : tabs) + funcStrArray[i] + "\n";
}
return str;
},
getRow: function(indent, data, isPropertyContent) {
var tabs = "";
for (var i = 0; i < indent && !isPropertyContent; i++) {
tabs += this.tabStr;
}
if (data != null && data.length > 0 && data.charAt(data.length - 1) != "\n") {
data = data + "\n";
}
return tabs + data;
}
}

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -0,0 +1,50 @@
var tableRelationData = {
// "name": "user_info",
// "children": [
// {
// "name": "user_auth",
// "children": []
// },{
// "name": "group_info",
// "children": []
// }]
}
var tableRelationOption = {
tooltip: {
trigger: 'item',
triggerOn: 'mousemove'
},
series: [
{
type: 'tree',
/*orient: 'vertical',*/
data: [tableRelationData],
top: '1%',
left: '7%',
bottom: '1%',
right: '20%',
symbolSize: 7,
label: {
normal: {
position: 'left',
verticalAlign: 'middle',
align: 'right',
fontSize: 14
}
},
leaves: {
label: {
normal: {
position: 'right',
verticalAlign: 'middle',
align: 'left'
}
}
},
expandAndCollapse: true,
animationDuration: 550,
animationDurationUpdate: 750
}
]
}

View File

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 290 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,436 @@
/*!
* Chosen, a Select Box Enhancer for jQuery and Prototype
* by Patrick Filler for Harvest, http://getharvest.com
*
* Copyright (c) 2011-2016 Harvest http://getharvest.com
* MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
*/
.chosen-container {
position: relative;
display: inline-block;
font-size: 13px;
vertical-align: middle;
zoom: 1;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
*display: inline;
}
.chosen-container .chosen-drop {
position: absolute;
top: 100%;
left: -9999px;
z-index: 1010;
width: 100%;
background: #fff;
border: 1px solid #cbcbcb;
border: 1px solid rgba(0, 0, 0, .15);
border-top: 0;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
}
.chosen-container .chosen-drop.chosen-drop-size-limited {
border-top: 1px solid rgba(0, 0, 0, .15);
}
.chosen-container.chosen-with-drop .chosen-drop {
left: 0;
}
.chosen-container a {
cursor: pointer;
}
.chosen-container.chosen-up .chosen-drop {
top: inherit;
bottom: 100%;
margin-top: auto;
margin-bottom: -1px;
border-radius: 2px 2px 0 0;
-webkit-box-shadow: 0 -3px 5px rgba(0, 0, 0, .175);
box-shadow: 0 -3px 5px rgba(0, 0, 0, .175);
}
.chosen-container-single .chosen-single {
display: block;
width: 100%;
height: 32px;
padding: 5px 8px;
overflow: hidden;
line-height: 1.53846154;
color: #222;
text-decoration: none;
white-space: nowrap;
vertical-align: middle;
background-color: #fff;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
}
.chosen-container-single .chosen-default {
color: #808080;
}
.chosen-container-single .chosen-single > span {
display: block;
margin-right: 26px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.chosen-container-single .chosen-single-with-deselect span {
margin-right: 38px;
}
.chosen-container-single .chosen-single abbr {
position: absolute;
top: 7px;
right: 24px;
display: block;
width: 20px;
height: 20px;
font-size: 19.5px;
font-weight: bold;
line-height: 14px;
color: #000;
text-align: center;
text-shadow: 0 1px 0 #fff;
filter: alpha(opacity=20);
opacity: .2;
}
.chosen-container-single .chosen-single abbr:before {
content: '×';
}
.chosen-container-single .chosen-single abbr:hover,
.chosen-container-single .chosen-single abbr:focus {
color: #000;
text-decoration: none;
cursor: pointer;
filter: alpha(opacity=50);
opacity: .5;
}
.chosen-container-single .chosen-single div {
position: absolute;
top: 0;
right: 0;
display: block;
height: 100%;
padding: 5px 8px;
}
.chosen-container-single .chosen-single div b {
display: inline-block;
width: 0;
height: 0;
margin-bottom: 2px;
margin-left: 2px;
vertical-align: middle;
border-top: 4px dashed;
border-top: 4px solid \9;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
}
.chosen-container-single .chosen-search {
position: relative;
z-index: 1010;
padding: 3px 4px;
margin: 0;
white-space: nowrap;
}
.chosen-container-single .chosen-search input[type="text"] {
width: 100%;
height: 27px;
padding: 2px 26px 2px 8px;
margin: 1px 0;
font-size: 12px;
line-height: 1.5;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 4px;
outline: 0;
}
.chosen-container-single .chosen-search input[type="text"]:focus {
border-color: #145ccd;
}
.chosen-container-single .chosen-search:before {
position: absolute;
top: 10px;
right: 10px;
display: block;
font-family: ZenIcon;
font-size: 14px;
font-style: normal;
font-weight: normal;
font-variant: normal;
line-height: 1;
color: #808080;
text-transform: none;
content: '\e603';
speak: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.chosen-container-single .chosen-drop {
margin-top: -1px;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border-radius: 0 0 4px 4px;
}
.chosen-container-single.chosen-container-single-nosearch .chosen-search {
position: absolute;
left: -9999px;
}
.chosen-container .chosen-results {
position: relative;
max-height: 240px;
padding: 0;
margin: 0;
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.chosen-container .chosen-results li {
display: none;
padding: 5px 10px;
margin: 0;
line-height: 15px;
list-style: none;
-webkit-transition: background-color .2s cubic-bezier(.175, .885, .32, 1);
-o-transition: background-color .2s cubic-bezier(.175, .885, .32, 1);
transition: background-color .2s cubic-bezier(.175, .885, .32, 1);
-webkit-touch-callout: none;
}
.chosen-container .chosen-results li.active-result {
display: list-item;
cursor: pointer;
}
.chosen-container .chosen-results li.disabled-result {
display: list-item;
color: #ccc;
cursor: default;
}
.chosen-container .chosen-results li.highlighted {
color: #fff;
background-color: #3280fc;
}
.chosen-container .chosen-results li.no-results {
display: list-item;
background: #f4f4f4;
}
.chosen-container .chosen-results li.group-result {
display: list-item;
font-weight: bold;
cursor: default;
}
.chosen-container .chosen-results li.group-option {
padding-left: 15px;
}
.chosen-container .chosen-results li em {
font-style: normal;
text-decoration: underline;
}
.chosen-container-multi .chosen-choices {
position: relative;
width: 100%;
min-height: 32px;
min-height: 30px \0;
padding: 0;
margin: 0;
overflow: hidden;
cursor: text;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
}
.chosen-container-multi .chosen-choices:before,
.chosen-container-multi .chosen-choices:after {
/* 1 */
display: table;
content: " ";
/* 2 */
}
.chosen-container-multi .chosen-choices:after {
clear: both;
}
.chosen-container-multi .chosen-choices li {
display: block;
float: left;
padding: 0 6px;
margin: 5px 0 0 6px;
list-style: none;
}
.chosen-container-multi .chosen-choices li.search-field {
padding: 0;
margin-bottom: 4px;
white-space: nowrap;
}
.chosen-container-multi .chosen-choices li.search-field input[type="text"] {
height: 20px;
font-size: 100%;
color: #808080;
background: transparent !important;
border: 0 !important;
border-radius: 0;
outline: 0;
-webkit-box-shadow: none;
box-shadow: none;
}
.chosen-container-multi .chosen-choices li.search-field .default {
color: #999;
}
.chosen-container-multi .chosen-choices li.search-field:before {
position: absolute;
right: 8px;
bottom: 8px;
display: block;
font-family: ZenIcon;
font-size: 14px;
font-style: normal;
font-weight: normal;
font-variant: normal;
line-height: 1;
color: #808080;
text-transform: none;
content: '\e603';
opacity: 0;
-webkit-transition: opacity .2s cubic-bezier(.175, .885, .32, 1);
-o-transition: opacity .2s cubic-bezier(.175, .885, .32, 1);
transition: opacity .2s cubic-bezier(.175, .885, .32, 1);
speak: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.chosen-container-multi .chosen-choices li.search-choice {
position: relative;
padding: 3px 20px 3px 5px;
line-height: 12px;
cursor: default;
background-color: #f1f1f1;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid #ddd;
border-radius: 3px;
-webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, .05);
box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, .05);
-webkit-transition: all .4s cubic-bezier(.175, .885, .32, 1);
-o-transition: all .4s cubic-bezier(.175, .885, .32, 1);
transition: all .4s cubic-bezier(.175, .885, .32, 1);
}
.chosen-container-multi .chosen-choices li.search-choice:hover {
background-color: #fff;
border-color: #c4c4c4;
-webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, .1);
box-shadow: 0 1px 0 rgba(0, 0, 0, .1);
}
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
position: absolute;
top: 0;
right: 0;
display: block;
width: 20px;
height: 20px;
font-size: 15.6px;
font-weight: bold;
line-height: 14px;
color: #000;
text-align: center;
text-shadow: 0 1px 0 #fff;
filter: alpha(opacity=20);
opacity: .2;
}
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:before {
content: '×';
}
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover,
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
filter: alpha(opacity=50);
opacity: .5;
}
.chosen-container-multi .chosen-choices li.search-choice-disabled {
padding-right: 5px;
color: #666;
background-color: #e4e4e4;
border: 1px solid #ccc;
}
.chosen-container-multi .chosen-choices li.search-choice-focus {
background: #d4d4d4;
}
.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close {
background-position: -42px -10px;
}
.chosen-container-multi .chosen-results {
padding: 5px 0;
margin: 0;
}
.chosen-container-multi .chosen-drop .result-selected {
display: list-item;
color: #ccc;
cursor: default;
}
.chosen-container-active .chosen-single {
border-color: #145ccd;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(20, 92, 205, .6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(20, 92, 205, .6);
}
.chosen-container-active.chosen-with-drop .chosen-single {
border: 1px solid #cbcbcb;
border: 1px solid rgba(0, 0, 0, .15);
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
}
.chosen-container-active.chosen-with-drop .chosen-single div {
background: transparent;
border-left: none;
}
.chosen-container-active.chosen-with-drop .chosen-single div b {
content: "";
border-top: 0 dotted;
border-bottom: 4px solid;
}
.chosen-container-active.chosen-with-drop.chosen-up .chosen-single {
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 4px;
border-bottom-left-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
}
.chosen-container-active .chosen-choices {
border-color: #145ccd;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(20, 92, 205, .6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(20, 92, 205, .6);
}
.chosen-container-active .chosen-choices li.search-field input[type="text"] {
color: #111 !important;
}
.chosen-container-active .chosen-choices li.search-field:before {
opacity: 1;
}
.chosen-disabled {
cursor: default;
opacity: .5 !important;
}
.chosen-disabled .chosen-single {
cursor: default;
}
.chosen-disabled .chosen-choices .search-choice .search-choice-close {
cursor: default;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

191
zyplayer-doc-manage/LICENSE Normal file
View File

@@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "{}" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright 2018 暮光:城中城
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,37 @@
# zyplayer-doc-manage
#### 项目介绍
定位为所有文档的管理项目
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本项目
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 码云特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目
5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

View File

@@ -0,0 +1,85 @@
<?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-manage</artifactId>
<version>1.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>zyplayer-doc-manage</name>
<description>定位为所有文档的管理项目swagger文档、数据库文档、、、、等</description>
<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>
<swagger.mg.ui.version>2.0.1</swagger.mg.ui.version>
<velocity.engine.core.version>2.0</velocity.engine.core.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>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>
<!-- json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- 在线文档解析页面 -->
<dependency>
<groupId>com.zyplayer</groupId>
<artifactId>zyplayer-doc-swagger</artifactId>
<version>${swagger.mg.ui.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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.mapper;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
public interface ZyplayerStorageMapper extends BaseMapper<ZyplayerStorage> {
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.mapper;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
public interface ZyplayerStorageMapper extends BaseMapper<ZyplayerStorage> {
}

View File

@@ -0,0 +1,67 @@
package com.zyplayer.doc.manage.repository.support.plus.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 hongli.zhang
* @since 2018-11-27
*/
public class ZyplayerStorage implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String docKey;
private String docValue;
private Date creationTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDocKey() {
return docKey;
}
public void setDocKey(String docKey) {
this.docKey = docKey;
}
public String getDocValue() {
return docValue;
}
public void setDocValue(String docValue) {
this.docValue = docValue;
}
public Date getCreationTime() {
return creationTime;
}
public void setCreationTime(Date creationTime) {
this.creationTime = creationTime;
}
@Override
public String toString() {
return "ZyplayerStorage{" +
"id=" + id +
", docKey=" + docKey +
", docValue=" + docValue +
", creationTime=" + creationTime +
"}";
}
}

View File

@@ -0,0 +1,67 @@
package com.zyplayer.doc.manage.repository.support.plus.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 hongli.zhang
* @since 2018-11-27
*/
public class ZyplayerStorage implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String docKey;
private String docValue;
private Date creationTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDocKey() {
return docKey;
}
public void setDocKey(String docKey) {
this.docKey = docKey;
}
public String getDocValue() {
return docValue;
}
public void setDocValue(String docValue) {
this.docValue = docValue;
}
public Date getCreationTime() {
return creationTime;
}
public void setCreationTime(Date creationTime) {
this.creationTime = creationTime;
}
@Override
public String toString() {
return "ZyplayerStorage{" +
"id=" + id +
", docKey=" + docKey +
", docValue=" + docValue +
", creationTime=" + creationTime +
"}";
}
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.service;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
public interface ZyplayerStorageService extends IService<ZyplayerStorage> {
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.service;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
public interface ZyplayerStorageService extends IService<ZyplayerStorage> {
}

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.service.impl;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.zyplayer.doc.manage.repository.support.plus.manage.mapper.ZyplayerStorageMapper;
import com.zyplayer.doc.manage.repository.support.plus.manage.service.ZyplayerStorageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
@Service
public class ZyplayerStorageServiceImpl extends ServiceImpl<ZyplayerStorageMapper, ZyplayerStorage> implements ZyplayerStorageService {
}

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.manage.repository.support.plus.manage.service.impl;
import com.zyplayer.doc.manage.repository.support.plus.manage.entity.ZyplayerStorage;
import com.zyplayer.doc.manage.repository.support.plus.manage.mapper.ZyplayerStorageMapper;
import com.zyplayer.doc.manage.repository.support.plus.manage.service.ZyplayerStorageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author hongli.zhang
* @since 2018-11-27
*/
@Service
public class ZyplayerStorageServiceImpl extends ServiceImpl<ZyplayerStorageMapper, ZyplayerStorage> implements ZyplayerStorageService {
}

View File

@@ -0,0 +1,40 @@
package com.zyplayer.doc.manage;
import java.net.InetAddress;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
/**
* 程序启动器
*/
@SpringBootApplication
@MapperScan("com.zyplayer.doc.manage.repository")
public class Application extends SpringBootServletInitializer {
private static Logger logger = LoggerFactory.getLogger(Application.class);
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext application = SpringApplication.run(Application.class, args);
Environment env = application.getEnvironment();
logger.info("\n----------------------------------------------------------\n\t" +
"\t\t地址列表\n\t"+
"文档地址http://{}:{}/document.html\n"+
"----------------------------------------------------------",
InetAddress.getLocalHost().getHostAddress(), env.getProperty("server.port")
);
}
}

View File

@@ -0,0 +1,60 @@
package com.zyplayer.doc.manage.framework.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.mg.swagger.framework.service.MgStorageService;
import com.zyplayer.doc.manage.repository.manage.entity.ZyplayerStorage;
import com.zyplayer.doc.manage.service.manage.ZyplayerStorageService;
/**
* 申明为@Service之后网页上才能使用存储能力同时需要在@EnableSwagger2的地方添加@EnableSwaggerMgUi注解
* 才能开启存储的接口<br/>
* 开放存储能力的好处:<br/>
* 所有网页的配置、调试值都可以存储到服务器的数据库中,便于团队所有人的调试,一人配置,所有人受益<br/>
* 如果不开启的话数据是存放在浏览器的localStorage中每个人、每个浏览器都得配置一次才能使用<br/>
*
* @author 暮光:城中城
* @since 2018年8月19日
*/
@Service
public class MgStorageServiceImpl implements MgStorageService {
@Autowired
ZyplayerStorageService zyplayerStorageService;
/**
* 使用数据库来存储,例: storageMapper.select(key);
*/
@Override
public String get(String key) {
QueryWrapper<ZyplayerStorage> wrapper = new QueryWrapper<>();
wrapper.eq(true, "doc_key", key);
ZyplayerStorage zyplayerStorage = zyplayerStorageService.getOne(wrapper);
if (zyplayerStorage == null) {
return null;
}
return zyplayerStorage.getDocValue();
}
/**
* 使用数据库来存储,例: storageMapper.updateOrInsert(key, value);
*/
@Override
public void put(String key, String value) {
ZyplayerStorage entity = new ZyplayerStorage();
entity.setDocValue(value);
UpdateWrapper<ZyplayerStorage> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq(true, "doc_key", key);
boolean update = zyplayerStorageService.update(entity, updateWrapper);
if (!update) {
entity = new ZyplayerStorage();
entity.setDocValue(value);
entity.setDocKey(key);
zyplayerStorageService.save(entity);
}
}
}

View File

@@ -0,0 +1,22 @@
package com.zyplayer.doc.manage.framework.config;
import org.springframework.context.annotation.Configuration;
import com.mg.swagger.framework.configuration.EnableSwaggerMgUi;
/**
* 不需要管理本项目的文档,只需要开启@EnableSwaggerMgUi即可
* @author 暮光:城中城
* @since 2018年11月11日
*/
@Configuration
@EnableSwaggerMgUi(
selfDoc = false,// 不开启自身的文档,本项目只当管理文档的项目使用
defaultResources = {// selfDoc=false时有用启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址
//"http://localhost:8080/swagger-resources"
}
)
public class SwaggerConfiguration {
}

View File

@@ -0,0 +1,52 @@
package com.zyplayer.doc.manage.framework.config;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
@Component
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
format.setLenient(true);
DateFormatter dateFormatter = new DateFormatter();
dateFormatter.setPattern("yyyy-MM-dd HH:mm:ss");
dateFormatter.setLenient(true);
registry.addFormatter(dateFormatter);
}
@Bean
public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(new MediaType("application", "json", Charset.forName("UTF-8")));
fastJsonHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteDateUseDateFormat);
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
return fastJsonHttpMessageConverter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, fastJsonHttpMessageConverter());
}
}

View File

@@ -0,0 +1,65 @@
package com.zyplayer.doc.manage.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 2018-11-27
*/
public class ZyplayerStorage implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String docKey;
private String docValue;
private Date creationTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDocKey() {
return docKey;
}
public void setDocKey(String docKey) {
this.docKey = docKey;
}
public String getDocValue() {
return docValue;
}
public void setDocValue(String docValue) {
this.docValue = docValue;
}
public Date getCreationTime() {
return creationTime;
}
public void setCreationTime(Date creationTime) {
this.creationTime = creationTime;
}
@Override
public String toString() {
return "ZyplayerStorage{" + "id=" + id + ", docKey=" + docKey + ", docValue=" + docValue + ", creationTime=" + creationTime + "}";
}
}

View File

@@ -0,0 +1,18 @@
package com.zyplayer.doc.manage.repository.manage.mapper;
import com.zyplayer.doc.manage.repository.manage.entity.ZyplayerStorage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 暮光:城中城
* @since 2018-11-27
*/
public interface ZyplayerStorageMapper extends BaseMapper<ZyplayerStorage> {
Integer selectTop();
}

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