Unverified Commit 2fb2abce authored by ikiler's avatar ikiler Committed by GitHub

Feature datacenter (#966)

* 后台增加样例查询接口

* 单独拆出数据中心元数据模块,增加样例数据功能

* 修改代码风格符合规定

* 修改数据中心放到注册中心右侧,删除无用的class属性

* 元数据管理页面涉及后台访问的UI添加加载图标显示,对加载慢的场景起到提示作用

* 添加数据查询功能

* 数据查询功能分页bug修复

* 后端查询分页限制,数据库处理逻辑不同的交由不同driver处理

* 前端查询优化

* oracle,phonix,sqlserver  paging is not implemented, use the default method

* merge conflict

Co-authored-by: steve <woai1998>
parent 90a82dd0
...@@ -24,7 +24,9 @@ import com.dlink.common.result.ProTableResult; ...@@ -24,7 +24,9 @@ import com.dlink.common.result.ProTableResult;
import com.dlink.common.result.Result; import com.dlink.common.result.Result;
import com.dlink.constant.CommonConstant; import com.dlink.constant.CommonConstant;
import com.dlink.metadata.driver.DriverPool; import com.dlink.metadata.driver.DriverPool;
import com.dlink.metadata.result.JdbcSelectResult;
import com.dlink.model.DataBase; import com.dlink.model.DataBase;
import com.dlink.model.QueryData;
import com.dlink.service.DataBaseService; import com.dlink.service.DataBaseService;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -178,6 +180,19 @@ public class DataBaseController { ...@@ -178,6 +180,19 @@ public class DataBaseController {
return Result.succeed(databaseService.listColumns(id, schemaName, tableName), "获取成功"); return Result.succeed(databaseService.listColumns(id, schemaName, tableName), "获取成功");
} }
/**
* 获取元数据的指定表的数据
*/
@PostMapping("/queryData")
public Result queryData(@RequestBody QueryData queryData) {
JdbcSelectResult jdbcSelectResult = databaseService.queryData(queryData);
if (jdbcSelectResult.isSuccess()) {
return Result.succeed(jdbcSelectResult, "获取成功");
} else {
return Result.failed(jdbcSelectResult,"查询失败");
}
}
/** /**
* 获取 SqlGeneration * 获取 SqlGeneration
*/ */
......
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
package com.dlink.service; package com.dlink.service;
import com.dlink.db.service.ISuperService; import com.dlink.db.service.ISuperService;
import com.dlink.metadata.result.JdbcSelectResult;
import com.dlink.model.Column; import com.dlink.model.Column;
import com.dlink.model.DataBase; import com.dlink.model.DataBase;
import com.dlink.model.QueryData;
import com.dlink.model.Schema; import com.dlink.model.Schema;
import com.dlink.model.SqlGeneration; import com.dlink.model.SqlGeneration;
...@@ -53,6 +55,8 @@ public interface DataBaseService extends ISuperService<DataBase> { ...@@ -53,6 +55,8 @@ public interface DataBaseService extends ISuperService<DataBase> {
String getSqlCreate(Integer id, String schemaName, String tableName); String getSqlCreate(Integer id, String schemaName, String tableName);
JdbcSelectResult queryData(QueryData queryData);
SqlGeneration getSqlGeneration(Integer id, String schemaName, String tableName); SqlGeneration getSqlGeneration(Integer id, String schemaName, String tableName);
List<String> listEnabledFlinkWith(); List<String> listEnabledFlinkWith();
......
...@@ -24,8 +24,10 @@ import com.dlink.constant.CommonConstant; ...@@ -24,8 +24,10 @@ import com.dlink.constant.CommonConstant;
import com.dlink.db.service.impl.SuperServiceImpl; import com.dlink.db.service.impl.SuperServiceImpl;
import com.dlink.mapper.DataBaseMapper; import com.dlink.mapper.DataBaseMapper;
import com.dlink.metadata.driver.Driver; import com.dlink.metadata.driver.Driver;
import com.dlink.metadata.result.JdbcSelectResult;
import com.dlink.model.Column; import com.dlink.model.Column;
import com.dlink.model.DataBase; import com.dlink.model.DataBase;
import com.dlink.model.QueryData;
import com.dlink.model.Schema; import com.dlink.model.Schema;
import com.dlink.model.SqlGeneration; import com.dlink.model.SqlGeneration;
import com.dlink.model.Table; import com.dlink.model.Table;
...@@ -144,6 +146,15 @@ public class DataBaseServiceImpl extends SuperServiceImpl<DataBaseMapper, DataBa ...@@ -144,6 +146,15 @@ public class DataBaseServiceImpl extends SuperServiceImpl<DataBaseMapper, DataBa
return driver.getCreateTableSql(table); return driver.getCreateTableSql(table);
} }
@Override
public JdbcSelectResult queryData(QueryData queryData) {
DataBase dataBase = getById(queryData.getId());
Asserts.checkNotNull(dataBase, "该数据源不存在!");
Driver driver = Driver.build(dataBase.getDriverConfig());
StringBuilder queryOption = driver.genQueryOption(queryData);
return driver.query(queryOption.toString(), null);
}
@Override @Override
public SqlGeneration getSqlGeneration(Integer id, String schemaName, String tableName) { public SqlGeneration getSqlGeneration(Integer id, String schemaName, String tableName) {
DataBase dataBase = getById(id); DataBase dataBase = getById(id);
......
package com.dlink.model;
import lombok.Data;
@Data
public class QueryData {
private String id;
private String schemaName;
private String tableName;
private Option option;
@Data
public class Option {
private String where;
private String order;
private String limitStart;
private String limitEnd;
}
}
package com.dlink.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.regex.Pattern;
public class TextUtil {
/**
* 判断字符串是否为空
*/
public static boolean isEmpty(CharSequence s) {
if (s == null) {
return true;
} else {
return s.length() == 0;
}
}
/**
* 整个字符是否是数字
*
* @param str 字符串
* @return true 数字 false 字符串
*/
public static boolean isInteger(String str) {
Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
return pattern.matcher(str).matches();
}
/**
* 将字符串转化为sha1加密字符串
*
* @param data 要加密的字符串
*/
public static String sha1(String data) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
md.update(data.getBytes());
StringBuffer buf = new StringBuffer();
byte[] bits = md.digest();
for (int i = 0; i < bits.length; i++) {
int a = bits[i];
if (a < 0) {
a += 256;
}
if (a < 16) {
buf.append("0");
}
buf.append(Integer.toHexString(a));
}
return buf.toString();
}
/**
* 将字符串转化为md5加密字符串
*
* @param data 要加密的字符串
*/
public static String md5(String data) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
md.update(data.getBytes());
StringBuffer buf = new StringBuffer();
byte[] bits = md.digest();
for (int i = 0; i < bits.length; i++) {
int a = bits[i];
if (a < 0) {
a += 256;
}
if (a < 16) {
buf.append("0");
}
buf.append(Integer.toHexString(a));
}
return buf.toString();
}
}
...@@ -24,10 +24,12 @@ import com.dlink.constant.CommonConstant; ...@@ -24,10 +24,12 @@ import com.dlink.constant.CommonConstant;
import com.dlink.metadata.query.IDBQuery; import com.dlink.metadata.query.IDBQuery;
import com.dlink.metadata.result.JdbcSelectResult; import com.dlink.metadata.result.JdbcSelectResult;
import com.dlink.model.Column; import com.dlink.model.Column;
import com.dlink.model.QueryData;
import com.dlink.model.Schema; import com.dlink.model.Schema;
import com.dlink.model.Table; import com.dlink.model.Table;
import com.dlink.result.SqlExplainResult; import com.dlink.result.SqlExplainResult;
import com.dlink.utils.LogUtil; import com.dlink.utils.LogUtil;
import com.dlink.utils.TextUtil;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
...@@ -423,6 +425,46 @@ public abstract class AbstractJdbcDriver extends AbstractDriver { ...@@ -423,6 +425,46 @@ public abstract class AbstractJdbcDriver extends AbstractDriver {
return res; return res;
} }
/**
* 标准sql where与order语法都是相同的
* 不同数据库limit语句不一样,需要单独交由driver去处理,例如oracle
* 通过{@query(String sql, Integer limit)}去截断返回数据,但是在大量数据情况下会导致数据库负载过高。
*/
@Override
public StringBuilder genQueryOption(QueryData queryData) {
String where = queryData.getOption().getWhere();
String order = queryData.getOption().getOrder();
String limitStart = queryData.getOption().getLimitStart();
String limitEnd = queryData.getOption().getLimitEnd();
StringBuilder optionBuilder = new StringBuilder()
.append("select * from ")
.append(queryData.getSchemaName())
.append(".")
.append(queryData.getTableName());
if (where != null && !where.equals("")) {
optionBuilder.append(" where ").append(where);
}
if (order != null && !order.equals("")) {
optionBuilder.append(" order by ").append(order);
}
if (TextUtil.isEmpty(limitStart)) {
limitStart = "0";
}
if (TextUtil.isEmpty(limitEnd)) {
limitEnd = "100";
}
optionBuilder.append(" limit ")
.append(limitStart)
.append(",")
.append(limitEnd);
return optionBuilder;
}
@Override @Override
public JdbcSelectResult query(String sql, Integer limit) { public JdbcSelectResult query(String sql, Integer limit) {
if (Asserts.isNull(limit)) { if (Asserts.isNull(limit)) {
......
...@@ -23,6 +23,7 @@ import com.dlink.assertion.Asserts; ...@@ -23,6 +23,7 @@ import com.dlink.assertion.Asserts;
import com.dlink.exception.MetaDataException; import com.dlink.exception.MetaDataException;
import com.dlink.metadata.result.JdbcSelectResult; import com.dlink.metadata.result.JdbcSelectResult;
import com.dlink.model.Column; import com.dlink.model.Column;
import com.dlink.model.QueryData;
import com.dlink.model.Schema; import com.dlink.model.Schema;
import com.dlink.model.Table; import com.dlink.model.Table;
import com.dlink.result.SqlExplainResult; import com.dlink.result.SqlExplainResult;
...@@ -137,6 +138,8 @@ public interface Driver { ...@@ -137,6 +138,8 @@ public interface Driver {
JdbcSelectResult query(String sql, Integer limit); JdbcSelectResult query(String sql, Integer limit);
StringBuilder genQueryOption(QueryData queryData);
JdbcSelectResult executeSql(String sql, Integer limit); JdbcSelectResult executeSql(String sql, Integer limit);
List<SqlExplainResult> explain(String sql); List<SqlExplainResult> explain(String sql);
......
...@@ -25,6 +25,7 @@ import com.dlink.metadata.convert.OracleTypeConvert; ...@@ -25,6 +25,7 @@ import com.dlink.metadata.convert.OracleTypeConvert;
import com.dlink.metadata.query.IDBQuery; import com.dlink.metadata.query.IDBQuery;
import com.dlink.metadata.query.OracleQuery; import com.dlink.metadata.query.OracleQuery;
import com.dlink.model.Column; import com.dlink.model.Column;
import com.dlink.model.QueryData;
import com.dlink.model.Table; import com.dlink.model.Table;
import java.util.HashMap; import java.util.HashMap;
...@@ -65,6 +66,31 @@ public class OracleDriver extends AbstractJdbcDriver { ...@@ -65,6 +66,31 @@ public class OracleDriver extends AbstractJdbcDriver {
return "Oracle数据库"; return "Oracle数据库";
} }
/**
* oracel sql拼接,目前还未实现limit方法
* */
@Override
public StringBuilder genQueryOption(QueryData queryData) {
String where = queryData.getOption().getWhere();
String order = queryData.getOption().getOrder();
StringBuilder optionBuilder = new StringBuilder()
.append("select * from ")
.append(queryData.getSchemaName())
.append(".")
.append(queryData.getTableName());
if (where != null && !where.equals("")) {
optionBuilder.append(" where ").append(where);
}
if (order != null && !order.equals("")) {
optionBuilder.append(" order by ").append(order);
}
return optionBuilder;
}
@Override @Override
public String getCreateTableSql(Table table) { public String getCreateTableSql(Table table) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
......
...@@ -26,6 +26,7 @@ import com.dlink.metadata.query.IDBQuery; ...@@ -26,6 +26,7 @@ import com.dlink.metadata.query.IDBQuery;
import com.dlink.metadata.query.PhoenixQuery; import com.dlink.metadata.query.PhoenixQuery;
import com.dlink.metadata.result.JdbcSelectResult; import com.dlink.metadata.result.JdbcSelectResult;
import com.dlink.model.Column; import com.dlink.model.Column;
import com.dlink.model.QueryData;
import com.dlink.model.Table; import com.dlink.model.Table;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
...@@ -57,6 +58,32 @@ public class PhoenixDriver extends AbstractJdbcDriver { ...@@ -57,6 +58,32 @@ public class PhoenixDriver extends AbstractJdbcDriver {
return "Phoenix"; return "Phoenix";
} }
/**
* sql拼接,目前还未实现limit方法
* */
@Override
public StringBuilder genQueryOption(QueryData queryData) {
String where = queryData.getOption().getWhere();
String order = queryData.getOption().getOrder();
StringBuilder optionBuilder = new StringBuilder()
.append("select * from ")
.append(queryData.getSchemaName())
.append(".")
.append(queryData.getTableName());
if (where != null && !where.equals("")) {
optionBuilder.append(" where ").append(where);
}
if (order != null && !order.equals("")) {
optionBuilder.append(" order by ").append(order);
}
return optionBuilder;
}
@Override @Override
public String getName() { public String getName() {
return "Phoenix"; return "Phoenix";
......
...@@ -25,6 +25,7 @@ import com.dlink.metadata.convert.SqlServerTypeConvert; ...@@ -25,6 +25,7 @@ import com.dlink.metadata.convert.SqlServerTypeConvert;
import com.dlink.metadata.query.IDBQuery; import com.dlink.metadata.query.IDBQuery;
import com.dlink.metadata.query.SqlServerQuery; import com.dlink.metadata.query.SqlServerQuery;
import com.dlink.model.Column; import com.dlink.model.Column;
import com.dlink.model.QueryData;
import com.dlink.model.Table; import com.dlink.model.Table;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -58,6 +59,31 @@ public class SqlServerDriver extends AbstractJdbcDriver { ...@@ -58,6 +59,31 @@ public class SqlServerDriver extends AbstractJdbcDriver {
return "SqlServer数据库"; return "SqlServer数据库";
} }
/**
* sql拼接,目前还未实现limit方法
* */
@Override
public StringBuilder genQueryOption(QueryData queryData) {
String where = queryData.getOption().getWhere();
String order = queryData.getOption().getOrder();
StringBuilder optionBuilder = new StringBuilder()
.append("select * from ")
.append(queryData.getSchemaName())
.append(".")
.append(queryData.getTableName());
if (where != null && !where.equals("")) {
optionBuilder.append(" where ").append(where);
}
if (order != null && !order.equals("")) {
optionBuilder.append(" order by ").append(order);
}
return optionBuilder;
}
@Override @Override
public String getCreateTableSql(Table table) { public String getCreateTableSql(Table table) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
......
...@@ -54,6 +54,20 @@ export default [ ...@@ -54,6 +54,20 @@ export default [
component: './DevOps/JobInfo', component: './DevOps/JobInfo',
hideInMenu: true, hideInMenu: true,
}, },
{
path: '/datacenter',
name: 'datacenter',
icon: 'database',
routes: [
{
component: './DataCenter/MetaData',
path: '/datacenter/metadata',
name: 'metadata',
icon: 'cluster',
},
],
},
{ {
path: '/registration', path: '/registration',
name: 'registration', name: 'registration',
......
...@@ -22,7 +22,7 @@ import {executeDDL, getMSCatalogs} from "@/pages/DataStudio/service"; ...@@ -22,7 +22,7 @@ import {executeDDL, getMSCatalogs} from "@/pages/DataStudio/service";
import FlinkSQL from "./FlinkSQL"; import FlinkSQL from "./FlinkSQL";
import {MetaStoreCatalogType, SessionType, TaskType} from "@/pages/DataStudio/model"; import {MetaStoreCatalogType, SessionType, TaskType} from "@/pages/DataStudio/model";
import {message, Modal} from "antd"; import {message, Modal} from "antd";
import {addOrUpdateData, getData, handleRemove} from "@/components/Common/crud"; import {addOrUpdateData, getData, handleRemove, postAll} from "@/components/Common/crud";
/*--- 保存sql ---*/ /*--- 保存sql ---*/
export function saveTask(current: any, dispatch: any) { export function saveTask(current: any, dispatch: any) {
...@@ -222,6 +222,10 @@ export function showAlertGroup(dispatch: any) { ...@@ -222,6 +222,10 @@ export function showAlertGroup(dispatch: any) {
export function showMetaDataTable(id: number) { export function showMetaDataTable(id: number) {
return getData('api/database/getSchemasAndTables', {id: id}); return getData('api/database/getSchemasAndTables', {id: id});
} }
/*--- 刷新 数据表样例数据 ---*/
export function showTableData(id: number,schemaName:String,tableName:String,option:{}) {
return postAll('api/database/queryData', {id: id,schemaName:schemaName,tableName:tableName,option:option});
}
/*--- 刷新 Flink Jobs ---*/ /*--- 刷新 Flink Jobs ---*/
export function showFlinkJobs(clusterId: number) { export function showFlinkJobs(clusterId: number) {
......
...@@ -70,4 +70,9 @@ export default { ...@@ -70,4 +70,9 @@ export default {
'menu.dev.ant-design': 'Ant Design UI框架', 'menu.dev.ant-design': 'Ant Design UI框架',
'menu.dev.ant-design.docs': '官方文档', 'menu.dev.ant-design.docs': '官方文档',
'menu.dev.ant-design.preview': '官方预览', 'menu.dev.ant-design.preview': '官方预览',
'menu.datacenter': '元数据中心',
'menu.datacenter.metadata': '元数据',
}; };
...@@ -31,7 +31,7 @@ const Tables = (props: any) => { ...@@ -31,7 +31,7 @@ const Tables = (props: any) => {
<Descriptions.Item label="Rows">{table.rows}</Descriptions.Item> <Descriptions.Item label="Rows">{table.rows}</Descriptions.Item>
<Descriptions.Item label="Type">{table.type}</Descriptions.Item> <Descriptions.Item label="Type">{table.type}</Descriptions.Item>
<Descriptions.Item label="Engine">{table.engine}</Descriptions.Item> <Descriptions.Item label="Engine">{table.engine}</Descriptions.Item>
<Descriptions.Item label="Options" span={3}> <Descriptions.Item label="Options" >
{table.options} {table.options}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="Status"><Badge status="processing" text="Running" /></Descriptions.Item> <Descriptions.Item label="Status"><Badge status="processing" text="Running" /></Descriptions.Item>
......
.margin_10{
margin: 10px;
}
.mrgin_top_40{
margin-top: 40px;
}
import {useEffect, useState} from "react";
import {Alert, AutoComplete, Button, Col, Input, Row, Spin, Table, Tooltip} from "antd";
import {showTableData} from "@/components/Studio/StudioEvent/DDL";
import styles from './index.less';
import { SearchOutlined} from "@ant-design/icons";
import Divider from "antd/es/divider";
const TableData = (props: any) => {
// 数据库id,数据库名称,表名称
const {dbId, table, schema,rows} = props;
// 表数据
const [tableData, setableData] = useState<{ columns: {}[],rowData: {}[] }>({columns: [], rowData: []});
// 加载状态
const [loading, setLoading] = useState<boolean>(false);
// 列名和列信息数据
const [columns, setColumns] = useState<string[]>([]);
const [errMsg, setErrMsg] = useState<{isErr:boolean,msg:string}>({isErr:false,msg:""});
//使用多选框进行自由列选择,屏蔽不需要看见的列,目前实现有些问题,暂时屏蔽
// 是否展开字段选择
// const [showFilter, setShowFilter] = useState(false);
// 是否全选,全选状态相关
// const [state, setState] = useState<{ checkedList: [], indeterminate: boolean, checkAll: boolean }>({checkedList: [], indeterminate: true, checkAll: false});
// 条件查询时联想输入使用
const [options, setOptions] = useState<{whereOption: {}[],orderOption:{}[] }>({whereOption:[],orderOption:[]});
// where输入框内容
const [optionInput, setOptionInput] = useState<{whereInput:string,orderInput:string}>({whereInput:"",orderInput:""});
const [page, setPage] = useState<{ page:number,pageSize:number }>({page:0 ,pageSize:10});
// const [defaultInput,setDefaultInput]
// 获取数据库数据
const fetchData = async (whereInput:string,orderInput:string) => {
setLoading(true);
let temp= {rowData: [], columns: []}
let option = {where:whereInput,
order:orderInput,limitStart:"0",limitEnd:"500"}
await showTableData(dbId, schema, table, option).then(result => {
if (result.code == 1){
setErrMsg({isErr:true,msg:result.datas.error})
}else {
setErrMsg({isErr:false,msg:""})
}
let data = result.datas;
setColumns(data.columns)
for (const columnsKey in data.columns) {
temp.columns.push({
title: data.columns[columnsKey],
dataIndex: data.columns[columnsKey],
key: data.columns[columnsKey],
ellipsis: true
})
}
for (const row of result.datas.rowData) {
row.key = row.id
temp.rowData.push(row)
}
})
setableData(temp);
setLoading(false)
};
useEffect(() => {
setColumns([])
setableData({columns: [], rowData: []})
setErrMsg({isErr:false,msg:""})
setOptions({whereOption:[],orderOption:[]})
setOptionInput({whereInput:"",orderInput:""})
setPage({page:0 ,pageSize:10})
setLoading(false)
fetchData("","");
}, [dbId, table, schema]);
//使用多选框进行自由列选择,屏蔽不需要看见的列,目前实现有些问题,暂时屏蔽
// // 单项选择监听
// const onChange = checkedList => {
// setState({
// checkedList,
// indeterminate:
// !!checkedList.length && checkedList.length < columns.length,
// checkAll: checkedList.length === columns.length
// });
// };
//
// //全选按钮监听
// const onCheckAllChange = e => {
// setState({
// checkedList: e.target.checked ? columns : [],
// indeterminate: false,
// checkAll: e.target.checked
// });
// };
// 条件查询时反馈联想信息
const handleRecommend = (value: string) => {
if (columns==null){
return []
}
let inputSplit: string[] = value.split(" ");
let recommend: { value: string }[] = []
var lastWord = inputSplit[inputSplit.length - 1]
inputSplit.pop()
console.log(inputSplit)
for (let column of columns) {
if (column.startsWith(lastWord)) {
let msg = inputSplit.join("") + " "+column
recommend.push({value: msg })
}
}
return recommend;
};
const handleWhere = (value:string) =>{
let result = handleRecommend(value)
setOptions({
whereOption:result,
orderOption:[]
})
}
const handleOrder = (value:string) =>{
let result = handleRecommend(value)
setOptions({
orderOption:result,
whereOption:[]
})
}
return (
<div>
<Spin spinning={loading} delay={500}>
<div className={styles.mrgin_top_40}>
{errMsg.isErr?(
<Alert
message="Error"
description={errMsg.msg}
type="error"
showIcon
/>
):<></>}
<Row>
<Col span={12}>
<AutoComplete
value={optionInput.whereInput}
options={options.whereOption}
style={{width: "100%"}}
onSearch={handleWhere}
onSelect={(value:string, option)=>{
setOptionInput({whereInput:value,
orderInput:optionInput.orderInput})
}}
>
<Input addonBefore="WHERE" placeholder="查询条件"
onChange={(value)=>{
setOptionInput({whereInput:value.target.value,
orderInput:optionInput.orderInput})
}}
/>
</AutoComplete>
</Col>
<Col span={12}>
<AutoComplete
value={optionInput.orderInput}
options={options.orderOption}
style={{width: "100%"}}
onSearch={handleOrder}
onSelect={(value:string, option)=>{
setOptionInput({whereInput:optionInput.whereInput,
orderInput:value})
}}
>
<Input addonBefore="ORDER BY" placeholder="排序" onChange={(value)=>{
setOptionInput({whereInput:optionInput.whereInput,
orderInput:value.target.value})
}}/>
</AutoComplete>
</Col>
</Row>
{/*//使用多选框进行自由列选择,屏蔽不需要看见的列,目前实现有些问题,暂时屏蔽*/}
{/*{showFilter ? (*/}
{/* <div>*/}
{/* <Checkbox*/}
{/* indeterminate={state.indeterminate}*/}
{/* onChange={onCheckAllChange}*/}
{/* checked={state.checkAll}*/}
{/* >*/}
{/* 全选*/}
{/* </Checkbox>*/}
{/* <br/>*/}
{/* <CheckboxGroup*/}
{/* options={columns}*/}
{/* value={state.checkedList}*/}
{/* onChange={onChange}*/}
{/* />*/}
{/* </div>*/}
{/*) : (<></>)}*/}
<Row className={styles.margin_10}>
<Col span={23}/>
{/*<Col span={1}>*/}
{/* <Tooltip title="字段过滤">*/}
{/* <Button type="primary" shape="circle" icon={<FilterOutlined/>} size="middle" onClick={(event) => {*/}
{/* setShowFilter(!showFilter)*/}
{/* }}/>*/}
{/* </Tooltip>*/}
{/*</Col>*/}
<Col span={1}>
<Tooltip title="查询">
<Button type="primary" shape="circle" icon={<SearchOutlined/>} size="middle" onClick={(event)=>{
fetchData(optionInput.whereInput,optionInput.orderInput)
}}/>
</Tooltip>
</Col>
</Row>
</div>
<Divider orientation="left" plain>数据</Divider>
<div>
<Table style={{height: '95vh'}}
columns={tableData.columns}
dataSource={tableData.rowData}
pagination={{pageSize:page.pageSize,
onChange: (pageNum, pageSize) => {
setPage({page:pageNum,pageSize:pageSize});
}}}
scroll={{y: "80vh", x: true}}
/>
</div>
</Spin>
</div>
)
};
export default TableData
.container {
background: #ffffff;
height: 95vh;
padding: 8px
}
.content-height{
height: 100%;
}
import { PageContainer } from '@ant-design/pro-layout'; //
import styles from './index.less';
import { Row, Col, Tabs, Select, Tag, Empty, Tree, Spin } from 'antd';
import React, { Key, useEffect, useState } from 'react';
import { showMetaDataTable } from '@/components/Studio/StudioEvent/DDL';
import { Scrollbars } from 'react-custom-scrollbars';
import { getData } from '@/components/Common/crud';
import {
BarsOutlined,
ConsoleSqlOutlined,
DatabaseOutlined,
DownOutlined,
ReadOutlined,
TableOutlined,
} from '@ant-design/icons';
import { TreeDataNode } from '@/components/Studio/StudioTree/Function';
import Tables from '@/pages/DataBase/Tables';
import Columns from '@/pages/DataBase/Columns';
import Divider from 'antd/es/divider';
import Generation from '@/pages/DataBase/Generation';
import TableData from '@/pages/DataCenter/MetaData/TableData';
const { DirectoryTree } = Tree;
const { TabPane } = Tabs;
const Container: React.FC<{}> = (props: any) => {
// const { dispatch} = props;
let [database, setDatabase] = useState([
{
id: '',
name: '',
alias: '',
type: '',
enabled: '',
},
]);
const [databaseId, setDatabaseId] = useState<number>();
const [treeData, setTreeData] = useState<[]>([]);
const [row, setRow] = useState<TreeDataNode>();
const [loadingDatabase, setloadingDatabase] = useState(false);
const fetchDatabaseList = async () => {
const res = getData('api/database/listEnabledAll');
await res.then((result) => {
database = result.datas;
});
setDatabase(database);
};
const fetchDatabase = async (databaseId: number) => {
setloadingDatabase(true);
setDatabaseId(databaseId);
const res = showMetaDataTable(databaseId);
await res.then((result) => {
let tables = result.datas;
if (tables) {
for (let i = 0; i < tables.length; i++) {
tables[i].title = tables[i].name;
tables[i].key = tables[i].name;
tables[i].icon = <DatabaseOutlined />;
tables[i].children = tables[i].tables;
for (let j = 0; j < tables[i].children.length; j++) {
tables[i].children[j].title = tables[i].children[j].name;
tables[i].children[j].key = tables[i].name + '.' + tables[i].children[j].name;
tables[i].children[j].icon = <TableOutlined />;
tables[i].children[j].isLeaf = true;
tables[i].children[j].schema = tables[i].name;
tables[i].children[j].table = tables[i].children[j].name;
}
}
setTreeData(tables);
} else {
setTreeData([]);
}
});
setloadingDatabase(false);
};
useEffect(() => {
fetchDatabaseList();
}, []);
const getDataBaseOptions = () => {
return (
<>
{database.map(({ id, name, alias, type, enabled }) => (
<Select.Option
key={id}
value={id}
label={
<>
<Tag color={enabled ? 'processing' : 'error'}>{type}</Tag>
{alias === '' ? name : alias}
</>
}
>
<Tag color={enabled ? 'processing' : 'error'}>{type}</Tag>
{alias === '' ? name : alias}
</Select.Option>
))}
</>
);
};
const onChangeDataBase = (value: number) => {
onRefreshTreeData(value);
};
const showTableInfo = (selected: boolean, node: TreeDataNode) => {
if (node.isLeaf) {
setRow(node);
}
};
const onRefreshTreeData = (databaseId: number) => {
if (!databaseId) return;
fetchDatabase(databaseId);
};
return (
<div className={styles.container}>
<div>
<>
<Row gutter={24}>
<Col span={4}>
<Select
style={{
width: '90%',
}}
placeholder="选择数据源"
optionLabelProp="label"
onChange={onChangeDataBase}
>
{getDataBaseOptions()}
</Select>
<Spin spinning={loadingDatabase} delay={500}>
<Scrollbars
style={{
height: '90vh',
}}
>
{treeData.length > 0 ? (
<DirectoryTree
showIcon
switcherIcon={<DownOutlined />}
treeData={treeData}
onSelect={(
selectedKeys: Key[],
{ event, selected, node, selectedNodes, nativeEvent }
) => {
showTableInfo(selected, node);
}}
/>
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
)}
</Scrollbars>
</Spin>
</Col>
<Col span={20}>
<div>
<div>
<Tabs defaultActiveKey="describe">
<TabPane
tab={
<span>
<ReadOutlined />
描述
</span>
}
key="describe"
>
<Divider orientation="left" plain>
表信息
</Divider>
{row ? (
<Tables table={row} />
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
)}
<Divider orientation="left" plain>
字段信息
</Divider>
{row ? (
<Columns dbId={databaseId} schema={row.schema} table={row.table} />
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
)}
</TabPane>
<TabPane
tab={
<span>
<BarsOutlined />
数据查询
</span>
}
key="exampleData"
>
{row ? (
<TableData dbId={databaseId} schema={row.schema} table={row.table} rows={row.rows}/>
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
)}
</TabPane>
<TabPane
tab={
<span>
<ConsoleSqlOutlined />
SQL 生成
</span>
}
key="sqlGeneration"
>
{row ? (
<Generation dbId={databaseId} schema={row.schema} table={row.table} />
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
)}
</TabPane>
</Tabs>
</div>
</div>
</Col>
</Row>
</>
</div>
</div>
);
};
export default () => {
return (
<PageContainer>
<Container />
</PageContainer>
);
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment