表数据导出优化,增加表关系图功能

This commit is contained in:
暮光:城中城
2021-06-08 23:04:15 +08:00
parent dcbb2b4ac8
commit 1d5e0e2bf1
42 changed files with 977 additions and 316 deletions

View File

@@ -39,8 +39,8 @@
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
<version>4.1.8</version>
<artifactId>hutool-all</artifactId>
<version>5.6.6</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>

View File

@@ -0,0 +1,9 @@
package com.zyplayer.doc.core.util;
/**
* zyplayer-doc版本号
* @since 2021-06-06
*/
public class ZyplayerDocVersion {
public static final String version = "1.0.8";
}

View File

@@ -0,0 +1,170 @@
package com.zyplayer.doc.data.repository.manage.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
/**
* <p>
* 表关系
* </p>
*
* @author 暮光:城中城
* @since 2021-06-07
*/
public class DbTableRelation implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键自增ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 数据源ID
*/
private Long datasourceId;
/**
* 源库名
*/
private String startDbName;
/**
* 源表名
*/
private String startTableName;
/**
* 源字段名
*/
private String startColumnName;
/**
* 目标库名
*/
private String endDbName;
/**
* 目标表名
*/
private String endTableName;
/**
* 目标字段名
*/
private String endColumnName;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人名字
*/
private String createUserName;
/**
* 创建时间
*/
private Date createTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getDatasourceId() {
return datasourceId;
}
public void setDatasourceId(Long datasourceId) {
this.datasourceId = datasourceId;
}
public String getStartDbName() {
return startDbName;
}
public void setStartDbName(String startDbName) {
this.startDbName = startDbName;
}
public String getStartTableName() {
return startTableName;
}
public void setStartTableName(String startTableName) {
this.startTableName = startTableName;
}
public String getStartColumnName() {
return startColumnName;
}
public void setStartColumnName(String startColumnName) {
this.startColumnName = startColumnName;
}
public String getEndDbName() {
return endDbName;
}
public void setEndDbName(String endDbName) {
this.endDbName = endDbName;
}
public String getEndTableName() {
return endTableName;
}
public void setEndTableName(String endTableName) {
this.endTableName = endTableName;
}
public String getEndColumnName() {
return endColumnName;
}
public void setEndColumnName(String endColumnName) {
this.endColumnName = endColumnName;
}
public Long getCreateUserId() {
return createUserId;
}
public void setCreateUserId(Long createUserId) {
this.createUserId = createUserId;
}
public String getCreateUserName() {
return createUserName;
}
public void setCreateUserName(String createUserName) {
this.createUserName = createUserName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "DbTableRelation{" +
"id=" + id +
", datasourceId=" + datasourceId +
", startDbName=" + startDbName +
", startTableName=" + startTableName +
", startColumnName=" + startColumnName +
", endDbName=" + endDbName +
", endTableName=" + endTableName +
", endColumnName=" + endColumnName +
", createUserId=" + createUserId +
", createUserName=" + createUserName +
", createTime=" + createTime +
"}";
}
}

View File

@@ -0,0 +1,16 @@
package com.zyplayer.doc.data.repository.manage.mapper;
import com.zyplayer.doc.data.repository.manage.entity.DbTableRelation;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 表关系 Mapper 接口
* </p>
*
* @author 暮光:城中城
* @since 2021-06-07
*/
public interface DbTableRelationMapper extends BaseMapper<DbTableRelation> {
}

View File

