Commit 2cda298f authored by wenmo's avatar wenmo

tree和tabs联动

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