表数据导出支持
This commit is contained in:
@@ -15,8 +15,11 @@ zyplayer-doc是一款在线文档工具,现有swagger 文档、dubbo文档、
|
|||||||
2. 集成了本项目内的各个子模块功能,是各模块的协调管理模块。
|
2. 集成了本项目内的各个子模块功能,是各模块的协调管理模块。
|
||||||
|
|
||||||
### 二、zyplayer-doc-db 数据库文档
|
### 二、zyplayer-doc-db 数据库文档
|
||||||
|
一款在线管理数据库的工具,你可以将所有的数据源统一管理到这里面,团队间的各成员就不必每人在自己电脑上装一个数据库管理软件,
|
||||||
|
然后再添加数据源,修改账号密码也可以统一进行修改,新员工进入后对他关心的数据源进行授权即可查看。
|
||||||
|
|
||||||
1. 支持MySQL、SQLServer、Oracle、PostgreSQL、Hive、Impala数据源。
|
1. 支持MySQL、SQLServer、Oracle、PostgreSQL、Hive、Impala数据源。
|
||||||
2. 支持数据库表、字段文档查看修改,表文档导出、建表语句DDL导出。
|
2. 支持数据库表、字段文档查看修改,表文档导出、建表语句DDL导出、表数据导出。
|
||||||
3. 支持SQL执行、表数据预览、不同数据库之间的数据互导,支持多数据源管理。
|
3. 支持SQL执行、表数据预览、不同数据库之间的数据互导,支持多数据源管理。
|
||||||
4. 支持按人员、按数据源对用户授权,可给用户 库表注释查看、注释修改、SQL执行、函数修改等粒度的授权。
|
4. 支持按人员、按数据源对用户授权,可给用户 库表注释查看、注释修改、SQL执行、函数修改等粒度的授权。
|
||||||
5. 支持库函数和存储过程的增删改查,修改记录查询等。
|
5. 支持库函数和存储过程的增删改查,修改记录查询等。
|
||||||
|
|||||||
@@ -4,12 +4,15 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
import com.alibaba.fastjson.util.TypeUtils;
|
import com.alibaba.fastjson.util.TypeUtils;
|
||||||
import com.zyplayer.doc.core.annotation.AuthMan;
|
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.json.ResponseJson;
|
||||||
import com.zyplayer.doc.core.util.StringUtil;
|
import com.zyplayer.doc.core.util.StringUtil;
|
||||||
import com.zyplayer.doc.data.config.security.DocUserUtil;
|
import com.zyplayer.doc.data.config.security.DocUserUtil;
|
||||||
import com.zyplayer.doc.data.repository.support.consts.DocAuthConst;
|
import com.zyplayer.doc.data.repository.support.consts.DocAuthConst;
|
||||||
import com.zyplayer.doc.db.controller.param.DataViewParam;
|
import com.zyplayer.doc.db.controller.param.DataViewParam;
|
||||||
|
import com.zyplayer.doc.db.controller.vo.TableColumnVo;
|
||||||
import com.zyplayer.doc.db.framework.consts.DbAuthType;
|
import com.zyplayer.doc.db.framework.consts.DbAuthType;
|
||||||
|
import com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto;
|
||||||
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteParam;
|
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteParam;
|
||||||
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteResult;
|
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteResult;
|
||||||
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteType;
|
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteType;
|
||||||
@@ -18,8 +21,10 @@ import com.zyplayer.doc.db.framework.json.DocDbResponseJson;
|
|||||||
import com.zyplayer.doc.db.framework.utils.JSONUtil;
|
import com.zyplayer.doc.db.framework.utils.JSONUtil;
|
||||||
import com.zyplayer.doc.db.service.DbBaseFactory;
|
import com.zyplayer.doc.db.service.DbBaseFactory;
|
||||||
import com.zyplayer.doc.db.service.DbBaseService;
|
import com.zyplayer.doc.db.service.DbBaseService;
|
||||||
|
import com.zyplayer.doc.db.service.download.BaseDownloadService;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.collections.MapUtils;
|
import org.apache.commons.collections.MapUtils;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@@ -27,7 +32,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表数据查看控制器
|
* 表数据查看控制器
|
||||||
@@ -45,30 +53,26 @@ public class DbDataViewController {
|
|||||||
SqlExecutor sqlExecutor;
|
SqlExecutor sqlExecutor;
|
||||||
@Resource
|
@Resource
|
||||||
DbBaseFactory dbBaseFactory;
|
DbBaseFactory dbBaseFactory;
|
||||||
|
@Resource
|
||||||
|
BaseDownloadService baseDownloadService;
|
||||||
|
|
||||||
@PostMapping(value = "/query")
|
@PostMapping(value = "/query")
|
||||||
public ResponseJson execute(DataViewParam dataViewParam) {
|
public ResponseJson query(DataViewParam param) {
|
||||||
boolean manageAuth = DocUserUtil.haveAuth(DocAuthConst.DB_DATASOURCE_MANAGE);
|
|
||||||
boolean select = DocUserUtil.haveCustomAuth(DbAuthType.SELECT.getName(), DocAuthConst.DB + dataViewParam.getSourceId());
|
|
||||||
boolean update = DocUserUtil.haveCustomAuth(DbAuthType.UPDATE.getName(), DocAuthConst.DB + dataViewParam.getSourceId());
|
|
||||||
if (!manageAuth && !select && !update) {
|
|
||||||
return DocDbResponseJson.warn("没有该数据源的执行权限");
|
|
||||||
}
|
|
||||||
// 数据查询
|
// 数据查询
|
||||||
ExecuteType executeType = (manageAuth || update) ? ExecuteType.ALL : ExecuteType.SELECT;
|
ExecuteType executeType = this.getExecuteType(param.getSourceId());
|
||||||
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(dataViewParam.getSourceId());
|
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(param.getSourceId());
|
||||||
String queryPageSql = dbBaseService.getQueryPageSql(dataViewParam);
|
String queryPageSql = dbBaseService.getQueryPageSql(param);
|
||||||
ExecuteResult executeResult = this.query(dataViewParam.getSourceId(), dataViewParam.getExecuteId(), executeType, queryPageSql);
|
ExecuteResult executeResult = this.query(param.getSourceId(), param.getExecuteId(), executeType, queryPageSql);
|
||||||
// 数据组装
|
// 数据组装
|
||||||
List<String> resultList = new LinkedList<>();
|
List<String> resultList = new LinkedList<>();
|
||||||
resultList.add(JSON.toJSONString(executeResult, JSONUtil.serializeConfig, SerializerFeature.WriteMapNullValue));
|
resultList.add(JSON.toJSONString(executeResult, JSONUtil.serializeConfig, SerializerFeature.WriteMapNullValue));
|
||||||
DocDbResponseJson responseJson = DocDbResponseJson.ok(resultList);
|
DocDbResponseJson responseJson = DocDbResponseJson.ok(resultList);
|
||||||
// 计算总条数,第一页才查询总条数
|
// 计算总条数,第一页才查询总条数
|
||||||
if (CollectionUtils.isNotEmpty(executeResult.getResult()) && Objects.equals(dataViewParam.getPageNum(), 1)) {
|
if (CollectionUtils.isNotEmpty(executeResult.getResult()) && Objects.equals(param.getPageNum(), 1)) {
|
||||||
responseJson.setTotal((long) executeResult.getResult().size());
|
responseJson.setTotal((long) executeResult.getResult().size());
|
||||||
if (executeResult.getResult().size() >= dataViewParam.getPageSize()) {
|
if (executeResult.getResult().size() >= param.getPageSize()) {
|
||||||
String queryCountSql = dbBaseService.getQueryCountSql(dataViewParam);
|
String queryCountSql = dbBaseService.getQueryCountSql(param);
|
||||||
ExecuteResult countResult = this.query(dataViewParam.getSourceId(), dataViewParam.getExecuteId(), executeType, queryCountSql);
|
ExecuteResult countResult = this.query(param.getSourceId(), param.getExecuteId(), executeType, queryCountSql);
|
||||||
if (CollectionUtils.isNotEmpty(countResult.getResult()) && MapUtils.isNotEmpty(countResult.getResult().get(0))) {
|
if (CollectionUtils.isNotEmpty(countResult.getResult()) && MapUtils.isNotEmpty(countResult.getResult().get(0))) {
|
||||||
Map<String, Object> countMap = countResult.getResult().get(0);
|
Map<String, Object> countMap = countResult.getResult().get(0);
|
||||||
Optional<Object> countAny = countMap.values().stream().findAny();
|
Optional<Object> countAny = countMap.values().stream().findAny();
|
||||||
@@ -79,6 +83,80 @@ public class DbDataViewController {
|
|||||||
return responseJson;
|
return responseJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单表数据下载
|
||||||
|
*
|
||||||
|
* @param response
|
||||||
|
* @param param
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping(value = "/download")
|
||||||
|
public ResponseJson download(HttpServletResponse response, DataViewParam param) {
|
||||||
|
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(param.getSourceId());
|
||||||
|
// 获取列信息等
|
||||||
|
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());
|
||||||
|
Set<String> retainColumnSet = StringUtils.isBlank(param.getRetainColumn()) ? Collections.emptySet() : Stream.of(param.getRetainColumn().split(",")).collect(Collectors.toSet());
|
||||||
|
List<TableColumnDescDto> columnList = tableColumnVo.getColumnList().stream().filter(item -> retainColumnSet.isEmpty() || retainColumnSet.contains(item.getName())).collect(Collectors.toList());
|
||||||
|
// 数据查询
|
||||||
|
String queryAllSql = dbBaseService.getQueryAllSql(param);
|
||||||
|
ExecuteParam executeParam = new ExecuteParam();
|
||||||
|
executeParam.setDatasourceId(param.getSourceId());
|
||||||
|
executeParam.setExecuteId(param.getExecuteId());
|
||||||
|
executeParam.setExecuteType(this.getExecuteType(param.getSourceId()));
|
||||||
|
executeParam.setSql(queryAllSql);
|
||||||
|
// 最大支持10w行数据,总得有个上限
|
||||||
|
executeParam.setMaxRows(100000);
|
||||||
|
try {
|
||||||
|
dbBaseService.downloadSingleTableData(response, param, executeParam, columnList, conditionSet);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return DocDbResponseJson.error("导出失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
return DocDbResponseJson.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多表下载
|
||||||
|
*
|
||||||
|
* @param response
|
||||||
|
* @param param
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping(value = "/downloadMultiple")
|
||||||
|
public ResponseJson downloadMultiple(HttpServletResponse response, DataViewParam param) {
|
||||||
|
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(param.getSourceId());
|
||||||
|
if (StringUtils.isBlank(param.getTableName())) {
|
||||||
|
return DocDbResponseJson.warn("请选择导出的表");
|
||||||
|
}
|
||||||
|
StringBuilder resultSb = new StringBuilder();
|
||||||
|
String[] tableNameArr = param.getTableName().split(",");
|
||||||
|
try {
|
||||||
|
for (String tabName : tableNameArr) {
|
||||||
|
// 获取列信息等
|
||||||
|
TableColumnVo tableColumnVo = dbBaseService.getTableColumnList(param.getSourceId(), param.getDbName(), tabName);
|
||||||
|
Set<String> conditionSet = StringUtils.isBlank(param.getConditionColumn()) ? Collections.emptySet() : Stream.of(param.getConditionColumn().split(",")).collect(Collectors.toSet());
|
||||||
|
List<TableColumnDescDto> columnList = tableColumnVo.getColumnList();
|
||||||
|
// 数据查询
|
||||||
|
String queryAllSql = dbBaseService.getQueryAllSql(param);
|
||||||
|
ExecuteParam executeParam = new ExecuteParam();
|
||||||
|
executeParam.setDatasourceId(param.getSourceId());
|
||||||
|
executeParam.setExecuteId(param.getExecuteId());
|
||||||
|
executeParam.setExecuteType(this.getExecuteType(param.getSourceId()));
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
String prefix = Objects.equals(param.getDownloadType(), "json") ? ".json" : ".sql";
|
||||||
|
baseDownloadService.sendResponse(response, param.getTableName(), prefix, resultSb.toString());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return DocDbResponseJson.error("导出失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
return DocDbResponseJson.ok();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行数据查询
|
* 执行数据查询
|
||||||
*
|
*
|
||||||
@@ -102,5 +180,15 @@ public class DbDataViewController {
|
|||||||
return ExecuteResult.error(StringUtil.getException(e), executeSql);
|
return ExecuteResult.error(StringUtil.getException(e), executeSql);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ExecuteType getExecuteType(Long sourceId) {
|
||||||
|
boolean manageAuth = DocUserUtil.haveAuth(DocAuthConst.DB_DATASOURCE_MANAGE);
|
||||||
|
boolean select = DocUserUtil.haveCustomAuth(DbAuthType.SELECT.getName(), DocAuthConst.DB + sourceId);
|
||||||
|
boolean update = DocUserUtil.haveCustomAuth(DbAuthType.UPDATE.getName(), DocAuthConst.DB + sourceId);
|
||||||
|
if (!manageAuth && !select && !update) {
|
||||||
|
throw new ConfirmException("没有该数据源的执行权限");
|
||||||
|
}
|
||||||
|
return (manageAuth || update) ? ExecuteType.ALL : ExecuteType.SELECT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.zyplayer.doc.db.controller.param;
|
||||||
|
|
||||||
|
public class DataDownloadParam {
|
||||||
|
private Long sourceId;
|
||||||
|
private String dbName;
|
||||||
|
private String tableName;
|
||||||
|
private String downloadType;
|
||||||
|
private String conditionColumn;
|
||||||
|
|
||||||
|
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 getDownloadType() {
|
||||||
|
return downloadType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDownloadType(String downloadType) {
|
||||||
|
this.downloadType = downloadType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConditionColumn() {
|
||||||
|
return conditionColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConditionColumn(String conditionColumn) {
|
||||||
|
this.conditionColumn = conditionColumn;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,11 @@ public class DataViewParam {
|
|||||||
private String orderColumn;
|
private String orderColumn;
|
||||||
private String orderType;
|
private String orderType;
|
||||||
private String condition;
|
private String condition;
|
||||||
|
private String downloadType;
|
||||||
|
private String retainColumn;
|
||||||
|
private String conditionColumn;
|
||||||
|
private Integer dropTableFlag;
|
||||||
|
private Integer createTableFlag;
|
||||||
|
|
||||||
public Integer getOffset() {
|
public Integer getOffset() {
|
||||||
return ((this.pageNum - 1) * this.pageSize);
|
return ((this.pageNum - 1) * this.pageSize);
|
||||||
@@ -86,4 +91,44 @@ public class DataViewParam {
|
|||||||
public void setCondition(String condition) {
|
public void setCondition(String condition) {
|
||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDownloadType() {
|
||||||
|
return downloadType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDownloadType(String downloadType) {
|
||||||
|
this.downloadType = downloadType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConditionColumn() {
|
||||||
|
return conditionColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConditionColumn(String conditionColumn) {
|
||||||
|
this.conditionColumn = conditionColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDropTableFlag() {
|
||||||
|
return dropTableFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDropTableFlag(Integer dropTableFlag) {
|
||||||
|
this.dropTableFlag = dropTableFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCreateTableFlag() {
|
||||||
|
return createTableFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateTableFlag(Integer createTableFlag) {
|
||||||
|
this.createTableFlag = createTableFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRetainColumn() {
|
||||||
|
return retainColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRetainColumn(String retainColumn) {
|
||||||
|
this.retainColumn = retainColumn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,16 @@ public class SqlExecutor {
|
|||||||
return this.execute(factoryBean, param, null);
|
return this.execute(factoryBean, param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行sql,返回结果
|
||||||
|
* @author 暮光:城中城
|
||||||
|
* @since 2019年8月18日
|
||||||
|
*/
|
||||||
|
public ExecuteResult execute(ExecuteParam param, ResultHandler handler) {
|
||||||
|
DatabaseFactoryBean factoryBean = databaseRegistrationBean.getOrCreateFactoryById(param.getDatasourceId());
|
||||||
|
return this.execute(factoryBean, param, handler);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行sql,可通过handler回调每一行的结果
|
* 执行sql,可通过handler回调每一行的结果
|
||||||
* @author 暮光:城中城
|
* @author 暮光:城中城
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class PoiUtil {
|
|||||||
.append("-- 表结构:" + entry.getKey() + "\n")
|
.append("-- 表结构:" + entry.getKey() + "\n")
|
||||||
.append("-- ----------------------------\n")
|
.append("-- ----------------------------\n")
|
||||||
.append("DROP TABLE IF EXISTS `" + entry.getKey() + "`;\n")
|
.append("DROP TABLE IF EXISTS `" + entry.getKey() + "`;\n")
|
||||||
.append(entry.getValue()).append(";\n\n");
|
.append(entry.getValue()).append("\n\n");
|
||||||
}
|
}
|
||||||
IoUtil.write(response.getOutputStream(), "utf-8", true, ddlSqlSb.toString());
|
IoUtil.write(response.getOutputStream(), "utf-8", true, ddlSqlSb.toString());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package com.zyplayer.doc.db.service;
|
package com.zyplayer.doc.db.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateTime;
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.zyplayer.doc.core.exception.ConfirmException;
|
import com.zyplayer.doc.core.exception.ConfirmException;
|
||||||
import com.zyplayer.doc.data.config.security.DocUserUtil;
|
import com.zyplayer.doc.data.config.security.DocUserUtil;
|
||||||
import com.zyplayer.doc.data.repository.support.consts.DocAuthConst;
|
import com.zyplayer.doc.data.repository.support.consts.DocAuthConst;
|
||||||
@@ -14,12 +17,16 @@ import com.zyplayer.doc.db.framework.db.bean.DatabaseRegistrationBean;
|
|||||||
import com.zyplayer.doc.db.framework.db.dto.*;
|
import com.zyplayer.doc.db.framework.db.dto.*;
|
||||||
import com.zyplayer.doc.db.framework.db.enums.DatabaseProductEnum;
|
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.base.BaseMapper;
|
||||||
|
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteParam;
|
||||||
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteResult;
|
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteResult;
|
||||||
import com.zyplayer.doc.db.framework.db.mapper.base.SqlExecutor;
|
import com.zyplayer.doc.db.framework.db.mapper.base.SqlExecutor;
|
||||||
|
import com.zyplayer.doc.db.service.download.BaseDownloadService;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -34,6 +41,8 @@ public abstract class DbBaseService {
|
|||||||
@Resource
|
@Resource
|
||||||
SqlExecutor sqlExecutor;
|
SqlExecutor sqlExecutor;
|
||||||
@Resource
|
@Resource
|
||||||
|
BaseDownloadService baseDownloadService;
|
||||||
|
@Resource
|
||||||
DatabaseRegistrationBean databaseRegistrationBean;
|
DatabaseRegistrationBean databaseRegistrationBean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -337,6 +346,23 @@ public abstract class DbBaseService {
|
|||||||
throw new ConfirmException("暂未支持的数据库类型");
|
throw new ConfirmException("暂未支持的数据库类型");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取全量数据查询的SQL
|
||||||
|
*
|
||||||
|
* @return 分页查询的SQL
|
||||||
|
* @author 暮光:城中城
|
||||||
|
* @since 2020年4月24日
|
||||||
|
*/
|
||||||
|
public String getQueryAllSql(DataViewParam dataViewParam) {
|
||||||
|
String queryColumns = StringUtils.defaultIfBlank(dataViewParam.getRetainColumn(), "*");
|
||||||
|
StringBuilder sqlSb = new StringBuilder();
|
||||||
|
sqlSb.append(String.format("select %s from %s.%s", queryColumns, dataViewParam.getDbName(), dataViewParam.getTableName()));
|
||||||
|
if (StringUtils.isNotBlank(dataViewParam.getCondition())) {
|
||||||
|
sqlSb.append(String.format(" where %s", dataViewParam.getCondition()));
|
||||||
|
}
|
||||||
|
return sqlSb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取分页查询的SQL
|
* 获取分页查询的SQL
|
||||||
*
|
*
|
||||||
@@ -372,4 +398,40 @@ public abstract class DbBaseService {
|
|||||||
}
|
}
|
||||||
return sqlSb.toString();
|
return sqlSb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出单表数据
|
||||||
|
*
|
||||||
|
* @author 暮光:城中城
|
||||||
|
* @since 2020年6月5日
|
||||||
|
*/
|
||||||
|
public void downloadSingleTableData(HttpServletResponse response, DataViewParam param, ExecuteParam executeParam, List<TableColumnDescDto> dataCols, Set<String> conditionSet) throws Exception {
|
||||||
|
if (Objects.equals(param.getDownloadType(), "insert")) {
|
||||||
|
String resultStr = baseDownloadService.downloadDataByInsert(param, executeParam, dataCols, conditionSet);
|
||||||
|
baseDownloadService.sendResponse(response, param.getTableName(), ".sql", resultStr);
|
||||||
|
} else if (Objects.equals(param.getDownloadType(), "update")) {
|
||||||
|
String resultStr = baseDownloadService.downloadDataByUpdate(param, executeParam, dataCols, conditionSet);
|
||||||
|
baseDownloadService.sendResponse(response, param.getTableName(), ".sql", resultStr);
|
||||||
|
} else if (Objects.equals(param.getDownloadType(), "json")) {
|
||||||
|
String resultStr = baseDownloadService.downloadDataByJson(param, executeParam, dataCols, conditionSet);
|
||||||
|
baseDownloadService.sendResponse(response, param.getTableName(), ".json", resultStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取表数据
|
||||||
|
*
|
||||||
|
* @author 暮光:城中城
|
||||||
|
* @since 2020年6月5日
|
||||||
|
*/
|
||||||
|
public String getDownloadTableData(DataViewParam param, ExecuteParam executeParam, List<TableColumnDescDto> dataCols, Set<String> conditionSet) throws Exception {
|
||||||
|
if (Objects.equals(param.getDownloadType(), "insert")) {
|
||||||
|
return baseDownloadService.downloadDataByInsert(param, executeParam, dataCols, conditionSet);
|
||||||
|
} else if (Objects.equals(param.getDownloadType(), "update")) {
|
||||||
|
return baseDownloadService.downloadDataByUpdate(param, executeParam, dataCols, conditionSet);
|
||||||
|
} else if (Objects.equals(param.getDownloadType(), "json")) {
|
||||||
|
return baseDownloadService.downloadDataByJson(param, executeParam, dataCols, conditionSet);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class MysqlServiceImpl extends DbBaseService {
|
|||||||
tableDdlVo.setOracle("// TODO 等待大佬来实现转换");
|
tableDdlVo.setOracle("// TODO 等待大佬来实现转换");
|
||||||
// TODO 将建表语句转换为其他数据库的,还不知道怎么做,先这样留着,看有没大佬来实现
|
// TODO 将建表语句转换为其他数据库的,还不知道怎么做,先这样留着,看有没大佬来实现
|
||||||
if (CollectionUtils.isNotEmpty(tableDdlList)) {
|
if (CollectionUtils.isNotEmpty(tableDdlList)) {
|
||||||
tableDdlVo.setMysql(tableDdlList.get(0).get("Create Table"));
|
tableDdlVo.setMysql(tableDdlList.get(0).get("Create Table") + ";");
|
||||||
}
|
}
|
||||||
return tableDdlVo;
|
return tableDdlVo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
package com.zyplayer.doc.db.service.download;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateTime;
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.zyplayer.doc.db.controller.param.DataViewParam;
|
||||||
|
import com.zyplayer.doc.db.controller.vo.TableDdlVo;
|
||||||
|
import com.zyplayer.doc.db.framework.db.dto.TableColumnDescDto;
|
||||||
|
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.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础的数据导出服务类,按照MySQL规范写的,不满足的可新增类来实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class BaseDownloadService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
SqlExecutor sqlExecutor;
|
||||||
|
@Resource
|
||||||
|
DbBaseFactory dbBaseFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出数据为insert语句格式
|
||||||
|
*
|
||||||
|
* @author 暮光:城中城
|
||||||
|
* @since 2020年6月5日
|
||||||
|
*/
|
||||||
|
public String downloadDataByInsert(DataViewParam param, ExecuteParam executeParam, List<TableColumnDescDto> dataCols, Set<String> conditionSet) throws Exception {
|
||||||
|
String dbTableName = String.format("`%s`.`%s`", param.getDbName(), param.getTableName());
|
||||||
|
StringBuilder resultSb = new StringBuilder();
|
||||||
|
if (Objects.equals(param.getCreateTableFlag(), 1)) {
|
||||||
|
resultSb.append("-- 导出表 ").append(dbTableName).append(" 结构\n");
|
||||||
|
if (Objects.equals(param.getDropTableFlag(), 1)) {
|
||||||
|
resultSb.append("DROP TABLE IF EXISTS ").append(dbTableName).append(";\n");
|
||||||
|
}
|
||||||
|
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(param.getSourceId());
|
||||||
|
TableDdlVo tableDdlVo = dbBaseService.getTableDdl(param.getSourceId(), param.getDbName(), param.getTableName());
|
||||||
|
resultSb.append(tableDdlVo.getTableDDLByType()).append("\n\n");
|
||||||
|
}
|
||||||
|
resultSb.append("-- 导出表 ").append(dbTableName).append(" 数据\n");
|
||||||
|
Pattern pattern = Pattern.compile("\t|\r\n|\r|\n|\\s+");
|
||||||
|
String executeSql = pattern.matcher(executeParam.getSql()).replaceAll(" ");
|
||||||
|
resultSb.append("-- 导出查询SQL:").append(executeSql).append(";\n");
|
||||||
|
// 执行数据查询操作
|
||||||
|
sqlExecutor.execute(executeParam, item -> {
|
||||||
|
StringBuilder names = new StringBuilder();
|
||||||
|
for (TableColumnDescDto dataCol : dataCols) {
|
||||||
|
if (names.length() > 0) names.append(", ");
|
||||||
|
names.append(dataCol.getName());
|
||||||
|
}
|
||||||
|
StringBuilder values = new StringBuilder();
|
||||||
|
for (TableColumnDescDto dataCol : dataCols) {
|
||||||
|
if (values.length() > 0) values.append(", ");
|
||||||
|
Object val = item.get(dataCol.getName());
|
||||||
|
if (this.isNumber(dataCol.getType())) {
|
||||||
|
values.append(val);
|
||||||
|
} else {
|
||||||
|
val = (val == null) ? "" : val;
|
||||||
|
val = val.toString().replaceAll("'", "''");
|
||||||
|
values.append("'").append(val).append("'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String resultData = "insert into " + dbTableName + " (" + names + ") values (" + values + ");\n";
|
||||||
|
resultSb.append(resultData);
|
||||||
|
});
|
||||||
|
return resultSb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出数据为update语句格式
|
||||||
|
*
|
||||||
|
* @author 暮光:城中城
|
||||||
|
* @since 2020年6月5日
|
||||||
|
*/
|
||||||
|
public String downloadDataByUpdate(DataViewParam param, ExecuteParam executeParam, List<TableColumnDescDto> dataCols, Set<String> conditionSet) throws Exception {
|
||||||
|
String dbTableName = String.format("`%s`.`%s`", param.getDbName(), param.getTableName());
|
||||||
|
StringBuilder resultSb = new StringBuilder();
|
||||||
|
Pattern pattern = Pattern.compile("\t|\r\n|\r|\n|\\s+");
|
||||||
|
String executeSql = pattern.matcher(executeParam.getSql()).replaceAll(" ");
|
||||||
|
resultSb.append("-- 导出查询SQL:").append(executeSql).append(";\n");
|
||||||
|
// 执行数据查询操作
|
||||||
|
sqlExecutor.execute(executeParam, item -> {
|
||||||
|
StringBuilder values = new StringBuilder();
|
||||||
|
StringBuilder where = new StringBuilder();
|
||||||
|
for (TableColumnDescDto dataCol : dataCols) {
|
||||||
|
if (values.length() > 0) values.append(", ");
|
||||||
|
values.append(dataCol.getName()).append("=");
|
||||||
|
Object val = item.get(dataCol.getName());
|
||||||
|
if (this.isNumber(dataCol.getType())) {
|
||||||
|
values.append(val);
|
||||||
|
if (conditionSet.contains(dataCol.getName())) {
|
||||||
|
if (where.length() > 0) where.append(" and ");
|
||||||
|
where.append(dataCol.getName()).append(" = ").append(val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val = (val == null) ? "" : val;
|
||||||
|
val = val.toString().replaceAll("'", "''");
|
||||||
|
values.append("'").append(val).append("'");
|
||||||
|
if (conditionSet.contains(dataCol.getName())) {
|
||||||
|
if (where.length() > 0) where.append(" and ");
|
||||||
|
where.append(dataCol.getName()).append(" = ").append("'").append(val).append("'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (where.length() > 0) where.insert(0, " where ");
|
||||||
|
String resultData = "update " + dbTableName + " set " + values + where + ";\n";
|
||||||
|
resultSb.append(resultData);
|
||||||
|
});
|
||||||
|
return resultSb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出数据为json格式
|
||||||
|
*
|
||||||
|
* @author 暮光:城中城
|
||||||
|
* @since 2020年6月5日
|
||||||
|
*/
|
||||||
|
public String downloadDataByJson(DataViewParam param, ExecuteParam executeParam, List<TableColumnDescDto> dataCols, Set<String> conditionSet) throws Exception {
|
||||||
|
StringBuilder resultSb = new StringBuilder();
|
||||||
|
resultSb.append("[");
|
||||||
|
sqlExecutor.execute(executeParam, item -> {
|
||||||
|
JSONObject result = new JSONObject();
|
||||||
|
for (TableColumnDescDto dataCol : dataCols) {
|
||||||
|
result.put(dataCol.getName(), item.get(dataCol.getName()));
|
||||||
|
}
|
||||||
|
String resultData = result.toJSONString();
|
||||||
|
if (resultSb.length() > 1) {
|
||||||
|
resultSb.append(",");
|
||||||
|
}
|
||||||
|
resultSb.append(resultData);
|
||||||
|
});
|
||||||
|
resultSb.append("]");
|
||||||
|
return resultSb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
response.setContentType("application/octet-stream");
|
||||||
|
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
IoUtil.write(response.getOutputStream(), "utf-8", true, dataStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是数值类型
|
||||||
|
*
|
||||||
|
* @param type 类型
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public boolean isNumber(String type) {
|
||||||
|
return type.contains("int")
|
||||||
|
|| type.contains("bit")
|
||||||
|
|| type.contains("float")
|
||||||
|
|| type.contains("double")
|
||||||
|
|| type.contains("decimal")
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.168eac24.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.168eac24.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.b6b9fe42.css rel=preload as=style><link href=css/chunk-vendors.8924efc6.css rel=preload as=style><link href=js/app.fca745a8.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.fca745a8.js></script></body></html>
|
||||||
File diff suppressed because one or more lines are too long
@@ -3,112 +3,51 @@ package com.zyplayer.doc.manage.framework.exception;
|
|||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.zyplayer.doc.core.exception.ConfirmException;
|
import com.zyplayer.doc.core.exception.ConfirmException;
|
||||||
import com.zyplayer.doc.core.json.DocResponseJson;
|
import com.zyplayer.doc.core.json.DocResponseJson;
|
||||||
import com.zyplayer.doc.core.json.ResponseJson;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.method.HandlerMethod;
|
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
|
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局异常处理器
|
* 全局异常处理器
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class GlobalHandlerExceptionResolver extends SimpleMappingExceptionResolver {
|
public class GlobalHandlerExceptionResolver extends SimpleMappingExceptionResolver {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalHandlerExceptionResolver.class);
|
private static final Logger logger = LoggerFactory.getLogger(GlobalHandlerExceptionResolver.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||||
LOGGER.error("---自定义异常处理---", ex);
|
response.setCharacterEncoding("UTF-8");
|
||||||
request.setAttribute("throwable", ex);
|
response.setStatus(HttpStatus.OK.value());
|
||||||
ModelAndView mv = new ModelAndView();
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
response.setStatus(HttpStatus.OK.value());// 设置状态码
|
|
||||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);// 设置ContentType
|
|
||||||
response.setCharacterEncoding("UTF-8");// 避免乱码
|
|
||||||
response.setHeader("Cache-Control", "no-cache, must-revalidate");
|
response.setHeader("Cache-Control", "no-cache, must-revalidate");
|
||||||
DocResponseJson<Object> responseJson = null;
|
DocResponseJson<Object> responseJson;
|
||||||
if (ex instanceof ConfirmException) {// 提示性异常
|
// 无需处理的异常
|
||||||
responseJson = DocResponseJson.warn(ex.getMessage());
|
if (ex instanceof HttpMediaTypeNotAcceptableException) {
|
||||||
} else {// 其他异常
|
|
||||||
responseJson = DocResponseJson.warn("系统错误");
|
responseJson = DocResponseJson.warn("系统错误");
|
||||||
}
|
|
||||||
boolean isResponseBody = isResponseBody(handler);// 是否返回body
|
|
||||||
// 返回页面或者返回内容处理
|
|
||||||
if (!isResponseBody) {
|
|
||||||
mv.addObject("errJson", responseJson);
|
|
||||||
String customErrPage = (String) request.getAttribute("customErrPage");
|
|
||||||
// 有定义过错误页面的直接返回自定义的错误页面
|
|
||||||
if(StringUtils.isNotBlank(customErrPage)) {
|
|
||||||
mv.setViewName(customErrPage);
|
|
||||||
} else {// 否则返回默认的错误页面
|
|
||||||
mv.setViewName("/statics/common/500.html");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
// 其他异常
|
||||||
String jsonStr = JSON.toJSONString(responseJson);
|
logger.error("---自定义异常处理---", ex);
|
||||||
response.getWriter().write(jsonStr);
|
if (ex instanceof ConfirmException) {
|
||||||
} catch (IOException e) {
|
responseJson = DocResponseJson.warn(ex.getMessage());
|
||||||
e.printStackTrace();
|
} else {
|
||||||
|
responseJson = DocResponseJson.warn("系统错误");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mv;
|
try {
|
||||||
}
|
String jsonStr = JSON.toJSONString(responseJson);
|
||||||
|
response.getWriter().write(jsonStr);
|
||||||
/**
|
} catch (Exception e) {
|
||||||
* 如果是HttpMessageNotReadableException 则获取错误字段
|
logger.warn("write error:" + e.getMessage());
|
||||||
* @param exception
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getExceptionField(String exception) {
|
|
||||||
Pattern pattern = Pattern.compile("Unrecognized field \"(\\w*)[$\"]");
|
|
||||||
Matcher matcher = pattern.matcher(exception);
|
|
||||||
String field = "";
|
|
||||||
if (matcher.find()) {
|
|
||||||
field = matcher.group(1);
|
|
||||||
} else {
|
|
||||||
pattern = Pattern.compile("Field error in object '.+' on field '(\\w+)'");
|
|
||||||
matcher = pattern.matcher(exception);
|
|
||||||
if (matcher.find()) {
|
|
||||||
field = matcher.group(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return field;
|
return new ModelAndView();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否返回body
|
|
||||||
* @author
|
|
||||||
* @since 2017年5月11日
|
|
||||||
* @param handler
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean isResponseBody(Object handler){
|
|
||||||
if (handler instanceof HandlerMethod) {
|
|
||||||
HandlerMethod mathod = (HandlerMethod) handler;
|
|
||||||
ResponseBody body = mathod.getMethodAnnotation(ResponseBody.class);
|
|
||||||
if(body == null){
|
|
||||||
RestController restController = mathod.getMethod().getDeclaringClass().getAnnotation(RestController.class);
|
|
||||||
if(restController == null){
|
|
||||||
if(!mathod.getMethod().getReturnType().isAssignableFrom(ResponseJson.class)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,27 +9,37 @@
|
|||||||
<el-button v-on:click="doExecutorClick" type="primary" plain size="small" icon="el-icon-video-play">筛选</el-button>
|
<el-button v-on:click="doExecutorClick" type="primary" plain size="small" icon="el-icon-video-play">筛选</el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-button icon="el-icon-refresh-left" size="small" @click="refreshData">重置</el-button>
|
<el-button icon="el-icon-refresh-left" size="small" @click="refreshData">重置</el-button>
|
||||||
|
<el-button @click="downloadTableData" type="success" size="small" icon="el-icon-download" plain style="margin-left: 30px;">导出</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-card>
|
<el-card>
|
||||||
<div v-if="!!executeError" style="color: #f00;">{{executeError}}</div>
|
<div v-if="!!executeError" style="color: #f00;">{{executeError}}</div>
|
||||||
<div v-else-if="sqlExecuting" v-loading="sqlExecuting" style="padding: 20px 0;">数据加载中...</div>
|
<div v-else-if="sqlExecuting" v-loading="sqlExecuting" style="padding: 20px 0;">数据加载中...</div>
|
||||||
<div v-else-if="executeResultList.length <= 0" v-loading="sqlExecuting" style="padding: 20px 0;">暂无数据</div>
|
<div v-else-if="executeResultList.length <= 0" v-loading="sqlExecuting" style="padding: 20px 0;">暂无数据</div>
|
||||||
<div v-else>
|
<div v-else style="position: relative;">
|
||||||
<el-tabs :value="executeShowTable">
|
<div style="position: absolute;right: 0;z-index: 1;">
|
||||||
|
<!-- 复制选中行 -->
|
||||||
|
<el-dropdown @command="handleCopyCheckLineCommand" v-show="this.choiceResultObj[this.executeShowTable] && this.choiceResultObj[this.executeShowTable].length > 0">
|
||||||
|
<el-button type="primary" size="small" icon="el-icon-document-copy">
|
||||||
|
复制选中行<i class="el-icon-arrow-down el-icon--right"></i>
|
||||||
|
</el-button>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item command="insert">SQL Inserts</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="update">SQL Updates</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="json">JSON</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
<el-tabs v-model="executeShowTable">
|
||||||
<el-tab-pane label="信息" name="table0">
|
<el-tab-pane label="信息" name="table0">
|
||||||
<pre>{{executeResultInfo}}</pre>
|
<pre>{{executeResultInfo}}</pre>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="'结果'+resultItem.index" :name="'table'+resultItem.index" v-for="resultItem in executeResultList" v-if="!!resultItem.index">
|
<el-tab-pane :label="'结果'+resultItem.index" :name="resultItem.name" v-for="resultItem in executeResultList" v-if="!!resultItem.index">
|
||||||
<div v-if="!!resultItem.errMsg" style="color: #f00;">{{resultItem.errMsg}}</div>
|
<div v-if="!!resultItem.errMsg" style="color: #f00;">{{resultItem.errMsg}}</div>
|
||||||
<el-table v-else :data="resultItem.dataList" stripe border
|
<el-table v-else :data="resultItem.dataList" stripe border style="width: 100%; margin-bottom: 5px;" class="execute-result-table" max-height="600"
|
||||||
style="width: 100%; margin-bottom: 5px;"
|
@selection-change="handleSelectionChange">
|
||||||
class="execute-result-table" :max-height="tableMaxHeight"
|
<el-table-column type="selection" width="55"></el-table-column>
|
||||||
@sort-change="tableSortChange"
|
<el-table-column type="index" width="50"></el-table-column>
|
||||||
:default-sort="tableSort">
|
|
||||||
<el-table-column width="60px" v-if="resultItem.dataCols.length > 0">
|
|
||||||
<template slot-scope="scope">{{scope.row._index}}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column sortable v-for="item in resultItem.dataCols" :prop="item.prop" :label="item.prop" :width="item.width">
|
<el-table-column sortable v-for="item in resultItem.dataCols" :prop="item.prop" :label="item.prop" :width="item.width">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<textarea readonly :value="scope.row[item.prop]" class="el-textarea__inner" rows="1"></textarea>
|
<textarea readonly :value="scope.row[item.prop]" class="el-textarea__inner" rows="1"></textarea>
|
||||||
@@ -51,6 +61,52 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
|
<!--选择导出为update的条件列弹窗-->
|
||||||
|
<el-dialog :visible.sync="exportConditionVisible" width="500px" title="选择更新语句条件">
|
||||||
|
<div>
|
||||||
|
更新条件列:
|
||||||
|
<el-select v-model="conditionDataColsChoice" multiple placeholder="请选择" style="width: 370px;">
|
||||||
|
<el-option v-for="item in conditionDataCols" :key="item.prop" :label="item.prop" :value="item.prop"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="exportConditionVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="doCopyCheckLineUpdate">确 定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
<!--导出选择弹窗-->
|
||||||
|
<el-dialog :visible.sync="downloadDataVisible" width="600px" title="表数据导出">
|
||||||
|
<el-form label-width="120px">
|
||||||
|
<el-form-item label="导出类型:">
|
||||||
|
<el-select v-model="downloadDataParam.downloadType" filterable placeholder="请选择导出类型" style="width: 370px;">
|
||||||
|
<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="downloadDataParam.downloadType === 'insert'">
|
||||||
|
<el-checkbox :true-label="1" :false-label="0" v-model="downloadDataParam.dropTableFlag" @change="dropTableFlagChange">删除表</el-checkbox>
|
||||||
|
<el-checkbox :true-label="1" :false-label="0" v-model="downloadDataParam.createTableFlag">创建表</el-checkbox>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="保留的列:">
|
||||||
|
<el-select v-model="downloadDataParam.retainColumnArr" multiple placeholder="不选则保留全部列" style="width: 370px;">
|
||||||
|
<el-option v-for="item in conditionDataCols" :key="item.prop" :label="item.prop" :value="item.prop"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="更新条件列:" v-if="downloadDataParam.downloadType === 'update'">
|
||||||
|
<el-select v-model="downloadDataParam.conditionArr" multiple placeholder="不选则是没有条件的更新" style="width: 370px;">
|
||||||
|
<el-option v-for="item in conditionDataCols" :key="item.prop" :label="item.prop" :value="item.prop"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="exportConditionVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="doDownloadTableData">确 定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
<form method="post" ref="downloadForm" :action="downloadFormParam.url" target="_blank">
|
||||||
|
<input type="hidden" :name="key" :value="val" v-for="(val,key) in downloadFormParam.param">
|
||||||
|
</form>
|
||||||
<span id="widthCalculate" style="visibility: hidden; white-space: nowrap;position: fixed;"></span>
|
<span id="widthCalculate" style="visibility: hidden; white-space: nowrap;position: fixed;"></span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -62,6 +118,7 @@
|
|||||||
import '../../common/lib/ace/ext-language_tools'
|
import '../../common/lib/ace/ext-language_tools'
|
||||||
import '../../common/lib/ace/snippets/sql'
|
import '../../common/lib/ace/snippets/sql'
|
||||||
import datasourceApi from '../../common/api/datasource'
|
import datasourceApi from '../../common/api/datasource'
|
||||||
|
import copyFormatter from './copy/index'
|
||||||
import sqlFormatter from "sql-formatter";
|
import sqlFormatter from "sql-formatter";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -80,6 +137,25 @@
|
|||||||
tableTotalCount: 0,
|
tableTotalCount: 0,
|
||||||
tableSort: {},
|
tableSort: {},
|
||||||
tableMaxHeight: 600,
|
tableMaxHeight: 600,
|
||||||
|
tableStatusInfo: {},
|
||||||
|
// 选择复制
|
||||||
|
choiceResultObj: {},
|
||||||
|
exportConditionVisible: false,
|
||||||
|
conditionDataCols: [],
|
||||||
|
conditionDataColsChoice: [],
|
||||||
|
// 导出
|
||||||
|
downloadDataVisible: false,
|
||||||
|
downloadDataParam: {
|
||||||
|
downloadType: 'insert',
|
||||||
|
dropTableFlag: 0,
|
||||||
|
createTableFlag: 0,
|
||||||
|
conditionArr: [],
|
||||||
|
retainColumnArr: [],
|
||||||
|
},
|
||||||
|
downloadFormParam: {
|
||||||
|
url: 'zyplayer-doc-db/data-view/download',
|
||||||
|
param: {}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
@@ -111,6 +187,9 @@
|
|||||||
this.vueQueryParam = to.query;
|
this.vueQueryParam = to.query;
|
||||||
let newName = {key: this.$route.fullPath, val: '数据-'+this.vueQueryParam.tableName};
|
let newName = {key: this.$route.fullPath, val: '数据-'+this.vueQueryParam.tableName};
|
||||||
this.$store.commit('global/addTableName', newName);
|
this.$store.commit('global/addTableName', newName);
|
||||||
|
datasourceApi.tableStatus(this.vueQueryParam).then(json => {
|
||||||
|
this.tableStatusInfo = json.data || {};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
handleCurrentChange(to) {
|
handleCurrentChange(to) {
|
||||||
this.currentPage = to;
|
this.currentPage = to;
|
||||||
@@ -123,7 +202,7 @@
|
|||||||
},
|
},
|
||||||
tableSortChange(sort) {
|
tableSortChange(sort) {
|
||||||
if (this.tableSort.prop === sort.prop && this.tableSort.order === sort.order) return;
|
if (this.tableSort.prop === sort.prop && this.tableSort.order === sort.order) return;
|
||||||
this.tableSort = {orderColumn: sort.prop, orderType: (sort.order === 'ascending' ? 'asc' : 'desc')};
|
this.tableSort = {prop: sort.prop, order: sort.order};
|
||||||
this.doExecutorSqlCommon();
|
this.doExecutorSqlCommon();
|
||||||
},
|
},
|
||||||
refreshData() {
|
refreshData() {
|
||||||
@@ -146,31 +225,31 @@
|
|||||||
if (!this.vueQueryParam.sourceId) {
|
if (!this.vueQueryParam.sourceId) {
|
||||||
this.$message.error("请先选择数据源");
|
this.$message.error("请先选择数据源");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.tableSort.orderColumn) {
|
if (!this.tableSort.prop) {
|
||||||
this.tableSort = {orderColumn: this.vueQueryParam.orderColumn, orderType: 'asc'};
|
this.tableSort = {prop: this.vueQueryParam.orderColumn, order: 'ascending'};
|
||||||
}
|
}
|
||||||
let conditionSql = this.sqlExecutorEditor.getSelectedText();
|
let conditionSql = this.sqlExecutorEditor.getSelectedText();
|
||||||
conditionSql = conditionSql || this.sqlExecutorEditor.getValue();
|
conditionSql = conditionSql || this.sqlExecutorEditor.getValue();
|
||||||
conditionSql = conditionSql || "";
|
conditionSql = conditionSql || "";
|
||||||
this.executeError = "";
|
this.executeError = "";
|
||||||
this.executeUseTime = "";
|
this.executeUseTime = "";
|
||||||
this.executeResultList = [];
|
this.executeResultList = [];
|
||||||
this.tableMaxHeight = document.body.clientHeight - 400;
|
this.tableMaxHeight = document.body.clientHeight - 400;
|
||||||
this.nowExecutorId = (new Date()).getTime() + Math.ceil(Math.random() * 1000);
|
this.nowExecutorId = (new Date()).getTime() + Math.ceil(Math.random() * 1000);
|
||||||
this.sqlExecuting = true;
|
this.sqlExecuting = true;
|
||||||
let param = {
|
let param = {
|
||||||
sourceId: this.vueQueryParam.sourceId,
|
sourceId: this.vueQueryParam.sourceId,
|
||||||
dbName: this.vueQueryParam.dbName,
|
dbName: this.vueQueryParam.dbName,
|
||||||
tableName: this.vueQueryParam.tableName,
|
tableName: this.vueQueryParam.tableName,
|
||||||
executeId: this.nowExecutorId,
|
executeId: this.nowExecutorId,
|
||||||
condition: conditionSql,
|
condition: conditionSql,
|
||||||
pageNum: this.currentPage,
|
pageNum: this.currentPage,
|
||||||
pageSize: this.pageSize,
|
pageSize: this.pageSize,
|
||||||
orderColumn: this.tableSort.orderColumn,
|
orderColumn: this.tableSort.prop,
|
||||||
orderType: this.tableSort.orderType,
|
orderType: (this.tableSort.order === 'ascending' ? 'asc' : 'desc'),
|
||||||
params: '',
|
params: '',
|
||||||
};
|
};
|
||||||
datasourceApi.dataViewQuery(param).then(json => {
|
datasourceApi.dataViewQuery(param).then(json => {
|
||||||
if (json.errCode !== 200) {
|
if (json.errCode !== 200) {
|
||||||
this.executeError = json.errMsg;
|
this.executeError = json.errMsg;
|
||||||
@@ -186,6 +265,7 @@
|
|||||||
let resultItem = this.dealExecuteResult(objItem);
|
let resultItem = this.dealExecuteResult(objItem);
|
||||||
if (resultItem.updateCount < 0) {
|
if (resultItem.updateCount < 0) {
|
||||||
resultItem.index = itemIndex;
|
resultItem.index = itemIndex;
|
||||||
|
resultItem.name = 'table' + itemIndex;
|
||||||
itemIndex++;
|
itemIndex++;
|
||||||
}
|
}
|
||||||
executeResultList.push(resultItem);
|
executeResultList.push(resultItem);
|
||||||
@@ -225,9 +305,6 @@
|
|||||||
width = (width > 200) ? 200 : width;
|
width = (width > 200) ? 200 : width;
|
||||||
executeResultCols.push({prop: key, width: width + 50});
|
executeResultCols.push({prop: key, width: width + 50});
|
||||||
}
|
}
|
||||||
for (var i = 0; i < dataList.length; i++) {
|
|
||||||
dataList[i]._index = i + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var resultObj = {};
|
var resultObj = {};
|
||||||
resultObj.dataList = dataList;
|
resultObj.dataList = dataList;
|
||||||
@@ -237,6 +314,71 @@
|
|||||||
resultObj.updateCount = resultData.updateCount;
|
resultObj.updateCount = resultData.updateCount;
|
||||||
return resultObj;
|
return resultObj;
|
||||||
},
|
},
|
||||||
|
handleSelectionChange(val) {
|
||||||
|
this.$set(this.choiceResultObj, this.executeShowTable, val);
|
||||||
|
},
|
||||||
|
doCopyCheckLineUpdate() {
|
||||||
|
let choiceData = this.choiceResultObj[this.executeShowTable] || [];
|
||||||
|
if (choiceData.length > 0) {
|
||||||
|
let dataCols = this.executeResultList.find(item => item.name === this.executeShowTable).dataCols;
|
||||||
|
let tableName = '`' + this.vueQueryParam.dbName + '`.`' + this.vueQueryParam.tableName + '`';
|
||||||
|
let copyData = copyFormatter.format('update', this.editorDbProduct, dataCols, choiceData, this.conditionDataColsChoice, tableName);
|
||||||
|
this.conditionDataColsChoice = [];
|
||||||
|
this.exportConditionVisible = false;
|
||||||
|
this.$copyText(copyData).then(
|
||||||
|
res => this.$message.success("内容已复制到剪切板!"),
|
||||||
|
err => this.$message.error("抱歉,复制失败!")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleCopyCheckLineCommand(type) {
|
||||||
|
let choiceData = this.choiceResultObj[this.executeShowTable] || [];
|
||||||
|
if (choiceData.length > 0) {
|
||||||
|
let dataCols = this.executeResultList.find(item => item.name === this.executeShowTable).dataCols;
|
||||||
|
if (type === 'update') {
|
||||||
|
// 选择更新的条件列
|
||||||
|
this.conditionDataCols = dataCols;
|
||||||
|
this.exportConditionVisible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let tableName = '`' + this.vueQueryParam.dbName + '`.`' + this.vueQueryParam.tableName + '`';
|
||||||
|
let copyData = copyFormatter.format(type, this.editorDbProduct, dataCols, choiceData, '', tableName);
|
||||||
|
this.$copyText(copyData).then(
|
||||||
|
res => this.$message.success("内容已复制到剪切板!"),
|
||||||
|
err => this.$message.error("抱歉,复制失败!")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doDownloadTableData() {
|
||||||
|
let conditionSql = this.sqlExecutorEditor.getSelectedText();
|
||||||
|
conditionSql = conditionSql || this.sqlExecutorEditor.getValue();
|
||||||
|
conditionSql = conditionSql || "";
|
||||||
|
this.nowExecutorId = (new Date()).getTime() + Math.ceil(Math.random() * 1000);
|
||||||
|
this.downloadFormParam.param = {
|
||||||
|
sourceId: this.vueQueryParam.sourceId,
|
||||||
|
dbName: this.vueQueryParam.dbName,
|
||||||
|
tableName: this.vueQueryParam.tableName,
|
||||||
|
downloadType: this.downloadDataParam.downloadType,
|
||||||
|
conditionColumn: this.downloadDataParam.conditionArr.join(","),
|
||||||
|
retainColumn: this.downloadDataParam.retainColumnArr.join(","),
|
||||||
|
dropTableFlag: this.downloadDataParam.dropTableFlag,
|
||||||
|
createTableFlag: this.downloadDataParam.createTableFlag,
|
||||||
|
condition: conditionSql,
|
||||||
|
executeId: this.nowExecutorId,
|
||||||
|
};
|
||||||
|
setTimeout(() => this.$refs.downloadForm.submit(), 0);
|
||||||
|
this.downloadDataVisible = false;
|
||||||
|
},
|
||||||
|
downloadTableData() {
|
||||||
|
this.downloadDataParam.conditionArr = [];
|
||||||
|
this.conditionDataCols = this.executeResultList.find(item => item.name === this.executeShowTable).dataCols;
|
||||||
|
this.downloadDataVisible = true;
|
||||||
|
},
|
||||||
|
dropTableFlagChange() {
|
||||||
|
if (this.downloadDataParam.dropTableFlag === 1) {
|
||||||
|
this.downloadDataParam.createTableFlag = 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
initAceEditor(editor, minLines) {
|
initAceEditor(editor, minLines) {
|
||||||
return ace.edit(editor, {
|
return ace.edit(editor, {
|
||||||
theme: "ace/theme/monokai",
|
theme: "ace/theme/monokai",
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
<div style="position: absolute;right: 0;z-index: 1;">
|
<div style="position: absolute;right: 0;z-index: 1;">
|
||||||
<!-- 复制选中行 -->
|
<!-- 复制选中行 -->
|
||||||
<el-dropdown @command="handleCopyCheckLineCommand" v-show="this.choiceResultObj[this.executeShowTable] && this.choiceResultObj[this.executeShowTable].length > 0">
|
<el-dropdown @command="handleCopyCheckLineCommand" v-show="this.choiceResultObj[this.executeShowTable] && this.choiceResultObj[this.executeShowTable].length > 0">
|
||||||
<el-button type="primary" size="small">
|
<el-button type="primary" size="small" icon="el-icon-document-copy">
|
||||||
复制选中行<i class="el-icon-arrow-down el-icon--right"></i>
|
复制选中行<i class="el-icon-arrow-down el-icon--right"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
@@ -466,7 +466,7 @@
|
|||||||
let choiceData = this.choiceResultObj[this.executeShowTable] || [];
|
let choiceData = this.choiceResultObj[this.executeShowTable] || [];
|
||||||
if (choiceData.length > 0) {
|
if (choiceData.length > 0) {
|
||||||
let dataCols = this.executeResultList.find(item => item.name === this.executeShowTable).dataCols;
|
let dataCols = this.executeResultList.find(item => item.name === this.executeShowTable).dataCols;
|
||||||
let copyData = copyFormatter.format('update', this.editorDbProduct, dataCols, choiceData, this.conditionDataColsChoice);
|
let copyData = copyFormatter.format('update', this.editorDbProduct, dataCols, choiceData, this.conditionDataColsChoice, '`table`');
|
||||||
this.conditionDataColsChoice = [];
|
this.conditionDataColsChoice = [];
|
||||||
this.exportConditionVisible = false;
|
this.exportConditionVisible = false;
|
||||||
this.$copyText(copyData).then(
|
this.$copyText(copyData).then(
|
||||||
@@ -485,7 +485,7 @@
|
|||||||
this.exportConditionVisible = true;
|
this.exportConditionVisible = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let copyData = copyFormatter.format(type, this.editorDbProduct, dataCols, choiceData);
|
let copyData = copyFormatter.format(type, this.editorDbProduct, dataCols, choiceData, '', '`table`');
|
||||||
this.$copyText(copyData).then(
|
this.$copyText(copyData).then(
|
||||||
res => this.$message.success("内容已复制到剪切板!"),
|
res => this.$message.success("内容已复制到剪切板!"),
|
||||||
err => this.$message.error("抱歉,复制失败!")
|
err => this.$message.error("抱歉,复制失败!")
|
||||||
|
|||||||
@@ -24,26 +24,34 @@
|
|||||||
<input type="hidden" :name="key" :value="val" v-for="(val,key) in downloadFormParam.param">
|
<input type="hidden" :name="key" :value="val" v-for="(val,key) in downloadFormParam.param">
|
||||||
</form>
|
</form>
|
||||||
<!--导出选项弹窗-->
|
<!--导出选项弹窗-->
|
||||||
<el-dialog :visible.sync="exportTypeChoiceVisible" width="500px">
|
<el-dialog :visible.sync="exportTypeChoiceVisible" width="600px">
|
||||||
<span slot="title">库表导出选项</span>
|
<span slot="title">库表导出选项</span>
|
||||||
<el-form label-width="120px">
|
<el-form label-width="100px">
|
||||||
<el-form-item label="导出类型:">
|
<el-form-item label="导出类型:">
|
||||||
<el-radio-group v-model="exportType" @change="exportTypeChange">
|
<el-select v-model="exportType" filterable placeholder="请选择导出类型" style="width: 300px;">
|
||||||
<el-radio :label="1">表结构文档</el-radio>
|
<el-option label="表结构文档" :value="1"></el-option>
|
||||||
<el-radio :label="2">建表语句SQL</el-radio>
|
<el-option label="建表语句SQL" :value="2"></el-option>
|
||||||
</el-radio-group>
|
<el-option label="表数据" :value="3"></el-option>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="导出格式:" v-if="exportType == 1">
|
<el-form-item label="导出格式:" v-if="exportType == 1">
|
||||||
<el-radio-group v-model="exportFormat">
|
<el-select v-model="exportFormat" filterable placeholder="请选择导出格式" style="width: 300px;">
|
||||||
<el-radio :label="1">HTML格式</el-radio>
|
<el-option label="HTML格式" :value="1"></el-option>
|
||||||
<el-radio :label="2">Excel格式</el-radio>
|
<el-option label="Excel格式" :value="2"></el-option>
|
||||||
<el-radio :label="3">Word格式</el-radio>
|
<el-option label="Word格式" :value="3"></el-option>
|
||||||
</el-radio-group>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="导出格式:" v-else-if="exportType == 2">
|
<el-form-item label="导出格式:" v-else-if="exportType == 2">
|
||||||
<el-radio-group v-model="exportFormat">
|
<el-select v-model="exportFormat" filterable placeholder="请选择导出格式" style="width: 300px;">
|
||||||
<el-radio :label="1">SQL格式</el-radio>
|
<el-option label="SQL格式" :value="1"></el-option>
|
||||||
</el-radio-group>
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="导出格式:" v-else-if="exportType == 3">
|
||||||
|
<el-select v-model="downloadType" filterable placeholder="请选择导出类型" style="width: 300px;">
|
||||||
|
<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>
|
||||||
</el-form>
|
</el-form>
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
@@ -78,6 +86,8 @@
|
|||||||
url: 'zyplayer-doc-db/doc-db/exportDatabase',
|
url: 'zyplayer-doc-db/doc-db/exportDatabase',
|
||||||
param: {}
|
param: {}
|
||||||
},
|
},
|
||||||
|
// 数据导出
|
||||||
|
downloadType: 'insert',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* @since 2021年5月23日
|
* @since 2021年5月23日
|
||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
insert(dataCols, choiceData) {
|
insert(dataCols, choiceData, tableName = '`table`') {
|
||||||
// 复制为insert语句
|
// 复制为insert语句
|
||||||
let copyData = '';
|
let copyData = '';
|
||||||
let names = '';
|
let names = '';
|
||||||
@@ -24,11 +24,11 @@ export default {
|
|||||||
values += "'" + val + "'";
|
values += "'" + val + "'";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
copyData += 'insert into `table` (' + names + ') values (' + values + ');\n';
|
copyData += 'insert into ' + tableName + ' (' + names + ') values (' + values + ');\n';
|
||||||
});
|
});
|
||||||
return copyData;
|
return copyData;
|
||||||
},
|
},
|
||||||
update(dataCols, choiceData, condition=[]) {
|
update(dataCols, choiceData, condition=[], tableName = '`table`') {
|
||||||
// 复制为update语句
|
// 复制为update语句
|
||||||
let copyData = '';
|
let copyData = '';
|
||||||
choiceData.forEach(item => {
|
choiceData.forEach(item => {
|
||||||
@@ -53,11 +53,11 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (where.length > 0) where = ' where ' + where;
|
if (where.length > 0) where = ' where ' + where;
|
||||||
copyData += 'update `table` set ' + values + where + ';\n';
|
copyData += 'update ' + tableName + ' set ' + values + where + ';\n';
|
||||||
});
|
});
|
||||||
return copyData;
|
return copyData;
|
||||||
},
|
},
|
||||||
json(dataCols, choiceData) {
|
json(dataCols, choiceData, tableName) {
|
||||||
// 复制为json
|
// 复制为json
|
||||||
return JSON.stringify(choiceData);
|
return JSON.stringify(choiceData);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import base from './base'
|
import base from './base'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
format(type, product, dataCols, choiceData, condition) {
|
format(type, product, dataCols, choiceData, condition, tableName) {
|
||||||
let formatter = this.getProduct(product);
|
let formatter = this.getProduct(product);
|
||||||
if (type === 'insert') {
|
if (type === 'insert') {
|
||||||
// 复制为insert语句
|
// 复制为insert语句
|
||||||
return formatter.insert(dataCols, choiceData);
|
return formatter.insert(dataCols, choiceData, tableName);
|
||||||
} else if (type === 'update') {
|
} else if (type === 'update') {
|
||||||
// 复制为update语句
|
// 复制为update语句
|
||||||
return formatter.update(dataCols, choiceData, condition);
|
return formatter.update(dataCols, choiceData, condition, tableName);
|
||||||
} else if (type === 'json') {
|
} else if (type === 'json') {
|
||||||
// 复制为json
|
// 复制为json
|
||||||
return formatter.json(dataCols, choiceData);
|
return formatter.json(dataCols, choiceData, tableName);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getProduct(product) {
|
getProduct(product) {
|
||||||
|
|||||||
Reference in New Issue
Block a user