Commit 36a5d11e authored by wenmo's avatar wenmo

StudioDataBase

parent a0d8113c
package com.dlink.controller; package com.dlink.controller;
import com.dlink.assertion.Asserts;
import com.dlink.common.result.ProTableResult; import com.dlink.common.result.ProTableResult;
import com.dlink.common.result.Result; import com.dlink.common.result.Result;
import com.dlink.model.DataBase; import com.dlink.model.DataBase;
...@@ -78,10 +79,44 @@ public class DataBaseController { ...@@ -78,10 +79,44 @@ public class DataBaseController {
} }
/** /**
* 全部心跳监测 * 获取可用的集群列表
*/
@GetMapping("/listEnabledAll")
public Result listEnabledAll() {
List<DataBase> dataBases = databaseService.listEnabledAll();
return Result.succeed(dataBases,"获取成功");
}
/**
* 连接测试
*/ */
@PostMapping("/testConnect") @PostMapping("/testConnect")
public Result testConnect(@RequestBody DataBase database) { public Result testConnect(@RequestBody DataBase database) {
return Result.succeed(databaseService.checkHeartBeat(database),"获取成功"); return Result.succeed(databaseService.checkHeartBeat(database),"获取成功");
} }
/**
* 全部心跳监测
*/
@PostMapping("/checkHeartBeats")
public Result checkHeartBeats() {
List<DataBase> dataBases = databaseService.listEnabledAll();
for (int i = 0; i < dataBases.size(); i++) {
DataBase dataBase = dataBases.get(i);
databaseService.checkHeartBeat(dataBase);
databaseService.updateById(dataBase);
}
return Result.succeed("状态刷新完成");
}
/**
* 心跳检测指定ID
*/
@GetMapping("/checkHeartBeatById")
public Result checkHeartBeatById(@RequestParam Integer id) {
DataBase dataBase = databaseService.getById(id);
Asserts.checkNotNull(dataBase,"该数据源不存在!");
databaseService.checkHeartBeat(dataBase);
databaseService.updateById(dataBase);
return Result.succeed(dataBase,"状态刷新完成");
}
} }
\ No newline at end of file
...@@ -3,6 +3,8 @@ package com.dlink.service; ...@@ -3,6 +3,8 @@ package com.dlink.service;
import com.dlink.db.service.ISuperService; import com.dlink.db.service.ISuperService;
import com.dlink.model.DataBase; import com.dlink.model.DataBase;
import java.util.List;
/** /**
* DataBaseService * DataBaseService
* *
...@@ -14,4 +16,6 @@ public interface DataBaseService extends ISuperService<DataBase> { ...@@ -14,4 +16,6 @@ public interface DataBaseService extends ISuperService<DataBase> {
boolean checkHeartBeat(DataBase dataBase); boolean checkHeartBeat(DataBase dataBase);
boolean saveOrUpdateDataBase(DataBase dataBase); boolean saveOrUpdateDataBase(DataBase dataBase);
List<DataBase> listEnabledAll();
} }
package com.dlink.service.impl; package com.dlink.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dlink.assertion.Asserts; import com.dlink.assertion.Asserts;
import com.dlink.db.service.impl.SuperServiceImpl; import com.dlink.db.service.impl.SuperServiceImpl;
import com.dlink.mapper.DataBaseMapper; import com.dlink.mapper.DataBaseMapper;
...@@ -9,6 +10,7 @@ import com.dlink.service.DataBaseService; ...@@ -9,6 +10,7 @@ import com.dlink.service.DataBaseService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
/** /**
...@@ -53,4 +55,9 @@ public class DataBaseServiceImpl extends SuperServiceImpl<DataBaseMapper, DataBa ...@@ -53,4 +55,9 @@ public class DataBaseServiceImpl extends SuperServiceImpl<DataBaseMapper, DataBa
return updateById(dataBase); return updateById(dataBase);
} }
} }
@Override
public List<DataBase> listEnabledAll() {
return this.list(new QueryWrapper<DataBase>().eq("enabled",1));
}
} }
...@@ -110,3 +110,13 @@ export function showCluster(dispatch: any) { ...@@ -110,3 +110,13 @@ export function showCluster(dispatch: any) {
}); });
}); });
} }
/*--- 刷新 数据源 ---*/
export function showDataBase(dispatch: any) {
const res = getData('api/database/listEnabledAll');
res.then((result) => {
result.datas && dispatch && dispatch({
type: "Studio/saveDataBase",
payload: result.datas,
});
});
}
import {
message, Input, Button, Space, Table, Dropdown, Menu, Empty, Divider,
Tooltip
} from "antd";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi";
import {useState} from "react";
import styles from "./index.less";
import {
SearchOutlined,
DownOutlined,
DeleteOutlined,
CommentOutlined,
PoweroffOutlined,
PlusOutlined
} from '@ant-design/icons';
import React from "react";
import {showDataBase} from "../../StudioEvent/DDL";
import DBForm from "@/pages/DataBase/components/DBForm";
const StudioDataBase = (props: any) => {
const {database, dispatch} = props;
const [chooseDBModalVisible, handleDBFormModalVisible] = useState<boolean>(false);
const [values, setValues] = useState<any>({});
const getColumns = () => {
let columns: any = [{
title: "名称",
dataIndex: "alias",
key: "alias",
sorter: true,
}, {
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => [
<a
onClick={() => {
message.success('敬请期待');
}}
>
详情
</a>, <Divider type="vertical"/>, <a
onClick={() => {
message.success('敬请期待');
}}
>
管理
</a>
],
},];
return columns;
};
const onRefreshDataBase = () => {
showDataBase(dispatch);
};
const onCreateDataBase = () => {
setValues({});
handleDBFormModalVisible(true);
};
return (
<>
<Tooltip title="新建数据源">
<Button
type="text"
icon={<PlusOutlined/>}
onClick={onCreateDataBase}
/>
</Tooltip>
<div style={{float: "right"}}>
<Tooltip title="刷新数据源">
<Button
type="text"
icon={<SearchOutlined/>}
onClick={onRefreshDataBase}
/>
</Tooltip>
</div>
{database.length > 0 ? (
<Table dataSource={database} columns={getColumns()} size="small"/>) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)}
<DBForm
onCancel={() => {
handleDBFormModalVisible(false);
setValues({});
}}
modalVisible={chooseDBModalVisible}
onSubmit={() => {
showDataBase(dispatch);
}}
values={values}
/>
</>
);
};
export default connect(({Studio}: { Studio: StateType }) => ({
database: Studio.database,
}))(StudioDataBase);
...@@ -5,6 +5,8 @@ import {connect} from "umi"; ...@@ -5,6 +5,8 @@ import {connect} from "umi";
import styles from "./index.less"; import styles from "./index.less";
import StudioTree from "../StudioTree"; import StudioTree from "../StudioTree";
import StudioConnector from "./StudioConnector"; import StudioConnector from "./StudioConnector";
import React from "react";
import StudioDataBase from "./StudioDataBase";
const { TabPane } = Tabs; const { TabPane } = Tabs;
...@@ -25,7 +27,7 @@ const StudioLeftTool = (props:any) => { ...@@ -25,7 +27,7 @@ const StudioLeftTool = (props:any) => {
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</TabPane> </TabPane>
<TabPane tab={<span><DatabaseOutlined /> 数据源</span>} key="DataSource" > <TabPane tab={<span><DatabaseOutlined /> 数据源</span>} key="DataSource" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> <StudioDataBase />
</TabPane> </TabPane>
<TabPane tab={<span><AppstoreOutlined /> 元数据</span>} key="MetaData" > <TabPane tab={<span><AppstoreOutlined /> 元数据</span>} key="MetaData" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
......
...@@ -250,8 +250,8 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -250,8 +250,8 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
position: 'absolute', position: 'absolute',
// left: `${pageX - 50}px`, // left: `${pageX - 50}px`,
// top: `${pageY - 202}px`, // top: `${pageY - 202}px`,
left: `${pageX - 25}px`, left: `${pageX}px`,
top: `${pageY - 140}px`, top: `${pageY - 120}px`,
}; };
let menuItems; let menuItems;
if(rightClickNode&&rightClickNode.isLeaf){ if(rightClickNode&&rightClickNode.isLeaf){
......
...@@ -11,7 +11,7 @@ import {StateType} from "@/pages/FlinkSqlStudio/model"; ...@@ -11,7 +11,7 @@ import {StateType} from "@/pages/FlinkSqlStudio/model";
import StudioConsole from "./StudioConsole"; import StudioConsole from "./StudioConsole";
import StudioLeftTool from "./StudioLeftTool"; import StudioLeftTool from "./StudioLeftTool";
import StudioRightTool from "./StudioRightTool"; import StudioRightTool from "./StudioRightTool";
import {listSession, showCluster} from "@/components/Studio/StudioEvent/DDL"; import {listSession, showCluster, showDataBase} from "@/components/Studio/StudioEvent/DDL";
type StudioProps = { type StudioProps = {
rightClickMenu:StateType['rightClickMenu']; rightClickMenu:StateType['rightClickMenu'];
...@@ -24,6 +24,7 @@ const Studio: React.FC<StudioProps> = (props) => { ...@@ -24,6 +24,7 @@ const Studio: React.FC<StudioProps> = (props) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
showCluster(dispatch); showCluster(dispatch);
showDataBase(dispatch);
listSession(dispatch); listSession(dispatch);
const onClick=()=>{ const onClick=()=>{
...@@ -36,7 +37,7 @@ const Studio: React.FC<StudioProps> = (props) => { ...@@ -36,7 +37,7 @@ const Studio: React.FC<StudioProps> = (props) => {
}; };
return ( return (
<div onClick={onClick}> <div onClick={onClick} style={{'margin':'-24px'}}>
<StudioMenu form={form}/> <StudioMenu form={form}/>
<Card bordered={false} className={styles.card} size="small" id="studio_card"> <Card bordered={false} className={styles.card} size="small" id="studio_card">
<Row> <Row>
......
...@@ -43,6 +43,10 @@ const DBForm: React.FC<UpdateFormProps> = (props) => { ...@@ -43,6 +43,10 @@ const DBForm: React.FC<UpdateFormProps> = (props) => {
const [dbType, setDbType] = useState<string>(); const [dbType, setDbType] = useState<string>();
const chooseOne = (item:DataBaseItem)=>{ const chooseOne = (item:DataBaseItem)=>{
if(item.type!='MySql'){
message.success('敬请期待');
return;
}
setDbType(item.type); setDbType(item.type);
}; };
......
...@@ -20,6 +20,7 @@ import {ActionType} from "@ant-design/pro-table"; ...@@ -20,6 +20,7 @@ import {ActionType} from "@ant-design/pro-table";
import styles from './index.less'; import styles from './index.less';
import {DataBaseItem} from "@/pages/DataBase/data"; import {DataBaseItem} from "@/pages/DataBase/data";
import {checkHeartBeat} from "@/pages/DataBase/service";
const {Text} = Typography; const {Text} = Typography;
...@@ -41,6 +42,10 @@ const DataBaseTableList: React.FC<{}> = (props: any) => { ...@@ -41,6 +42,10 @@ const DataBaseTableList: React.FC<{}> = (props: any) => {
handleDBFormModalVisible(true); handleDBFormModalVisible(true);
}; };
const onCheckHeartBeat = (row: DataBaseItem) => {
checkHeartBeat(row.id);
actionRef.current?.reloadAndRest?.();
};
return ( return (
<PageContainer> <PageContainer>
...@@ -78,9 +83,11 @@ const DataBaseTableList: React.FC<{}> = (props: any) => { ...@@ -78,9 +83,11 @@ const DataBaseTableList: React.FC<{}> = (props: any) => {
</div> </div>
} }
actions={[ actions={[
<SettingOutlined key="setting"/>, <HeartOutlined key="setting" onClick={()=>{
onCheckHeartBeat(row);
}}/>,
<EditOutlined key="edit" onClick={() => { <EditOutlined key="edit" onClick={() => {
onEdit(row) onEdit(row);
}}/>, }}/>,
<EllipsisOutlined key="ellipsis"/>, <EllipsisOutlined key="ellipsis"/>,
]} ]}
......
import request from "umi-request"; import request from "umi-request";
import {handleAddOrUpdate, handleOption, postAll} from "@/components/Common/crud"; import {getInfoById, handleAddOrUpdate, handleOption, postAll} from "@/components/Common/crud";
import {DataBaseItem} from "@/pages/DataBase/data"; import {DataBaseItem} from "@/pages/DataBase/data";
import {message} from "antd"; import {message} from "antd";
import {Protocol} from "puppeteer-core";
export async function createOrModifyDatabase(databse: DataBaseItem) { export async function createOrModifyDatabase(databse: DataBaseItem) {
return handleAddOrUpdate('/api/database', databse); return handleAddOrUpdate('/api/database', databse);
...@@ -18,3 +19,15 @@ export async function testDatabaseConnect(databse: DataBaseItem) { ...@@ -18,3 +19,15 @@ export async function testDatabaseConnect(databse: DataBaseItem) {
message.error('请求失败,请重试'); message.error('请求失败,请重试');
} }
} }
export async function checkHeartBeat(id: number) {
const hide = message.loading('正在检测心跳');
try {
const {datas} = await getInfoById('/api/database/checkHeartBeatById',id);
hide();
datas.status==1?message.success("数据源心跳正常,检测时间为"+datas.heartbeatTime):message.error("数据源心跳异常,检测时间为"+datas.heartbeatTime);
} catch (error) {
hide();
message.error('请求失败,请重试');
}
}
...@@ -17,6 +17,25 @@ export type ClusterType = { ...@@ -17,6 +17,25 @@ export type ClusterType = {
updateTime: Date, updateTime: Date,
} }
export type DataBaseType = {
id: number,
name: string,
alias: string,
groupName: string,
type: string,
url: string,
username: string,
password: string,
note: string,
dbVersion: string,
status: boolean,
healthTime: Date,
heartbeatTime: Date,
enabled: boolean,
createTime: Date,
updateTime: Date,
};
export type TaskType = { export type TaskType = {
id?: number, id?: number,
catalogueId?: number, catalogueId?: number,
...@@ -62,13 +81,6 @@ export type TabsType = { ...@@ -62,13 +81,6 @@ export type TabsType = {
panes?: TabsItemType[]; panes?: TabsItemType[];
} }
export type RightClickMenu = {
pageX: number,
pageY: number,
id: number,
name: string
};
export type ConnectorType = { export type ConnectorType = {
tablename: string; tablename: string;
} }
...@@ -86,8 +98,10 @@ export type SessionType = { ...@@ -86,8 +98,10 @@ export type SessionType = {
createTime?: string; createTime?: string;
connectors: ConnectorType[]; connectors: ConnectorType[];
} }
export type StateType = { export type StateType = {
cluster?: ClusterType[]; cluster?: ClusterType[];
database?: DataBaseType[];
currentSession?: SessionType; currentSession?: SessionType;
current?: TabsItemType; current?: TabsItemType;
sql?: string; sql?: string;
...@@ -121,6 +135,7 @@ export type ModelType = { ...@@ -121,6 +135,7 @@ export type ModelType = {
quitCurrentSession: Reducer<StateType>; quitCurrentSession: Reducer<StateType>;
saveResult: Reducer<StateType>; saveResult: Reducer<StateType>;
saveCluster: Reducer<StateType>; saveCluster: Reducer<StateType>;
saveDataBase: Reducer<StateType>;
}; };
}; };
...@@ -128,6 +143,7 @@ const Model: ModelType = { ...@@ -128,6 +143,7 @@ const Model: ModelType = {
namespace: 'Studio', namespace: 'Studio',
state: { state: {
cluster: [], cluster: [],
database: [],
currentSession: { currentSession: {
connectors: [], connectors: [],
}, },
...@@ -316,7 +332,6 @@ const Model: ModelType = { ...@@ -316,7 +332,6 @@ const Model: ModelType = {
}; };
}, },
saveSession(state, {payload}) { saveSession(state, {payload}) {
console.log(payload);
return { return {
...state, ...state,
session: [...payload], session: [...payload],
...@@ -358,6 +373,11 @@ const Model: ModelType = { ...@@ -358,6 +373,11 @@ const Model: ModelType = {
...state, ...state,
cluster: payload, cluster: payload,
}; };
},saveDataBase(state, {payload}) {
return {
...state,
database: payload,
};
}, },
}, },
}; };
......
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