Commit 5e8f3caf authored by wenmo's avatar wenmo

面板拖动+滚动条适配

parent 9fdab641
...@@ -12,7 +12,7 @@ export default defineConfig({ ...@@ -12,7 +12,7 @@ export default defineConfig({
babelPlugins: [], babelPlugins: [],
babelOptions: {}, babelOptions: {},
}, },
webpack5: { /*webpack5: {
// lazyCompilation: {}, // lazyCompilation: {},
}, },*/
}); });
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
"nzh": "^1.0.3", "nzh": "^1.0.3",
"omit.js": "^2.0.2", "omit.js": "^2.0.2",
"react": "^17.0.0", "react": "^17.0.0",
"react-custom-scrollbars": "^4.2.1",
"react-dev-inspector": "^1.1.1", "react-dev-inspector": "^1.1.1",
"react-dom": "^17.0.0", "react-dom": "^17.0.0",
"react-helmet-async": "^1.0.4", "react-helmet-async": "^1.0.4",
......
import React, { useRef, useState } from 'react'; import React, { useRef, useState } from 'react';
import useDraggable from '../../hooks/useDraggable'; import useDraggable from '../../hooks/useDraggable';
import styles from './DraggleLayout.less'; import styles from './DraggleLayout.less';
import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model";
function DraggleLayout({ function DraggleLayout({
children, // 两列布局 children, // 两列布局
min = 0, // 左侧最小宽度 min = 400, // 左侧最小宽度
max = Infinity, // 左侧最大宽度 max = Infinity, // 左侧最大宽度
containerWidth = 0, // 容器宽度 containerWidth = 0, // 容器宽度
containerHeight = 0, // 容器高度 containerHeight = 0, // 容器高度
initLeftWidth = 0, // 初始左侧容器宽度 initLeftWidth = 0, // 初始左侧容器宽度
handler = null, // 拖拽器 handler = null, // 拖拽器
onWidthChange = width => width, // 左侧容器高度变化 onWidthChange = width => width, // 左侧容器高度变化
}) { toolWidth,
dispatch
}) {
const ref = useRef(null); const ref = useRef(null);
const [position, setPosition] = useState({ x: initLeftWidth, y: 0 }); const [position, setPosition] = useState({ x: initLeftWidth, y: 0 });
...@@ -25,6 +29,10 @@ function DraggleLayout({ ...@@ -25,6 +29,10 @@ function DraggleLayout({
if (_x > max) _x = max; if (_x > max) _x = max;
if (onWidthChange) onWidthChange(_x); if (onWidthChange) onWidthChange(_x);
setPosition({ x: _x, y }); setPosition({ x: _x, y });
dispatch&&dispatch({
type: "Studio/saveToolWidth",
payload: _x,
});
}, },
}, },
{ overbound: false }, { overbound: false },
...@@ -64,4 +72,6 @@ function DraggleLayout({ ...@@ -64,4 +72,6 @@ function DraggleLayout({
); );
} }
export default DraggleLayout; export default connect(({Studio}: { Studio: StateType }) => ({
toolWidth: Studio.toolWidth,
}))(DraggleLayout);
.root {
position: relative;
//display: flex;
display: block;
//margin: 24px auto;
.top {
width: 100%;
position: relative;
.handler {
position: absolute;
right: 0;
bottom: 0;
height: auto;
width: 100%;
user-select: none;
color: #fff;
text-align: center;
cursor: n-resize;
display: flex;
flex-direction: column;
justify-content: center;
}
}
.bottom {
width: 100%;
}
}
import React, { useRef, useState } from 'react';
import useDraggable from '../../hooks/useDraggable';
import styles from './DraggleVerticalLayout.less';
import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model";
function DraggleVerticalLayout({
children, // 两行布局
min = 100, // 顶部最小高度
max = Infinity, // 底部最大高度
containerWidth = 0, // 容器宽度
containerHeight = 0, // 容器高度
initTopHeight = 0, // 初始顶部容器高度
handler = null, // 拖拽器
onHeightChange = height => height, // 左侧容器高度变化
toolHeight,
dispatch,
}) {
const ref = useRef(null);
const [position, setPosition] = useState({ x: 0, y: toolHeight });
const [props] = useDraggable(
ref,
{
onMouseMove: ({ x, y }) => {
let _y = y;
if (_y < min) _y = min;
if (_y > max) _y = max;
if (onHeightChange) onHeightChange(_y);
setPosition({ x, y:_y });
dispatch&&dispatch({
type: "Studio/saveToolHeight",
payload: _y,
});
},
},
{ overbound: false },
);
const _handler = handler ? (
React.cloneElement(handler, {
...handler.props,
style: {
...handler.props.style,
pointerEvents: 'none',
},
})
) : (
<span style={{ fontSize: 18, pointerEvents: 'none' }}></span>
);
return (
<div
ref={ref}
className={styles.root}
style={{ width: containerWidth, height: containerHeight }}
>
<div className={styles.top} style={{ height: position.y }}>
{children[0]}
<div className={styles.handler} {...props}>
{_handler}
</div>
</div>
<div
className={styles.bottom}
style={{ height: containerHeight - position.y }}
>
{children[1]}
</div>
</div>
);
}
export default connect(({Studio}: { Studio: StateType }) => ({
toolHeight: Studio.toolHeight,
}))(DraggleVerticalLayout);
import { Tabs,Empty } from "antd"; import {Tabs, Empty} from "antd";
import {CodeOutlined, TableOutlined,RadarChartOutlined,CalendarOutlined,FileSearchOutlined,DesktopOutlined import {
,FunctionOutlined,ApartmentOutlined} from "@ant-design/icons"; CodeOutlined, TableOutlined, RadarChartOutlined, CalendarOutlined, FileSearchOutlined, DesktopOutlined
, FunctionOutlined, ApartmentOutlined
} from "@ant-design/icons";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi"; import {connect} from "umi";
import styles from "./index.less"; import styles from "./index.less";
...@@ -10,107 +12,126 @@ import StudioHistory from "./StudioHistory"; ...@@ -10,107 +12,126 @@ import StudioHistory from "./StudioHistory";
import StudioFX from "./StudioFX"; import StudioFX from "./StudioFX";
import StudioCA from "./StudioCA"; import StudioCA from "./StudioCA";
import StudioProcess from "./StudioProcess"; import StudioProcess from "./StudioProcess";
const { TabPane } = Tabs; import {Scrollbars} from 'react-custom-scrollbars';
const {TabPane} = Tabs;
const StudioConsole = (props: any) => {
const StudioConsole = (props:any) => { const {height} = props;
let consoleHeight = (height - 37.6);
return ( return (
<Tabs defaultActiveKey="StudioMsg" size="small" tabPosition="top" style={{ <Tabs defaultActiveKey="StudioMsg" size="small" tabPosition="top" style={{
border: "1px solid #f0f0f0",height:"50%",overflow:"auto",width: "100%"}}> border: "1px solid #f0f0f0", height: height, margin: "0 32px"
}}>
<TabPane <TabPane
tab={ tab={
<span> <span>
<CodeOutlined /> <CodeOutlined/>
信息 信息
</span> </span>
} }
key="StudioMsg" key="StudioMsg"
> >
<StudioMsg /> <Scrollbars style={{height: consoleHeight}}>
<StudioMsg/>
</Scrollbars>
</TabPane> </TabPane>
<TabPane <TabPane
tab={ tab={
<span> <span>
<TableOutlined /> <TableOutlined/>
结果 结果
</span> </span>
} }
key="StudioTable" key="StudioTable"
> >
<StudioTable /> <Scrollbars style={{height: consoleHeight}}>
<StudioTable/>
</Scrollbars>
</TabPane> </TabPane>
<TabPane <TabPane
tab={ tab={
<span> <span>
<RadarChartOutlined /> <RadarChartOutlined/>
指标 指标
</span> </span>
} }
key="StudioMetrics" key="StudioMetrics"
> >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> <Scrollbars style={{height: consoleHeight}}>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>
</Scrollbars>
</TabPane> </TabPane>
<TabPane <TabPane
tab={ tab={
<span> <span>
<ApartmentOutlined /> <ApartmentOutlined/>
血缘 血缘
</span> </span>
} }
key="StudioConsanguinity" key="StudioConsanguinity"
> >
<StudioCA /> <Scrollbars style={{height: consoleHeight}}>
<StudioCA/>
</Scrollbars>
</TabPane> </TabPane>
<TabPane <TabPane
tab={ tab={
<span> <span>
<DesktopOutlined /> <DesktopOutlined/>
进程 进程
</span> </span>
} }
key="StudioProcess" key="StudioProcess"
> >
<StudioProcess /> <Scrollbars style={{height: consoleHeight}}>
<StudioProcess/>
</Scrollbars>
</TabPane> </TabPane>
<TabPane <TabPane
tab={ tab={
<span> <span>
<CalendarOutlined /> <CalendarOutlined/>
历史 历史
</span> </span>
} }
key="StudioHistory" key="StudioHistory"
> >
<StudioHistory /> <Scrollbars style={{height: consoleHeight}}>
<StudioHistory/>
</Scrollbars>
</TabPane> </TabPane>
<TabPane <TabPane
tab={ tab={
<span> <span>
<FunctionOutlined /> <FunctionOutlined/>
函数 函数
</span> </span>
} }
key="StudioFX" key="StudioFX"
> >
<StudioFX /> <Scrollbars style={{height: consoleHeight}}>
<StudioFX/>
</Scrollbars>
</TabPane> </TabPane>
<TabPane <TabPane
tab={ tab={
<span> <span>
<FileSearchOutlined /> <FileSearchOutlined/>
文档 文档
</span> </span>
} }
key="StudioDocument" key="StudioDocument"
> >
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> <Scrollbars style={{height: consoleHeight}}>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>
</Scrollbars>
</TabPane> </TabPane>
</Tabs> </Tabs>
); );
}; };
export default connect(({ Studio }: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
sql: Studio.sql, sql: Studio.sql,
}))(StudioConsole); }))(StudioConsole);
import { import {
message, Button, Table, Empty, Divider, message, Button, Table, Empty, Divider,
Tooltip,Drawer Tooltip, Drawer
} from "antd"; } from "antd";
import ProDescriptions from '@ant-design/pro-descriptions'; import ProDescriptions from '@ant-design/pro-descriptions';
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
...@@ -15,11 +15,11 @@ import React from "react"; ...@@ -15,11 +15,11 @@ import React from "react";
import {showCluster} from "../../StudioEvent/DDL"; import {showCluster} from "../../StudioEvent/DDL";
import {handleAddOrUpdate} from "@/components/Common/crud"; import {handleAddOrUpdate} from "@/components/Common/crud";
import ClusterForm from "@/pages/Cluster/components/ClusterForm"; import ClusterForm from "@/pages/Cluster/components/ClusterForm";
import {SavePointTableListItem} from "@/components/Studio/StudioRightTool/StudioSavePoint/data"; import {Scrollbars} from 'react-custom-scrollbars';
const StudioCluster = (props: any) => { const StudioCluster = (props: any) => {
const {cluster, dispatch} = props; const {cluster, toolHeight, dispatch} = props;
const [createModalVisible, handleCreateModalVisible] = useState<boolean>(false); const [createModalVisible, handleCreateModalVisible] = useState<boolean>(false);
const [row, setRow] = useState<{}>(); const [row, setRow] = useState<{}>();
...@@ -40,7 +40,7 @@ const StudioCluster = (props: any) => { ...@@ -40,7 +40,7 @@ const StudioCluster = (props: any) => {
title: "集群名", title: "集群名",
dataIndex: "alias", dataIndex: "alias",
key: "alias", key: "alias",
},{ }, {
title: '名称', title: '名称',
dataIndex: 'name', dataIndex: 'name',
}, },
...@@ -88,7 +88,7 @@ const StudioCluster = (props: any) => { ...@@ -88,7 +88,7 @@ const StudioCluster = (props: any) => {
title: '当前 JobManager 地址', title: '当前 JobManager 地址',
sorter: true, sorter: true,
dataIndex: 'jobManagerHost', dataIndex: 'jobManagerHost',
},{ }, {
title: '版本', title: '版本',
sorter: true, sorter: true,
dataIndex: 'version', dataIndex: 'version',
...@@ -209,11 +209,12 @@ const StudioCluster = (props: any) => { ...@@ -209,11 +209,12 @@ const StudioCluster = (props: any) => {
<Tooltip title="刷新 Flink 集群"> <Tooltip title="刷新 Flink 集群">
<Button <Button
type="text" type="text"
icon={<ReloadOutlined />} icon={<ReloadOutlined/>}
onClick={onRefreshCluster} onClick={onRefreshCluster}
/> />
</Tooltip> </Tooltip>
</div> </div>
<Scrollbars style={{height: (toolHeight - 32)}}>
{cluster.length > 0 ? ( {cluster.length > 0 ? (
<Table dataSource={cluster} columns={getColumns()} size="small"/>) : ( <Table dataSource={cluster} columns={getColumns()} size="small"/>) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)} <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)}
...@@ -252,10 +253,12 @@ const StudioCluster = (props: any) => { ...@@ -252,10 +253,12 @@ const StudioCluster = (props: any) => {
/> />
)} )}
</Drawer> </Drawer>
</Scrollbars>
</> </>
); );
}; };
export default connect(({Studio}: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
cluster: Studio.cluster, cluster: Studio.cluster,
toolHeight: Studio.toolHeight,
}))(StudioCluster); }))(StudioCluster);
...@@ -25,10 +25,11 @@ import { ...@@ -25,10 +25,11 @@ import {
} from '@ant-design/pro-form'; } from '@ant-design/pro-form';
import ProDescriptions from '@ant-design/pro-descriptions'; import ProDescriptions from '@ant-design/pro-descriptions';
import SessionForm from "@/components/Studio/StudioLeftTool/StudioConnector/components/SessionForm"; import SessionForm from "@/components/Studio/StudioLeftTool/StudioConnector/components/SessionForm";
import { Scrollbars } from 'react-custom-scrollbars';
const StudioConnector = (props: any) => { const StudioConnector = (props: any) => {
const {current, dispatch, currentSession, session} = props; const {current,toolHeight, 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>('');
...@@ -295,6 +296,7 @@ const StudioConnector = (props: any) => { ...@@ -295,6 +296,7 @@ const StudioConnector = (props: any) => {
</Tooltip> </Tooltip>
</>)} </>)}
</div> </div>
<Scrollbars style={{height: (toolHeight - 32)}}>
{currentSession.connectors && currentSession.connectors.length > 0 ? ( {currentSession.connectors && currentSession.connectors.length > 0 ? (
<Table dataSource={currentSession.connectors} columns={getColumns()} size="small"/>) : ( <Table dataSource={currentSession.connectors} columns={getColumns()} size="small"/>) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)} <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)}
...@@ -341,6 +343,7 @@ const StudioConnector = (props: any) => { ...@@ -341,6 +343,7 @@ const StudioConnector = (props: any) => {
useRemote: true, useRemote: true,
}} }}
/> />
</Scrollbars>
</> </>
); );
}; };
...@@ -349,4 +352,5 @@ export default connect(({Studio}: { Studio: StateType }) => ({ ...@@ -349,4 +352,5 @@ export default connect(({Studio}: { Studio: StateType }) => ({
current: Studio.current, current: Studio.current,
currentSession: Studio.currentSession, currentSession: Studio.currentSession,
session: Studio.session, session: Studio.session,
toolHeight: Studio.toolHeight,
}))(StudioConnector); }))(StudioConnector);
...@@ -13,10 +13,11 @@ import { ...@@ -13,10 +13,11 @@ import {
import React from "react"; import React from "react";
import {showDataBase} from "../../StudioEvent/DDL"; import {showDataBase} from "../../StudioEvent/DDL";
import DBForm from "@/pages/DataBase/components/DBForm"; import DBForm from "@/pages/DataBase/components/DBForm";
import { Scrollbars } from 'react-custom-scrollbars';
const StudioDataBase = (props: any) => { const StudioDataBase = (props: any) => {
const {database, dispatch} = props; const {database,toolHeight, dispatch} = props;
const [chooseDBModalVisible, handleDBFormModalVisible] = useState<boolean>(false); const [chooseDBModalVisible, handleDBFormModalVisible] = useState<boolean>(false);
const [values, setValues] = useState<any>({}); const [values, setValues] = useState<any>({});
...@@ -76,6 +77,7 @@ const StudioDataBase = (props: any) => { ...@@ -76,6 +77,7 @@ const StudioDataBase = (props: any) => {
/> />
</Tooltip> </Tooltip>
</div> </div>
<Scrollbars style={{height: (toolHeight - 32)}}>
{database.length > 0 ? ( {database.length > 0 ? (
<Table dataSource={database} columns={getColumns()} size="small"/>) : ( <Table dataSource={database} columns={getColumns()} size="small"/>) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)} <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)}
...@@ -90,10 +92,12 @@ const StudioDataBase = (props: any) => { ...@@ -90,10 +92,12 @@ const StudioDataBase = (props: any) => {
}} }}
values={values} values={values}
/> />
</Scrollbars>
</> </>
); );
}; };
export default connect(({Studio}: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
database: Studio.database, database: Studio.database,
toolHeight: Studio.toolHeight,
}))(StudioDataBase); }))(StudioDataBase);
...@@ -13,15 +13,14 @@ import { ...@@ -13,15 +13,14 @@ import {
} from '@ant-design/icons'; } from '@ant-design/icons';
import React from "react"; import React from "react";
import {showMetaDataTable} from "@/components/Studio/StudioEvent/DDL"; import {showMetaDataTable} from "@/components/Studio/StudioEvent/DDL";
import {convertToTreeData} from "@/components/Studio/StudioTree/Function"; import { Scrollbars } from 'react-custom-scrollbars';
import {getCatalogueTreeData} from "@/pages/FlinkSqlStudio/service";
const { DirectoryTree } = Tree; const { DirectoryTree } = Tree;
const {Option} = Select; const {Option} = Select;
const StudioMetaData = (props: any) => { const StudioMetaData = (props: any) => {
const {database, dispatch} = props; const {database,toolHeight, dispatch} = props;
const [databaseId, setDataBaseId] = useState<number>(); const [databaseId, setDataBaseId] = useState<number>();
const [treeData, setTreeData] = useState<[]>([]); const [treeData, setTreeData] = useState<[]>([]);
...@@ -78,16 +77,19 @@ const StudioMetaData = (props: any) => { ...@@ -78,16 +77,19 @@ const StudioMetaData = (props: any) => {
/> />
</Tooltip> </Tooltip>
</div> </div>
<Scrollbars style={{height: (toolHeight - 32)}}>
<DirectoryTree <DirectoryTree
multiple multiple
switcherIcon={<DownOutlined/>} switcherIcon={<DownOutlined/>}
treeData={treeData} treeData={treeData}
height={400} height={400}
/> />
</Scrollbars>
</> </>
); );
}; };
export default connect(({Studio}: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
database: Studio.database, database: Studio.database,
toolHeight: Studio.toolHeight,
}))(StudioMetaData); }))(StudioMetaData);
...@@ -13,9 +13,10 @@ import StudioMetaData from "./StudioMetaData"; ...@@ -13,9 +13,10 @@ import StudioMetaData from "./StudioMetaData";
const { TabPane } = Tabs; const { TabPane } = Tabs;
const StudioLeftTool = (props:any) => { const StudioLeftTool = (props:any) => {
const {toolHeight} = props;
return ( return (
<Tabs defaultActiveKey="1" size="small" tabPosition="left" style={{ height: "100%"}}> <Tabs defaultActiveKey="1" size="small" tabPosition="left" style={{ height: toolHeight}}>
<TabPane tab={<span><BarsOutlined/> 目录</span>} key="StudioTree"> <TabPane tab={<span><BarsOutlined/> 目录</span>} key="StudioTree">
<StudioTree/> <StudioTree/>
</TabPane> </TabPane>
...@@ -40,4 +41,5 @@ const StudioLeftTool = (props:any) => { ...@@ -40,4 +41,5 @@ const StudioLeftTool = (props:any) => {
export default connect(({ Studio }: { Studio: StateType }) => ({ export default connect(({ Studio }: { Studio: StateType }) => ({
sql: Studio.sql, sql: Studio.sql,
toolHeight: Studio.toolHeight,
}))(StudioLeftTool); }))(StudioLeftTool);
...@@ -8,13 +8,14 @@ import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined} from "@ant-design/i ...@@ -8,13 +8,14 @@ import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined} from "@ant-design/i
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";
import { Scrollbars } from 'react-custom-scrollbars';
const { Option } = Select; const { Option } = Select;
const { Text } = Typography; const { Text } = Typography;
const StudioConfig = (props: any) => { const StudioConfig = (props: any) => {
const {current,form,dispatch,tabs,currentSession} = props; const {current,form,dispatch,tabs,currentSession,toolHeight} = props;
form.setFieldsValue(current.task); form.setFieldsValue(current.task);
...@@ -50,6 +51,7 @@ const StudioConfig = (props: any) => { ...@@ -50,6 +51,7 @@ const StudioConfig = (props: any) => {
</div> </div>
</Col> </Col>
</Row> </Row>
<Scrollbars style={{height:(toolHeight-32)}}>
<Form <Form
form={form} form={form}
layout="vertical" layout="vertical"
...@@ -86,6 +88,7 @@ const StudioConfig = (props: any) => { ...@@ -86,6 +88,7 @@ const StudioConfig = (props: any) => {
} }
</Form.Item> </Form.Item>
</Form> </Form>
</Scrollbars>
</> </>
); );
}; };
...@@ -95,4 +98,5 @@ export default connect(({Studio}: { Studio: StateType }) => ({ ...@@ -95,4 +98,5 @@ export default connect(({Studio}: { Studio: StateType }) => ({
current: Studio.current, current: Studio.current,
currentSession: Studio.currentSession, currentSession: Studio.currentSession,
tabs: Studio.tabs, tabs: Studio.tabs,
toolHeight: Studio.toolHeight,
}))(StudioConfig); }))(StudioConfig);
import React, {useRef, useState} from "react"; import React, {useRef, useState} from "react";
import {DownOutlined, HeartOutlined, PlusOutlined, UserOutlined} from '@ant-design/icons'; import {MinusSquareOutlined} from '@ant-design/icons';
import {ActionType, ProColumns} from "@ant-design/pro-table"; import {ActionType, ProColumns} from "@ant-design/pro-table";
import {Drawer,Table} from 'antd'; import {Drawer,Row,Col,Tooltip,Button} from 'antd';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import ProDescriptions from '@ant-design/pro-descriptions'; import ProDescriptions from '@ant-design/pro-descriptions';
import {queryData} from "@/components/Common/crud"; import {queryData} from "@/components/Common/crud";
import {SavePointTableListItem} from "@/components/Studio/StudioRightTool/StudioSavePoint/data"; import {SavePointTableListItem} from "@/components/Studio/StudioRightTool/StudioSavePoint/data";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi"; import {connect} from "umi";
import { Scrollbars } from 'react-custom-scrollbars';
const url = '/api/savepoints'; const url = '/api/savepoints';
const StudioSavePoint: React.FC<{}> = (props: any) => { const StudioSavePoint: React.FC<{}> = (props: any) => {
const {current,dispatch} = props; const {current,toolHeight,dispatch} = props;
const [row, setRow] = useState<SavePointTableListItem>(); const [row, setRow] = useState<SavePointTableListItem>();
const actionRef = useRef<ActionType>(); const actionRef = useRef<ActionType>();
...@@ -70,6 +71,19 @@ const StudioSavePoint: React.FC<{}> = (props: any) => { ...@@ -70,6 +71,19 @@ const StudioSavePoint: React.FC<{}> = (props: any) => {
return ( return (
<> <>
<Row>
<Col span={24}>
<div style={{float: "right"}}>
<Tooltip title="最小化">
<Button
type="text"
icon={<MinusSquareOutlined />}
/>
</Tooltip>
</div>
</Col>
</Row>
<Scrollbars style={{height:(toolHeight-32)}}>
<ProTable<SavePointTableListItem> <ProTable<SavePointTableListItem>
actionRef={actionRef} actionRef={actionRef}
rowKey="id" rowKey="id"
...@@ -99,10 +113,12 @@ const StudioSavePoint: React.FC<{}> = (props: any) => { ...@@ -99,10 +113,12 @@ const StudioSavePoint: React.FC<{}> = (props: any) => {
/> />
)} )}
</Drawer> </Drawer>
</Scrollbars>
</> </>
); );
}; };
export default connect(({ Studio }: { Studio: StateType }) => ({ export default connect(({ Studio }: { Studio: StateType }) => ({
current: Studio.current, current: Studio.current,
toolHeight: Studio.toolHeight,
}))(StudioSavePoint); }))(StudioSavePoint);
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, Badge, Tooltip, Button, Typography,Space} from "antd"; import {Form, InputNumber, Input, Switch, Select, Tag, Row, Col, Badge, Tooltip, Button, Typography, Space} from "antd";
import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined,MinusCircleOutlined} from "@ant-design/icons"; import {InfoCircleOutlined, PlusOutlined, MinusSquareOutlined, MinusCircleOutlined} 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";
import {JarStateType} from "@/pages/Jar/model"; import {JarStateType} from "@/pages/Jar/model";
import {Scrollbars} from 'react-custom-scrollbars';
const { Option } = Select; const {Option} = Select;
const { Text } = Typography; const {Text} = Typography;
const StudioSetting = (props: any) => { const StudioSetting = (props: any) => {
const {sessionCluster,clusterConfiguration,current,form,dispatch,tabs,currentSession,jars} = props; const {sessionCluster, clusterConfiguration, current, form, dispatch, tabs, currentSession, jars, toolHeight} = props;
const getClusterOptions = ()=>{ const getClusterOptions = () => {
let itemList = [(<Option key={0} value={0} label={(<><Tag color="default">Local</Tag>本地环境</>)}> let itemList = [(<Option key={0} value={0} label={(<><Tag color="default">Local</Tag>本地环境</>)}>
<Tag color="default">Local</Tag> <Tag color="default">Local</Tag>
本地环境 本地环境
</Option>)]; </Option>)];
for(let item of sessionCluster){ for (let item of sessionCluster) {
let tag =(<><Tag color={item.enabled?"processing":"error"}>{item.type}</Tag>{item.alias}</>); let tag = (<><Tag color={item.enabled ? "processing" : "error"}>{item.type}</Tag>{item.alias}</>);
itemList.push(<Option key={item.id} value={item.id} label={tag}> itemList.push(<Option key={item.id} value={item.id} label={tag}>
{tag} {tag}
</Option>) </Option>)
...@@ -28,10 +29,10 @@ const StudioSetting = (props: any) => { ...@@ -28,10 +29,10 @@ const StudioSetting = (props: any) => {
return itemList; return itemList;
}; };
const getClusterConfigurationOptions = ()=>{ const getClusterConfigurationOptions = () => {
let itemList = []; let itemList = [];
for(let item of clusterConfiguration){ for (let item of clusterConfiguration) {
let tag =(<><Tag color={item.enabled?"processing":"error"}>{item.type}</Tag>{item.alias}</>); let tag = (<><Tag color={item.enabled ? "processing" : "error"}>{item.type}</Tag>{item.alias}</>);
itemList.push(<Option key={item.id} value={item.id} label={tag}> itemList.push(<Option key={item.id} value={item.id} label={tag}>
{tag} {tag}
</Option>) </Option>)
...@@ -39,10 +40,10 @@ const StudioSetting = (props: any) => { ...@@ -39,10 +40,10 @@ const StudioSetting = (props: any) => {
return itemList; return itemList;
}; };
const getJarOptions = ()=>{ const getJarOptions = () => {
let itemList = []; let itemList = [];
for(let item of jars){ for (let item of jars) {
let tag =(<><Tag color={item.enabled?"processing":"error"}>{item.type}</Tag>{item.alias}</>); let tag = (<><Tag color={item.enabled ? "processing" : "error"}>{item.type}</Tag>{item.alias}</>);
itemList.push(<Option key={item.id} value={item.id} label={tag}> itemList.push(<Option key={item.id} value={item.id} label={tag}>
{tag} {tag}
</Option>) </Option>)
...@@ -50,29 +51,29 @@ const StudioSetting = (props: any) => { ...@@ -50,29 +51,29 @@ const StudioSetting = (props: any) => {
return itemList; return itemList;
}; };
useEffect(()=>{ useEffect(() => {
form.setFieldsValue(current.task); form.setFieldsValue(current.task);
},[current.task]); }, [current.task]);
const onValuesChange = (change:any,all:any)=>{ const onValuesChange = (change: any, all: any) => {
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==newTabs.activeKey){ if (newTabs.panes[i].key == newTabs.activeKey) {
for(let key in change){ for (let key in change) {
newTabs.panes[i].task[key]=all[key]; newTabs.panes[i].task[key] = all[key];
} }
break; break;
} }
} }
dispatch&&dispatch({ dispatch && dispatch({
type: "Studio/saveTabs", type: "Studio/saveTabs",
payload: newTabs, payload: newTabs,
}); });
}; };
const onChangeClusterSession = ()=>{ const onChangeClusterSession = () => {
showTables(currentSession.session,dispatch); showTables(currentSession.session, dispatch);
}; };
return ( return (
<> <>
...@@ -82,12 +83,13 @@ const StudioSetting = (props: any) => { ...@@ -82,12 +83,13 @@ const StudioSetting = (props: any) => {
<Tooltip title="最小化"> <Tooltip title="最小化">
<Button <Button
type="text" type="text"
icon={<MinusSquareOutlined />} icon={<MinusSquareOutlined/>}
/> />
</Tooltip> </Tooltip>
</div> </div>
</Col> </Col>
</Row> </Row>
<Scrollbars style={{height: (toolHeight - 32)}}>
<Form <Form
form={form} form={form}
layout="vertical" layout="vertical"
...@@ -105,18 +107,19 @@ const StudioSetting = (props: any) => { ...@@ -105,18 +107,19 @@ const StudioSetting = (props: any) => {
<Option value="yarn-application">yarn-application</Option> <Option value="yarn-application">yarn-application</Option>
</Select> </Select>
</Form.Item> </Form.Item>
{(current.task.type=='yarn-session'||current.task.type=='standalone')?( {(current.task.type == 'yarn-session' || current.task.type == 'standalone') ? (
<Row> <Row>
<Col span={24}> <Col span={24}>
<Form.Item label="Flink集群" tooltip={`选择Flink集群进行 ${current.task.type} 模式的远程提交任务`} name="clusterId" <Form.Item label="Flink集群" tooltip={`选择Flink集群进行 ${current.task.type} 模式的远程提交任务`} name="clusterId"
className={styles.form_item}> className={styles.form_item}>
{ {
currentSession.session? currentSession.session ?
(currentSession.sessionConfig&&currentSession.sessionConfig.clusterId? (currentSession.sessionConfig && currentSession.sessionConfig.clusterId ?
(<><Badge status="success"/><Text type="success">{currentSession.sessionConfig.clusterName}</Text></>) (<><Badge status="success"/><Text
:(<><Badge status="error"/><Text type="danger">本地模式</Text></>) type="success">{currentSession.sessionConfig.clusterName}</Text></>)
):(<Select : (<><Badge status="error"/><Text type="danger">本地模式</Text></>)
style={{ width: '100%' }} ) : (<Select
style={{width: '100%'}}
placeholder="选择Flink集群" placeholder="选择Flink集群"
defaultValue={0} defaultValue={0}
optionLabelProp="label" optionLabelProp="label"
...@@ -127,14 +130,15 @@ const StudioSetting = (props: any) => { ...@@ -127,14 +130,15 @@ const StudioSetting = (props: any) => {
} }
</Form.Item> </Form.Item>
</Col> </Col>
</Row>):''} </Row>) : ''}
{(current.task.type=='yarn-per-job'||current.task.type=='yarn-application')?( {(current.task.type == 'yarn-per-job' || current.task.type == 'yarn-application') ? (
<Row> <Row>
<Col span={24}> <Col span={24}>
<Form.Item label="Flink集群配置" tooltip={`选择Flink集群配置进行 ${current.task.type} 模式的远程提交任务`} name="clusterConfigurationId" <Form.Item label="Flink集群配置" tooltip={`选择Flink集群配置进行 ${current.task.type} 模式的远程提交任务`}
name="clusterConfigurationId"
className={styles.form_item}> className={styles.form_item}>
<Select <Select
style={{ width: '100%' }} style={{width: '100%'}}
placeholder="选择Flink集群配置" placeholder="选择Flink集群配置"
defaultValue={0} defaultValue={0}
optionLabelProp="label" optionLabelProp="label"
...@@ -143,14 +147,16 @@ const StudioSetting = (props: any) => { ...@@ -143,14 +147,16 @@ const StudioSetting = (props: any) => {
</Select> </Select>
</Form.Item> </Form.Item>
</Col> </Col>
</Row>):''} </Row>) : ''}
{(current.task.type=='yarn-application')?( {(current.task.type == 'yarn-application') ? (
<Row> <Row>
<Col span={24}> <Col span={24}>
<Form.Item label="可执行 Jar" tooltip={`选择可执行 Jar 进行 ${current.task.type} 模式的远程提交 Jar 任务。当该参数项存在值时,将只提交可执行 Jar.`} name="jarId" <Form.Item label="可执行 Jar"
tooltip={`选择可执行 Jar 进行 ${current.task.type} 模式的远程提交 Jar 任务。当该参数项存在值时,将只提交可执行 Jar.`}
name="jarId"
className={styles.form_item}> className={styles.form_item}>
<Select <Select
style={{ width: '100%' }} style={{width: '100%'}}
placeholder="选择可执行Jar,非必填" placeholder="选择可执行Jar,非必填"
allowClear allowClear
optionLabelProp="label" optionLabelProp="label"
...@@ -159,12 +165,12 @@ const StudioSetting = (props: any) => { ...@@ -159,12 +165,12 @@ const StudioSetting = (props: any) => {
</Select> </Select>
</Form.Item> </Form.Item>
</Col> </Col>
</Row>):''} </Row>) : ''}
<Form.Item <Form.Item
label="作业名" className={styles.form_item} name="jobName" label="作业名" className={styles.form_item} name="jobName"
tooltip='设置任务名称,默认为作业名' tooltip='设置任务名称,默认为作业名'
> >
<Input placeholder="自定义作业名" /> <Input placeholder="自定义作业名"/>
</Form.Item> </Form.Item>
<Row> <Row>
<Col span={12}> <Col span={12}>
...@@ -178,7 +184,7 @@ const StudioSetting = (props: any) => { ...@@ -178,7 +184,7 @@ const StudioSetting = (props: any) => {
label="Parallelism" className={styles.form_item} name="parallelism" label="Parallelism" className={styles.form_item} name="parallelism"
tooltip="设置Flink任务的并行度,最小为 1" tooltip="设置Flink任务的并行度,最小为 1"
> >
<InputNumber min={1} max={9999} defaultValue={1} /> <InputNumber min={1} max={9999} defaultValue={1}/>
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
...@@ -186,7 +192,7 @@ const StudioSetting = (props: any) => { ...@@ -186,7 +192,7 @@ const StudioSetting = (props: any) => {
<Col span={12}> <Col span={12}>
<Form.Item <Form.Item
label="Fragment" className={styles.form_item} name="fragment" valuePropName="checked" label="Fragment" className={styles.form_item} name="fragment" valuePropName="checked"
tooltip={{ title: '【增强特性】 开启FlinkSql片段机制,使用“:=”进行定义(以“;”结束),“${}”进行调用', icon: <InfoCircleOutlined /> }} tooltip={{title: '【增强特性】 开启FlinkSql片段机制,使用“:=”进行定义(以“;”结束),“${}”进行调用', icon: <InfoCircleOutlined/>}}
> >
<Switch checkedChildren="启用" unCheckedChildren="禁用" <Switch checkedChildren="启用" unCheckedChildren="禁用"
/> />
...@@ -195,7 +201,10 @@ const StudioSetting = (props: any) => { ...@@ -195,7 +201,10 @@ const StudioSetting = (props: any) => {
<Col span={12}> <Col span={12}>
<Form.Item <Form.Item
label="启用语句集" className={styles.form_item} name="statementSet" valuePropName="checked" label="启用语句集" className={styles.form_item} name="statementSet" valuePropName="checked"
tooltip={{ title: '【增强特性】 开启语句集机制,将把多个 Insert 语句合成一个 JobGraph 再进行提交,Select 语句无效', icon: <InfoCircleOutlined /> }} tooltip={{
title: '【增强特性】 开启语句集机制,将把多个 Insert 语句合成一个 JobGraph 再进行提交,Select 语句无效',
icon: <InfoCircleOutlined/>
}}
> >
<Switch checkedChildren="启用" unCheckedChildren="禁用" <Switch checkedChildren="启用" unCheckedChildren="禁用"
/> />
...@@ -219,40 +228,40 @@ const StudioSetting = (props: any) => { ...@@ -219,40 +228,40 @@ const StudioSetting = (props: any) => {
tooltip='从SavePointPath恢复Flink任务' tooltip='从SavePointPath恢复Flink任务'
> >
<Input placeholder="hdfs://..."/> <Input placeholder="hdfs://..."/>
</Form.Item>):'' </Form.Item>) : ''
} }
<Form.Item <Form.Item
label="其他配置" className={styles.form_item} label="其他配置" className={styles.form_item}
tooltip={{ title: '其他配置项,将被应用于执行环境,如 pipeline.name', icon: <InfoCircleOutlined /> }} tooltip={{title: '其他配置项,将被应用于执行环境,如 pipeline.name', icon: <InfoCircleOutlined/>}}
> >
<Form.List name="config" <Form.List name="config"
> >
{(fields, { add, remove }) => ( {(fields, {add, remove}) => (
<> <>
{fields.map(({ key, name, fieldKey, ...restField }) => ( {fields.map(({key, name, fieldKey, ...restField}) => (
<Space key={key} style={{ display: 'flex' }} align="baseline"> <Space key={key} style={{display: 'flex'}} align="baseline">
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'key']} name={[name, 'key']}
// fieldKey={[fieldKey, 'key']} // fieldKey={[fieldKey, 'key']}
style={{ marginBottom: '5px' }} style={{marginBottom: '5px'}}
> >
<Input placeholder="参数" /> <Input placeholder="参数"/>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'value']} name={[name, 'value']}
// fieldKey={[fieldKey, 'value']} // fieldKey={[fieldKey, 'value']}
style={{ marginBottom: '5px' }} style={{marginBottom: '5px'}}
> >
<Input placeholder="值" /> <Input placeholder="值"/>
</Form.Item> </Form.Item>
<MinusCircleOutlined onClick={() => remove(name)} /> <MinusCircleOutlined onClick={() => remove(name)}/>
</Space> </Space>
))} ))}
<Form.Item> <Form.Item>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}> <Button type="dashed" onClick={() => add()} block icon={<PlusOutlined/>}>
添加配置项 添加配置项
</Button> </Button>
</Form.Item> </Form.Item>
...@@ -261,16 +270,18 @@ const StudioSetting = (props: any) => { ...@@ -261,16 +270,18 @@ const StudioSetting = (props: any) => {
</Form.List> </Form.List>
</Form.Item> </Form.Item>
</Form> </Form>
</Scrollbars>
</> </>
); );
}; };
export default connect(({Studio,Jar}: { Studio: StateType,Jar: JarStateType }) => ({ export default connect(({Studio, Jar}: { Studio: StateType, Jar: JarStateType }) => ({
sessionCluster: Studio.sessionCluster, sessionCluster: Studio.sessionCluster,
clusterConfiguration: Studio.clusterConfiguration, clusterConfiguration: Studio.clusterConfiguration,
current: Studio.current, current: Studio.current,
tabs: Studio.tabs, tabs: Studio.tabs,
session: Studio.session, session: Studio.session,
currentSession: Studio.currentSession, currentSession: Studio.currentSession,
toolHeight: Studio.toolHeight,
jars: Jar.jars, jars: Jar.jars,
}))(StudioSetting); }))(StudioSetting);
...@@ -7,16 +7,15 @@ import StudioConfig from "./StudioConfig"; ...@@ -7,16 +7,15 @@ import StudioConfig from "./StudioConfig";
import StudioSetting from "./StudioSetting"; import StudioSetting from "./StudioSetting";
import StudioSavePoint from "./StudioSavePoint"; import StudioSavePoint from "./StudioSavePoint";
const { TabPane } = Tabs; const { TabPane } = Tabs;
const StudioRightTool = (props:any) => { const StudioRightTool = (props:any) => {
// const [form] = Form.useForm(); // const [form] = Form.useForm();
const {form} = props; const {form,toolHeight} = props;
return ( return (
<Tabs defaultActiveKey="1" size="small" tabPosition="right" style={{ height: "100%",overflow:"auto"}}> <Tabs defaultActiveKey="1" size="small" tabPosition="right" style={{ height: toolHeight}}>
<TabPane tab={<span><SettingOutlined /> 作业配置</span>} key="StudioSetting" > <TabPane tab={<span><SettingOutlined /> 作业配置</span>} key="StudioSetting" >
<StudioSetting form={form} /> <StudioSetting form={form} />
</TabPane> </TabPane>
...@@ -35,4 +34,5 @@ const StudioRightTool = (props:any) => { ...@@ -35,4 +34,5 @@ const StudioRightTool = (props:any) => {
export default connect(({ Studio }: { Studio: StateType }) => ({ export default connect(({ Studio }: { Studio: StateType }) => ({
sql: Studio.sql, sql: Studio.sql,
toolHeight: Studio.toolHeight,
}))(StudioRightTool); }))(StudioRightTool);
import {message, Tabs } from 'antd'; import {message, Tabs} from 'antd';
import React, {useState} from 'react'; import React, {useState} from 'react';
import {connect} from "umi"; import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import styles from './index.less'; import styles from './index.less';
import StudioEdit from '../StudioEdit'; import StudioEdit from '../StudioEdit';
import {saveTask} from "@/components/Studio/StudioEvent/DDL"; import {saveTask} from "@/components/Studio/StudioEvent/DDL";
const { TabPane } = Tabs;
const {TabPane} = Tabs;
const EditorTabs = (props: any) => { const EditorTabs = (props: any) => {
const {tabs,dispatch,current} = props; const {tabs, dispatch, current, toolHeight,width} = props;
const onChange = (activeKey: any) => { const onChange = (activeKey: any) => {
dispatch({ dispatch({
...@@ -18,11 +19,11 @@ const EditorTabs = (props: any) => { ...@@ -18,11 +19,11 @@ const EditorTabs = (props: any) => {
}; };
const onEdit = (targetKey: any, action: any) => { const onEdit = (targetKey: any, action: any) => {
if(action=='add'){ if (action == 'add') {
add(); add();
}else if(action=='remove'){ } else if (action == 'remove') {
if(current.isModified){ if (current.isModified) {
saveTask(current,dispatch); saveTask(current, dispatch);
} }
remove(targetKey); remove(targetKey);
} }
...@@ -32,7 +33,7 @@ const EditorTabs = (props: any) => { ...@@ -32,7 +33,7 @@ const EditorTabs = (props: any) => {
message.warn('敬请期待'); message.warn('敬请期待');
}; };
const remove = (targetKey:any) => { const remove = (targetKey: any) => {
let newActiveKey = tabs.activeKey; let newActiveKey = tabs.activeKey;
let lastIndex = 0; let lastIndex = 0;
tabs.panes.forEach((pane, i) => { tabs.panes.forEach((pane, i) => {
...@@ -52,26 +53,25 @@ const EditorTabs = (props: any) => { ...@@ -52,26 +53,25 @@ const EditorTabs = (props: any) => {
dispatch({ dispatch({
type: "Studio/saveTabs", type: "Studio/saveTabs",
payload: { payload: {
activeKey:newActiveKey, activeKey: newActiveKey,
panes:newPanes, panes: newPanes,
}, },
}); });
}; };
return ( return (
<Tabs <Tabs
hideAdd hideAdd
type="editable-card" type="editable-card"
size="small" size="small"
onChange={onChange} onChange={onChange}
activeKey={tabs.activeKey+''} activeKey={tabs.activeKey + ''}
onEdit={onEdit} onEdit={onEdit}
className={styles["edit-tabs"]} className={styles["edit-tabs"]}
style={{height:"50%"}} style={{height: toolHeight}}
> >
{tabs.panes.map(pane => ( {tabs.panes.map(pane => (
<TabPane tab={pane.title} key={pane.key} closable={pane.closable}> <TabPane tab={pane.title} key={pane.key} closable={pane.closable}>
<StudioEdit tabsKey={pane.key} height='100%'/> <StudioEdit tabsKey={pane.key} height={(toolHeight - 32)} width={width}/>
</TabPane> </TabPane>
))} ))}
</Tabs> </Tabs>
...@@ -79,8 +79,9 @@ const EditorTabs = (props: any) => { ...@@ -79,8 +79,9 @@ const EditorTabs = (props: any) => {
) )
}; };
export default connect(({ Studio }: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
current: Studio.current, current: Studio.current,
sql: Studio.sql, sql: Studio.sql,
tabs: Studio.tabs, tabs: Studio.tabs,
toolHeight: Studio.toolHeight,
}))(EditorTabs); }))(EditorTabs);
...@@ -13,6 +13,7 @@ import { ...@@ -13,6 +13,7 @@ import {
import UpdateCatalogueForm from './components/UpdateCatalogueForm'; import UpdateCatalogueForm from './components/UpdateCatalogueForm';
import {ActionType} from "@ant-design/pro-table"; import {ActionType} from "@ant-design/pro-table";
import UpdateTaskForm from "@/components/Studio/StudioTree/components/UpdateTaskForm"; import UpdateTaskForm from "@/components/Studio/StudioTree/components/UpdateTaskForm";
import { Scrollbars } from 'react-custom-scrollbars';
const { DirectoryTree } = Tree; const { DirectoryTree } = Tree;
...@@ -48,7 +49,7 @@ const getParentKey = (key, tree) => { ...@@ -48,7 +49,7 @@ const getParentKey = (key, tree) => {
}; };
const StudioTree: React.FC<StudioTreeProps> = (props) => { const StudioTree: React.FC<StudioTreeProps> = (props) => {
const {rightClickMenu,dispatch,tabs,refs} = props; const {rightClickMenu,dispatch,tabs,refs,toolHeight} = props;
const [treeData, setTreeData] = useState<TreeDataNode[]>(); const [treeData, setTreeData] = useState<TreeDataNode[]>();
const [dataList, setDataList] = useState<[]>(); const [dataList, setDataList] = useState<[]>();
...@@ -362,6 +363,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -362,6 +363,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
</div> </div>
</Col> </Col>
</Row> </Row>
<Scrollbars style={{height:(toolHeight-32)}}>
{/*<Search style={{marginBottom: 8}} placeholder="Search" onChange={onChange}/>*/} {/*<Search style={{marginBottom: 8}} placeholder="Search" onChange={onChange}/>*/}
<DirectoryTree <DirectoryTree
multiple multiple
...@@ -415,6 +417,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -415,6 +417,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
isCreate={isCreate} isCreate={isCreate}
/> />
) : null} ) : null}
</Scrollbars>
</div> </div>
); );
}; };
...@@ -425,4 +428,5 @@ export default connect(({Studio}: { Studio: StateType }) => ({ ...@@ -425,4 +428,5 @@ export default connect(({Studio}: { Studio: StateType }) => ({
tabs: Studio.tabs, tabs: Studio.tabs,
rightClickMenu: Studio.rightClickMenu, rightClickMenu: Studio.rightClickMenu,
refs: Studio.refs, refs: Studio.refs,
toolHeight: Studio.toolHeight,
}))(StudioTree); }))(StudioTree);
...@@ -17,41 +17,53 @@ ...@@ -17,41 +17,53 @@
background-color: #ffffff; background-color: #ffffff;
} }
:global { :global {
/* --- tool窗口 滚动条 --- start */
.scrollbars-tool{
height: calc((100vh - 116px)/2 - 32px)!important;
}
/* --- tool窗口 滚动条 --- end */
/* --- 水平 tabs --- start */
.ant-tabs-top > .ant-tabs-nav, .ant-tabs-bottom > .ant-tabs-nav, .ant-tabs-top > div > .ant-tabs-nav, .ant-tabs-bottom > div > .ant-tabs-nav {
margin: 0;
}
/* --- 水平 tabs --- end */
/* --- card 内偏移样式 --- start */ /* --- card 内偏移样式 --- start */
#studio_card > .ant-card-body { #studio_card > .ant-card-body {
padding: 0px; padding: 0px;
} }
/* --- card 内偏移样式 --- start */ /* --- card 内偏移样式 --- end */
/* --- list toolbar隐藏滚动条 --- start */ /* --- list toolbar隐藏滚动条 --- start */
.ant-pro-table-list-toolbar { .ant-pro-table-list-toolbar {
overflow-x: hidden; overflow-x: hidden;
overflow-y: hidden; overflow-y: hidden;
line-height: 1; line-height: 1;
} }
/* --- list toolbar隐藏滚动条 --- start */ /* --- list toolbar隐藏滚动条 --- end */
/* --- list toolbar修改内偏移 --- start */ /* --- list toolbar修改内偏移 --- start */
.ant-pro-table-list-toolbar-container { .ant-pro-table-list-toolbar-container {
padding: 0; padding: 0;
} }
/* --- list toolbar修改内偏移 --- start */ /* --- list toolbar修改内偏移 --- end */
/* --- prodescription item宽度 --- start */ /* --- prodescription item宽度 --- start */
.ant-descriptions-item-content { .ant-descriptions-item-content {
width: 100%; width: 100%;
} }
/* --- prodescription item宽度 --- start */ /* --- prodescription item宽度 --- end */
/* --- table 宽度 --- start */ /* --- table 宽度 --- start */
.ant-table-wrapper { .ant-table-wrapper {
width: 100%; width: 100%;
} }
/* --- table 宽度 --- start */ /* --- table 宽度 --- end */
/* --- 右键菜单选项 高度 --- start */ /* --- 右键菜单选项 高度 --- start */
.ant-menu-vertical > .ant-menu-item, .ant-menu-vertical-left > .ant-menu-item, .ant-menu-vertical-right > .ant-menu-item, .ant-menu-inline > .ant-menu-item, .ant-menu-vertical > .ant-menu-submenu > .ant-menu-submenu-title, .ant-menu-vertical-left > .ant-menu-submenu > .ant-menu-submenu-title, .ant-menu-vertical-right > .ant-menu-submenu > .ant-menu-submenu-title, .ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title { .ant-menu-vertical > .ant-menu-item, .ant-menu-vertical-left > .ant-menu-item, .ant-menu-vertical-right > .ant-menu-item, .ant-menu-inline > .ant-menu-item, .ant-menu-vertical > .ant-menu-submenu > .ant-menu-submenu-title, .ant-menu-vertical-left > .ant-menu-submenu > .ant-menu-submenu-title, .ant-menu-vertical-right > .ant-menu-submenu > .ant-menu-submenu-title, .ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title {
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
} }
/* --- 右键菜单选项 高度 --- start */ /* --- 右键菜单选项 高度 --- end */
} }
/* --- tabs 垂直样式 --- start */ /* --- tabs 垂直样式 --- start */
......
import React, {useEffect, useRef, useState,useCallback} from "react"; import React, {useEffect, useRef, useState, useCallback} from "react";
import {connect} from "umi"; import {connect} from "umi";
import styles from './index.less'; import styles from './index.less';
import {} from "@ant-design/icons"; import {} from "@ant-design/icons";
import StudioMenu from "./StudioMenu"; import StudioMenu from "./StudioMenu";
import {Row, Col, Card, Form,BackTop} from "antd"; import {Row, Col, Card, Form, BackTop} from "antd";
import StudioTabs from "./StudioTabs"; import StudioTabs from "./StudioTabs";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import StudioConsole from "./StudioConsole"; import StudioConsole from "./StudioConsole";
...@@ -15,28 +15,31 @@ import { ...@@ -15,28 +15,31 @@ import {
} from "@/components/Studio/StudioEvent/DDL"; } from "@/components/Studio/StudioEvent/DDL";
import {loadSettings} from "@/pages/Settings/function"; import {loadSettings} from "@/pages/Settings/function";
import DraggleLayout from "@/components/DraggleLayout"; import DraggleLayout from "@/components/DraggleLayout";
import DraggleVerticalLayout from "@/components/DraggleLayout/DraggleVerticalLayout";
type StudioProps = { type StudioProps = {
rightClickMenu:StateType['rightClickMenu']; rightClickMenu: StateType['rightClickMenu'];
dispatch:any; dispatch: any;
}; };
const Studio: React.FC<StudioProps> = (props) => { const Studio: React.FC<StudioProps> = (props) => {
const {rightClickMenu,dispatch} = props; const {rightClickMenu, toolHeight, toolWidth, dispatch} = props;
const [form] = Form.useForm(); const [form] = Form.useForm();
const VIEW = { const VIEW = {
rightToolWidth:300, rightToolWidth: 300,
leftToolWidth:300, leftToolWidth: 300,
marginTop:116, marginTop: 116,
topHeight: 35.6,
bottomHeight: 153.6,
}; };
const [size, setSize] = useState({ const [size, setSize] = useState({
width: document.documentElement.clientWidth-1, width: document.documentElement.clientWidth - 1,
height: document.documentElement.clientHeight, height: document.documentElement.clientHeight,
}); });
const onResize = useCallback(() => { const onResize = useCallback(() => {
setSize({ setSize({
width: document.documentElement.clientWidth-1, width: document.documentElement.clientWidth - 1,
height: document.documentElement.clientHeight, height: document.documentElement.clientHeight,
}) })
}, []); }, []);
...@@ -50,7 +53,7 @@ const Studio: React.FC<StudioProps> = (props) => { ...@@ -50,7 +53,7 @@ const Studio: React.FC<StudioProps> = (props) => {
}, [onResize]); }, [onResize]);
loadSettings(dispatch); loadSettings(dispatch);
getFillAllByVersion('',dispatch); getFillAllByVersion('', dispatch);
showCluster(dispatch); showCluster(dispatch);
showSessionCluster(dispatch); showSessionCluster(dispatch);
showClusterConfiguration(dispatch); showClusterConfiguration(dispatch);
...@@ -58,9 +61,9 @@ const Studio: React.FC<StudioProps> = (props) => { ...@@ -58,9 +61,9 @@ const Studio: React.FC<StudioProps> = (props) => {
listSession(dispatch); listSession(dispatch);
showJars(dispatch); showJars(dispatch);
const onClick=()=>{ const onClick = () => {
if(rightClickMenu){ if (rightClickMenu) {
dispatch&&dispatch({ dispatch && dispatch({
type: "Studio/showRightClickMenu", type: "Studio/showRightClickMenu",
payload: false, payload: false,
}); });
...@@ -68,15 +71,31 @@ const Studio: React.FC<StudioProps> = (props) => { ...@@ -68,15 +71,31 @@ const Studio: React.FC<StudioProps> = (props) => {
}; };
return ( return (
<div onClick={onClick} style={{'margin':'-24px'}}> <div onClick={onClick} style={{'margin': '-24px'}}>
<StudioMenu form={form}/> <StudioMenu form={form}/>
<Card bordered={false} className={styles.card} size="small" id="studio_card" style={{marginBottom:0}}> <Card bordered={false} className={styles.card} size="small" id="studio_card" style={{marginBottom: 0}}>
<DraggleVerticalLayout
containerWidth={size.width}
containerHeight={(size.height - VIEW.marginTop)}
min={(VIEW.topHeight)}
max={(size.height - VIEW.bottomHeight)}
initTopHeight={VIEW.topHeight}
handler={
<div
style={{
height: 4,
width: '100%',
background: 'rgb(240, 240, 240)',
}}
/>
}
>
<Row> <Row>
<DraggleLayout <DraggleLayout
containerWidth={size.width-VIEW.rightToolWidth} containerWidth={size.width - VIEW.rightToolWidth}
containerHeight={(size.height-VIEW.marginTop)/2} containerHeight={toolHeight}
min={VIEW.leftToolWidth} min={VIEW.leftToolWidth}
max={size.width*(1/2)} max={size.width * (1 / 2)}
initLeftWidth={VIEW.leftToolWidth} initLeftWidth={VIEW.leftToolWidth}
handler={ handler={
<div <div
...@@ -89,39 +108,34 @@ const Studio: React.FC<StudioProps> = (props) => { ...@@ -89,39 +108,34 @@ const Studio: React.FC<StudioProps> = (props) => {
} }
> >
<Col className={styles["vertical-tabs"]}> <Col className={styles["vertical-tabs"]}>
<StudioLeftTool className={styles["vertical-tabs"]} style={{ <StudioLeftTool style={{
height: (size.height-VIEW.marginTop),
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
}}/> }}/>
</Col> </Col>
<Col <Col>
style={{ <StudioTabs width={size.width - VIEW.rightToolWidth - toolWidth}/>
height: ((size.height-VIEW.marginTop)),
}}>
<StudioTabs
style={{
height: ((size.height-VIEW.marginTop)/2),
}}
/>
<StudioConsole
style={{
height: ((size.height-VIEW.marginTop)/2),
}}
/>
</Col> </Col>
</DraggleLayout> </DraggleLayout>
<Col id='StudioRightTool' style={{width:VIEW.rightToolWidth,height:(size.height-VIEW.marginTop)}} className={styles["vertical-tabs"]}> <Col id='StudioRightTool' style={{width: VIEW.rightToolWidth}} className={styles["vertical-tabs"]}>
<StudioRightTool form={form}/> <StudioRightTool form={form}/>
</Col> </Col>
</Row> </Row>
<Row>
<Col span={24}>
<StudioConsole height={size.height - toolHeight - VIEW.marginTop}/>
</Col>
</Row>
</DraggleVerticalLayout>
</Card> </Card>
<BackTop /> <BackTop/>
</div> </div>
) )
}; };
export default connect(({Studio}: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
rightClickMenu: Studio.rightClickMenu, rightClickMenu: Studio.rightClickMenu,
toolHeight: Studio.toolHeight,
toolWidth: Studio.toolWidth,
}))(Studio); }))(Studio);
...@@ -122,6 +122,8 @@ export type SessionType = { ...@@ -122,6 +122,8 @@ export type SessionType = {
} }
export type StateType = { export type StateType = {
toolHeight?: number;
toolWidth?: number;
cluster?: ClusterType[]; cluster?: ClusterType[];
sessionCluster?: ClusterType[]; sessionCluster?: ClusterType[];
clusterConfiguration?: ClusterConfigurationType[]; clusterConfiguration?: ClusterConfigurationType[];
...@@ -147,6 +149,8 @@ export type ModelType = { ...@@ -147,6 +149,8 @@ export type ModelType = {
saveTask: Effect; saveTask: Effect;
}; };
reducers: { reducers: {
saveToolHeight: Reducer<StateType>;
saveToolWidth: Reducer<StateType>;
saveSql: Reducer<StateType>; saveSql: Reducer<StateType>;
saveCurrentPath: Reducer<StateType>; saveCurrentPath: Reducer<StateType>;
saveMonaco: Reducer<StateType>; saveMonaco: Reducer<StateType>;
...@@ -169,6 +173,8 @@ export type ModelType = { ...@@ -169,6 +173,8 @@ export type ModelType = {
const Model: ModelType = { const Model: ModelType = {
namespace: 'Studio', namespace: 'Studio',
state: { state: {
toolHeight: 400,
toolWidth: 300,
cluster: [], cluster: [],
sessionCluster: [], sessionCluster: [],
clusterConfiguration: [], clusterConfiguration: [],
...@@ -271,6 +277,17 @@ const Model: ModelType = { ...@@ -271,6 +277,17 @@ const Model: ModelType = {
}, },
reducers: { reducers: {
saveToolHeight(state, {payload}) {
return {
...state,
toolHeight: payload,
};
},saveToolWidth(state, {payload}) {
return {
...state,
toolWidth: payload,
};
},
saveSql(state, {payload}) { saveSql(state, {payload}) {
const tabs = state.tabs; const tabs = state.tabs;
let newCurrent = state.current; let newCurrent = state.current;
......
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