Commit 9f3e81e2 authored by godkaikai's avatar godkaikai

新增图表

parent 35d04ca9
......@@ -48,6 +48,7 @@
"dependencies": {
"@ant-design/charts": "^1.2.10",
"@ant-design/icons": "^4.5.0",
"@ant-design/plots": "^1.0.7",
"@ant-design/pro-descriptions": "^1.6.8",
"@ant-design/pro-form": "^1.18.3",
"@ant-design/pro-layout": "^6.18.0",
......
@import '~antd/es/style/themes/default.less';
.form_setting{
padding-left: 10px;
}
.form_item{
margin-bottom: 5px;
}
import {Button, Tag,Row, Col,Form,Select, Empty} from "antd";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi";
import styles from "./index.less";
import {FireOutlined, SearchOutlined,RedoOutlined} from '@ant-design/icons';
import {useState} from "react";
import React from "react";
const {Option} = Select;
export type LineChartConfig = {
xField: string,
yField: string,
seriesField?: string,
xAxis?: {
type?: string,
},
};
export type LineChartProps = {
onChange: (values: Partial<LineChartConfig>) => void;
data: [];
column: [];
};
const LineChartSetting: React.FC<LineChartProps> = (props) => {
const {data,column,onChange: handleChange,dispatch} = props;
const onValuesChange = (change: any, all: any) => {
handleChange(all);
};
const getColumnOptions = () => {
const itemList = [];
for (const item of column) {
itemList.push(<Option key={item} value={item} label={item}>
{item}
</Option>)
}
return itemList;
};
return (
<>
<Form
className={styles.form_setting}
onValuesChange={onValuesChange}
>
<Row>
<Col span={12}>
<Form.Item
label="x 轴" className={styles.form_item} name="xField"
>
{column&&column.length > 0 ? (
<Select defaultValue={column[0]} value={column[0]}>
{getColumnOptions()}
</Select>):(<Select >
{column&&getColumnOptions()}
</Select>)}
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="y 轴" className={styles.form_item} name="yField"
>
{column&&column.length > 0 ? (
<Select defaultValue={column[0]} value={column[0]}>
{getColumnOptions()}
</Select>):(<Select >
{column&&getColumnOptions()}
</Select>)}
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="分组字段" className={styles.form_item} name="seriesField"
>
{column&&column.length > 0 ? (
<Select defaultValue={column[0]} value={column[0]}>
{getColumnOptions()}
</Select>):(<Select >
{column&&getColumnOptions()}
</Select>)}
</Form.Item>
</Col>
</Row>
</Form>
</>
);
};
export default connect(({ Studio }: { Studio: StateType }) => ({
current: Studio.current,
result: Studio.result,
}))(LineChartSetting);
@import '~antd/es/style/themes/default.less';
.form_setting{
padding-left: 10px;
}
.form_item{
margin-bottom: 5px;
}
import {Button, Tag,Row, Col,Form,Select, Empty} from "antd";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi";
import styles from "./index.less";
import {FireOutlined, SearchOutlined,RedoOutlined} from '@ant-design/icons';
import {CHART, isSql} from "@/components/Studio/conf";
import { Line } from '@ant-design/plots';
import {useEffect, useState} from "react";
import LineChartSetting from "./LineChartSetting";
import {showJobData} from "@/components/Studio/StudioEvent/DQL";
const {Option} = Select;
const Chart = (props:any) => {
const {current,result,dispatch} = props;
const [config, setConfig] = useState({});
const [data, setData] = useState([]);
const [column, setColumn] = useState([]);
const [type, setType] = useState<string>(CHART.LINE);
useEffect(() => {
toBuild();
}, [result,current.console.result]);
const toBuild = () => {
if(isSql(current.task.dialect)){
setData(current.console.result.result.rowData);
setColumn(current.console.result.result.columns);
}else{
setData(result.rowData);
setColumn(result.columns);
}
};
const toRebuild = () => {
if(!isSql(current.task.diagnosticCodesToIgnore)){
showJobData(current.console.result.jobId,dispatch);
}
};
const onValuesChange = (change: any, all: any) => {
if(change.type){
setType(change.type);
}
};
const renderChartSetting = () => {
switch (type){
case CHART.LINE:
return <LineChartSetting data={data} column={column} onChange={(value) => {
setConfig(value);
}} />;
default:
return <LineChartSetting />;
}
};
const renderChartContent = () => {
if(column.length==0){
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />;
}
switch (type){
case CHART.LINE:
return <Line data={data} {...config} />;
default:
return <Line data={data} {...config} />;
}
};
return (
<div style={{width: '100%'}}>
<Row>
<Col span={16} style={{padding:'20px'}}>
{renderChartContent()}
</Col>
<Col span={8}>
<Form
className={styles.form_setting}
onValuesChange={onValuesChange}
>
<Row>
<Col span={12}>
<Form.Item
label="图形类型" className={styles.form_item} name="type"
>
<Select defaultValue={CHART.LINE} value={CHART.LINE}>
<Option value={CHART.LINE}>折线图</Option>
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Button type="primary" onClick={toRebuild} icon={<RedoOutlined />}>
重新渲染
</Button>
</Col>
</Row>
</Form>
{renderChartSetting()}
</Col>
</Row>
</div>
);
};
export default connect(({ Studio }: { Studio: StateType }) => ({
current: Studio.current,
result: Studio.result,
}))(Chart);
import {Tabs, Empty} from "antd";
import {
CodeOutlined, TableOutlined, RadarChartOutlined, CalendarOutlined, FileSearchOutlined, DesktopOutlined
, FunctionOutlined, ApartmentOutlined
, FunctionOutlined, ApartmentOutlined,BarChartOutlined
} from "@ant-design/icons";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi";
......@@ -13,6 +13,7 @@ import StudioFX from "./StudioFX";
import StudioCA from "./StudioCA";
import StudioProcess from "./StudioProcess";
import {Scrollbars} from 'react-custom-scrollbars';
import Chart from "@/components/Chart";
const {TabPane} = Tabs;
......@@ -50,6 +51,19 @@ const StudioConsole = (props: any) => {
<StudioTable/>
</Scrollbars>
</TabPane>
<TabPane
tab={
<span>
<BarChartOutlined />
统计
</span>
}
key="StudioChart"
>
<Scrollbars style={{height: consoleHeight}}>
<Chart/>
</Scrollbars>
</TabPane>
<TabPane
tab={
<span>
......
......@@ -11,14 +11,14 @@ import Button from "antd/es/button/button";
import Breadcrumb from "antd/es/breadcrumb/Breadcrumb";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi";
import {handleAddOrUpdate, postDataArray} from "@/components/Common/crud";
import {executeSql, explainSql, getJobPlan} from "@/pages/FlinkSqlStudio/service";
import { postDataArray} from "@/components/Common/crud";
import {executeSql, getJobPlan} from "@/pages/FlinkSqlStudio/service";
import StudioHelp from "./StudioHelp";
import StudioGraph from "./StudioGraph";
import {showCluster, showTables, saveTask} from "@/components/Studio/StudioEvent/DDL";
import {useEffect, useState} from "react";
import StudioExplain from "../StudioConsole/StudioExplain";
import {DIALECT, isSql} from "@/components/Studio/conf";
import {DIALECT, isOnline, isSql} from "@/components/Studio/conf";
import {
ModalForm,
} from '@ant-design/pro-form';
......@@ -37,10 +37,13 @@ const StudioMenu = (props: any) => {
const [modalVisible, handleModalVisible] = useState<boolean>(false);
const [exportModalVisible, handleExportModalVisible] = useState<boolean>(false);
const [graphModalVisible, handleGraphModalVisible] = useState<boolean>(false);
const [explainData, setExplainData] = useState([]);
const [graphData, setGraphData] = useState();
const execute = () => {
if(!isSql(current.task.dialect)&&!isOnline(current.task.type)){
message.warn(`该任务执行模式为【${current.task.type}】,不支持 SQL 查询,请手动保存后使用右侧按钮——作业提交`);
return;
}
let selectsql = null;
if (current.monaco.current) {
let selection = current.monaco.current.editor.getSelection();
......@@ -75,7 +78,7 @@ const StudioMenu = (props: any) => {
if (res.datas.success) {
message.success('执行成功');
} else {
message.success('执行失败');
message.error('执行失败');
}
let newTabs = tabs;
for (let i = 0; i < newTabs.panes.length; i++) {
......@@ -230,8 +233,8 @@ const StudioMenu = (props: any) => {
const runMenu = (
<Menu>
<Menu.Item onClick={execute}>同步执行</Menu.Item>
<Menu.Item onClick={submit}>异步提交</Menu.Item>
<Menu.Item onClick={execute}>SQL 查询</Menu.Item>
<Menu.Item onClick={submit}>提交作业</Menu.Item>
</Menu>
);
......@@ -348,7 +351,7 @@ const StudioMenu = (props: any) => {
/>
</Tooltip>)}
{(!current.task.dialect||current.task.dialect === DIALECT.FLINKSQL||isSql( current.task.dialect )) &&(
<Tooltip title="执行当前的 FlinkSql">
<Tooltip title="执行当前的 SQL">
<Button
type="text"
icon={<PlayCircleTwoTone/>}
......@@ -357,7 +360,7 @@ const StudioMenu = (props: any) => {
/>
</Tooltip>)}
{(!current.task.dialect||current.task.dialect === DIALECT.FLINKSQL||isSql( current.task.dialect )) &&(<>
<Tooltip title="提交当前的作业到集群">
<Tooltip title="提交当前的作业到集群,提交前请手动保存">
<Button
type="text"
icon={<RocketTwoTone/>}
......
......@@ -20,8 +20,12 @@ export const DIALECT = {
JAVA:'Java',
};
export const isSql = (type: string)=>{
switch (type){
export const CHART = {
LINE:'Line',
};
export const isSql = (dialect: string)=>{
switch (dialect){
case DIALECT.SQL:
case DIALECT.MYSQL:
case DIALECT.ORACLE:
......@@ -32,4 +36,16 @@ export const isSql = (type: string)=>{
default:
return false;
}
};
export const isOnline = (type: string)=>{
switch (type){
case RUN_MODE.LOCAL:
case RUN_MODE.STANDALONE:
case RUN_MODE.YARN_SESSION:
case RUN_MODE.KUBERNETES_SESSION:
return true;
default:
return false;
}
}
This diff is collapsed.
......@@ -172,6 +172,7 @@ export type ModelType = {
saveMonaco: Reducer<StateType>;
saveSqlMetaData: Reducer<StateType>;
saveTabs: Reducer<StateType>;
closeTabs: Reducer<StateType>;
changeActiveKey: Reducer<StateType>;
saveTaskData: Reducer<StateType>;
saveSession: Reducer<StateType>;
......@@ -420,6 +421,31 @@ const Model: ModelType = {
},
};
},
closeTabs(state, {payload}) {
const {deleteType, current} = payload;
const newTabs = state.tabs;
const firstKey = newTabs.panes[0].key;
let newCurrent = newTabs.panes[0];
if (deleteType === 'CLOSE_OTHER') {
const keys = [firstKey, current.key];
newCurrent = {...current};
newTabs.activeKey = current.key;
newTabs.panes = newTabs.panes.filter(item => keys.includes(item.key));
} else {
newTabs.panes = [];
newTabs.activeKey = firstKey
}
return {
...state,
current: {
...newCurrent
},
tabs: {
...newTabs,
}
};
},
changeActiveKey(state, {payload}) {
const {tabs} = state;
tabs.activeKey = payload;
......
......@@ -550,6 +550,12 @@ export default (): React.ReactNode => {
<li>
<Link>新增 UDF Java方言的Local模式的在线编写、调试、动态加载</Link>
</li>
<li>
<Link>新增 编辑器选项卡右键关闭其他和关闭所有</Link>
</li>
<li>
<Link>新增 统计选项卡的图标支持</Link>
</li>
</ul>
</Paragraph>
</Timeline.Item>
......
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