Commit 2cda298f authored by wenmo's avatar wenmo

tree和tabs联动

parent 38050864
...@@ -8,12 +8,7 @@ import com.dlink.service.TaskService; ...@@ -8,12 +8,7 @@ import com.dlink.service.TaskService;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -104,9 +99,9 @@ public class TaskController { ...@@ -104,9 +99,9 @@ public class TaskController {
/** /**
* 获取指定ID的信息 * 获取指定ID的信息
*/ */
@PostMapping("/getOneById") @GetMapping
public Result getOneById(@RequestBody Task task) throws Exception { public Result getOneById(@RequestParam Integer id) {
task = taskService.getById(task.getId()); Task task = taskService.getTaskInfoById(id);
return Result.succeed(task,"获取成功"); return Result.succeed(task,"获取成功");
} }
} }
......
package com.dlink.model; package com.dlink.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.dlink.db.model.SuperEntity; import com.dlink.db.model.SuperEntity;
import com.dlink.executor.Executor; import com.dlink.executor.Executor;
...@@ -36,6 +37,9 @@ public class Task extends SuperEntity{ ...@@ -36,6 +37,9 @@ public class Task extends SuperEntity{
private String note; private String note;
@TableField(exist = false)
private String statement;
public ExecutorSetting getLocalExecutorSetting(){ public ExecutorSetting getLocalExecutorSetting(){
return new ExecutorSetting(Executor.LOCAL,checkPoint,parallelism,fragment,savePointPath); return new ExecutorSetting(Executor.LOCAL,checkPoint,parallelism,fragment,savePointPath);
} }
......
...@@ -15,4 +15,5 @@ public interface TaskService extends ISuperService<Task> { ...@@ -15,4 +15,5 @@ public interface TaskService extends ISuperService<Task> {
SubmitResult submitByTaskId(Integer id); SubmitResult submitByTaskId(Integer id);
Task getTaskInfoById(Integer id);
} }
package com.dlink.service.impl; package com.dlink.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dlink.assertion.Assert; import com.dlink.assertion.Assert;
import com.dlink.cluster.FlinkCluster; import com.dlink.cluster.FlinkCluster;
import com.dlink.db.service.impl.SuperServiceImpl; import com.dlink.db.service.impl.SuperServiceImpl;
...@@ -46,4 +47,16 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen ...@@ -46,4 +47,16 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen
return jobManager.submit(statement.getStatement(), task.getRemoteExecutorSetting()); return jobManager.submit(statement.getStatement(), task.getRemoteExecutorSetting());
} }
@Override
public Task getTaskInfoById(Integer id) {
Task task = this.getById(id);
if(task!=null){
Statement statement = statementService.getById(id);
if(statement!=null){
task.setStatement(statement.getStatement());
}
}
return task;
}
} }
...@@ -48,6 +48,15 @@ export async function postAll(url:string,params?: any) { ...@@ -48,6 +48,15 @@ export async function postAll(url:string,params?: any) {
}); });
} }
export async function getInfoById(url:string,id:number) {
return request(url, {
method: 'GET',
params: {
id:id,
},
});
}
export const handleAddOrUpdate = async (url:string,fields: any) => { export const handleAddOrUpdate = async (url:string,fields: any) => {
const tipsTitle = fields.id ? "修改" : "添加"; const tipsTitle = fields.id ? "修改" : "添加";
const hide = message.loading(`正在${tipsTitle}`); const hide = message.loading(`正在${tipsTitle}`);
...@@ -112,3 +121,13 @@ export const handleOption = async (url:string,title:string,param:any) => { ...@@ -112,3 +121,13 @@ export const handleOption = async (url:string,title:string,param:any) => {
return false; return false;
} }
}; };
export const handleInfo = async (url:string,id:number) => {
try {
const {datas} = await getInfoById(url,id);
return datas;
} catch (error) {
message.error('获取失败,请重试');
return false;
}
};
...@@ -30,11 +30,11 @@ const menu = ( ...@@ -30,11 +30,11 @@ const menu = (
const StudioMenu = (props: any) => { const StudioMenu = (props: any) => {
const {sql,currentPath} = props; const {catalogue,currentPath} = props;
const [pathItem, setPathItem] = useState<[]>(); const [pathItem, setPathItem] = useState<[]>();
const executeSql = () => { const executeSql = () => {
console.log('获取' + sql); console.log('获取' + catalogue.sql);
}; };
const runMenu = ( const runMenu = (
...@@ -154,6 +154,6 @@ const StudioMenu = (props: any) => { ...@@ -154,6 +154,6 @@ const StudioMenu = (props: any) => {
}; };
export default connect(({Studio}: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
sql: Studio.sql, catalogue: Studio.catalogue,
currentPath: Studio.currentPath, currentPath: Studio.currentPath,
}))(StudioMenu); }))(StudioMenu);
import { Tabs } from 'antd'; import { Tabs } from 'antd';
import React from 'react'; import React, {useState} from 'react';
import StudioEdit from "../StudioEdit"; import StudioEdit from "../StudioEdit";
import {connect} from "umi"; import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
...@@ -10,96 +10,95 @@ const initialPanes = [ ...@@ -10,96 +10,95 @@ const initialPanes = [
{ title: '草稿', key: '0' ,value:'select * from ',closable: false,}, { title: '草稿', key: '0' ,value:'select * from ',closable: false,},
]; ];
class EditorTabs extends React.Component { const EditorTabs = (props: any) => {
newTabIndex = 1; const {tabs,dispatch} = props;
const [newTabIndex, setNewTabIndex] = useState<number>(0);
const [activeKey, setActiveKey] = useState<number>(tabs.activeKey);
const [panes, setPanes] = useState<any>(tabs.panes);
state = { const onChange = (activeKey: any) => {
activeKey: initialPanes[0].key, //setActiveKey(activeKey);
panes: initialPanes, dispatch({
}; type: "Studio/changeActiveKey",
payload: activeKey,
onChange = (activeKey: any) => { });
this.setState({ activeKey });
}; };
onEdit = (targetKey: any, action: any) => { const onEdit = (targetKey: any, action: any) => {
this[action](targetKey); console.log(targetKey)
console.log(action);
if(action=='add'){
add();
}else if(action=='remove'){
remove(targetKey);
}
}; };
updateValue = (targetKey: any, val: string)=>{ const updateValue = (targetKey: any, val: string)=>{
const { panes, activeKey } = this.state;
panes.forEach((pane, i) => { panes.forEach((pane, i) => {
if (pane.key === targetKey) { if (pane.key === targetKey) {
pane.value = val; //pane.value = val;
return; return;
} }
}); });
/*debugger;
this.setState({
panes:panes,
activeKey: activeKey,
});*/
}; };
add = () => { const add = () => {
const { panes } = this.state; let index = newTabIndex + 1;
const activeKey = this.newTabIndex++;
const newPanes = [...panes]; const newPanes = [...panes];
newPanes.push({ title: `未命名${activeKey}`,value:'', key: `${activeKey}` }); newPanes.push({ title: `未命名${index}`,value:'', key: -index });
this.setState({ setPanes(newPanes);
panes: newPanes, setActiveKey(-index);
activeKey: activeKey, setNewTabIndex(index);
});
}; };
remove = (targetKey:any) => { const remove = (targetKey:any) => {
const { panes, activeKey } = this.state; let newActiveKey = tabs.activeKey;
let newActiveKey = activeKey; let lastIndex = 0;
let lastIndex = 1; tabs.panes.forEach((pane, i) => {
panes.forEach((pane, i) => {
if (pane.key === targetKey) { if (pane.key === targetKey) {
lastIndex = i - 1; lastIndex = i - 1;
} }
}); });
const newPanes = panes.filter(pane => pane.key !== targetKey); let panes = tabs.panes;
const newPanes = panes.filter(pane => pane.key != targetKey);
if (newPanes.length && newActiveKey === targetKey) { if (newPanes.length && newActiveKey === targetKey) {
if (lastIndex >= 0) { if (lastIndex > 0) {
newActiveKey = newPanes[lastIndex].key; newActiveKey = newPanes[lastIndex].key;
} else { } else {
newActiveKey = newPanes[0].key; newActiveKey = newPanes[0].key;
} }
} }
this.setState({ dispatch({
panes: newPanes, type: "Studio/saveTabs",
activeKey: newActiveKey, payload: {
activeKey:newActiveKey,
panes:newPanes,
},
}); });
}; };
render() {
const { panes, activeKey } = this.state;
return ( return (
<>
<Tabs <Tabs
type="editable-card" type="editable-card"
size="small" size="small"
onChange={this.onChange} onChange={onChange}
activeKey={activeKey} activeKey={tabs.activeKey+''}
onEdit={this.onEdit} onEdit={onEdit}
> >
{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 value={{formulaContent:pane.value}} onChange={
(val: string)=>{
this.updateValue(pane.key,val);
}} />
</TabPane> </TabPane>
))} ))}
</Tabs> </Tabs>
); </>
} )
} };
export default connect(({ Studio }: { Studio: StateType }) => ({ export default connect(({ Studio }: { Studio: StateType }) => ({
current: Studio.current, current: Studio.current,
catalogue: Studio.catalogue, catalogue: Studio.catalogue,
sql: Studio.sql, sql: Studio.sql,
tabs: Studio.tabs,
}))(EditorTabs); }))(EditorTabs);
...@@ -9,6 +9,7 @@ export type DataType = { ...@@ -9,6 +9,7 @@ export type DataType = {
export interface TreeDataNode extends DataNode { export interface TreeDataNode extends DataNode {
name:string; name:string;
id:number; id:number;
taskId:number;
parentId:number; parentId:number;
path:string[]; path:string[];
} }
......
...@@ -6,7 +6,7 @@ import {getCatalogueTreeData} from "@/pages/FlinkSqlStudio/service"; ...@@ -6,7 +6,7 @@ import {getCatalogueTreeData} from "@/pages/FlinkSqlStudio/service";
import {convertToTreeData, DataType, TreeDataNode} from "@/components/Studio/StudioTree/Function"; import {convertToTreeData, DataType, TreeDataNode} from "@/components/Studio/StudioTree/Function";
import style from "./index.less"; import style from "./index.less";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import {handleAddOrUpdate, handleRemove} from "@/components/Common/crud"; import {getInfoById, handleAddOrUpdate, handleInfo, handleRemove} from "@/components/Common/crud";
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";
...@@ -44,7 +44,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -44,7 +44,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
const [treeData, setTreeData] = useState<TreeDataNode[]>(); const [treeData, setTreeData] = useState<TreeDataNode[]>();
const [dataList, setDataList] = useState<[]>(); const [dataList, setDataList] = useState<[]>();
const [rightClickNodeTreeItem,setRightClickNodeTreeItem] = useState<RightClickMenu>(); const [rightClickNodeTreeItem,setRightClickNodeTreeItem] = useState<RightClickMenu>();
const {currentPath,dispatch} = props; const {currentPath,dispatch,tabs} = props;
const [updateCatalogueModalVisible, handleUpdateCatalogueModalVisible] = useState<boolean>(false); const [updateCatalogueModalVisible, handleUpdateCatalogueModalVisible] = useState<boolean>(false);
const [updateTaskModalVisible, handleUpdateTaskModalVisible] = useState<boolean>(false); const [updateTaskModalVisible, handleUpdateTaskModalVisible] = useState<boolean>(false);
const [isCreate, setIsCreate] = useState<boolean>(true); const [isCreate, setIsCreate] = useState<boolean>(true);
...@@ -75,7 +75,9 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -75,7 +75,9 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
const handleMenuClick=(key:string)=>{ const handleMenuClick=(key:string)=>{
setRightClickNodeTreeItem(null); setRightClickNodeTreeItem(null);
if(key=='CreateCatalogue'){ if(key=='Open'){
toOpen(rightClickNode);
}else if(key=='CreateCatalogue'){
createCatalogue(rightClickNode); createCatalogue(rightClickNode);
}else if(key=='CreateTask'){ }else if(key=='CreateTask'){
createTask(rightClickNode); createTask(rightClickNode);
...@@ -86,6 +88,38 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -86,6 +88,38 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
} }
}; };
const toOpen=(node:TreeDataNode)=>{
if(node.isLeaf&&node.taskId) {
for(let item of tabs.panes){
if(item.key==node.taskId){
tabs.activeKey = node.taskId;
dispatch({
type: "Studio/changeActiveKey",
payload: tabs.activeKey,
});
return;
}
}
const result = getInfoById('api/task',node.taskId);
result.then(result=>{
let newTabs = tabs;
let newPane = {
title: node.name,
key: node.taskId,
value:(result.datas.statement?result.datas.statement:''),
closable: true,
task:result.datas
};
newTabs.activeKey = node.taskId;
newTabs.panes.push(newPane);
dispatch({
type: "Studio/saveTabs",
payload: newTabs,
});
})
}
};
const createCatalogue=(node:TreeDataNode)=>{ const createCatalogue=(node:TreeDataNode)=>{
if(!node.isLeaf) { if(!node.isLeaf) {
handleUpdateCatalogueModalVisible(true); handleUpdateCatalogueModalVisible(true);
...@@ -135,7 +169,6 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -135,7 +169,6 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
getTreeData(); getTreeData();
} }
}); });
}; };
const getNodeTreeRightClickMenu = () => { const getNodeTreeRightClickMenu = () => {
...@@ -151,6 +184,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -151,6 +184,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
style={tmpStyle} style={tmpStyle}
className={style.right_click_menu} className={style.right_click_menu}
> >
<Menu.Item key='Open'>{'打开'}</Menu.Item>
<Menu.Item key='CreateCatalogue'>{'创建目录'}</Menu.Item> <Menu.Item key='CreateCatalogue'>{'创建目录'}</Menu.Item>
<Menu.Item key='CreateTask'>{'创建作业'}</Menu.Item> <Menu.Item key='CreateTask'>{'创建作业'}</Menu.Item>
<Menu.Item key='Rename'>{'重命名'}</Menu.Item> <Menu.Item key='Rename'>{'重命名'}</Menu.Item>
...@@ -183,7 +217,6 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -183,7 +217,6 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
}; };
const onSelect = (selectedKeys:[], e:any) => { const onSelect = (selectedKeys:[], e:any) => {
console.log(e.node.path);
dispatch({ dispatch({
type: "Studio/saveCurrentPath", type: "Studio/saveCurrentPath",
payload: e.node.path, payload: e.node.path,
...@@ -248,5 +281,6 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -248,5 +281,6 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
export default connect(({Studio}: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
currentPath:Studio.currentPath currentPath:Studio.currentPath,
tabs: Studio.tabs,
}))(StudioTree); }))(StudioTree);
...@@ -10,6 +10,7 @@ import StudioTabs from "./StudioTabs"; ...@@ -10,6 +10,7 @@ import StudioTabs from "./StudioTabs";
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import StudioConsole from "./StudioConsole"; import StudioConsole from "./StudioConsole";
import StudioSetting from "./StudioSetting"; import StudioSetting from "./StudioSetting";
import StudioEdit from "./StudioEdit";
const {TabPane} = Tabs; const {TabPane} = Tabs;
...@@ -26,7 +27,6 @@ const Studio: React.FC<StudioProps> = ({sql}) => { ...@@ -26,7 +27,6 @@ const Studio: React.FC<StudioProps> = ({sql}) => {
}, [sql]); }, [sql]);
return ( return (
<div> <div>
<StudioMenu/> <StudioMenu/>
<Card bordered={false} className={styles.card} size="small"> <Card bordered={false} className={styles.card} size="small">
...@@ -40,6 +40,7 @@ const Studio: React.FC<StudioProps> = ({sql}) => { ...@@ -40,6 +40,7 @@ const Studio: React.FC<StudioProps> = ({sql}) => {
</Col> </Col>
<Col span={16}> <Col span={16}>
<StudioTabs/> <StudioTabs/>
<StudioEdit/>
<StudioConsole/> <StudioConsole/>
</Col> </Col>
<Col span={4}> <Col span={4}>
...@@ -74,6 +75,7 @@ export default connect(({Studio}: { Studio: StateType }) => ({ ...@@ -74,6 +75,7 @@ export default connect(({Studio}: { Studio: StateType }) => ({
catalogue: Studio.catalogue, catalogue: Studio.catalogue,
sql: Studio.sql, sql: Studio.sql,
cluster: Studio.cluster, cluster: Studio.cluster,
tabs: Studio.tabs,
}))(Studio); }))(Studio);
// export default Studio; // export default Studio;
import {Effect, Reducer} from "umi"; import {Effect, Reducer} from "umi";
import {executeSql} from "./service"; import {executeSql} from "./service";
import {message} from "antd"; import {message} from "antd";
import {queryData, removeData} from "@/components/Common/crud"; import {getInfoById, handleInfo, queryData, removeData} from "@/components/Common/crud";
export type CatalogueType = { export type CatalogueType = {
id?: number; id?: number;
...@@ -24,12 +24,45 @@ export type ClusterType = { ...@@ -24,12 +24,45 @@ export type ClusterType = {
updateTime: Date, updateTime: Date,
} }
export type TaskType = {
id: number,
catalogueId: number,
name: string,
alias: string,
type: string,
checkPoint: number,
savePointPath: string,
parallelism: number,
fragment: boolean,
clusterId: number,
clusterName: string,
note: string,
enabled: boolean,
createTime: Date,
updateTime: Date,
statement: string,
};
export type TabsItemType = {
title: string;
key: number ,
value:string;
closable: boolean;
task?:TaskType;
}
export type TabsType = {
activeKey: number;
panes?: TabsItemType[];
}
export type StateType = { export type StateType = {
current?: number; current?: number;
cluster?:ClusterType[]; cluster?:ClusterType[];
catalogue: CatalogueType[]; catalogue: CatalogueType[];
sql?: string; sql?: string;
currentPath?: string[]; currentPath?: string[];
tabs:TabsType;
}; };
export type ModelType = { export type ModelType = {
...@@ -64,6 +97,15 @@ const Model: ModelType = { ...@@ -64,6 +97,15 @@ const Model: ModelType = {
}], }],
sql: '', sql: '',
currentPath: [], currentPath: [],
tabs:{
activeKey: 0,
panes: [{
title: '草稿',
key: 0 ,
value:'',
closable: false,
}],
}
}, },
effects: { effects: {
...@@ -90,7 +132,9 @@ const Model: ModelType = { ...@@ -90,7 +132,9 @@ const Model: ModelType = {
} }
return { return {
...state, ...state,
catalogue:catalogues, catalogue:{
...catalogues
},
}; };
}, },
saveCurrentPath(state, { payload }) { saveCurrentPath(state, { payload }) {
...@@ -99,6 +143,24 @@ const Model: ModelType = { ...@@ -99,6 +143,24 @@ const Model: ModelType = {
currentPath:payload, currentPath:payload,
}; };
}, },
saveTabs(state, { payload }) {
return {
...state,
tabs:{
...payload
},
};
},
changeActiveKey(state, { payload }) {
let tabs = state.tabs;
tabs.activeKey = payload;
return {
...state,
tabs:{
...tabs,
},
};
},
}, },
}; };
......
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