Commit 2b9841c5 authored by wenmo's avatar wenmo

会话管理

parent 6961f0f3
...@@ -7,6 +7,7 @@ import com.dlink.explainer.ca.TableCANode; ...@@ -7,6 +7,7 @@ import com.dlink.explainer.ca.TableCANode;
import com.dlink.job.JobResult; import com.dlink.job.JobResult;
import com.dlink.result.IResult; import com.dlink.result.IResult;
import com.dlink.result.SelectResult; import com.dlink.result.SelectResult;
import com.dlink.session.ExecutorEntity;
import com.dlink.session.SessionInfo; import com.dlink.session.SessionInfo;
import java.util.List; import java.util.List;
...@@ -25,7 +26,7 @@ public interface StudioService { ...@@ -25,7 +26,7 @@ public interface StudioService {
SelectResult getJobData(String jobId); SelectResult getJobData(String jobId);
boolean createSession(SessionDTO sessionDTO,String createUser); SessionInfo createSession(SessionDTO sessionDTO, String createUser);
boolean clearSession(String session); boolean clearSession(String session);
......
...@@ -13,6 +13,7 @@ import com.dlink.result.IResult; ...@@ -13,6 +13,7 @@ import com.dlink.result.IResult;
import com.dlink.result.SelectResult; import com.dlink.result.SelectResult;
import com.dlink.service.ClusterService; import com.dlink.service.ClusterService;
import com.dlink.service.StudioService; import com.dlink.service.StudioService;
import com.dlink.session.ExecutorEntity;
import com.dlink.session.SessionConfig; import com.dlink.session.SessionConfig;
import com.dlink.session.SessionInfo; import com.dlink.session.SessionInfo;
import com.dlink.session.SessionPool; import com.dlink.session.SessionPool;
...@@ -59,7 +60,7 @@ public class StudioServiceImpl implements StudioService { ...@@ -59,7 +60,7 @@ public class StudioServiceImpl implements StudioService {
} }
@Override @Override
public boolean createSession(SessionDTO sessionDTO,String createUser) { public SessionInfo createSession(SessionDTO sessionDTO, String createUser) {
if(sessionDTO.isUseRemote()) { if(sessionDTO.isUseRemote()) {
Cluster cluster = clusterService.getById(sessionDTO.getClusterId()); Cluster cluster = clusterService.getById(sessionDTO.getClusterId());
SessionConfig sessionConfig = SessionConfig.build( SessionConfig sessionConfig = SessionConfig.build(
......
...@@ -271,9 +271,9 @@ public class JobManager extends RunTime { ...@@ -271,9 +271,9 @@ public class JobManager extends RunTime {
return ResultPool.get(jobId); return ResultPool.get(jobId);
} }
public static boolean createSession(String session, SessionConfig sessionConfig,String createUser){ public static SessionInfo createSession(String session, SessionConfig sessionConfig,String createUser){
if(SessionPool.exist(session)){ if(SessionPool.exist(session)){
return false; return SessionPool.getInfo(session);
} }
Executor sessionExecutor = null; Executor sessionExecutor = null;
if (sessionConfig.isUseRemote()) { if (sessionConfig.isUseRemote()) {
...@@ -281,8 +281,9 @@ public class JobManager extends RunTime { ...@@ -281,8 +281,9 @@ public class JobManager extends RunTime {
} else { } else {
sessionExecutor = Executor.buildLocalExecutor(sessionConfig.getExecutorSetting()); sessionExecutor = Executor.buildLocalExecutor(sessionConfig.getExecutorSetting());
} }
SessionPool.push(new ExecutorEntity(session,sessionConfig,createUser,LocalDateTime.now(), sessionExecutor)); ExecutorEntity executorEntity = new ExecutorEntity(session, sessionConfig, createUser, LocalDateTime.now(), sessionExecutor);
return true; SessionPool.push(executorEntity);
return SessionInfo.build(executorEntity);
} }
public static List<SessionInfo> listSession(String createUser){ public static List<SessionInfo> listSession(String createUser){
......
...@@ -72,4 +72,13 @@ public class SessionPool { ...@@ -72,4 +72,13 @@ public class SessionPool {
} }
return sessionInfos; return sessionInfos;
} }
public static SessionInfo getInfo(String sessionId){
ExecutorEntity executorEntity = get(sessionId);
if(executorEntity!=null){
return SessionInfo.build(executorEntity);
}else {
return null;
}
}
} }
...@@ -157,7 +157,7 @@ const StudioHistory = (props: any) => { ...@@ -157,7 +157,7 @@ const StudioHistory = (props: any) => {
{(row.status==2) ? {(row.status==2) ?
(<><Badge status="success"/><Text type="success">SUCCESS</Text></>): (<><Badge status="success"/><Text type="success">SUCCESS</Text></>):
(row.status==1) ? (row.status==1) ?
<><Badge status="error"/><Text type="secondary">RUNNING</Text></> : <><Badge status="success"/><Text type="secondary">RUNNING</Text></> :
(row.status==3) ? (row.status==3) ?
<><Badge status="error"/><Text type="danger">FAILED</Text></> : <><Badge status="error"/><Text type="danger">FAILED</Text></> :
(row.status==4) ? (row.status==4) ?
......
import {executeDDL} from "@/pages/FlinkSqlStudio/service"; import {executeDDL} from "@/pages/FlinkSqlStudio/service";
import FlinkSQL from "./FlinkSQL"; import FlinkSQL from "./FlinkSQL";
import {SessionType, TaskType} from "@/pages/FlinkSqlStudio/model"; import {SessionType} from "@/pages/FlinkSqlStudio/model";
import {Modal} from "antd"; import {Modal,message} from "antd";
import {getData, handleRemove} from "@/components/Common/crud"; import {addOrUpdateData, getData, handleRemove} from "@/components/Common/crud";
/*--- 创建会话 ---*/
export function createSession(session: SessionType,dispatch: any) {
const res = addOrUpdateData("api/studio/createSession",session)
res.then((result) => {
message.success(`创建会话【${session.session}】成功!`);
result.datas&&changeSession(result.datas,dispatch);
listSession(dispatch);
});
}
/*--- 查询会话列表 ---*/
export function listSession(dispatch: any) {
const res = getData("api/studio/listSession");
res.then((result)=>{
console.log(result.datas);
dispatch && dispatch({
type: "Studio/saveSession",
payload: result.datas,
});
});
}
/*--- 切换会话 ---*/
export function changeSession(session: SessionType, dispatch: any) { export function changeSession(session: SessionType, dispatch: any) {
dispatch && dispatch({ dispatch && dispatch({
type: "Studio/refreshCurrentSession", type: "Studio/refreshCurrentSession",
...@@ -13,13 +33,31 @@ export function changeSession(session: SessionType, dispatch: any) { ...@@ -13,13 +33,31 @@ export function changeSession(session: SessionType, dispatch: any) {
showTables(session.session,dispatch); showTables(session.session,dispatch);
},200); },200);
} }
/*--- 退出会话 ---*/
export function quitSession( dispatch: any) { export function quitSession( dispatch: any) {
dispatch && dispatch({ dispatch && dispatch({
type: "Studio/quitCurrentSession", type: "Studio/quitCurrentSession",
}); });
} }
/*--- 注销会话 ---*/
export function clearSession(session: string, dispatch: any) {
Modal.confirm({
title: '确认注销会话【' + session + '】?',
okText: '确认',
cancelText: '取消',
onOk: async () => {
let para = {
id: session,
};
const res = handleRemove('/api/studio/clearSession', [para]);
res.then((result) => {
quitSession(dispatch);
listSession(dispatch);
});
}
});
}
/*--- 刷新 Catalog Table ---*/
export function showTables(session: string, dispatch: any) { export function showTables(session: string, dispatch: any) {
if(session==null||session==''){ if(session==null||session==''){
return; return;
...@@ -43,7 +81,7 @@ export function showTables(session: string, dispatch: any) { ...@@ -43,7 +81,7 @@ export function showTables(session: string, dispatch: any) {
}); });
}); });
} }
/*--- 移除 Catalog Table ---*/
export function removeTable(tablename: string, session: string, dispatch: any) { export function removeTable(tablename: string, session: string, dispatch: any) {
Modal.confirm({ Modal.confirm({
title: '确定删除表【' + tablename + '】吗?', title: '确定删除表【' + tablename + '】吗?',
...@@ -62,24 +100,7 @@ export function removeTable(tablename: string, session: string, dispatch: any) { ...@@ -62,24 +100,7 @@ export function removeTable(tablename: string, session: string, dispatch: any) {
} }
}); });
} }
/*--- 刷新 集群 ---*/
export function clearSession(session: string, dispatch: any) {
Modal.confirm({
title: '确认清空会话【' + session + '】?',
okText: '确认',
cancelText: '取消',
onOk: async () => {
let para = {
id: session,
};
const res = handleRemove('/api/studio/clearSession', [para]);
res.then((result) => {
quitSession(dispatch);
});
}
});
}
export function showCluster(dispatch: any) { export function showCluster(dispatch: any) {
const res = getData('api/cluster/listEnabledAll'); const res = getData('api/cluster/listEnabledAll');
res.then((result) => { res.then((result) => {
......
import {message, Input, Button, Space, Table, Dropdown, Menu, Empty,Divider, import {
Tooltip} from "antd"; message, Input, Button, Space, Table, Dropdown, Menu, Empty, Divider,
Tooltip
} from "antd";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi"; import {connect} from "umi";
import {useState} from "react"; import {useState} from "react";
import styles from "./index.less"; import styles from "./index.less";
import { SearchOutlined,DownOutlined,DeleteOutlined,CommentOutlined ,PoweroffOutlined,PlusOutlined} from '@ant-design/icons'; import {
SearchOutlined,
DownOutlined,
DeleteOutlined,
CommentOutlined,
PoweroffOutlined,
PlusOutlined
} from '@ant-design/icons';
import React from "react"; import React from "react";
import {removeTable, showTables, clearSession, changeSession, quitSession} from "@/components/Studio/StudioEvent/DDL"; import {
removeTable, showTables, clearSession, changeSession, quitSession,
createSession, listSession
} from "@/components/Studio/StudioEvent/DDL";
import { import {
ModalForm, ModalForm,
} from '@ant-design/pro-form'; } from '@ant-design/pro-form';
...@@ -14,13 +26,13 @@ import ProDescriptions from '@ant-design/pro-descriptions'; ...@@ -14,13 +26,13 @@ import ProDescriptions from '@ant-design/pro-descriptions';
import {getData, handleAddOrUpdate} from "@/components/Common/crud"; import {getData, handleAddOrUpdate} from "@/components/Common/crud";
import SessionForm from "@/components/Studio/StudioLeftTool/StudioConnector/components/SessionForm"; import SessionForm from "@/components/Studio/StudioLeftTool/StudioConnector/components/SessionForm";
const StudioConnector = (props:any) => { const StudioConnector = (props: any) => {
const {current,dispatch,currentSession} = props; const {current, dispatch, currentSession, session} = props;
const [tableData,setTableData] = useState<[]>([]); const [tableData, setTableData] = useState<[]>([]);
const [loadings,setLoadings] = useState<boolean[]>([]); const [loadings, setLoadings] = useState<boolean[]>([]);
const [searchText,setSearchText] = useState<string>(''); const [searchText, setSearchText] = useState<string>('');
const [searchedColumn,setSearchedColumn] = useState<string>(''); const [searchedColumn, setSearchedColumn] = useState<string>('');
const [modalVisit, setModalVisit] = useState(false); const [modalVisit, setModalVisit] = useState(false);
const [type, setType] = useState<number>(); const [type, setType] = useState<number>();
const [sessionData, setSessionData] = useState<{}>(); const [sessionData, setSessionData] = useState<{}>();
...@@ -28,26 +40,26 @@ const StudioConnector = (props:any) => { ...@@ -28,26 +40,26 @@ const StudioConnector = (props:any) => {
const getColumnSearchProps = (dIndex) => ({ const getColumnSearchProps = (dIndex) => ({
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => ( filterDropdown: ({setSelectedKeys, selectedKeys, confirm, clearFilters}) => (
<div style={{ padding: 8 }}> <div style={{padding: 8}}>
<Input <Input
placeholder={`Search ${dIndex}`} placeholder={`Search ${dIndex}`}
value={selectedKeys[0]} value={selectedKeys[0]}
onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])} onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={() => handleSearch(selectedKeys, confirm, dIndex)} onPressEnter={() => handleSearch(selectedKeys, confirm, dIndex)}
style={{ marginBottom: 8, display: 'block' }} style={{marginBottom: 8, display: 'block'}}
/> />
<Space> <Space>
<Button <Button
type="primary" type="primary"
onClick={() => handleSearch(selectedKeys, confirm, dIndex)} onClick={() => handleSearch(selectedKeys, confirm, dIndex)}
icon={<SearchOutlined />} icon={<SearchOutlined/>}
size="small" size="small"
style={{ width: 90 }} style={{width: 90}}
> >
搜索 搜索
</Button> </Button>
<Button onClick={() => handleReset(clearFilters)} size="small" style={{ width: 90 }}> <Button onClick={() => handleReset(clearFilters)} size="small" style={{width: 90}}>
重置 重置
</Button> </Button>
<Button <Button
...@@ -63,7 +75,7 @@ const StudioConnector = (props:any) => { ...@@ -63,7 +75,7 @@ const StudioConnector = (props:any) => {
</Space> </Space>
</div> </div>
), ),
filterIcon: filtered => <SearchOutlined style={{ color: filtered ? '#1890ff' : undefined }} />, filterIcon: filtered => <SearchOutlined style={{color: filtered ? '#1890ff' : undefined}}/>,
onFilter: (value, record) => onFilter: (value, record) =>
record[dIndex] record[dIndex]
? record[dIndex].toString().toLowerCase().includes(value.toLowerCase()) ? record[dIndex].toString().toLowerCase().includes(value.toLowerCase())
...@@ -93,7 +105,7 @@ const StudioConnector = (props:any) => { ...@@ -93,7 +105,7 @@ const StudioConnector = (props:any) => {
}; };
const MoreBtn: React.FC<{ const MoreBtn: React.FC<{
item:any item: any
}> = ({item}) => ( }> = ({item}) => (
<Dropdown <Dropdown
overlay={ overlay={
...@@ -109,42 +121,42 @@ const StudioConnector = (props:any) => { ...@@ -109,42 +121,42 @@ const StudioConnector = (props:any) => {
</Dropdown> </Dropdown>
); );
const keyEvent=(key, item)=>{ const keyEvent = (key, item) => {
if(key=='delete'){ if (key == 'delete') {
removeTable(item.tablename,currentSession.session,dispatch); removeTable(item.tablename, currentSession.session, dispatch);
}else{ } else {
message.warn("敬请期待"); message.warn("敬请期待");
} }
}; };
const keySessionsEvent=(key, item)=>{ const keySessionsEvent = (key, item) => {
if(key=='delete'){ if (key == 'delete') {
clearSession(item.session,current.task,dispatch); clearSession(item.session, dispatch);
}else if(key=='connect'){ } else if (key == 'connect') {
changeSession(item,dispatch); changeSession(item, dispatch);
message.success('连接共享会话【'+item.session+'】成功!'); message.success('连接共享会话【' + item.session + '】成功!');
setModalVisit(false); setModalVisit(false);
}else{ } else {
message.warn("敬请期待"); message.warn("敬请期待");
} }
}; };
const getTables = () => { const getTables = () => {
showTables(currentSession.session,dispatch); showTables(currentSession.session, dispatch);
}; };
const onClearSession = () => { const onClearSession = () => {
clearSession(currentSession.session,dispatch); clearSession(currentSession.session, dispatch);
}; };
const getColumns=()=>{ const getColumns = () => {
let columns:any=[{ let columns: any = [{
title: "表名", title: "表名",
dataIndex: "tablename", dataIndex: "tablename",
key: "tablename", key: "tablename",
sorter: true, sorter: true,
...getColumnSearchProps("tablename"), ...getColumnSearchProps("tablename"),
},{ }, {
title: '操作', title: '操作',
dataIndex: 'option', dataIndex: 'option',
valueType: 'option', valueType: 'option',
...@@ -155,9 +167,9 @@ const StudioConnector = (props:any) => { ...@@ -155,9 +167,9 @@ const StudioConnector = (props:any) => {
}} }}
> >
描述 描述
</a>,<Divider type="vertical" />,<a </a>, <Divider type="vertical"/>, <a
onClick={() => { onClick={() => {
keyEvent('delete',record); keyEvent('delete', record);
}} }}
> >
删除 删除
...@@ -167,54 +179,54 @@ const StudioConnector = (props:any) => { ...@@ -167,54 +179,54 @@ const StudioConnector = (props:any) => {
return columns; return columns;
}; };
const getSessionsColumns=()=>{ const getSessionsColumns = () => {
let columns:any=[{ let columns: any = [{
title: "会话 Key", title: "会话 Key",
dataIndex: "session", dataIndex: "session",
key: "session", key: "session",
sorter: true, sorter: true,
...getColumnSearchProps("session"), ...getColumnSearchProps("session"),
},{ }, {
title: "执行模式", title: "执行模式",
key: "useRemote", key: "useRemote",
sorter: true, sorter: true,
...getColumnSearchProps("useRemote"), ...getColumnSearchProps("useRemote"),
render:function(text, record, index) { render: function (text, record, index) {
return record.sessionConfig.useRemote?'远程':'本地'; return record.sessionConfig.useRemote ? '远程' : '本地';
} }
},{ }, {
title: "集群名", title: "集群名",
key: "clusterName", key: "clusterName",
sorter: true, sorter: true,
...getColumnSearchProps("clusterName"), ...getColumnSearchProps("clusterName"),
render:function(text, record, index) { render: function (text, record, index) {
return record.sessionConfig.clusterName; return record.sessionConfig.clusterName;
} }
},{ }, {
title: "创建人", title: "创建人",
dataIndex: "createUser", dataIndex: "createUser",
key: "createUser", key: "createUser",
sorter: true, sorter: true,
...getColumnSearchProps("createUser"), ...getColumnSearchProps("createUser"),
},{ }, {
title: "创建时间", title: "创建时间",
dataIndex: "createTime", dataIndex: "createTime",
key: "createTime", key: "createTime",
sorter: true, sorter: true,
},{ }, {
title: '操作', title: '操作',
dataIndex: 'option', dataIndex: 'option',
valueType: 'option', valueType: 'option',
render: (_, record) => [ render: (_, record) => [
<a <a
onClick={() => { onClick={() => {
keySessionsEvent('connect',record); keySessionsEvent('connect', record);
}} }}
> >
连接 连接
</a>,<Divider type="vertical" />,<a </a>, <Divider type="vertical"/>, <a
onClick={() => { onClick={() => {
keySessionsEvent('delete',record); keySessionsEvent('delete', record);
}} }}
> >
删除 删除
...@@ -224,66 +236,69 @@ const StudioConnector = (props:any) => { ...@@ -224,66 +236,69 @@ const StudioConnector = (props:any) => {
return columns; return columns;
}; };
const createSessions=()=>{ const createSessions = () => {
handleCreateSessionModalVisible(true); handleCreateSessionModalVisible(true);
}; };
const showSessions=()=>{ const showSessions = () => {
setModalVisit(true); setModalVisit(true);
setType(1); setType(1);
const res = getData("api/studio/listSession"); listSession(dispatch);
res.then((result)=>{
setSessionData(result.datas);
});
}; };
const quitSessions=()=>{ const quitSessions = () => {
quitSession(dispatch); quitSession(dispatch);
message.success('退出共享会话成功!'); message.success('退出共享会话成功!');
}; };
return ( return (
<> <>
<Tooltip title="新建会话">
<Button
type="text"
icon={<PlusOutlined/>}
onClick={createSessions}
/>
</Tooltip>
<div style={{float: "right"}}> <div style={{float: "right"}}>
{session.length > 0 ? (
<Tooltip title="切换会话"> <Tooltip title="切换会话">
<Button <Button
type="text" type="text"
icon={<CommentOutlined />} icon={<CommentOutlined/>}
onClick={showSessions} onClick={showSessions}
/> />
</Tooltip> </Tooltip>
) : ''}
{currentSession.session && (
<>
<Tooltip title="退出会话"> <Tooltip title="退出会话">
<Button <Button
type="text" type="text"
icon={<PoweroffOutlined />} icon={<PoweroffOutlined/>}
onClick={quitSessions} onClick={quitSessions}
/> />
</Tooltip> </Tooltip>
<Tooltip title="新建会话">
<Button
type="text"
icon={<PlusOutlined />}
onClick={createSessions}
/>
</Tooltip>
<Tooltip title="刷新连接器"> <Tooltip title="刷新连接器">
<Button <Button
type="text" type="text"
icon={<SearchOutlined />} icon={<SearchOutlined/>}
onClick={getTables} onClick={getTables}
/> />
</Tooltip> </Tooltip>
<Tooltip title="注销会话"> <Tooltip title="注销会话">
<Button <Button
type="text" type="text"
icon={<DeleteOutlined />} icon={<DeleteOutlined/>}
onClick={onClearSession} onClick={onClearSession}
/> />
</Tooltip> </Tooltip>
</>)}
</div> </div>
{currentSession.connectors&&currentSession.connectors.length>0?(<Table dataSource={currentSession.connectors} columns={getColumns()} size="small" />):(<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />)} {currentSession.connectors && currentSession.connectors.length > 0 ? (
<Table dataSource={currentSession.connectors} columns={getColumns()} size="small"/>) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)}
<ModalForm <ModalForm
// title="新建表单"
visible={modalVisit} visible={modalVisit}
onFinish={async () => { onFinish={async () => {
setSessionData(undefined); setSessionData(undefined);
...@@ -297,15 +312,15 @@ const StudioConnector = (props:any) => { ...@@ -297,15 +312,15 @@ const StudioConnector = (props:any) => {
}, },
}} }}
> >
{type==1&& {type == 1 &&
(<ProDescriptions (<ProDescriptions
column={2} column={2}
title='全部共享会话' title='全部共享会话'
> >
<ProDescriptions.Item span={2} > <ProDescriptions.Item span={2}>
{sessionData? {session.length > 0 ?
(<Table dataSource={sessionData} columns={getSessionsColumns()} size="small" (<Table dataSource={session} columns={getSessionsColumns()} size="small"
/>):(<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />)} />) : (<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)}
</ProDescriptions.Item> </ProDescriptions.Item>
</ProDescriptions> </ProDescriptions>
) )
...@@ -313,27 +328,25 @@ const StudioConnector = (props:any) => { ...@@ -313,27 +328,25 @@ const StudioConnector = (props:any) => {
</ModalForm> </ModalForm>
<SessionForm <SessionForm
onSubmit={async (value) => { onSubmit={async (value) => {
console.log(value); createSession(value, dispatch);
const success = await handleAddOrUpdate("api/studio/createSession",value);
if (success) {
handleCreateSessionModalVisible(false); handleCreateSessionModalVisible(false);
}
}} }}
onCancel={() => { onCancel={() => {
handleCreateSessionModalVisible(false); handleCreateSessionModalVisible(false);
}} }}
updateModalVisible={createSessionModalVisible} updateModalVisible={createSessionModalVisible}
values={{ values={{
session:'', session: '',
type:'PUBLIC', type: 'PUBLIC',
useRemote:false, useRemote: true,
}} }}
/> />
</> </>
); );
}; };
export default connect(({ Studio }: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
current: Studio.current, current: Studio.current,
currentSession: Studio.currentSession, currentSession: Studio.currentSession,
session: Studio.session,
}))(StudioConnector); }))(StudioConnector);
...@@ -18,17 +18,17 @@ const StudioLeftTool = (props:any) => { ...@@ -18,17 +18,17 @@ const StudioLeftTool = (props:any) => {
<TabPane tab={<span><BarsOutlined/> 目录</span>} key="StudioTree" > <TabPane tab={<span><BarsOutlined/> 目录</span>} key="StudioTree" >
<StudioTree/> <StudioTree/>
</TabPane> </TabPane>
<TabPane tab={<span><DatabaseOutlined /> 数据源</span>} key="DataSource" > <TabPane tab={<span><MessageOutlined /> 会话</span>} key="Connectors" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> <StudioConnector />
</TabPane> </TabPane>
<TabPane tab={<span><AppstoreOutlined /> 元数据</span>} key="MetaData" > <TabPane tab={<span><ClusterOutlined /> 集群</span>} key="Cluster" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</TabPane> </TabPane>
<TabPane tab={<span><ClusterOutlined /> 集群</span>} key="Cluster" > <TabPane tab={<span><DatabaseOutlined /> 数据源</span>} key="DataSource" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</TabPane> </TabPane>
<TabPane tab={<span><MessageOutlined /> 会话</span>} key="Connectors" > <TabPane tab={<span><AppstoreOutlined /> 元数据</span>} key="MetaData" >
<StudioConnector /> <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</TabPane> </TabPane>
<TabPane tab={<span><FireOutlined /> 任务</span>} key="FlinkTask" > <TabPane tab={<span><FireOutlined /> 任务</span>} key="FlinkTask" >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
......
import styles from "./index.less"; import styles from "./index.less";
import {Menu, Dropdown, Tooltip, Row, Col, Popconfirm, notification, Modal,message} from "antd"; import {Menu, Dropdown, Tooltip, Row, Col, Popconfirm, notification, Modal, message} from "antd";
import {PauseCircleTwoTone, CopyTwoTone, DeleteTwoTone,PlayCircleTwoTone,DiffTwoTone, import {
FileAddTwoTone,FolderOpenTwoTone,SafetyCertificateTwoTone,SaveTwoTone,FlagTwoTone, PauseCircleTwoTone, CopyTwoTone, DeleteTwoTone, PlayCircleTwoTone, DiffTwoTone,
EnvironmentOutlined,SmileOutlined,RocketTwoTone,QuestionCircleTwoTone,MessageOutlined} from "@ant-design/icons"; FileAddTwoTone, FolderOpenTwoTone, SafetyCertificateTwoTone, SaveTwoTone, FlagTwoTone,
EnvironmentOutlined, SmileOutlined, RocketTwoTone, QuestionCircleTwoTone, MessageOutlined, ClusterOutlined
} from "@ant-design/icons";
import Space from "antd/es/space"; import Space from "antd/es/space";
import Divider from "antd/es/divider"; import Divider from "antd/es/divider";
import Button from "antd/es/button/button"; import Button from "antd/es/button/button";
import Breadcrumb from "antd/es/breadcrumb/Breadcrumb"; import Breadcrumb from "antd/es/breadcrumb/Breadcrumb";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi"; import {connect} from "umi";
import { postDataArray} from "@/components/Common/crud"; import {postDataArray} from "@/components/Common/crud";
import {executeSql} from "@/pages/FlinkSqlStudio/service"; import {executeSql} from "@/pages/FlinkSqlStudio/service";
import StudioHelp from "./StudioHelp"; import StudioHelp from "./StudioHelp";
import {showTables} from "@/components/Studio/StudioEvent/DDL"; import {showTables} from "@/components/Studio/StudioEvent/DDL";
...@@ -23,121 +25,121 @@ const menu = ( ...@@ -23,121 +25,121 @@ const menu = (
const StudioMenu = (props: any) => { const StudioMenu = (props: any) => {
const {tabs,current,currentPath,form,refs,dispatch,currentSession} = props; const {tabs, current, currentPath, form, refs, dispatch, currentSession} = props;
const execute = () => { const execute = () => {
let selectsql =null; let selectsql = null;
if(current.monaco.current) { if (current.monaco.current) {
let selection = current.monaco.current.editor.getSelection(); let selection = current.monaco.current.editor.getSelection();
selectsql = current.monaco.current.editor.getModel().getValueInRange(selection); selectsql = current.monaco.current.editor.getModel().getValueInRange(selection);
} }
if(selectsql==null||selectsql==''){ if (selectsql == null || selectsql == '') {
selectsql=current.value; selectsql = current.value;
} }
let useSession = !!currentSession.session; let useSession = !!currentSession.session;
let param ={ let param = {
useSession:useSession, useSession: useSession,
session:currentSession.session, session: currentSession.session,
useRemote:current.task.useRemote, useRemote: current.task.useRemote,
clusterId:current.task.clusterId, clusterId: current.task.clusterId,
useResult:current.task.useResult, useResult: current.task.useResult,
maxRowNum:current.task.maxRowNum, maxRowNum: current.task.maxRowNum,
statement:selectsql, statement: selectsql,
fragment:current.task.fragment, fragment: current.task.fragment,
jobName:current.task.jobName, jobName: current.task.jobName,
parallelism:current.task.parallelism, parallelism: current.task.parallelism,
checkPoint:current.task.checkPoint, checkPoint: current.task.checkPoint,
savePointPath:current.task.savePointPath, savePointPath: current.task.savePointPath,
}; };
const key = current.key; const key = current.key;
const taskKey = (Math.random()*1000)+''; const taskKey = (Math.random() * 1000) + '';
notification.success({ notification.success({
message: `新任务【${param.jobName}】正在执行`, message: `新任务【${param.jobName}】正在执行`,
description: param.statement.substring(0,40)+'...', description: param.statement.substring(0, 40) + '...',
duration:null, duration: null,
key:taskKey, key: taskKey,
icon: <SmileOutlined style={{ color: '#108ee9' }} />, icon: <SmileOutlined style={{color: '#108ee9'}}/>,
}); });
setTimeout(()=>{ setTimeout(() => {
refs?.history?.current?.reload(); refs?.history?.current?.reload();
},2000); }, 2000);
const result = executeSql(param); const result = executeSql(param);
result.then(res=>{ result.then(res => {
notification.close(taskKey); notification.close(taskKey);
if(res.datas.success){ if (res.datas.success) {
message.success('执行成功'); message.success('执行成功');
}else{ } else {
message.success('执行失败'); message.success('执行失败');
} }
let newTabs = tabs; let newTabs = tabs;
for(let i=0;i<newTabs.panes.length;i++){ for (let i = 0; i < newTabs.panes.length; i++) {
if(newTabs.panes[i].key==key){ if (newTabs.panes[i].key == key) {
/*let newResult = newTabs.panes[i].console.result; /*let newResult = newTabs.panes[i].console.result;
newResult.unshift(res.datas); newResult.unshift(res.datas);
newTabs.panes[i].console={ newTabs.panes[i].console={
result:newResult, result:newResult,
};*/ };*/
newTabs.panes[i].console.result=res.datas; newTabs.panes[i].console.result = res.datas;
break; break;
} }
} }
dispatch&&dispatch({ dispatch && dispatch({
type: "Studio/saveTabs", type: "Studio/saveTabs",
payload: newTabs, payload: newTabs,
}); });
useSession&&showTables(currentSession.session,dispatch); useSession && showTables(currentSession.session, dispatch);
}) })
}; };
const submit= () =>{ const submit = () => {
if(!current.task.id){ if (!current.task.id) {
message.error(`草稿【${current.title}】无法被提交,请创建或选择有效作业进行提交`); message.error(`草稿【${current.title}】无法被提交,请创建或选择有效作业进行提交`);
return; return;
} }
const taskKey = (Math.random()*1000)+''; const taskKey = (Math.random() * 1000) + '';
Modal.confirm({ Modal.confirm({
title: '异步提交作业', title: '异步提交作业',
content: `确定异步提交作业【${current.task.alias}】到其配置的集群吗?请确认您的作业是否已经被保存!`, content: `确定异步提交作业【${current.task.alias}】到其配置的集群吗?请确认您的作业是否已经被保存!`,
okText: '确认', okText: '确认',
cancelText: '取消', cancelText: '取消',
onOk:async () => { onOk: async () => {
let task = { let task = {
id:current.task.id, id: current.task.id,
}; };
notification.success({ notification.success({
message: `任务【${current.task.alias} 】正在异步提交`, message: `任务【${current.task.alias} 】正在异步提交`,
description: current.task.statement, description: current.task.statement,
duration:null, duration: null,
key:taskKey, key: taskKey,
icon: <SmileOutlined style={{ color: '#108ee9' }} />, icon: <SmileOutlined style={{color: '#108ee9'}}/>,
}); });
setTimeout(()=>{ setTimeout(() => {
refs?.history?.current?.reload(); refs?.history?.current?.reload();
},2000); }, 2000);
const res = await postDataArray('/api/task/submit',[task.id]); const res = await postDataArray('/api/task/submit', [task.id]);
notification.close(taskKey); notification.close(taskKey);
if(res.datas[0].success){ if (res.datas[0].success) {
message.success('异步提交成功'); message.success('异步提交成功');
}else{ } else {
message.success('异步提交失败'); message.success('异步提交失败');
} }
} }
}); });
}; };
const saveSqlAndSettingToTask = async() => { const saveSqlAndSettingToTask = async () => {
const fieldsValue = await form.validateFields(); const fieldsValue = await form.validateFields();
if(current.task){ if (current.task) {
let task = { let task = {
...current.task, ...current.task,
statement:current.value, statement: current.value,
...fieldsValue ...fieldsValue
}; };
dispatch&&dispatch({ dispatch && dispatch({
type: "Studio/saveTask", type: "Studio/saveTask",
payload: task, payload: task,
}); });
}else{ } else {
} }
}; };
...@@ -149,22 +151,23 @@ const StudioMenu = (props: any) => { ...@@ -149,22 +151,23 @@ const StudioMenu = (props: any) => {
</Menu> </Menu>
); );
const getPathItem = (paths)=>{ const getPathItem = (paths) => {
let itemList = []; let itemList = [];
for(let item of paths){ for (let item of paths) {
itemList.push(<Breadcrumb.Item>{item}</Breadcrumb.Item>) itemList.push(<Breadcrumb.Item>{item}</Breadcrumb.Item>)
} }
return itemList; return itemList;
}; };
const showHelp=()=>{ const showHelp = () => {
Modal.info({ Modal.info({
title: '使用帮助', title: '使用帮助',
width:1000, width: 1000,
content: ( content: (
<StudioHelp /> <StudioHelp/>
), ),
onOk() {}, onOk() {
},
}); });
}; };
return ( return (
...@@ -198,50 +201,58 @@ const StudioMenu = (props: any) => { ...@@ -198,50 +201,58 @@ const StudioMenu = (props: any) => {
<Divider className={styles["ant-divider-horizontal-0"]}/> <Divider className={styles["ant-divider-horizontal-0"]}/>
<Col span={24}> <Col span={24}>
<Row> <Row>
<Col span={8}> <Col span={4}>
<Breadcrumb className={styles["dw-path"]}> <Breadcrumb className={styles["dw-path"]}>
<EnvironmentOutlined /> <EnvironmentOutlined/>
<Divider type="vertical" /> <Divider type="vertical"/>
{getPathItem(currentPath)} {getPathItem(currentPath)}
{currentSession.session&&
(<>
<Divider type="vertical" />
<MessageOutlined />
<Divider type="vertical" />
<Breadcrumb.Item>{currentSession.session}</Breadcrumb.Item>
</>)
}
</Breadcrumb> </Breadcrumb>
</Col> </Col>
<Col span={8} offset={8}> <Col span={12}>
{currentSession.session &&
(
<Breadcrumb className={styles["dw-path"]}>
<Divider type="vertical"/>
<MessageOutlined/>
<Divider type="vertical"/>
{currentSession.session}
<Divider type="vertical"/>
<ClusterOutlined/>
<Divider type="vertical"/>
{currentSession.sessionConfig.useRemote ?
currentSession.sessionConfig.clusterName : '本地模式'}
</Breadcrumb>
)}
</Col>
<Col span={8}>
<Button <Button
type="text" type="text"
icon={<FileAddTwoTone twoToneColor="#ddd" />} icon={<FileAddTwoTone twoToneColor="#ddd"/>}
/> />
<Button <Button
type="text" type="text"
icon={<FolderOpenTwoTone twoToneColor="#ddd" />} icon={<FolderOpenTwoTone twoToneColor="#ddd"/>}
/> />
<Tooltip title="保存当前的 FlinkSql 及配置"> <Tooltip title="保存当前的 FlinkSql 及配置">
<Button <Button
type="text" type="text"
icon={<SaveTwoTone />} icon={<SaveTwoTone/>}
onClick={saveSqlAndSettingToTask} onClick={saveSqlAndSettingToTask}
/> />
</Tooltip> </Tooltip>
<Divider type="vertical" /> <Divider type="vertical"/>
<Button <Button
type="text" type="text"
icon={<SafetyCertificateTwoTone twoToneColor="#ddd" />} icon={<SafetyCertificateTwoTone twoToneColor="#ddd"/>}
/> />
<Button <Button
type="text" type="text"
icon={<FlagTwoTone twoToneColor="#ddd" />} icon={<FlagTwoTone twoToneColor="#ddd"/>}
/> />
<Tooltip title="执行当前的 FlinkSql"> <Tooltip title="执行当前的 FlinkSql">
<Button <Button
type="text" type="text"
icon={<PlayCircleTwoTone />} icon={<PlayCircleTwoTone/>}
//loading={loadings[2]} //loading={loadings[2]}
onClick={execute} onClick={execute}
/> />
...@@ -249,7 +260,7 @@ const StudioMenu = (props: any) => { ...@@ -249,7 +260,7 @@ const StudioMenu = (props: any) => {
<Tooltip title="提交当前的作业到集群"> <Tooltip title="提交当前的作业到集群">
<Button <Button
type="text" type="text"
icon={<RocketTwoTone />} icon={<RocketTwoTone/>}
onClick={submit} onClick={submit}
/> />
</Tooltip> </Tooltip>
...@@ -264,28 +275,28 @@ const StudioMenu = (props: any) => { ...@@ -264,28 +275,28 @@ const StudioMenu = (props: any) => {
{/*<Badge size="small" count={1} offset={[-5, 5]}>*/} {/*<Badge size="small" count={1} offset={[-5, 5]}>*/}
<Button <Button
type="text" type="text"
icon={<PauseCircleTwoTone twoToneColor="#ddd" />} icon={<PauseCircleTwoTone twoToneColor="#ddd"/>}
/> />
{/*</Badge>*/} {/*</Badge>*/}
</Tooltip> </Tooltip>
</Popconfirm> </Popconfirm>
<Divider type="vertical" /> <Divider type="vertical"/>
<Button <Button
type="text" type="text"
icon={<DiffTwoTone twoToneColor="#ddd" />} icon={<DiffTwoTone twoToneColor="#ddd"/>}
/> />
<Button <Button
type="text" type="text"
icon={<CopyTwoTone twoToneColor="#ddd" />} icon={<CopyTwoTone twoToneColor="#ddd"/>}
/> />
<Button <Button
type="text" type="text"
icon={<DeleteTwoTone twoToneColor="#ddd" />} icon={<DeleteTwoTone twoToneColor="#ddd"/>}
/> />
<Tooltip title="查看使用帮助"> <Tooltip title="查看使用帮助">
<Button <Button
type="text" type="text"
icon={<QuestionCircleTwoTone />} icon={<QuestionCircleTwoTone/>}
onClick={showHelp} onClick={showHelp}
/> />
</Tooltip> </Tooltip>
......
import {connect} from "umi"; import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import {Form, InputNumber,Input,Switch,Select,Tag,Row,Col,Divider,Tooltip,Button} from "antd"; import {
Form, InputNumber, Input, Switch, Select, Tag, Row, Col, Divider, Tooltip, Button, Badge,
Typography
} from "antd";
import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined} from "@ant-design/icons"; import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined} from "@ant-design/icons";
import styles from "./index.less"; import styles from "./index.less";
import {useEffect, useState} from "react"; import {useEffect, useState} from "react";
import {showTables} from "@/components/Studio/StudioEvent/DDL"; import {showTables} from "@/components/Studio/StudioEvent/DDL";
const { Option } = Select; const { Option } = Select;
const { Text } = Typography;
const StudioConfig = (props: any) => { const StudioConfig = (props: any) => {
...@@ -75,8 +79,11 @@ const StudioConfig = (props: any) => { ...@@ -75,8 +79,11 @@ const StudioConfig = (props: any) => {
label="远程执行" className={styles.form_item} name="useRemote" valuePropName="checked" label="远程执行" className={styles.form_item} name="useRemote" valuePropName="checked"
tooltip={{ title: '开启远程执行,将在远程集群进行任务执行', icon: <InfoCircleOutlined /> }} tooltip={{ title: '开启远程执行,将在远程集群进行任务执行', icon: <InfoCircleOutlined /> }}
> >
<Switch checkedChildren="启用" unCheckedChildren="禁用" {
/> currentSession.session?
(currentSession.sessionConfig&&currentSession.sessionConfig.useRemote?(<><Badge status="success"/><Text type="success">已启用</Text></>):(<><Badge status="error"/><Text type="danger">已禁用</Text></>)
):(<Switch checkedChildren="启用" unCheckedChildren="禁用"/>)
}
</Form.Item> </Form.Item>
</Form> </Form>
</> </>
......
import {connect} from "umi"; import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import {Form, InputNumber,Input,Switch,Select,Tag,Row,Col,Divider,Tooltip,Button} from "antd"; import {Form, InputNumber, Input, Switch, Select, Tag, Row, Col, Badge, Tooltip, Button, Typography} from "antd";
import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined} from "@ant-design/icons"; import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined} from "@ant-design/icons";
import styles from "./index.less"; import styles from "./index.less";
import {useEffect, useState} from "react"; import {useEffect, useState} from "react";
import {showCluster, showTables} from "@/components/Studio/StudioEvent/DDL"; import {showCluster, showTables} from "@/components/Studio/StudioEvent/DDL";
const { Option } = Select; const { Option } = Select;
const { Text } = Typography;
const StudioSetting = (props: any) => { const StudioSetting = (props: any) => {
...@@ -111,7 +112,12 @@ const StudioSetting = (props: any) => { ...@@ -111,7 +112,12 @@ const StudioSetting = (props: any) => {
<Col span={24}> <Col span={24}>
<Form.Item label="Flink集群" tooltip="选择Flink集群进行远程提交任务" name="clusterId" <Form.Item label="Flink集群" tooltip="选择Flink集群进行远程提交任务" name="clusterId"
className={styles.form_item}> className={styles.form_item}>
<Select {
currentSession.session?
(currentSession.sessionConfig&&currentSession.sessionConfig.clusterId?
(<><Badge status="success"/><Text type="success">{currentSession.sessionConfig.clusterName}</Text></>)
:(<><Badge status="error"/><Text type="danger">本地模式</Text></>)
):(<Select
style={{ width: '100%' }} style={{ width: '100%' }}
placeholder="选择Flink集群" placeholder="选择Flink集群"
defaultValue={0} defaultValue={0}
...@@ -119,7 +125,9 @@ const StudioSetting = (props: any) => { ...@@ -119,7 +125,9 @@ const StudioSetting = (props: any) => {
onChange={onChangeClusterSession} onChange={onChangeClusterSession}
> >
{getClusterOptions()} {getClusterOptions()}
</Select> </Select>)
}
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
......
...@@ -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 {showCluster} from "@/components/Studio/StudioEvent/DDL"; import {listSession, showCluster} 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);
listSession(dispatch);
const onClick=()=>{ const onClick=()=>{
if(rightClickMenu){ if(rightClickMenu){
......
...@@ -17,10 +17,12 @@ import { ...@@ -17,10 +17,12 @@ import {
handleAddOrUpdate, handleOption, handleRemove, queryData, handleAddOrUpdate, handleOption, handleRemove, queryData,
updateEnabled updateEnabled
} from "@/components/Common/crud"; } from "@/components/Common/crud";
import {showCluster} from "@/components/Studio/StudioEvent/DDL";
const url = '/api/cluster'; const url = '/api/cluster';
const ClusterTableList: React.FC<{}> = () => { const ClusterTableList: React.FC<{}> = (props: any) => {
const {dispatch} = props;
const [createModalVisible, handleModalVisible] = useState<boolean>(false); const [createModalVisible, handleModalVisible] = useState<boolean>(false);
const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false); const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
const [formValues, setFormValues] = useState({}); const [formValues, setFormValues] = useState({});
...@@ -38,16 +40,16 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -38,16 +40,16 @@ const ClusterTableList: React.FC<{}> = () => {
content: '确定删除该集群吗?', content: '确定删除该集群吗?',
okText: '确认', okText: '确认',
cancelText: '取消', cancelText: '取消',
onOk:async () => { onOk: async () => {
await handleRemove(url,[currentItem]); await handleRemove(url, [currentItem]);
actionRef.current?.reloadAndRest?.(); actionRef.current?.reloadAndRest?.();
} }
}); });
} }
}; };
const checkHeartBeats = async ()=>{ const checkHeartBeats = async () => {
await handleOption(url+'/heartbeats','心跳检测',null); await handleOption(url + '/heartbeats', '心跳检测', null);
actionRef.current?.reloadAndRest?.(); actionRef.current?.reloadAndRest?.();
}; };
...@@ -122,9 +124,9 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -122,9 +124,9 @@ const ClusterTableList: React.FC<{}> = () => {
], ],
filterMultiple: false, filterMultiple: false,
valueEnum: { valueEnum: {
'Yarn': { text: 'Yarn'}, 'Yarn': {text: 'Yarn'},
'Standalone': { text: 'Standalone'}, 'Standalone': {text: 'Standalone'},
'Others': { text: 'Others' }, 'Others': {text: 'Others'},
}, },
}, },
{ {
...@@ -162,8 +164,8 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -162,8 +164,8 @@ const ClusterTableList: React.FC<{}> = () => {
], ],
filterMultiple: false, filterMultiple: false,
valueEnum: { valueEnum: {
1: { text: '正常', status: 'Success' }, 1: {text: '正常', status: 'Success'},
0: { text: '异常', status: 'Error' }, 0: {text: '异常', status: 'Error'},
}, },
}, },
{ {
...@@ -193,8 +195,8 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -193,8 +195,8 @@ const ClusterTableList: React.FC<{}> = () => {
], ],
filterMultiple: false, filterMultiple: false,
valueEnum: { valueEnum: {
true: { text: '已启用', status: 'Success' }, true: {text: '已启用', status: 'Success'},
false: { text: '已禁用', status: 'Error' }, false: {text: '已禁用', status: 'Error'},
}, },
}, },
{ {
...@@ -203,14 +205,14 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -203,14 +205,14 @@ const ClusterTableList: React.FC<{}> = () => {
sorter: true, sorter: true,
valueType: 'dateTime', valueType: 'dateTime',
hideInForm: true, hideInForm: true,
hideInTable:true, hideInTable: true,
renderFormItem: (item, { defaultRender, ...rest }, form) => { renderFormItem: (item, {defaultRender, ...rest}, form) => {
const status = form.getFieldValue('status'); const status = form.getFieldValue('status');
if (`${status}` === '0') { if (`${status}` === '0') {
return false; return false;
} }
if (`${status}` === '3') { if (`${status}` === '3') {
return <Input {...rest} placeholder="请输入异常原因!" />; return <Input {...rest} placeholder="请输入异常原因!"/>;
} }
return defaultRender(item); return defaultRender(item);
}, },
...@@ -221,13 +223,13 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -221,13 +223,13 @@ const ClusterTableList: React.FC<{}> = () => {
sorter: true, sorter: true,
valueType: 'dateTime', valueType: 'dateTime',
hideInForm: true, hideInForm: true,
renderFormItem: (item, { defaultRender, ...rest }, form) => { renderFormItem: (item, {defaultRender, ...rest}, form) => {
const status = form.getFieldValue('status'); const status = form.getFieldValue('status');
if (`${status}` === '0') { if (`${status}` === '0') {
return false; return false;
} }
if (`${status}` === '3') { if (`${status}` === '3') {
return <Input {...rest} placeholder="请输入异常原因!" />; return <Input {...rest} placeholder="请输入异常原因!"/>;
} }
return defaultRender(item); return defaultRender(item);
}, },
...@@ -264,10 +266,10 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -264,10 +266,10 @@ const ClusterTableList: React.FC<{}> = () => {
<PlusOutlined/> 新建 <PlusOutlined/> 新建
</Button>, </Button>,
<Button type="primary" onClick={() => checkHeartBeats()}> <Button type="primary" onClick={() => checkHeartBeats()}>
<HeartOutlined /> 心跳 <HeartOutlined/> 心跳
</Button>, </Button>,
]} ]}
request={(params, sorter, filter) => queryData(url,{...params, sorter, filter})} request={(params, sorter, filter) => queryData(url, {...params, sorter, filter})}
columns={columns} columns={columns}
rowSelection={{ rowSelection={{
onChange: (_, selectedRows) => setSelectedRows(selectedRows), onChange: (_, selectedRows) => setSelectedRows(selectedRows),
...@@ -285,14 +287,14 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -285,14 +287,14 @@ const ClusterTableList: React.FC<{}> = () => {
} }
> >
<Button type="primary" danger <Button type="primary" danger
onClick ={()=>{ onClick={() => {
Modal.confirm({ Modal.confirm({
title: '删除集群', title: '删除集群',
content: '确定删除选中的集群吗?', content: '确定删除选中的集群吗?',
okText: '确认', okText: '确认',
cancelText: '取消', cancelText: '取消',
onOk:async () => { onOk: async () => {
await handleRemove(url,selectedRowsState); await handleRemove(url, selectedRowsState);
setSelectedRows([]); setSelectedRows([]);
actionRef.current?.reloadAndRest?.(); actionRef.current?.reloadAndRest?.();
} }
...@@ -302,14 +304,14 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -302,14 +304,14 @@ const ClusterTableList: React.FC<{}> = () => {
批量删除 批量删除
</Button> </Button>
<Button type="primary" <Button type="primary"
onClick ={()=>{ onClick={() => {
Modal.confirm({ Modal.confirm({
title: '启用集群', title: '启用集群',
content: '确定启用选中的集群吗?', content: '确定启用选中的集群吗?',
okText: '确认', okText: '确认',
cancelText: '取消', cancelText: '取消',
onOk:async () => { onOk: async () => {
await updateEnabled(url,selectedRowsState, true); await updateEnabled(url, selectedRowsState, true);
setSelectedRows([]); setSelectedRows([]);
actionRef.current?.reloadAndRest?.(); actionRef.current?.reloadAndRest?.();
} }
...@@ -317,14 +319,14 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -317,14 +319,14 @@ const ClusterTableList: React.FC<{}> = () => {
}} }}
>批量启用</Button> >批量启用</Button>
<Button danger <Button danger
onClick ={()=>{ onClick={() => {
Modal.confirm({ Modal.confirm({
title: '禁用集群', title: '禁用集群',
content: '确定禁用选中的集群吗?', content: '确定禁用选中的集群吗?',
okText: '确认', okText: '确认',
cancelText: '取消', cancelText: '取消',
onOk:async () => { onOk: async () => {
await updateEnabled(url,selectedRowsState, false); await updateEnabled(url, selectedRowsState, false);
setSelectedRows([]); setSelectedRows([]);
actionRef.current?.reloadAndRest?.(); actionRef.current?.reloadAndRest?.();
} }
...@@ -336,12 +338,13 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -336,12 +338,13 @@ const ClusterTableList: React.FC<{}> = () => {
<CreateForm onCancel={() => handleModalVisible(false)} modalVisible={createModalVisible}> <CreateForm onCancel={() => handleModalVisible(false)} modalVisible={createModalVisible}>
<ProTable<ClusterTableListItem, ClusterTableListItem> <ProTable<ClusterTableListItem, ClusterTableListItem>
onSubmit={async (value) => { onSubmit={async (value) => {
const success = await handleAddOrUpdate(url,value); const success = await handleAddOrUpdate(url, value);
if (success) { if (success) {
handleModalVisible(false); handleModalVisible(false);
if (actionRef.current) { if (actionRef.current) {
actionRef.current.reload(); actionRef.current.reload();
} }
showCluster(dispatch);
} }
}} }}
rowKey="id" rowKey="id"
...@@ -352,13 +355,14 @@ const ClusterTableList: React.FC<{}> = () => { ...@@ -352,13 +355,14 @@ const ClusterTableList: React.FC<{}> = () => {
{formValues && Object.keys(formValues).length ? ( {formValues && Object.keys(formValues).length ? (
<UpdateForm <UpdateForm
onSubmit={async (value) => { onSubmit={async (value) => {
const success = await handleAddOrUpdate(url,value); const success = await handleAddOrUpdate(url, value);
if (success) { if (success) {
handleUpdateModalVisible(false); handleUpdateModalVisible(false);
setFormValues({}); setFormValues({});
if (actionRef.current) { if (actionRef.current) {
actionRef.current.reload(); actionRef.current.reload();
} }
showCluster(dispatch);
} }
}} }}
onCancel={() => { onCancel={() => {
......
...@@ -75,11 +75,13 @@ export type ConnectorType = { ...@@ -75,11 +75,13 @@ export type ConnectorType = {
export type SessionType = { export type SessionType = {
session?: string; session?: string;
sessionConfig?:{
type?: string; type?: string;
useRemote?: string; useRemote?: boolean;
clusterId?: number; clusterId?: number;
clusterName?: string; clusterName?: string;
address?: string; address?: string;
}
createUser?: string; createUser?: string;
createTime?: string; createTime?: string;
connectors: ConnectorType[]; connectors: ConnectorType[];
...@@ -157,7 +159,7 @@ const Model: ModelType = { ...@@ -157,7 +159,7 @@ const Model: ModelType = {
}, },
sql: '', sql: '',
monaco: {}, monaco: {},
currentPath: [], currentPath: ['草稿'],
tabs: { tabs: {
activeKey: 0, activeKey: 0,
panes: [{ panes: [{
...@@ -314,23 +316,11 @@ const Model: ModelType = { ...@@ -314,23 +316,11 @@ const Model: ModelType = {
}; };
}, },
saveSession(state, {payload}) { saveSession(state, {payload}) {
let newSession = state?.session; console.log(payload);
if(newSession) {
for (let i = 0; i < newSession.length; i++) {
if (newSession[i].key == payload) {
return {};
}
}
newSession.push(payload);
return { return {
...state, ...state,
session: newSession, session: [...payload],
}; };
}else {
return {
...state
};
}
}, },
showRightClickMenu(state, {payload}) { showRightClickMenu(state, {payload}) {
return { return {
......
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