@@ -0,0 +1,55 @@
package com.zyplayer.doc.data.repository.manage.param;
/**
* 表关系请求参数
* @author 暮光:城中城
* @since 2021-06-07
*/
public class TableRelationParam {
private Long sourceId;
private String dbName;
private String tableName;
private String columnName;
// 关系JSON大概是[{dbName: 'xxx', tableName: 'xxx', columnName: 'xxx'}]
private String relation;
public Long getSourceId() {
return sourceId;
}
public void setSourceId(Long sourceId) {
this.sourceId = sourceId;
}
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getRelation() {
return relation;
}
public void setRelation(String relation) {
this.relation = relation;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
}

View File

@@ -0,0 +1,66 @@
package com.zyplayer.doc.data.repository.manage.vo;
import java.util.List;
/**
* 表关系结构
* @author 暮光:城中城
* @since 2021-06-07
*/
public class TableRelationVo {
private String dbName;
private String tableName;
// name和columnName是一个name给前端使用的
private String name;
private String columnName;
private Integer nodeType;
private List<TableRelationVo> children;
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public List<TableRelationVo> getChildren() {
return children;
}
public void setChildren(List<TableRelationVo> children) {
this.children = children;
}
public Integer getNodeType() {
return nodeType;
}
public void setNodeType(Integer nodeType) {
this.nodeType = nodeType;
}
}

View File

@@ -20,7 +20,7 @@ public class CodeGenerator {
// final String[] tableName = { "zyplayer_storage", "auth_info", "user_auth", "user_info", "db_datasource" };
// final String[] tableName = { "wiki_space", "wiki_page", "wiki_page_content", "wiki_page_file", "wiki_page_comment", "wiki_page_zan" };
// final String[] tableName = { "db_datasource", "es_datasource", "db_favorite" };
final String[] tableName = {"db_proc_log"};
final String[] tableName = {"db_table_relation"};
// 代码生成器
AutoGenerator mpg = new AutoGenerator();

View File

@@ -0,0 +1,20 @@
package com.zyplayer.doc.data.service.manage;
import com.zyplayer.doc.data.repository.manage.entity.DbTableRelation;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zyplayer.doc.data.repository.manage.param.TableRelationParam;
import com.zyplayer.doc.data.repository.manage.vo.TableRelationVo;
/**
* <p>
* 表关系 服务类
* </p>
*
* @author 暮光:城中城
* @since 2021-06-07
*/
public interface DbTableRelationService extends IService<DbTableRelation> {
void update(TableRelationParam param);
}

View File

@@ -0,0 +1,72 @@
package com.zyplayer.doc.data.service.manage.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.sun.jersey.server.impl.wadl.WadlResource;
import com.zyplayer.doc.data.config.security.DocUserDetails;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import com.zyplayer.doc.data.repository.manage.entity.DbTableRelation;
import com.zyplayer.doc.data.repository.manage.mapper.DbTableRelationMapper;
import com.zyplayer.doc.data.repository.manage.param.TableRelationParam;
import com.zyplayer.doc.data.repository.manage.vo.TableRelationVo;
import com.zyplayer.doc.data.service.manage.DbTableRelationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
/**
* <p>
* 表关系 服务实现类
* </p>
*
* @author 暮光:城中城
* @since 2021-06-07
*/
@Service
public class DbTableRelationServiceImpl extends ServiceImpl<DbTableRelationMapper, DbTableRelation> implements DbTableRelationService {
@Override
@Transactional
public void update(TableRelationParam param) {
UpdateWrapper<DbTableRelation> removeWrapper = new UpdateWrapper<>();
removeWrapper.eq("datasource_id", param.getSourceId());
removeWrapper.and(wrapper -> wrapper.or(or -> or.eq("start_db_name", param.getDbName())
.eq("start_table_name", param.getTableName())
.eq("start_column_name", param.getColumnName())
).or(or -> or.eq("end_db_name", param.getDbName())
.eq("end_table_name", param.getTableName())
.eq("end_column_name", param.getColumnName())
));
this.remove(removeWrapper);
if(StringUtils.isEmpty(param.getRelation())) {
return;
}
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
List<TableRelationParam> tableRelationList = JSON.parseArray(param.getRelation(), TableRelationParam.class);
for (TableRelationParam relation : tableRelationList) {
if (StringUtils.isBlank(relation.getDbName())
|| StringUtils.isBlank(relation.getTableName())
|| StringUtils.isBlank(relation.getColumnName())) {
continue;
}
DbTableRelation tableRelation = new DbTableRelation();
tableRelation.setDatasourceId(param.getSourceId());
tableRelation.setStartDbName(param.getDbName());
tableRelation.setStartTableName(param.getTableName());
tableRelation.setStartColumnName(param.getColumnName());
tableRelation.setEndDbName(relation.getDbName());
tableRelation.setEndTableName(relation.getTableName());
tableRelation.setEndColumnName(relation.getColumnName());
tableRelation.setCreateTime(new Date());
tableRelation.setCreateUserId(currentUser.getUserId());
tableRelation.setCreateUserName(currentUser.getUsername());
this.save(tableRelation);
}
}
}

View File

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

View File

@@ -144,13 +144,6 @@ public class DatabaseDocController {
return DocDbResponseJson.ok(tableColumnVo);
}
@PostMapping(value = "/getTableColumnDescList")
public ResponseJson getTableColumnDescList(Long sourceId, String tableName) {
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(sourceId);
List<TableColumnDescDto> columnDescDto = dbBaseService.getTableColumnDescList(sourceId, tableName);
return DocDbResponseJson.ok(columnDescDto);
}
@PostMapping(value = "/getTableAndColumnBySearch")
public ResponseJson getTableAndColumnBySearch(Long sourceId, String dbName, String searchText) {
if (StringUtils.isBlank(searchText)) {

View File

@@ -1,7 +1,10 @@
package com.zyplayer.doc.db.controller;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.TypeUtils;
@@ -9,6 +12,7 @@ import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.core.exception.ConfirmException;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.core.util.StringUtil;
import com.zyplayer.doc.core.util.ZyplayerDocVersion;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import com.zyplayer.doc.data.repository.support.consts.DocAuthConst;
import com.zyplayer.doc.db.controller.param.DataViewParam;
@@ -29,12 +33,14 @@ import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -57,6 +63,9 @@ public class DbDataViewController {
DbBaseFactory dbBaseFactory;
@Resource
BaseDownloadService baseDownloadService;
// 最大允许导出的行数设置的过大有可能会导致内存溢出默认10W条
@Value("${zyplayer.doc.db.download-max-row:100000}")
Integer downloadMaxRow;
@PostMapping(value = "/query")
public ResponseJson query(DataViewParam param) {
@@ -73,13 +82,7 @@ public class DbDataViewController {
if (CollectionUtils.isNotEmpty(executeResult.getResult()) && Objects.equals(param.getPageNum(), 1)) {
responseJson.setTotal((long) executeResult.getResult().size());
if (executeResult.getResult().size() >= param.getPageSize()) {
String queryCountSql = dbBaseService.getQueryCountSql(param);
ExecuteResult countResult = this.query(param.getSourceId(), param.getExecuteId(), executeType, queryCountSql);
if (CollectionUtils.isNotEmpty(countResult.getResult()) && MapUtils.isNotEmpty(countResult.getResult().get(0))) {
Map<String, Object> countMap = countResult.getResult().get(0);
Optional<Object> countAny = countMap.values().stream().findAny();
countAny.ifPresent(count -> responseJson.setTotal(TypeUtils.castToLong(count)));
}
responseJson.setTotal(this.getDataCount(param, executeType));
}
}
return responseJson;
@@ -95,7 +98,11 @@ public class DbDataViewController {
@PostMapping(value = "/download")
public ResponseJson download(HttpServletResponse response, DataViewParam param) {
param.setExecuteId(RandomUtil.simpleUUID());
ExecuteType executeType = this.getExecuteType(param.getSourceId());
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(param.getSourceId());
if (this.getDataCount(param, executeType) > downloadMaxRow) {
return DocDbResponseJson.error(String.format("导出失败,表:%s 数据行数超过最大导出配置 %s请联系管理员修改", param.getTableName(), downloadMaxRow));
}
// 获取列信息等
TableColumnVo tableColumnVo = dbBaseService.getTableColumnList(param.getSourceId(), param.getDbName(), param.getTableName());
Set<String> conditionSet = StringUtils.isBlank(param.getConditionColumn()) ? Collections.emptySet() : Stream.of(param.getConditionColumn().split(",")).collect(Collectors.toSet());
@@ -106,10 +113,8 @@ public class DbDataViewController {
ExecuteParam executeParam = new ExecuteParam();
executeParam.setDatasourceId(param.getSourceId());
executeParam.setExecuteId(param.getExecuteId());
executeParam.setExecuteType(this.getExecuteType(param.getSourceId()));
executeParam.setExecuteType(executeType);
executeParam.setSql(queryAllSql);
// 最大支持10w行数据总得有个上限
executeParam.setMaxRows(100000);
try {
dbBaseService.downloadSingleTableData(response, param, executeParam, columnList, conditionSet);
} catch (Exception e) {
@@ -131,45 +136,85 @@ public class DbDataViewController {
if (StringUtils.isBlank(param.getTableNames())) {
return DocDbResponseJson.warn("请选择导出的表");
}
param.setExecuteId(RandomUtil.simpleUUID());
param.setExecuteId(IdUtil.simpleUUID());
String tempDir = System.getProperty("java.io.tmpdir");
boolean multipleFile = Objects.equals(param.getDownloadFileType(), 2);
boolean isJson = Objects.equals(param.getDownloadType(), "json");
StringBuilder resultSb = new StringBuilder("/*\n" +
" zyplayer-doc 表数据导出\n" +
"\n" +
" 数据库 : " + param.getDbName() + "\n" +
" 数据库类型 : " + dbBaseService.getDatabaseProduct().name() + "\n" +
" 导出时间 : " + DateTime.now().toString() + "\n" +
" 软件版本 : " + ZyplayerDocVersion.version + "\n" +
"*/\n\n");
String[] tableNameArr = param.getTableNames().split(",");
String tempDirName = tempDir + "zyplayer-doc-" + IdUtil.fastSimpleUUID();
try {
for (String tabName : tableNameArr) {
param.setTableName(tabName);
// 先校验总条数是否超过限制
for (String tableName : tableNameArr) {
param.setTableName(tableName);
ExecuteType executeType = this.getExecuteType(param.getSourceId());
if (this.getDataCount(param, executeType) > downloadMaxRow) {
return DocDbResponseJson.error(String.format("导出失败,表:%s 数据行数超过最大导出配置 %s请联系管理员修改", tableName, downloadMaxRow));
}
}
// 创建临时文件夹
FileUtil.mkdir(tempDirName);
// 再分表查数据
String suffix = isJson ? ".json" : ".sql";
for (String tableName : tableNameArr) {
param.setTableName(tableName);
ExecuteType executeType = this.getExecuteType(param.getSourceId());
// 获取列信息等
TableColumnVo tableColumnVo = dbBaseService.getTableColumnList(param.getSourceId(), param.getDbName(), tabName);
TableColumnVo tableColumnVo = dbBaseService.getTableColumnList(param.getSourceId(), param.getDbName(), tableName);
List<TableColumnDescDto> columnList = tableColumnVo.getColumnList();
// 找主键作为更新条件
Set<String> conditionSet = columnList.stream().filter(item -> Objects.equals(item.getIspramary(), "1")).map(TableColumnDescDto::getName).collect(Collectors.toSet());
Set<String> conditionSet = columnList.stream().filter(item -> Objects.equals(item.getPrimaryKey(), "1")).map(TableColumnDescDto::getName).collect(Collectors.toSet());
// 数据查询
String queryAllSql = dbBaseService.getQueryAllSql(param);
ExecuteParam executeParam = new ExecuteParam();
executeParam.setDatasourceId(param.getSourceId());
executeParam.setExecuteId(param.getExecuteId());
executeParam.setExecuteType(this.getExecuteType(param.getSourceId()));
executeParam.setExecuteType(executeType);
executeParam.setSql(queryAllSql);
// 最大支持10w行数据总得有个上限
executeParam.setMaxRows(100000);
String downloadTableData = dbBaseService.getDownloadTableData(param, executeParam, columnList, conditionSet);
resultSb.append(String.format("-- 导出数据表:`%s`.`%s` --\n", param.getDbName(), tabName));
resultSb.append(downloadTableData).append("\n");
// 写入临时文件
if (multipleFile) {
File tempFile = FileUtil.file(tempDirName + "/" + tableName + suffix);
String tableDataSb = isJson ? downloadTableData : String.format("-- 导出数据表:`%s`.`%s` --\n", param.getDbName(), tableName) + downloadTableData;
FileUtil.writeUtf8String(tableDataSb, tempFile);
} else {
resultSb.append(String.format("-- 导出数据表:`%s`.`%s` --\n", param.getDbName(), tableName));
resultSb.append(downloadTableData).append("\n");
}
}
if (multipleFile) {
baseDownloadService.sendResponse(response, param.getDbName(), tempDirName);
} else {
baseDownloadService.sendResponse(response, param.getDbName(), suffix, resultSb.toString());
}
String prefix = Objects.equals(param.getDownloadType(), "json") ? ".json" : ".sql";
baseDownloadService.sendResponse(response, param.getDbName(), prefix, resultSb.toString());
} catch (Exception e) {
e.printStackTrace();
return DocDbResponseJson.error("导出失败:" + e.getMessage());
} finally {
FileUtil.del(tempDirName);
}
return DocDbResponseJson.ok();
}
private Long getDataCount(DataViewParam param, ExecuteType executeType) {
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(param.getSourceId());
String queryCountSql = dbBaseService.getQueryCountSql(param);
ExecuteResult countResult = this.query(param.getSourceId(), param.getExecuteId(), executeType, queryCountSql);
if (CollectionUtils.isNotEmpty(countResult.getResult()) && MapUtils.isNotEmpty(countResult.getResult().get(0))) {
Map<String, Object> countMap = countResult.getResult().get(0);
Optional<Object> countAny = countMap.values().stream().findAny();
return TypeUtils.castToLong(countAny.orElse(0));
}
return 0L;
}
/**
* 执行数据查询
*

View File

@@ -0,0 +1,134 @@
package com.zyplayer.doc.db.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.data.repository.manage.entity.DbTableRelation;
import com.zyplayer.doc.data.repository.manage.param.TableRelationParam;
import com.zyplayer.doc.data.repository.manage.vo.TableRelationVo;
import com.zyplayer.doc.data.service.manage.DbTableRelationService;
import com.zyplayer.doc.db.controller.vo.TableColumnVo;
import com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto;
import com.zyplayer.doc.db.framework.json.DocDbResponseJson;
import com.zyplayer.doc.db.service.DbBaseFactory;
import com.zyplayer.doc.db.service.DbBaseService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.*;
/**
* 表关系控制器
*
* @author 暮光:城中城
* @since 2021年6月6日
*/
@AuthMan
@RestController
@RequestMapping("/zyplayer-doc-db/table-relation")
public class DbTableRelationController {
private static Logger logger = LoggerFactory.getLogger(DbTableRelationController.class);
@Resource
DbBaseFactory dbBaseFactory;
@Resource
DbTableRelationService dbTableRelationService;
@PostMapping(value = "/update")
public ResponseJson update(TableRelationParam param) {
dbTableRelationService.update(param);
return DocDbResponseJson.ok();
}
@PostMapping(value = "/getRelation")
public ResponseJson getRelation(TableRelationParam param) {
TableRelationVo relationVo = new TableRelationVo();
relationVo.setDbName(param.getDbName());
relationVo.setName(param.getTableName());
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(param.getSourceId());
TableColumnVo tableColumn = dbBaseService.getTableColumnList(param.getSourceId(), param.getDbName(), param.getTableName());
if (CollectionUtils.isNotEmpty(tableColumn.getColumnList())) {
Set<String> drillPath = new HashSet<>();
List<TableRelationVo> childrenRelationList = new LinkedList<>();
for (TableColumnDescDto columnDto : tableColumn.getColumnList()) {
drillPath.add(param.getDbName() + "." + param.getTableName() + "." + columnDto.getName());
TableRelationVo relationVoChildren = new TableRelationVo();
relationVoChildren.setNodeType(1);
relationVoChildren.setDbName(param.getDbName());
relationVoChildren.setTableName(param.getTableName());
relationVoChildren.setName(columnDto.getName());
relationVoChildren.setColumnName(columnDto.getName());
relationVoChildren.setChildren(this.getRelation(param.getSourceId(), param.getDbName(), param.getTableName(), columnDto.getName(), drillPath,1));
childrenRelationList.add(relationVoChildren);
}
relationVo.setChildren(childrenRelationList);
}
return DocDbResponseJson.ok(relationVo);
}
public List<TableRelationVo> getRelation(Long sourceId, String dbName, String tableName, String columnName, Set<String> drillPath, int recursion) {
// 最大支持5层关系链展示
if (recursion >= 5) {
return Collections.emptyList();
}
QueryWrapper<DbTableRelation> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("datasource_id", sourceId);
queryWrapper.and(wrapper -> wrapper.or(or -> or.eq("start_db_name", dbName)
.eq("start_table_name", tableName)
.eq("start_column_name", columnName)
).or(or -> or.eq("end_db_name", dbName)
.eq("end_table_name", tableName)
.eq("end_column_name", columnName)
));
List<TableRelationVo> resultRelationList = new LinkedList<>();
List<DbTableRelation> relationList = dbTableRelationService.list(queryWrapper);
if (CollectionUtils.isEmpty(relationList)) {
return resultRelationList;
}
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(sourceId);
for (DbTableRelation tableRelation : relationList) {
String endDbName = tableRelation.getStartDbName();
String endTableName = tableRelation.getStartTableName();
String endColumnName = tableRelation.getStartColumnName();
if (Objects.equals(tableRelation.getStartDbName(), dbName)
&& Objects.equals(tableRelation.getStartTableName(), tableName)
&& Objects.equals(tableRelation.getStartColumnName(), columnName)) {
endDbName = tableRelation.getEndDbName();
endTableName = tableRelation.getEndTableName();
endColumnName = tableRelation.getEndColumnName();
}
if (drillPath.contains(endDbName + "." + endTableName + "." + endColumnName)) {
continue;
}
drillPath.add(endDbName + "." + endTableName + "." + endColumnName);
TableRelationVo relationVo = new TableRelationVo();
relationVo.setDbName(endDbName);
relationVo.setTableName(endTableName);
relationVo.setName("表:"+endTableName + "\n列" + endColumnName);
relationVo.setColumnName(endColumnName);
TableColumnVo tableColumn = dbBaseService.getTableColumnList(sourceId, endDbName, endTableName);
if (CollectionUtils.isNotEmpty(tableColumn.getColumnList())) {
List<TableRelationVo> childrenRelationList = new LinkedList<>();
for (TableColumnDescDto columnDto : tableColumn.getColumnList()) {
TableRelationVo relationVoChildren = new TableRelationVo();
relationVoChildren.setNodeType(1);
relationVoChildren.setDbName(endDbName);
relationVoChildren.setTableName(endTableName);
relationVoChildren.setName(columnDto.getName());
relationVoChildren.setColumnName(columnDto.getName());
relationVoChildren.setChildren(this.getRelation(sourceId, endDbName, endTableName, columnDto.getName(), drillPath, recursion + 1));
childrenRelationList.add(relationVoChildren);
}
relationVo.setChildren(childrenRelationList);
}
resultRelationList.add(relationVo);
}
return resultRelationList;
}
}

View File

@@ -17,6 +17,7 @@ public class DataViewParam {
private String conditionColumn;
private Integer dropTableFlag;
private Integer createTableFlag;
private Integer downloadFileType;
public Integer getOffset() {
return ((this.pageNum - 1) * this.pageSize);
@@ -141,4 +142,12 @@ public class DataViewParam {
public void setTableNames(String tableNames) {
this.tableNames = tableNames;
}
public Integer getDownloadFileType() {
return downloadFileType;
}
public void setDownloadFileType(Integer downloadFileType) {
this.downloadFileType = downloadFileType;
}
}

View File

@@ -14,7 +14,7 @@ public class TableColumnDescDto {
@ColumnWidth(15)
@ExcelProperty("是否自增")
private String isidenity;
private String selfIncrement;
@ColumnWidth(20)
@ExcelProperty("类型")
@@ -34,7 +34,7 @@ public class TableColumnDescDto {
@ColumnWidth(10)
@ExcelProperty("主键")
private String ispramary;
private String primaryKey;
@ColumnWidth(80)
@ExcelProperty("注释")
@@ -48,14 +48,6 @@ public class TableColumnDescDto {
this.name = name;
}
public String getIsidenity() {
return isidenity;
}
public void setIsidenity(String isidenity) {
this.isidenity = isidenity;
}
public String getType() {
return type;
}
@@ -80,14 +72,6 @@ public class TableColumnDescDto {
this.length = length;
}
public String getIspramary() {
return ispramary;
}
public void setIspramary(String ispramary) {
this.ispramary = ispramary;
}
public String getDescription() {
return description;
}
@@ -111,4 +95,20 @@ public class TableColumnDescDto {
public void setNumericScale(String numericScale) {
this.numericScale = numericScale;
}
public String getSelfIncrement() {
return selfIncrement;
}
public void setSelfIncrement(String selfIncrement) {
this.selfIncrement = selfIncrement;
}
public String getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(String primaryKey) {
this.primaryKey = primaryKey;
}
}

View File

@@ -55,16 +55,6 @@ public interface BaseMapper {
*/
List<TableColumnDescDto> getTableColumnList(@Param("dbName") String dbName, @Param("tableName") String tableName);
/**
* 获取字段注释
*
* @param tableName 表名
* @return 表字段注释
* @author 暮光:城中城
* @since 2018年8月8日
*/
List<TableColumnDescDto> getTableColumnDescList(@Param("tableName") String tableName);
/**
* 模糊搜索表和字段
*

View File

@@ -2,51 +2,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="TABLE_NAME" property="tableName" jdbcType="VARCHAR" />
<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="NUMERIC_SCALE" property="numericScale" 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>
<resultMap id="TableStatusDtoMap" type="com.zyplayer.doc.db.controller.vo.TableStatusVo">
<result column="Name" property="name"/>
<result column="Engine" property="engine"/>
<result column="Version" property="version"/>
<result column="Row_format" property="rowFormat"/>
<result column="Rows" property="rows"/>
<result column="Avg_row_length" property="avgRowLength"/>
<result column="Data_length" property="dataLength"/>
<result column="Max_data_length" property="maxDataLength"/>
<result column="Index_length" property="indexLength"/>
<result column="Data_free" property="dataFree"/>
<result column="Auto_increment" property="autoIncrement"/>
<result column="Create_time" property="createTime"/>
<result column="Update_time" property="updateTime"/>
<result column="Check_time" property="checkTime"/>
<result column="Collation" property="collation"/>
<result column="Checksum" property="checksum"/>
<result column="Create_options" property="createOptions"/>
<result column="Comment" property="comment"/>
</resultMap>
<select id="getDatabaseList" resultType="com.zyplayer.doc.db.framework.db.dto.DatabaseInfoDto">
select TABLE_SCHEMA dbName
from `information_schema`.tables
<!--排除系统库-->
where TABLE_SCHEMA != 'information_schema'
group by TABLE_SCHEMA
select SCHEMA_NAME dbName from `information_schema`.SCHEMATA
</select>
<select id="getTableDdl" resultType="java.util.Map">
@@ -59,27 +16,35 @@
<if test="dbName != null">where table_schema=#{dbName}</if>
</select>
<select id="getTableColumnList" resultMap="TableColumnDescDtoMap">
SELECT table_name as TABLE_NAME,COLUMN_NAME as NAME,column_comment DESCRIPTION,data_type TYPE,
COALESCE(CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION) as `LENGTH`,NUMERIC_SCALE as NUMERIC_SCALE,
if(COLUMN_KEY='PRI','1','0') as ISPRAMARY,
if(is_nullable='YES','1','0') NULLABLE
<select id="getTableColumnList" resultType="com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto">
SELECT table_name as tableName,COLUMN_NAME as name,column_comment description,data_type type,
COALESCE(CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION) as `length`,NUMERIC_SCALE as numericScale,
if(COLUMN_KEY='PRI','1','0') as primaryKey,
if(is_nullable='YES','1','0') nullable
FROM `INFORMATION_SCHEMA`.Columns
WHERE table_schema=#{dbName}
<if test="tableName != null">and table_name=#{tableName}</if>
ORDER BY ordinal_position
</select>
<select id="getTableStatus" resultMap="TableStatusDtoMap">
show table status from `${dbName}` like #{tableName}
<select id="getTableStatus" resultType="com.zyplayer.doc.db.controller.vo.TableStatusVo">
<!-- show table status from `${dbName}` like #{tableName} -->
select TABLE_NAME as name, ENGINE as engine, VERSION as version, ROW_FORMAT as rowFormat,
TABLE_ROWS as `rows`, AVG_ROW_LENGTH as avgRowLength, DATA_LENGTH as dataLength,
MAX_DATA_LENGTH as maxDataLength, INDEX_LENGTH as indexLength, DATA_FREE as dataFree,
AUTO_INCREMENT as autoIncrement, CREATE_TIME as createTime, UPDATE_TIME as updateTime,
CHECK_TIME as checkTime, TABLE_COLLATION as `collation`, CHECKSUM as checksum,
CREATE_OPTIONS as createOptions, TABLE_COMMENT as comment
from `information_schema`.tables
where table_schema=#{dbName} and table_name=#{tableName}
</select>
<select id="getTableColumnDescList" resultMap="TableColumnDescDtoMap">
<select id="getTableColumnDescList" resultType="com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto">
select 1
</select>
<select id="getTableAndColumnBySearch" resultMap="QueryTableColumnDescDtoMap">
SELECT TABLE_NAME, COLUMN_NAME, column_comment DESCRIPTION
<select id="getTableAndColumnBySearch" resultType="com.zyplayer.doc.db.framework.db.dto.QueryTableColumnDescDto">
SELECT TABLE_NAME as tableName, column_name as columnName, column_comment as description
FROM `INFORMATION_SCHEMA`.Columns
WHERE table_schema=#{dbName} AND (COLUMN_NAME like #{searchText} or column_comment like #{searchText})
</select>

View File

@@ -5,11 +5,11 @@
<resultMap id="TableColumnDescDtoMap" type="com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto">
<result column="TABLE_NAME" property="tableName" jdbcType="VARCHAR"/>
<result column="NAME" property="name" jdbcType="VARCHAR"/>
<result column="ISIDENITY" property="isidenity" jdbcType="VARCHAR"/>
<result column="ISIDENITY" property="selfIncrement" 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="ISPRAMARY" property="primaryKey" jdbcType="VARCHAR"/>
<result column="DESCRIPTION" property="description" jdbcType="VARCHAR"/>
</resultMap>

View File

@@ -4,11 +4,11 @@
<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="ISIDENITY" property="selfIncrement" 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="ISPRAMARY" property="primaryKey" jdbcType="VARCHAR" />
<result column="DESCRIPTION" property="description" jdbcType="VARCHAR" />
</resultMap>
@@ -53,14 +53,6 @@
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

View File

@@ -1,11 +1,26 @@
package com.zyplayer.doc.db.framework.db.mapper.sqlserver;
import com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* sqlserver数据库的mapper持有对象
*
*
* @author 暮光:城中城
* @since 2018年8月8日
*/
public interface SqlServerMapper {
/**
* 获取字段注释
*
* @param tableName 表名
* @return 表字段注释
* @author 暮光:城中城
* @since 2018年8月8日
*/
List<TableColumnDescDto> getTableColumnDescList(@Param("tableName") String tableName);
}

View File

@@ -0,0 +1,14 @@
<?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">
<select id="getTableColumnDescList" resultType="com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto">
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>
</mapper>

View File

@@ -6,6 +6,7 @@ import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import com.zyplayer.doc.core.util.ZyplayerDocVersion;
import com.zyplayer.doc.db.controller.vo.DatabaseExportVo;
import com.zyplayer.doc.db.controller.vo.TableColumnVo;
import com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto;
@@ -47,6 +48,7 @@ public class PoiUtil {
" 数据库 : " + dbName + "\n" +
" 数据库类型 : " + dbType + "\n" +
" 导出时间 : " + DateTime.now().toString() + "\n" +
" 软件版本 : " + ZyplayerDocVersion.version + "\n" +
"*/\n\n");
for (Map.Entry<String, String> entry : ddlSqlMap.entrySet()) {
ddlSqlSb.append("-- ----------------------------\n")
@@ -145,8 +147,8 @@ public class PoiUtil {
// 写入表格
for (TableColumnDescDto dto : tableColumnDescDtos) {
String nullable = Objects.equals(dto.getNullable(), "1") ? "允许" : "不允许";
dataList.add(Arrays.asList(dto.getName(), dto.getIsidenity(), dto.getType(), nullable, dto.getLength(),
dto.getNumericScale(), dto.getIspramary(), dto.getDescription()));
dataList.add(Arrays.asList(dto.getName(), dto.getSelfIncrement(), dto.getType(), nullable, dto.getLength(),
dto.getNumericScale(), dto.getPrimaryKey(), dto.getDescription()));
}
PoiUtil.createTable(document, dataList);
}

View File

@@ -144,19 +144,6 @@ public abstract class DbBaseService {
return tableColumnVo;
}
/**
* 获取字段注释
*
* @param tableName 表名
* @return 表字段注释
* @author 暮光:城中城
* @since 2018年8月8日
*/
public List<TableColumnDescDto> getTableColumnDescList(Long sourceId, String tableName) {
BaseMapper baseMapper = this.getViewAuthBaseMapper(sourceId);
return baseMapper.getTableColumnDescList(tableName);
}
/**
* 模糊搜索表和字段
*

View File

@@ -52,11 +52,6 @@ public class HiveServiceImpl extends DbBaseService {
return tableDdlVo;
}
@Override
public List<TableColumnDescDto> getTableColumnDescList(Long sourceId, String tableName) {
throw new ConfirmException("不支持的操作");
}
@Override
public List<QueryTableColumnDescDto> getTableAndColumnBySearch(Long sourceId, String dbName, String searchText) {
throw new ConfirmException("不支持的操作");

View File

@@ -3,7 +3,7 @@ package com.zyplayer.doc.db.service;
import com.zyplayer.doc.db.controller.vo.TableColumnVo;
import com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto;
import com.zyplayer.doc.db.framework.db.enums.DatabaseProductEnum;
import com.zyplayer.doc.db.framework.db.mapper.base.BaseMapper;
import com.zyplayer.doc.db.framework.db.mapper.sqlserver.SqlServerMapper;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -22,8 +22,8 @@ public class SqlserverServiceImpl extends DbBaseService {
public TableColumnVo getTableColumnList(Long sourceId, String dbName, String tableName) {
TableColumnVo tableColumnVo = super.getTableColumnList(sourceId, dbName, tableName);
// SQLSERVER 要单独查字段注释
BaseMapper baseMapper = this.getViewAuthBaseMapper(sourceId);
List<TableColumnDescDto> columnDescList = baseMapper.getTableColumnDescList(tableName);
SqlServerMapper sqlServerMapper = databaseRegistrationBean.getBaseMapper(sourceId, SqlServerMapper.class);
List<TableColumnDescDto> columnDescList = sqlServerMapper.getTableColumnDescList(tableName);
Map<String, TableColumnDescDto> columnMap = tableColumnVo.getColumnList().stream().collect(Collectors.toMap(TableColumnDescDto::getName, val -> val));
// 字段注释
for (TableColumnDescDto descDto : columnDescList) {

View File

@@ -1,7 +1,11 @@
package com.zyplayer.doc.db.service.download;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson.JSONObject;
import com.zyplayer.doc.db.controller.param.DataViewParam;
import com.zyplayer.doc.db.controller.vo.TableDdlVo;
@@ -10,10 +14,13 @@ import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteParam;
import com.zyplayer.doc.db.framework.db.mapper.base.SqlExecutor;
import com.zyplayer.doc.db.service.DbBaseFactory;
import com.zyplayer.doc.db.service.DbBaseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.net.URLEncoder;
import java.util.List;
import java.util.Objects;
@@ -25,6 +32,7 @@ import java.util.regex.Pattern;
*/
@Service
public class BaseDownloadService {
private static Logger logger = LoggerFactory.getLogger(BaseDownloadService.class);
@Resource
SqlExecutor sqlExecutor;
@@ -141,10 +149,13 @@ public class BaseDownloadService {
}
resultSb.append(resultData);
});
resultSb.append("]");
resultSb.append("]\n");
return resultSb.toString();
}
/**
* 发送字符串到response
*/
public void sendResponse(HttpServletResponse response, String tableName, String prefix, String dataStr) throws Exception {
String fileNameOrigin = tableName + "." + DateTime.now().toString("yyyyMMddHHmmss");
String fileName = URLEncoder.encode(fileNameOrigin, "UTF-8") + prefix;
@@ -154,6 +165,31 @@ public class BaseDownloadService {
IoUtil.write(response.getOutputStream(), "utf-8", true, dataStr);
}
/**
* 把文件夹压缩为zip后发送
*/
public void sendResponse(HttpServletResponse response, String tableName, String tempDirName) throws Exception {
File zipTempFile = File.createTempFile("zyplayer-doc-" + IdUtil.fastSimpleUUID(), ".zip");
ZipUtil.zip(zipTempFile, CharsetUtil.defaultCharset(), false, FileUtil.file(tempDirName));
String fileNameOrigin = tableName + "." + DateTime.now().toString("yyyyMMddHHmmss");
String fileName = URLEncoder.encode(fileNameOrigin, "UTF-8") + ".zip";
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.setCharacterEncoding("utf-8");
try {
IoUtil.write(response.getOutputStream(), true, FileUtil.readBytes(zipTempFile));
} catch (Exception e) {
logger.error("发送数据流失败", e);
} finally {
// 删除临时文件
try {
zipTempFile.delete();
} catch (Exception e) {
logger.error("删除临时ZIP文件失败", e);
}
}
}
/**
* 是否是数值类型
*

View File

@@ -1 +0,0 @@
#app,.el-container,.el-menu{height:100%}.el-header{background-color:#1d4e89!important}.database-list-tree{background-color:#fafafa}.database-list-tree .el-tree-node>.el-tree-node__children{overflow:unset}.el-tree-node__content .el-icon-more{margin-left:5px;color:#606266;font-size:12px;display:none;padding:2px 5px}.el-tree-node__content:hover .el-icon-more{display:inline-block}.login-container{border-radius:5px;-moz-border-radius:5px;background-clip:padding-box;margin:0 auto;width:350px;padding:35px 35px 15px 35px;background:#fff;border:1px solid #eaeaea;-webkit-box-shadow:0 0 25px #cac6c6;box-shadow:0 0 25px #cac6c6}.title{margin:0 auto 40px auto;text-align:center;color:#505458}.remember{margin:0 0 35px 0}.my-info-vue .box-card{margin:10px}.table-info-vue .el-dialog__body{padding:0 20px 10px}.table-info-vue .el-form-item{margin-bottom:5px}.table-info-vue .edit-table-desc{cursor:pointer;color:#409eff}.table-info-vue .description{cursor:pointer;min-height:23px}.table-info-vue .el-table td,.table-info-vue .el-table th{padding:5px 0}.table-info-vue .status-info-row{padding:8px 0}.table-info-vue .status-info-row .label{width:80px;display:inline-block;text-align:right;color:#606266}.table-database-vue .el-table td,.table-database-vue .el-table th{padding:5px 0}.table-database-vue .label{width:140px;text-align:right}.table-database-vue .el-table th,.table-procedure-edit-vue .el-table td,.table-procedure-vue .el-table td{padding:5px 0}body,html{margin:0;padding:0;height:100%}.header-right-user-name{color:#fff;padding-right:5px}.el-menu-vertical{border-right:0}.el-menu-vertical,.el-menu-vertical .el-menu{background:#fafafa}.el-header{background-color:#409eff;color:#333;line-height:40px;text-align:right;height:40px!important}.data-transfer-vue .el-button+.el-button{margin-left:4px}.data-executor-vue .ace-monokai .ace_print-margin{display:none}.data-executor-vue .el-card__body{padding:10px}.data-executor-vue .el-table td,.el-table th{padding:6px 0}.data-executor-vue .execute-result-table .el-input__inner{height:25px;line-height:25px;padding:0 5px}.data-executor-vue .execute-result-table .el-textarea__inner{height:27px;min-height:27px;line-height:25px;padding:0 5px;resize:none}.data-executor-vue .execute-use-time{font-size:12px;margin-right:10px}.data-executor-vue-out .el-tabs__nav-scroll{padding-left:20px}.data-executor-vue-out .el-button+.el-button{margin-left:0}.data-executor-vue-out .el-table__body-wrapper{height:calc(100vh - 180px);overflow-y:auto}

View File

@@ -0,0 +1 @@
#app,.el-container,.el-menu{height:100%}.el-header{background-color:#1d4e89!important}.database-list-tree{background-color:#fafafa}.database-list-tree .el-tree-node>.el-tree-node__children{overflow:unset}.el-tree-node__content .el-icon-more{margin-left:5px;color:#606266;font-size:12px;display:none;padding:2px 5px}.el-tree-node__content:hover .el-icon-more{display:inline-block}.login-container{border-radius:5px;-moz-border-radius:5px;background-clip:padding-box;margin:0 auto;width:350px;padding:35px 35px 15px 35px;background:#fff;border:1px solid #eaeaea;-webkit-box-shadow:0 0 25px #cac6c6;box-shadow:0 0 25px #cac6c6}.title{margin:0 auto 40px auto;text-align:center;color:#505458}.remember{margin:0 0 35px 0}.my-info-vue .box-card{margin:10px}.table-info-vue{padding:0 20px}.table-info-vue .el-dialog__body{padding:0 20px 10px}.table-info-vue .el-form-item{margin-bottom:5px}.table-info-vue .edit-table-desc{cursor:pointer;color:#409eff}.table-info-vue .description{cursor:pointer;min-height:23px}.table-info-vue .el-table td,.table-info-vue .el-table th{padding:5px 0}.table-info-vue .status-info-row{padding:8px 0}.table-info-vue .status-info-row .label{width:80px;display:inline-block;text-align:right;color:#606266}.table-database-vue .el-table td,.table-database-vue .el-table th{padding:5px 0}.table-database-vue .label{width:140px;text-align:right}.table-database-vue .el-table th,.table-procedure-edit-vue .el-table td,.table-procedure-vue .el-table td{padding:5px 0}body,html{margin:0;padding:0;height:100%}.header-right-user-name{color:#fff;padding-right:5px}.el-menu-vertical{border-right:0}.el-menu-vertical,.el-menu-vertical .el-menu{background:#fafafa}.el-header{background-color:#409eff;color:#333;line-height:40px;text-align:right;height:40px!important}.data-executor-vue .ace-monokai .ace_print-margin{display:none}.data-executor-vue .el-card__body{padding:10px}.data-executor-vue .el-table td,.el-table th{padding:6px 0}.data-executor-vue .execute-result-table .el-input__inner{height:25px;line-height:25px;padding:0 5px}.data-executor-vue .execute-result-table .el-textarea__inner{height:27px;min-height:27px;line-height:25px;padding:0 5px;resize:none}.data-executor-vue .execute-use-time{font-size:12px;margin-right:10px}.data-executor-vue-out .el-tabs__nav-scroll{padding-left:20px}.data-executor-vue-out .el-button+.el-button{margin-left:0}.data-executor-vue-out .el-table__body-wrapper{height:calc(100vh - 180px);overflow-y:auto}.data-transfer-vue .el-button+.el-button{margin-left:4px}

View File

@@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon-db.png><title>数据库文档管理</title><link href=css/app.b6b9fe42.css rel=preload as=style><link href=css/chunk-vendors.8924efc6.css rel=preload as=style><link href=js/app.3a1822c4.js rel=preload as=script><link href=js/chunk-vendors.d40f789d.js rel=preload as=script><link href=css/chunk-vendors.8924efc6.css rel=stylesheet><link href=css/app.b6b9fe42.css rel=stylesheet></head><body><noscript><strong>We're sorry but zyplayer-db-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.d40f789d.js></script><script src=js/app.3a1822c4.js></script></body></html>
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon-db.png><title>数据库文档管理</title><link href=css/app.f232fb4e.css rel=preload as=style><link href=css/chunk-vendors.8924efc6.css rel=preload as=style><link href=js/app.a0ea103c.js rel=preload as=script><link href=js/chunk-vendors.96aa31ea.js rel=preload as=script><link href=css/chunk-vendors.8924efc6.css rel=stylesheet><link href=css/app.f232fb4e.css rel=stylesheet></head><body><noscript><strong>We're sorry but zyplayer-db-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.96aa31ea.js></script><script src=js/app.a0ea103c.js></script></body></html>

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

View File

@@ -1,6 +1,8 @@
package com.zyplayer.doc.manage.framework.interceptor;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.server.HttpServerRequest;
import com.zyplayer.doc.core.util.ThreadLocalUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,7 +31,7 @@ public class RequestInfoInterceptor implements HandlerInterceptor {
Long startTime = startTimeThreadLocal.get();
startTime = Optional.ofNullable(startTime).orElse(System.currentTimeMillis());
long totalTime = System.currentTimeMillis() - startTime;// 结束时间
String clientIP = HttpUtil.getClientIP(request);
String clientIP = ServletUtil.getClientIP(request);
logger.info("IP{},总耗时:{}msURI{}", clientIP, totalTime, request.getRequestURI());
ThreadLocalUtil.clean();
startTimeThreadLocal.remove();

View File

@@ -55,7 +55,10 @@ zyplayer:
git-remote-username:
# git远程仓库登录密码
git-remote-password:
# ------swagger相关配置------
# ------数据库相关配置------
db:
# 最大允许导出的行数,设置的过大有可能会导致内存溢出
download-max-row: 100000
swagger:
proxy-request:
# 允许代理请求的域名,正则表达式,多个使用 ; 分割,必须设置,防止通过代理接口访问到内部资源,实在觉得没必要可设置为:.+

View File

@@ -494,5 +494,21 @@ CREATE TABLE `db_proc_log` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='';
DROP TABLE IF EXISTS `db_table_relation`;
CREATE TABLE `db_table_relation` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`datasource_id` bigint(20) DEFAULT NULL COMMENT 'ID',
`start_db_name` varchar(100) DEFAULT NULL COMMENT '',
`start_table_name` varchar(100) DEFAULT NULL COMMENT '',
`start_column_name` varchar(100) DEFAULT NULL COMMENT '',
`end_db_name` varchar(100) DEFAULT NULL COMMENT '',
`end_table_name` varchar(100) DEFAULT NULL COMMENT '',
`end_column_name` varchar(100) DEFAULT NULL COMMENT '',
`create_user_id` bigint(20) DEFAULT NULL COMMENT 'ID',
`create_user_name` varchar(20) DEFAULT NULL COMMENT '',
`create_time` datetime DEFAULT NULL COMMENT '',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='';
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -14,7 +14,7 @@
<template slot-scope="scope">{{scope.row.nullable ? '允许' : '不允许'}}</template>
</el-table-column>
<el-table-column label="主键" width="50">
<template slot-scope="scope">{{scope.row.ispramary ? '是' : '否'}}</template>
<template slot-scope="scope">{{scope.row.primaryKey ? '是' : '否'}}</template>
</el-table-column>
<el-table-column label="注释">
<template slot-scope="scope">

View File

@@ -1902,7 +1902,7 @@
},
"asn1.js": {
"version": "4.10.1",
"resolved": "http://registry.npm.taobao.org/asn1.js/download/asn1.js-4.10.1.tgz",
"resolved": "https://registry.npm.taobao.org/asn1.js/download/asn1.js-4.10.1.tgz",
"integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=",
"dev": true,
"requires": {
@@ -1923,7 +1923,7 @@
"dependencies": {
"inherits": {
"version": "2.0.1",
"resolved": "http://registry.npm.taobao.org/inherits/download/inherits-2.0.1.tgz",
"resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finherits%2Fdownload%2Finherits-2.0.1.tgz",
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
"dev": true
},
@@ -2065,7 +2065,7 @@
},
"babel-helper-vue-jsx-merge-props": {
"version": "2.0.3",
"resolved": "http://registry.npm.taobao.org/babel-helper-vue-jsx-merge-props/download/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
"resolved": "https://registry.npm.taobao.org/babel-helper-vue-jsx-merge-props/download/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
"integrity": "sha1-Iq69OzOQIyjlEyk6jkmSs4T58bY="
},
"babel-loader": {
@@ -2104,7 +2104,7 @@
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "http://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz",
"resolved": "https://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
"core-js": "^2.4.0",
@@ -2237,7 +2237,7 @@
},
"bn.js": {
"version": "4.11.8",
"resolved": "http://registry.npm.taobao.org/bn.js/download/bn.js-4.11.8.tgz",
"resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.8.tgz",
"integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=",
"dev": true
},
@@ -3010,7 +3010,7 @@
},
"color-convert": {
"version": "1.9.3",
"resolved": "http://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz",
"resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcolor-convert%2Fdownload%2Fcolor-convert-1.9.3.tgz",
"integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=",
"dev": true,
"requires": {
@@ -3662,7 +3662,7 @@
},
"deepmerge": {
"version": "1.5.2",
"resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz",
"resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz?cache=0&sync_timestamp=1572279812893&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdeepmerge%2Fdownload%2Fdeepmerge-1.5.2.tgz",
"integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M="
},
"default-gateway": {
@@ -4017,19 +4017,19 @@
},
"domain-browser": {
"version": "1.2.0",
"resolved": "http://registry.npm.taobao.org/domain-browser/download/domain-browser-1.2.0.tgz",
"resolved": "https://registry.npm.taobao.org/domain-browser/download/domain-browser-1.2.0.tgz?cache=0&sync_timestamp=1574051269386&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomain-browser%2Fdownload%2Fdomain-browser-1.2.0.tgz",
"integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=",
"dev": true
},
"domelementtype": {
"version": "1.3.1",
"resolved": "http://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.1.tgz",
"resolved": "https://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomelementtype%2Fdownload%2Fdomelementtype-1.3.1.tgz",
"integrity": "sha1-0EjESzew0Qp/Kj1f7j9DM9eQSB8=",
"dev": true
},
"domhandler": {
"version": "2.4.2",
"resolved": "http://registry.npm.taobao.org/domhandler/download/domhandler-2.4.2.tgz",
"resolved": "https://registry.npm.taobao.org/domhandler/download/domhandler-2.4.2.tgz",
"integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=",
"dev": true,
"requires": {
@@ -4168,7 +4168,7 @@
},
"emojis-list": {
"version": "2.1.0",
"resolved": "http://registry.npm.taobao.org/emojis-list/download/emojis-list-2.1.0.tgz",
"resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-2.1.0.tgz",
"integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
"dev": true
},
@@ -4656,7 +4656,7 @@
},
"faye-websocket": {
"version": "0.10.0",
"resolved": "http://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.10.0.tgz",
"resolved": "https://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.10.0.tgz",
"integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
"dev": true,
"requires": {
@@ -5521,7 +5521,7 @@
},
"glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz",
"resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1569136652060&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz",
"integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
"dev": true,
"requires": {
@@ -5625,7 +5625,7 @@
},
"has-ansi": {
"version": "2.0.0",
"resolved": "http://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz",
"resolved": "https://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz",
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"dev": true,
"requires": {
@@ -5696,7 +5696,7 @@
},
"hash-sum": {
"version": "1.0.2",
"resolved": "http://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz",
"resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz",
"integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
"dev": true
},
@@ -5858,7 +5858,7 @@
},
"htmlparser2": {
"version": "3.10.1",
"resolved": "http://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz",
"resolved": "https://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz",
"integrity": "sha1-vWedw/WYl7ajS7EHSchVu1OpOS8=",
"dev": true,
"requires": {
@@ -5935,7 +5935,7 @@
},
"http-proxy-middleware": {
"version": "0.19.1",
"resolved": "http://registry.npm.taobao.org/http-proxy-middleware/download/http-proxy-middleware-0.19.1.tgz",
"resolved": "https://registry.npm.taobao.org/http-proxy-middleware/download/http-proxy-middleware-0.19.1.tgz",
"integrity": "sha1-GDx9xKoUeRUDBkmMIQza+WCApDo=",
"dev": true,
"requires": {
@@ -6144,13 +6144,13 @@
},
"ipaddr.js": {
"version": "1.9.0",
"resolved": "http://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.9.0.tgz",
"resolved": "https://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.9.0.tgz",
"integrity": "sha1-N9905DCg5HVQ/lSi3v4w2KzZX2U=",
"dev": true
},
"is-absolute-url": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-2.1.0.tgz",
"resolved": "https://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-2.1.0.tgz?cache=0&sync_timestamp=1569736493122&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-absolute-url%2Fdownload%2Fis-absolute-url-2.1.0.tgz",
"integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=",
"dev": true
},
@@ -6197,7 +6197,7 @@
},
"is-buffer": {
"version": "1.1.6",
"resolved": "http://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz",
"resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz?cache=0&sync_timestamp=1569905495687&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-buffer%2Fdownload%2Fis-buffer-1.1.6.tgz",
"integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=",
"dev": true
},
@@ -6422,7 +6422,7 @@
},
"isarray": {
"version": "1.0.0",
"resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
"resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz?cache=0&sync_timestamp=1562592096220&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fisarray%2Fdownload%2Fisarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
},
@@ -7038,7 +7038,7 @@
},
"memory-fs": {
"version": "0.4.1",
"resolved": "http://registry.npm.taobao.org/memory-fs/download/memory-fs-0.4.1.tgz",
"resolved": "https://registry.npm.taobao.org/memory-fs/download/memory-fs-0.4.1.tgz?cache=0&sync_timestamp=1570537491040&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmemory-fs%2Fdownload%2Fmemory-fs-0.4.1.tgz",
"integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
"dev": true,
"requires": {
@@ -7518,7 +7518,7 @@
},
"normalize-wheel": {
"version": "1.0.1",
"resolved": "https://registry.npm.taobao.org/normalize-wheel/download/normalize-wheel-1.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnormalize-wheel%2Fdownload%2Fnormalize-wheel-1.0.1.tgz",
"resolved": "https://registry.npm.taobao.org/normalize-wheel/download/normalize-wheel-1.0.1.tgz",
"integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
},
"npm-run-path": {
@@ -7792,7 +7792,7 @@
},
"p-limit": {
"version": "1.3.0",
"resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz",
"resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-1.3.0.tgz",
"integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=",
"dev": true,
"requires": {
@@ -7905,7 +7905,7 @@
},
"pascalcase": {
"version": "0.1.1",
"resolved": "http://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz",
"resolved": "https://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz",
"integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
"dev": true
},
@@ -7953,7 +7953,7 @@
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "http://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz",
"resolved": "https://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz?cache=0&sync_timestamp=1574278262588&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-to-regexp%2Fdownload%2Fpath-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
"dev": true
},
@@ -8581,7 +8581,7 @@
},
"postcss-value-parser": {
"version": "3.3.1",
"resolved": "http://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz",
"resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz",
"integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=",
"dev": true
},
@@ -8825,13 +8825,13 @@
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.5.2.tgz",
"resolved": "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz",
"integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=",
"dev": true
},
"query-string": {
"version": "4.3.4",
"resolved": "https://registry.npm.taobao.org/query-string/download/query-string-4.3.4.tgz",
"resolved": "https://registry.npm.taobao.org/query-string/download/query-string-4.3.4.tgz?cache=0&sync_timestamp=1573620418700&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fquery-string%2Fdownload%2Fquery-string-4.3.4.tgz",
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
"dev": true,
"requires": {
@@ -8937,7 +8937,7 @@
},
"readdirp": {
"version": "2.2.1",
"resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz",
"resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz?cache=0&sync_timestamp=1571011714883&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-2.2.1.tgz",
"integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=",
"dev": true,
"requires": {
@@ -9285,12 +9285,12 @@
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz",
"resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1562377642757&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz",
"integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
},
"safe-regex": {
"version": "1.1.0",
"resolved": "http://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz",
"resolved": "https://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz?cache=0&sync_timestamp=1571687334026&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-regex%2Fdownload%2Fsafe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"dev": true,
"requires": {
@@ -9990,7 +9990,7 @@
},
"stream-http": {
"version": "2.8.3",
"resolved": "http://registry.npm.taobao.org/stream-http/download/stream-http-2.8.3.tgz",
"resolved": "https://registry.npm.taobao.org/stream-http/download/stream-http-2.8.3.tgz",
"integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=",
"dev": true,
"requires": {
@@ -10448,7 +10448,7 @@
"dependencies": {
"commander": {
"version": "2.19.0",
"resolved": "https://registry.npm.taobao.org/commander/download/commander-2.19.0.tgz",
"resolved": "https://registry.npm.taobao.org/commander/download/commander-2.19.0.tgz?cache=0&sync_timestamp=1573464045808&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.19.0.tgz",
"integrity": "sha1-9hmKqE5bg8RgVLlN3tv+1e6f8So=",
"dev": true
},
@@ -10849,7 +10849,7 @@
},
"wangeditor": {
"version": "3.1.1",
"resolved": "https://registry.npm.taobao.org/wangeditor/download/wangeditor-3.1.1.tgz",
"resolved": "http://registry.npm.taobao.org/wangeditor/download/wangeditor-3.1.1.tgz",
"integrity": "sha1-+9PB1JdpI8nt67hbKdMLNVEq0Dk="
},
"watchpack": {

View File

@@ -104,6 +104,12 @@ export default {
dataViewQuery: data => {
return request({url: '/zyplayer-doc-db/data-view/query', method: 'post', data: Qs.stringify(data)});
},
updateTableColumnRelation: data => {
return request({url: '/zyplayer-doc-db/table-relation/update', method: 'post', data: Qs.stringify(data)});
},
getTableColumnRelation: data => {
return request({url: '/zyplayer-doc-db/table-relation/getRelation', method: 'post', data: Qs.stringify(data)});
},
systemUpgradeInfo: data => {
return request({url: '/system/info/upgrade', method: 'post', data: Qs.stringify(data)});
},

View File

@@ -28,11 +28,11 @@
<span slot="title">库表导出选项</span>
<el-form label-width="100px">
<el-form-item label="导出类型:">
<el-select v-model="exportType" @change="exportTypeChange" filterable placeholder="请选择导出类型" style="width: 430px;">
<el-option label="表结构文档" :value="1"></el-option>
<el-option label="建表语句SQL" :value="2"></el-option>
<el-option label="表数据" :value="3"></el-option>
</el-select>
<el-radio-group v-model="exportType" @change="exportTypeChange">
<el-radio :label="3">表数据</el-radio>
<el-radio :label="1">表结构文档</el-radio>
<el-radio :label="2">建表语句SQL</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="导出格式:" v-if="exportType == 1">
<el-select v-model="exportFormat" filterable placeholder="请选择导出格式" style="width: 430px;">
@@ -41,22 +41,25 @@
<el-option label="Word格式" :value="3"></el-option>
</el-select>
</el-form-item>
<el-form-item label="导出格式:" v-else-if="exportType == 2">
<el-select v-model="exportFormat" filterable placeholder="请选择导出格式" style="width: 430px;">
<el-option label="SQL格式" :value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item label="导出格式:" v-else-if="exportType == 3">
<el-select v-model="downloadType" filterable placeholder="请选择导出类型" style="width: 430px;">
<el-option label="SQL Inserts" value="insert"></el-option>
<el-option label="SQL Updates" value="update"></el-option>
<el-option label="JSON" value="json"></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据表:" v-if="exportType == 3 && downloadType === 'insert'">
<el-checkbox :true-label="1" :false-label="0" v-model="dropTableFlag" @change="dropTableFlagChange">删除表{{dropTableFlag==1?'!!':''}}</el-checkbox>
<el-checkbox :true-label="1" :false-label="0" v-model="createTableFlag" @change="createTableFlagChange">创建表</el-checkbox>
</el-form-item>
<template v-else-if="exportType == 3">
<el-form-item label="导出格式:">
<el-select v-model="downloadType" filterable placeholder="请选择导出类型" style="width: 430px;">
<el-option label="SQL Inserts" value="insert"></el-option>
<el-option label="SQL Updates" value="update"></el-option>
<el-option label="JSON" value="json"></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据表:" v-if="downloadType === 'insert'">
<el-checkbox :true-label="1" :false-label="0" v-model="dropTableFlag" @change="dropTableFlagChange">删除表{{dropTableFlag==1?'!!':''}}</el-checkbox>
<el-checkbox :true-label="1" :false-label="0" v-model="createTableFlag" @change="createTableFlagChange">创建表</el-checkbox>
</el-form-item>
<el-form-item label="导出方式:">
<el-radio-group v-model="downloadFileType">
<el-radio :label="1">单个文件</el-radio>
<el-radio :label="2">zip压缩文件</el-radio>
</el-radio-group>
</el-form-item>
</template>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="exportTypeChoiceVisible = false"> </el-button>
@@ -78,8 +81,9 @@
choiceDatasourceId: "",
choiceDatabase: "",
choiceTable: "",
exportType: 1,
exportType: 3,
exportFormat: 1,
downloadFileType: 1,
exportTypeChoiceVisible: false,
// 页面展示相关
nowDatasourceShow: {},
@@ -136,6 +140,7 @@
downloadType: this.downloadType,
dropTableFlag: this.dropTableFlag,
createTableFlag: this.createTableFlag,
downloadFileType: this.downloadFileType,
tableNames: tableNames,
};
if (this.exportType == 3) {

View File

@@ -4,12 +4,12 @@
<el-tab-pane label="表字段" name="columns">
<div v-loading="columnListLoading">
<div style="text-align: right; margin-bottom: 10px;">
<el-button size="small" @click="showCreateTableDdl" style="margin-left: 10px;" icon="el-icon-magic-stick">DDL</el-button>
<el-button size="small" plain type="primary" @click="showCreateTableDdl" style="margin-left: 10px;" icon="el-icon-magic-stick">DDL</el-button>
</div>
<el-table :data="columnList" stripe border style="width: 100%; margin-bottom: 5px;">
<el-table-column prop="name" label="字段名" width="220"></el-table-column>
<el-table-column label="自增" width="50">
<template slot-scope="scope">{{scope.row.isidentity ? '是' : '否'}}</template>
<template slot-scope="scope">{{scope.row.selfIncrement ? '是' : '否'}}</template>
</el-table-column>
<el-table-column prop="type" label="类型" width="110"></el-table-column>
<el-table-column prop="length" label="长度" width="110"></el-table-column>
@@ -20,7 +20,7 @@
<template slot-scope="scope">{{scope.row.nullable==1 ? '允许' : '不允许'}}</template>
</el-table-column>
<el-table-column label="主键" width="50">
<template slot-scope="scope">{{scope.row.ispramary==1 ? '是' : '否'}}</template>
<template slot-scope="scope">{{scope.row.primaryKey==1 ? '是' : '否'}}</template>
</el-table-column>
<el-table-column>
<template slot="header" slot-scope="scope">
@@ -83,25 +83,6 @@
<data-preview ref="dataPreview"></data-preview>
</el-tab-pane>
</el-tabs>
<!-- <el-card style="margin: 10px;">-->
<!-- <div slot="header" class="clearfix">-->
<!-- 表信息-->
<!-- <span style="float: right;margin-top: -5px;">-->
<!-- <el-button class="search-submit" size="small" type="primary" icon="el-icon-search" @click="previewTableData">查看表数据</el-button>-->
<!-- </span>-->
<!-- </div>-->
<!-- </el-card>-->
<!-- <el-card style="margin: 10px;">-->
<!-- <div slot="header" class="clearfix">-->
<!-- 字段信息-->
<!-- <el-tooltip effect="dark" content="点击注释列可编辑字段注释" placement="top">-->
<!-- <i class="el-icon-info" style="color: #999;"></i>-->
<!-- </el-tooltip>-->
<!-- <span style="float: right;margin-top: -5px;">-->
<!-- <el-button size="small" @click="showCreateTableDdl">DDL</el-button>-->
<!-- </span>-->
<!-- </div>-->
<!-- </el-card>-->
<!--增加数据源弹窗-->
<el-dialog :visible.sync="tableDDLInfoDialogVisible" :footer="null" width="760px">
<div slot="title">
@@ -216,7 +197,7 @@
setTimeout(() => this.tabActiveName = 'columns', 0);
return;
}
let primaryColumn = this.columnList.find(item => item.ispramary == 1) || this.columnList[0];
let primaryColumn = this.columnList.find(item => item.primaryKey == 1) || this.columnList[0];
this.$refs.dataPreview.init({
sourceId: this.vueQueryParam.sourceId,
dbName: this.vueQueryParam.dbName,

View File

@@ -1,14 +1,25 @@
<template>
<div class="data-executor-vue">
<div id="relationChart" style="width: 100%; height: max(calc(100vh - 160px), 600px);"></div>
<div style="width: max(100%, 1000px); height: calc(100vh - 160px);overflow: auto;">
<div id="relationChart" style="width: 1500px; height: 1000px;"></div>
</div>
<!--选择导出为update的条件列弹窗-->
<el-dialog :visible.sync="choiceRelationColumnVisible" width="500px" title="选择关联的表字段">
<div>
更新条件列
<el-dialog :visible.sync="choiceRelationColumnVisible" width="750px" :title="'选择关联的表字段 '+editNodeInfo.tableName+'.'+editNodeInfo.columnName">
<div v-for="item in editRelationArr" style="margin-top: 10px;">
<el-select v-model="item.dbName" @change="dbNameChangeEvents(item)" filterable placeholder="请选择数据库" style="margin-right: 10px;width: 200px;">
<el-option v-for="db in databaseList" :key="db.dbName" :label="db.dbName" :value="db.dbName"></el-option>
</el-select>
<el-select v-model="item.tableName" @change="tableNameChangeEvents(item)" filterable placeholder="请选择数据表" style="margin-right: 10px;width: 200px;">
<el-option v-for="table in dbTableList[item.dbName]" :key="table.tableName" :label="table.tableName" :value="table.tableName"></el-option>
</el-select>
<el-select v-model="item.columnName" filterable placeholder="请选择表字段" style="margin-right: 10px;width: 200px;">
<el-option v-for="columns in dbTableColumnList[item.dbName+'.'+item.tableName]" :key="columns.name" :label="columns.name" :value="columns.name"></el-option>
</el-select>
<el-button icon="el-icon-delete" circle @click="delTableColumnRelation(item)"></el-button>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="choiceRelationColumnVisible = false"> </el-button>
<el-button type="primary" @click=""> </el-button>
<el-button @click="addTableColumnRelation">添加关联</el-button>
<el-button type="primary" @click="doUpdateTableColumnRelation"> </el-button>
</span>
</el-dialog>
</div>
@@ -26,6 +37,11 @@
relationChart: {},
relationChartData: {},
relationChartOption: {},
editNodeInfo: {},
editRelationArr: [],
databaseList: [],
dbTableList: {},
dbTableColumnList: {},
// 选择复制
choiceRelationColumnVisible: false,
columnListLoading: false,
@@ -66,9 +82,9 @@
},
label: {
backgroundColor: '#fff',
position: 'left',
position: 'right',
verticalAlign: 'middle',
align: 'right'
align: 'left'
},
leaves: {
label: {
@@ -89,41 +105,83 @@
// 使用刚指定的配置项和数据显示图表。
this.relationChart.setOption(this.relationChartOption);
this.relationChart.on('click', (params) => {
console.log(params);
var dataIndex = params.data.index;
var description = params.data.description;
if (!!params.data.columnName) {
if (params.data.nodeType == 1) {
this.editNodeInfo = params.data;
let children = this.editNodeInfo.children || [];
this.editRelationArr = [];
if (children.length <= 0) {
this.editRelationArr.push({dbName: this.pageParam.dbName, tableName: '', columnName: ''});
} else {
children.forEach(item => {
this.editRelationArr.push({dbName: item.dbName, tableName: item.tableName, columnName: item.columnName});
});
}
let dbNameArr = [], tableNameArr = [];
this.editRelationArr.forEach(item => {
if (dbNameArr.indexOf(item.dbName) < 0) {
dbNameArr.push(item.dbName);
this.dbNameChangeEvents(item);
}
if (tableNameArr.indexOf(item.dbName + '.' + item.tableName) < 0) {
tableNameArr.push(item.dbName + '.' + item.tableName);
this.tableNameChangeEvents(item);
}
});
this.choiceRelationColumnVisible = true;
} else {
params.data.collapsed = true;
}
});
this.relationChart.on('contextmenu', function (params) {
console.log(params);
});
datasourceApi.tableColumnList(this.pageParam).then(json => {
this.columnList = json.data.columnList || [];
this.tableInfo = json.data.tableInfo || {};
this.doGetTableColumnRelation();
datasourceApi.databaseList({sourceId: this.pageParam.sourceId}).then(json => {
this.databaseList = json.data || [];
});
},
doGetTableColumnRelation() {
// 先清空,不然直接重新渲染会有连接线清除不掉
this.relationChart.clear();
datasourceApi.getTableColumnRelation(this.pageParam).then(json => {
this.relationChartData = json.data || {};
this.relationChartOption.series[0].data = [json.data || {}];
this.columnListLoading = false;
this.changeTableRelationOption(this.relationChartData, this.columnList);
this.relationChart.setOption(this.relationChartOption);
setTimeout(() => this.relationChart.resize(), 0);
});
},
changeTableRelationOption(data, columnList) {
let childrenArr = [];
for (let i = 0; i < columnList.length; i++) {
let item = columnList[i];
childrenArr.push({
name: item.name,
tableName: item.tableName,
columnName: item.name,
children: [],
collapsed: false,
});
delTableColumnRelation(item) {
this.editRelationArr = this.editRelationArr.filter(re => re !== item);
},
addTableColumnRelation() {
this.editRelationArr.push({dbName: this.pageParam.dbName, tableName: '', columnName: ''});
},
doUpdateTableColumnRelation() {
let param = {
dbName: this.editNodeInfo.dbName,
tableName: this.editNodeInfo.tableName,
columnName: this.editNodeInfo.columnName,
sourceId: this.pageParam.sourceId,
relation: JSON.stringify(this.editRelationArr)
}
data.children = childrenArr;
}
datasourceApi.updateTableColumnRelation(param).then(json => {
this.choiceRelationColumnVisible = false;
this.doGetTableColumnRelation();
});
},
dbNameChangeEvents(item) {
datasourceApi.tableList({sourceId: this.pageParam.sourceId, dbName: item.dbName}).then(json => {
this.$set(this.dbTableList, item.dbName, json.data || []);
});
},
tableNameChangeEvents(item) {
datasourceApi.tableColumnList({
sourceId: this.pageParam.sourceId,
dbName: item.dbName,
tableName: item.tableName
}).then(json => {
this.$set(this.dbTableColumnList, item.dbName + '.' + item.tableName, json.data.columnList || []);
});
},
}
}
</script>