Commit b7d9b0dc authored by wenmo's avatar wenmo

作业剪切和粘贴

parent cea2b80b
...@@ -217,4 +217,16 @@ public class CatalogueController { ...@@ -217,4 +217,16 @@ public class CatalogueController {
return Result.failed("重命名失败"); return Result.failed("重命名失败");
} }
} }
/**
* 重命名节点和作业
*/
@PutMapping("/moveCatalogue")
public Result moveCatalogue(@RequestBody Catalogue catalogue) throws Exception {
if (catalogueService.moveCatalogue(catalogue.getId(), catalogue.getParentId())) {
return Result.succeed(true, "移动成功");
} else {
return Result.failed(false, "移动失败");
}
}
} }
...@@ -25,4 +25,6 @@ public interface CatalogueService extends ISuperService<Catalogue> { ...@@ -25,4 +25,6 @@ public interface CatalogueService extends ISuperService<Catalogue> {
boolean toRename(Catalogue catalogue); boolean toRename(Catalogue catalogue);
boolean removeCatalogueAndTaskById(Integer id); boolean removeCatalogueAndTaskById(Integer id);
boolean moveCatalogue(Integer id, Integer parentId);
} }
...@@ -15,6 +15,9 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -15,6 +15,9 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
import static com.dlink.assertion.Asserts.isNotNull;
import static com.dlink.assertion.Asserts.isNull;
/** /**
* CatalogueServiceImpl * CatalogueServiceImpl
* *
...@@ -29,9 +32,6 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata ...@@ -29,9 +32,6 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata
@Autowired @Autowired
private StatementService statementService; private StatementService statementService;
@Autowired
private CatalogueMapper catalogueMapper;
@Override @Override
public List<Catalogue> getAllData() { public List<Catalogue> getAllData() {
return this.list(); return this.list();
...@@ -39,7 +39,7 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata ...@@ -39,7 +39,7 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata
@Override @Override
public Catalogue findByParentIdAndName(Integer parent_id, String name) { public Catalogue findByParentIdAndName(Integer parent_id, String name) {
return catalogueMapper.selectOne(Wrappers.<Catalogue>query().eq("parent_id", parent_id).eq("name", name)); return baseMapper.selectOne(Wrappers.<Catalogue>query().eq("parent_id", parent_id).eq("name", name));
} }
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
...@@ -83,7 +83,7 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata ...@@ -83,7 +83,7 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata
@Override @Override
public boolean toRename(Catalogue catalogue) { public boolean toRename(Catalogue catalogue) {
Catalogue oldCatalogue = this.getById(catalogue.getId()); Catalogue oldCatalogue = this.getById(catalogue.getId());
if (oldCatalogue == null) { if (isNull(oldCatalogue)) {
return false; return false;
} else { } else {
Task task = new Task(); Task task = new Task();
...@@ -99,10 +99,10 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata ...@@ -99,10 +99,10 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata
@Override @Override
public boolean removeCatalogueAndTaskById(Integer id) { public boolean removeCatalogueAndTaskById(Integer id) {
Catalogue catalogue = this.getById(id); Catalogue catalogue = this.getById(id);
if (catalogue == null) { if (isNull(catalogue)) {
return false; return false;
} else { } else {
if (catalogue.getTaskId() != null) { if (isNotNull(catalogue.getTaskId())) {
taskService.removeById(catalogue.getTaskId()); taskService.removeById(catalogue.getTaskId());
statementService.removeById(catalogue.getTaskId()); statementService.removeById(catalogue.getTaskId());
} }
...@@ -110,4 +110,15 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata ...@@ -110,4 +110,15 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata
return true; return true;
} }
} }
@Override
public boolean moveCatalogue(Integer id, Integer parentId) {
Catalogue catalogue = this.getById(id);
if (isNull(catalogue)) {
return false;
} else {
catalogue.setParentId(parentId);
return updateById(catalogue);
}
}
} }
import {executeDDL} from "@/pages/FlinkSqlStudio/service"; import {executeDDL} from "@/pages/FlinkSqlStudio/service";
import FlinkSQL from "./FlinkSQL"; import FlinkSQL from "./FlinkSQL";
import {SessionType} from "@/pages/FlinkSqlStudio/model"; import {SessionType} from "@/pages/FlinkSqlStudio/model";
import {Modal,message} from "antd"; import {Modal, message} from "antd";
import {addOrUpdateData, getData, handleRemove} from "@/components/Common/crud"; import {addOrUpdateData, getData, handleRemove} from "@/components/Common/crud";
/*--- 保存sql ---*/ /*--- 保存sql ---*/
export function saveTask(current:any,dispatch: any){ export function saveTask(current: any, dispatch: any) {
if (current.task) { if (current.task) {
let task = { let task = {
...current.task, ...current.task,
...@@ -19,24 +19,26 @@ export function saveTask(current:any,dispatch: any){ ...@@ -19,24 +19,26 @@ export function saveTask(current:any,dispatch: any){
} }
/*--- 创建会话 ---*/ /*--- 创建会话 ---*/
export function createSession(session: SessionType,dispatch: any) { export function createSession(session: SessionType, dispatch: any) {
const res = addOrUpdateData("api/studio/createSession",session) const res = addOrUpdateData("api/studio/createSession", session)
res.then((result) => { res.then((result) => {
message.success(`创建会话【${session.session}】成功!`); message.success(`创建会话【${session.session}】成功!`);
result.datas&&changeSession(result.datas,dispatch); result.datas && changeSession(result.datas, dispatch);
listSession(dispatch); listSession(dispatch);
}); });
} }
/*--- 查询会话列表 ---*/ /*--- 查询会话列表 ---*/
export function listSession(dispatch: any) { export function listSession(dispatch: any) {
const res = getData("api/studio/listSession"); const res = getData("api/studio/listSession");
res.then((result)=>{ res.then((result) => {
dispatch && dispatch({ dispatch && dispatch({
type: "Studio/saveSession", type: "Studio/saveSession",
payload: result.datas, payload: result.datas,
}); });
}); });
} }
/*--- 切换会话 ---*/ /*--- 切换会话 ---*/
export function changeSession(session: SessionType, dispatch: any) { export function changeSession(session: SessionType, dispatch: any) {
dispatch && dispatch({ dispatch && dispatch({
...@@ -44,15 +46,17 @@ export function changeSession(session: SessionType, dispatch: any) { ...@@ -44,15 +46,17 @@ export function changeSession(session: SessionType, dispatch: any) {
payload: session, payload: session,
}); });
setTimeout(function () { setTimeout(function () {
showTables(session.session,dispatch); showTables(session.session, dispatch);
},200); }, 200);
} }
/*--- 退出会话 ---*/ /*--- 退出会话 ---*/
export function quitSession( dispatch: any) { export function quitSession(dispatch: any) {
dispatch && dispatch({ dispatch && dispatch({
type: "Studio/quitCurrentSession", type: "Studio/quitCurrentSession",
}); });
} }
/*--- 注销会话 ---*/ /*--- 注销会话 ---*/
export function clearSession(session: string, dispatch: any) { export function clearSession(session: string, dispatch: any) {
Modal.confirm({ Modal.confirm({
...@@ -71,9 +75,10 @@ export function clearSession(session: string, dispatch: any) { ...@@ -71,9 +75,10 @@ export function clearSession(session: string, dispatch: any) {
} }
}); });
} }
/*--- 刷新 Catalog Table ---*/ /*--- 刷新 Catalog Table ---*/
export function showTables(session: string, dispatch: any) { export function showTables(session: string, dispatch: any) {
if(session==null||session==''){ if (session == null || session == '') {
return; return;
} }
const res = executeDDL({ const res = executeDDL({
...@@ -90,11 +95,12 @@ export function showTables(session: string, dispatch: any) { ...@@ -90,11 +95,12 @@ export function showTables(session: string, dispatch: any) {
dispatch && dispatch({ dispatch && dispatch({
type: "Studio/refreshCurrentSession", type: "Studio/refreshCurrentSession",
payload: { payload: {
connectors:tableData connectors: tableData
}, },
}); });
}); });
} }
/*--- 移除 Catalog Table ---*/ /*--- 移除 Catalog Table ---*/
export function removeTable(tablename: string, session: string, dispatch: any) { export function removeTable(tablename: string, session: string, dispatch: any) {
Modal.confirm({ Modal.confirm({
...@@ -114,6 +120,7 @@ export function removeTable(tablename: string, session: string, dispatch: any) { ...@@ -114,6 +120,7 @@ export function removeTable(tablename: string, session: string, dispatch: any) {
} }
}); });
} }
/*--- 刷新 集群 ---*/ /*--- 刷新 集群 ---*/
export function showCluster(dispatch: any) { export function showCluster(dispatch: any) {
const res = getData('api/cluster/listEnabledAll'); const res = getData('api/cluster/listEnabledAll');
...@@ -124,6 +131,7 @@ export function showCluster(dispatch: any) { ...@@ -124,6 +131,7 @@ export function showCluster(dispatch: any) {
}); });
}); });
} }
/*--- 刷新 Session集群 ---*/ /*--- 刷新 Session集群 ---*/
export function showSessionCluster(dispatch: any) { export function showSessionCluster(dispatch: any) {
const res = getData('api/cluster/listSessionEnable'); const res = getData('api/cluster/listSessionEnable');
...@@ -134,6 +142,7 @@ export function showSessionCluster(dispatch: any) { ...@@ -134,6 +142,7 @@ export function showSessionCluster(dispatch: any) {
}); });
}); });
} }
/*--- 刷新 数据源 ---*/ /*--- 刷新 数据源 ---*/
export function showDataBase(dispatch: any) { export function showDataBase(dispatch: any) {
const res = getData('api/database/listEnabledAll'); const res = getData('api/database/listEnabledAll');
...@@ -144,6 +153,7 @@ export function showDataBase(dispatch: any) { ...@@ -144,6 +153,7 @@ export function showDataBase(dispatch: any) {
}); });
}); });
} }
/*--- 刷新 执行环境 ---*/ /*--- 刷新 执行环境 ---*/
export function showEnv(dispatch: any) { export function showEnv(dispatch: any) {
const res = getData('api/task/listFlinkSQLEnv'); const res = getData('api/task/listFlinkSQLEnv');
...@@ -154,6 +164,7 @@ export function showEnv(dispatch: any) { ...@@ -154,6 +164,7 @@ export function showEnv(dispatch: any) {
}); });
}); });
} }
/*--- 刷新 自定义Jar ---*/ /*--- 刷新 自定义Jar ---*/
export function showJars(dispatch: any) { export function showJars(dispatch: any) {
const res = getData('api/jar/listEnabledAll'); const res = getData('api/jar/listEnabledAll');
...@@ -164,6 +175,7 @@ export function showJars(dispatch: any) { ...@@ -164,6 +175,7 @@ export function showJars(dispatch: any) {
}); });
}); });
} }
/*--- 刷新 报警实例 ---*/ /*--- 刷新 报警实例 ---*/
export function showAlertInstance(dispatch: any) { export function showAlertInstance(dispatch: any) {
const res = getData('api/alertInstance/listEnabledAll'); const res = getData('api/alertInstance/listEnabledAll');
...@@ -174,6 +186,7 @@ export function showAlertInstance(dispatch: any) { ...@@ -174,6 +186,7 @@ export function showAlertInstance(dispatch: any) {
}); });
}); });
} }
/*--- 刷新 报警组 ---*/ /*--- 刷新 报警组 ---*/
export function showAlertGroup(dispatch: any) { export function showAlertGroup(dispatch: any) {
const res = getData('api/alertGroup/listEnabledAll'); const res = getData('api/alertGroup/listEnabledAll');
...@@ -184,29 +197,35 @@ export function showAlertGroup(dispatch: any) { ...@@ -184,29 +197,35 @@ export function showAlertGroup(dispatch: any) {
}); });
}); });
} }
/*--- 刷新 元数据表 ---*/ /*--- 刷新 元数据表 ---*/
export function showMetaDataTable(id:number) { export function showMetaDataTable(id: number) {
return getData('api/database/getSchemasAndTables',{id:id}); return getData('api/database/getSchemasAndTables', {id: id});
} }
/*--- 刷新 Flink Jobs ---*/ /*--- 刷新 Flink Jobs ---*/
export function showFlinkJobs(clusterId:number) { export function showFlinkJobs(clusterId: number) {
return getData('api/studio/listJobs',{clusterId:clusterId}); return getData('api/studio/listJobs', {clusterId: clusterId});
} }
/*--- 停止 Flink Jobs ---*/ /*--- 停止 Flink Jobs ---*/
export function cancelJob(clusterId:number,jobId:string) { export function cancelJob(clusterId: number, jobId: string) {
return getData('api/studio/cancel',{clusterId:clusterId,jobId:jobId}); return getData('api/studio/cancel', {clusterId: clusterId, jobId: jobId});
} }
/*--- 重启 Flink Jobs ---*/ /*--- 重启 Flink Jobs ---*/
export function restartJob(id: number) { export function restartJob(id: number, isOnLine: boolean) {
return getData('api/task/restartTask',{id}); return getData('api/task/restartTask', {id, isOnLine});
} }
/*--- 停止 SavePoint Jobs ---*/ /*--- 停止 SavePoint Jobs ---*/
export function savepointJob(clusterId:number,jobId:string,savePointType:string,name:string,taskId:number) { export function savepointJob(clusterId: number, jobId: string, savePointType: string, name: string, taskId: number) {
return getData('api/studio/savepoint',{clusterId,jobId,savePointType,name,taskId}); return getData('api/studio/savepoint', {clusterId, jobId, savePointType, name, taskId});
} }
/*--- 根据版本号获取所有自动补全的文档 ---*/ /*--- 根据版本号获取所有自动补全的文档 ---*/
export function getFillAllByVersion(version:string,dispatch: any) { export function getFillAllByVersion(version: string, dispatch: any) {
const res = getData('api/document/getFillAllByVersion',{version:version}); const res = getData('api/document/getFillAllByVersion', {version: version});
res.then((result) => { res.then((result) => {
result.datas && dispatch && dispatch({ result.datas && dispatch && dispatch({
type: "Document/saveAllFillDocuments", type: "Document/saveAllFillDocuments",
...@@ -214,6 +233,7 @@ export function getFillAllByVersion(version:string,dispatch: any) { ...@@ -214,6 +233,7 @@ export function getFillAllByVersion(version:string,dispatch: any) {
}); });
}); });
} }
/*--- 刷新 集群 ---*/ /*--- 刷新 集群 ---*/
export function showClusterConfiguration(dispatch: any) { export function showClusterConfiguration(dispatch: any) {
const res = getData('api/clusterConfiguration/listEnabledAll'); const res = getData('api/clusterConfiguration/listEnabledAll');
...@@ -224,27 +244,33 @@ export function showClusterConfiguration(dispatch: any) { ...@@ -224,27 +244,33 @@ export function showClusterConfiguration(dispatch: any) {
}); });
}); });
} }
/*--- 发布作业 ---*/ /*--- 发布作业 ---*/
export function releaseTask(id: number) { export function releaseTask(id: number) {
return getData('api/task/releaseTask',{id}); return getData('api/task/releaseTask', {id});
} }
/*--- 发布作业 ---*/ /*--- 发布作业 ---*/
export function developTask(id: number) { export function developTask(id: number) {
return getData('api/task/developTask',{id}); return getData('api/task/developTask', {id});
} }
/*--- 上线作业 ---*/ /*--- 上线作业 ---*/
export function onLineTask(id: number) { export function onLineTask(id: number) {
return getData('api/task/onLineTask',{id}); return getData('api/task/onLineTask', {id});
} }
/*--- 下线作业 ---*/ /*--- 下线作业 ---*/
export function offLineTask(id: number, type: string) { export function offLineTask(id: number, type: string) {
return getData('api/task/offLineTask',{id, type}); return getData('api/task/offLineTask', {id, type});
} }
/*--- 注销作业 ---*/ /*--- 注销作业 ---*/
export function cancelTask(id: number) { export function cancelTask(id: number) {
return getData('api/task/cancelTask',{id}); return getData('api/task/cancelTask', {id});
} }
/*--- 恢复作业 ---*/ /*--- 恢复作业 ---*/
export function recoveryTask(id: number) { export function recoveryTask(id: number) {
return getData('api/task/recoveryTask',{id}); return getData('api/task/recoveryTask', {id});
} }
import styles from "./index.less"; import styles from "./index.less";
import {Menu, Dropdown, Tooltip, Row, Col, notification, Modal, message} from "antd"; import {Menu, Dropdown, Tooltip, Row, Col, notification, Modal, message} from "antd";
import { import {
PauseCircleTwoTone, CarryOutTwoTone, DeleteTwoTone, PlayCircleTwoTone, CameraTwoTone,SnippetsTwoTone, PauseCircleTwoTone, CarryOutTwoTone, DeleteTwoTone, PlayCircleTwoTone, CameraTwoTone, SnippetsTwoTone,
FileAddTwoTone, FolderOpenTwoTone, SafetyCertificateTwoTone, SaveTwoTone, FlagTwoTone,CodeTwoTone, FileAddTwoTone, FolderOpenTwoTone, SafetyCertificateTwoTone, SaveTwoTone, FlagTwoTone, CodeTwoTone,
EnvironmentOutlined, SmileOutlined, RocketTwoTone, QuestionCircleTwoTone, MessageOutlined, ClusterOutlined EnvironmentOutlined, SmileOutlined, RocketTwoTone, QuestionCircleTwoTone, MessageOutlined, ClusterOutlined
, EditTwoTone, RestTwoTone , EditTwoTone, RestTwoTone
} from "@ant-design/icons"; } from "@ant-design/icons";
...@@ -51,7 +51,7 @@ const menu = ( ...@@ -51,7 +51,7 @@ const menu = (
const StudioMenu = (props: any) => { const StudioMenu = (props: any) => {
const {isFullScreen, tabs, current, currentPath, form,width,height, refs, dispatch, currentSession} = props; const {isFullScreen, tabs, current, currentPath, form, width, height, refs, dispatch, currentSession} = props;
const [modalVisible, handleModalVisible] = useState<boolean>(false); const [modalVisible, handleModalVisible] = useState<boolean>(false);
const [exportModalVisible, handleExportModalVisible] = useState<boolean>(false); const [exportModalVisible, handleExportModalVisible] = useState<boolean>(false);
const [graphModalVisible, handleGraphModalVisible] = useState<boolean>(false); const [graphModalVisible, handleGraphModalVisible] = useState<boolean>(false);
...@@ -59,15 +59,15 @@ const StudioMenu = (props: any) => { ...@@ -59,15 +59,15 @@ const StudioMenu = (props: any) => {
const [graphData, setGraphData] = useState(); const [graphData, setGraphData] = useState();
const onKeyDown = useCallback((e) => { const onKeyDown = useCallback((e) => {
if(e.keyCode === 83 && (e.ctrlKey === true || e.metaKey)){ if (e.keyCode === 83 && (e.ctrlKey === true || e.metaKey)) {
e.preventDefault(); e.preventDefault();
if(current) { if (current) {
props.saveTask(current); props.saveTask(current);
} }
} }
if(e.keyCode === 113){ if (e.keyCode === 113) {
e.preventDefault(); e.preventDefault();
if(current) { if (current) {
// handleEditModalVisible(true); // handleEditModalVisible(true);
props.changeFullScreen(true); props.changeFullScreen(true);
} }
...@@ -82,7 +82,7 @@ const StudioMenu = (props: any) => { ...@@ -82,7 +82,7 @@ const StudioMenu = (props: any) => {
}, [current]); }, [current]);
const execute = () => { const execute = () => {
if(!isSql(current.task.dialect)&&!isOnline(current.task.type)){ if (!isSql(current.task.dialect) && !isOnline(current.task.type)) {
message.warn(`该任务执行模式为【${current.task.type}】,不支持 SQL 查询,请手动保存后使用右侧按钮——作业提交`); message.warn(`该任务执行模式为【${current.task.type}】,不支持 SQL 查询,请手动保存后使用右侧按钮——作业提交`);
return; return;
} }
...@@ -97,6 +97,7 @@ const StudioMenu = (props: any) => { ...@@ -97,6 +97,7 @@ const StudioMenu = (props: any) => {
let useSession = !!currentSession.session; let useSession = !!currentSession.session;
let param = { let param = {
...current.task, ...current.task,
taskId: current.task.id,
useSession: useSession, useSession: useSession,
session: currentSession.session, session: currentSession.session,
configJson: JSON.stringify(current.task.config), configJson: JSON.stringify(current.task.config),
...@@ -118,7 +119,7 @@ const StudioMenu = (props: any) => { ...@@ -118,7 +119,7 @@ const StudioMenu = (props: any) => {
result.then(res => { result.then(res => {
notification.close(taskKey); notification.close(taskKey);
if (res.datas.success) { if (res.datas.success) {
res.datas?.jobInstanceId&&props.changeTaskJobInstance(current.task.id,res.datas?.jobInstanceId); res.datas?.jobInstanceId && props.changeTaskJobInstance(current.task.id, res.datas?.jobInstanceId);
message.success('执行成功'); message.success('执行成功');
} else { } else {
message.error('执行失败'); message.error('执行失败');
...@@ -163,7 +164,7 @@ const StudioMenu = (props: any) => { ...@@ -163,7 +164,7 @@ const StudioMenu = (props: any) => {
const res = await postDataArray('/api/task/submit', [task.id]); const res = await postDataArray('/api/task/submit', [task.id]);
notification.close(taskKey); notification.close(taskKey);
if (res.datas[0].success) { if (res.datas[0].success) {
res.datas[0].jobInstanceId && props.changeTaskJobInstance(current.task.id,res.datas[0].jobInstanceId); res.datas[0].jobInstanceId && props.changeTaskJobInstance(current.task.id, res.datas[0].jobInstanceId);
message.success('异步提交成功'); message.success('异步提交成功');
} else { } else {
message.success('异步提交失败'); message.success('异步提交失败');
...@@ -177,7 +178,7 @@ const StudioMenu = (props: any) => { ...@@ -177,7 +178,7 @@ const StudioMenu = (props: any) => {
handleModalVisible(true); handleModalVisible(true);
}; };
const onGetStreamGraph=()=>{ const onGetStreamGraph = () => {
let selectsql = null; let selectsql = null;
if (current.monaco.current) { if (current.monaco.current) {
let selection = current.monaco.current.editor.getSelection(); let selection = current.monaco.current.editor.getSelection();
...@@ -196,36 +197,38 @@ const StudioMenu = (props: any) => { ...@@ -196,36 +197,38 @@ const StudioMenu = (props: any) => {
}; };
const res = getJobPlan(param); const res = getJobPlan(param);
handleGraphModalVisible(true); handleGraphModalVisible(true);
res.then((result)=>{ res.then((result) => {
if(result.code==0){ if (result.code == 0) {
setGraphData(buildGraphData(result.datas)); setGraphData(buildGraphData(result.datas));
}else{ } else {
setGraphData(undefined); setGraphData(undefined);
} }
}) })
}; };
const buildGraphData=(data)=>{ const buildGraphData = (data) => {
let edges = []; let edges = [];
for(let i in data.nodes){ for (let i in data.nodes) {
data.nodes[i].id=data.nodes[i].id.toString(); data.nodes[i].id = data.nodes[i].id.toString();
data.nodes[i].value={ data.nodes[i].value = {
title:data.nodes[i].pact, title: data.nodes[i].pact,
items: [ items: [
{ {
text: getRangeText(data.nodes[i].description), text: getRangeText(data.nodes[i].description),
}, },
{ {
text: '\r\nParallelism: ', text: '\r\nParallelism: ',
value: '\r\n '+data.nodes[i].parallelism, value: '\r\n ' + data.nodes[i].parallelism,
}, },
], ],
}; };
if(data.nodes[i].inputs){ if (data.nodes[i].inputs) {
for(let j in data.nodes[i].inputs){ for (let j in data.nodes[i].inputs) {
edges.push({source: data.nodes[i].inputs[j].id.toString(), edges.push({
source: data.nodes[i].inputs[j].id.toString(),
target: data.nodes[i].id.toString(), target: data.nodes[i].id.toString(),
value: data.nodes[i].inputs[j].ship_strategy}) value: data.nodes[i].inputs[j].ship_strategy
})
} }
} }
} }
...@@ -233,17 +236,17 @@ const StudioMenu = (props: any) => { ...@@ -233,17 +236,17 @@ const StudioMenu = (props: any) => {
return data; return data;
}; };
const getRangeText = (str:string) => { const getRangeText = (str: string) => {
str = escape2Html(str); str = escape2Html(str);
var canvas = getRangeText.canvas || (getRangeText.canvas = document.createElement("canvas")); var canvas = getRangeText.canvas || (getRangeText.canvas = document.createElement("canvas"));
var context = canvas.getContext("2d"); var context = canvas.getContext("2d");
context.font = "10px sans-serif"; context.font = "10px sans-serif";
let result = ''; let result = '';
let count = 1; let count = 1;
for(let i=0,len=str.length;i<len;i++){ for (let i = 0, len = str.length; i < len; i++) {
result += str[i]; result += str[i];
let width = context.measureText(result).width; let width = context.measureText(result).width;
if(width >= 110*count) { if (width >= 110 * count) {
result += '\r\n'; result += '\r\n';
count++; count++;
} }
...@@ -251,7 +254,7 @@ const StudioMenu = (props: any) => { ...@@ -251,7 +254,7 @@ const StudioMenu = (props: any) => {
return result; return result;
}; };
const getTextWidth = (text:string, font:string) => { const getTextWidth = (text: string, font: string) => {
var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas")); var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
var context = canvas.getContext("2d"); var context = canvas.getContext("2d");
context.font = font; context.font = font;
...@@ -259,13 +262,15 @@ const StudioMenu = (props: any) => { ...@@ -259,13 +262,15 @@ const StudioMenu = (props: any) => {
return metrics.width; return metrics.width;
} }
const escape2Html = (str:string) => { const escape2Html = (str: string) => {
let arrEntities={'lt':'<','gt':'>','nbsp':' ','amp':'&','quot':'"'}; let arrEntities = {'lt': '<', 'gt': '>', 'nbsp': ' ', 'amp': '&', 'quot': '"'};
return str.replace(/&(lt|gt|nbsp|amp|quot);/ig,function(all,t){return arrEntities[t];}); return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, function (all, t) {
return arrEntities[t];
});
} }
const toFullScreen = () => { const toFullScreen = () => {
if(current) { if (current) {
props.changeFullScreen(true); props.changeFullScreen(true);
} }
}; };
...@@ -287,10 +292,10 @@ const StudioMenu = (props: any) => { ...@@ -287,10 +292,10 @@ const StudioMenu = (props: any) => {
onOk: async () => { onOk: async () => {
const res = releaseTask(current.task.id); const res = releaseTask(current.task.id);
res.then((result) => { res.then((result) => {
if(result.code == CODE.SUCCESS) { if (result.code == CODE.SUCCESS) {
props.changeTaskStep(current.task.id,JOB_LIFE_CYCLE.RELEASE); props.changeTaskStep(current.task.id, JOB_LIFE_CYCLE.RELEASE);
message.success(`发布作业【${current.task.alias}】成功`); message.success(`发布作业【${current.task.alias}】成功`);
}else { } else {
message.error(`发布作业【${current.task.alias}】失败,原因:\n${result.msg}`); message.error(`发布作业【${current.task.alias}】失败,原因:\n${result.msg}`);
} }
}); });
...@@ -307,8 +312,8 @@ const StudioMenu = (props: any) => { ...@@ -307,8 +312,8 @@ const StudioMenu = (props: any) => {
onOk: async () => { onOk: async () => {
const res = developTask(current.task.id); const res = developTask(current.task.id);
res.then((result) => { res.then((result) => {
result.datas && props.changeTaskStep(current.task.id,JOB_LIFE_CYCLE.DEVELOP); result.datas && props.changeTaskStep(current.task.id, JOB_LIFE_CYCLE.DEVELOP);
if(result.code == CODE.SUCCESS) { if (result.code == CODE.SUCCESS) {
message.success(`维护作业【${current.task.alias}】成功`); message.success(`维护作业【${current.task.alias}】成功`);
} }
}); });
...@@ -325,11 +330,11 @@ const StudioMenu = (props: any) => { ...@@ -325,11 +330,11 @@ const StudioMenu = (props: any) => {
onOk: async () => { onOk: async () => {
const res = onLineTask(current.task.id); const res = onLineTask(current.task.id);
res.then((result) => { res.then((result) => {
if(result.code === CODE.SUCCESS) { if (result.code === CODE.SUCCESS) {
props.changeTaskStep(current.task.id,JOB_LIFE_CYCLE.ONLINE); props.changeTaskStep(current.task.id, JOB_LIFE_CYCLE.ONLINE);
result.datas?.jobInstanceId && props.changeTaskJobInstance(current.task.id,result.datas?.jobInstanceId); result.datas?.jobInstanceId && props.changeTaskJobInstance(current.task.id, result.datas?.jobInstanceId);
message.success(`上线作业【${current.task.alias}】成功`); message.success(`上线作业【${current.task.alias}】成功`);
}else { } else {
message.error(`上线作业【${current.task.alias}】失败,原因:\n${result.msg}`); message.error(`上线作业【${current.task.alias}】失败,原因:\n${result.msg}`);
} }
}); });
...@@ -344,15 +349,15 @@ const StudioMenu = (props: any) => { ...@@ -344,15 +349,15 @@ const StudioMenu = (props: any) => {
okText: '确认', okText: '确认',
cancelText: '取消', cancelText: '取消',
onOk: async () => { onOk: async () => {
const res = offLineTask(current.task.id,type); const res = offLineTask(current.task.id, type);
res.then((result) => { res.then((result) => {
if(result.code === CODE.SUCCESS) { if (result.code === CODE.SUCCESS) {
if(current.task.step === JOB_LIFE_CYCLE.ONLINE){ if (current.task.step === JOB_LIFE_CYCLE.ONLINE) {
props.changeTaskStep(current.task.id,JOB_LIFE_CYCLE.RELEASE); props.changeTaskStep(current.task.id, JOB_LIFE_CYCLE.RELEASE);
} }
props.changeTaskJobInstance(current.task.id,0); props.changeTaskJobInstance(current.task.id, 0);
message.success(`停止作业【${current.task.alias}】成功`); message.success(`停止作业【${current.task.alias}】成功`);
}else { } else {
message.error(`停止作业【${current.task.alias}】失败,原因:\n${result.msg}`); message.error(`停止作业【${current.task.alias}】失败,原因:\n${result.msg}`);
} }
}); });
...@@ -367,13 +372,13 @@ const StudioMenu = (props: any) => { ...@@ -367,13 +372,13 @@ const StudioMenu = (props: any) => {
okText: '确认', okText: '确认',
cancelText: '取消', cancelText: '取消',
onOk: async () => { onOk: async () => {
const res = offLineTask(current.task.id,type); const res = offLineTask(current.task.id, type);
res.then((result) => { res.then((result) => {
if(result.code === CODE.SUCCESS) { if (result.code === CODE.SUCCESS) {
props.changeTaskStep(current.task.id,JOB_LIFE_CYCLE.RELEASE); props.changeTaskStep(current.task.id, JOB_LIFE_CYCLE.RELEASE);
props.changeTaskJobInstance(current.task.id,0); props.changeTaskJobInstance(current.task.id, 0);
message.success(`下线作业【${current.task.alias}】成功`); message.success(`下线作业【${current.task.alias}】成功`);
}else { } else {
message.error(`下线作业【${current.task.alias}】失败,原因:\n${result.msg}`); message.error(`下线作业【${current.task.alias}】失败,原因:\n${result.msg}`);
} }
}); });
...@@ -390,10 +395,10 @@ const StudioMenu = (props: any) => { ...@@ -390,10 +395,10 @@ const StudioMenu = (props: any) => {
onOk: async () => { onOk: async () => {
const res = cancelTask(current.task.id); const res = cancelTask(current.task.id);
res.then((result) => { res.then((result) => {
if(result.code === CODE.SUCCESS) { if (result.code === CODE.SUCCESS) {
props.changeTaskStep(current.task.id,JOB_LIFE_CYCLE.CANCEL); props.changeTaskStep(current.task.id, JOB_LIFE_CYCLE.CANCEL);
message.success(`注销作业【${current.task.alias}】成功`); message.success(`注销作业【${current.task.alias}】成功`);
}else { } else {
message.error(`注销作业【${current.task.alias}】失败,原因:\n${result.msg}`); message.error(`注销作业【${current.task.alias}】失败,原因:\n${result.msg}`);
} }
}); });
...@@ -410,8 +415,8 @@ const StudioMenu = (props: any) => { ...@@ -410,8 +415,8 @@ const StudioMenu = (props: any) => {
onOk: async () => { onOk: async () => {
const res = recoveryTask(current.task.id); const res = recoveryTask(current.task.id);
res.then((result) => { res.then((result) => {
result.datas && props.changeTaskStep(current.task.id,JOB_LIFE_CYCLE.DEVELOP); result.datas && props.changeTaskStep(current.task.id, JOB_LIFE_CYCLE.DEVELOP);
if(result.code == CODE.SUCCESS) { if (result.code == CODE.SUCCESS) {
message.success(`恢复作业【${current.task.alias}】成功`); message.success(`恢复作业【${current.task.alias}】成功`);
} }
}); });
...@@ -420,19 +425,19 @@ const StudioMenu = (props: any) => { ...@@ -420,19 +425,19 @@ const StudioMenu = (props: any) => {
}; };
const isShowGetStreamGraphBtn = () => { const isShowGetStreamGraphBtn = () => {
return (!current.task.dialect||current.task.dialect === DIALECT.FLINKSQL); return (!current.task.dialect || current.task.dialect === DIALECT.FLINKSQL);
}; };
const isShowExecuteBtn = () => { const isShowExecuteBtn = () => {
return !isDeletedTask(current.task.step) && isExecuteSql( current.task.dialect ) && !isRunningTask(current.task.jobInstanceId); return !isDeletedTask(current.task.step) && isExecuteSql(current.task.dialect) && !isRunningTask(current.task.jobInstanceId);
}; };
const isShowSubmitBtn = () => { const isShowSubmitBtn = () => {
return !isDeletedTask(current.task.step) && isTask( current.task.dialect ) && !isRunningTask(current.task.jobInstanceId); return !isDeletedTask(current.task.step) && isTask(current.task.dialect) && !isRunningTask(current.task.jobInstanceId);
}; };
const isShowCancelTaskBtn = () => { const isShowCancelTaskBtn = () => {
return !isDeletedTask(current.task.step) && isTask( current.task.dialect ) && isRunningTask(current.task.jobInstanceId); return !isDeletedTask(current.task.step) && isTask(current.task.dialect) && isRunningTask(current.task.jobInstanceId);
}; };
const runMenu = ( const runMenu = (
...@@ -516,12 +521,12 @@ const StudioMenu = (props: any) => { ...@@ -516,12 +521,12 @@ const StudioMenu = (props: any) => {
</Breadcrumb> </Breadcrumb>
)} )}
</Col> </Col>
{current?.task? {current?.task ?
<Col span={8}> <Col span={8}>
<Tooltip title="全屏开发"> <Tooltip title="全屏开发">
<Button <Button
type="text" type="text"
icon={<CodeTwoTone />} icon={<CodeTwoTone/>}
onClick={toFullScreen} onClick={toFullScreen}
/> />
</Tooltip> </Tooltip>
...@@ -543,7 +548,7 @@ const StudioMenu = (props: any) => { ...@@ -543,7 +548,7 @@ const StudioMenu = (props: any) => {
<Tooltip title="导出当前的 Sql 及配置"> <Tooltip title="导出当前的 Sql 及配置">
<Button <Button
type="text" type="text"
icon={<SnippetsTwoTone />} icon={<SnippetsTwoTone/>}
onClick={exportSql} onClick={exportSql}
/> />
</Tooltip> </Tooltip>
...@@ -555,7 +560,7 @@ const StudioMenu = (props: any) => { ...@@ -555,7 +560,7 @@ const StudioMenu = (props: any) => {
onClick={onCheckSql} onClick={onCheckSql}
/> />
</Tooltip> </Tooltip>
{isShowGetStreamGraphBtn() &&( {isShowGetStreamGraphBtn() && (
<Tooltip title="获取当前的 FlinkSql 的执行图"> <Tooltip title="获取当前的 FlinkSql 的执行图">
<Button <Button
type="text" type="text"
...@@ -563,7 +568,7 @@ const StudioMenu = (props: any) => { ...@@ -563,7 +568,7 @@ const StudioMenu = (props: any) => {
onClick={onGetStreamGraph} onClick={onGetStreamGraph}
/> />
</Tooltip>)} </Tooltip>)}
{isShowExecuteBtn() &&( {isShowExecuteBtn() && (
<Tooltip title="执行当前的 SQL"> <Tooltip title="执行当前的 SQL">
<Button <Button
type="text" type="text"
...@@ -572,7 +577,7 @@ const StudioMenu = (props: any) => { ...@@ -572,7 +577,7 @@ const StudioMenu = (props: any) => {
onClick={execute} onClick={execute}
/> />
</Tooltip>)} </Tooltip>)}
{isShowSubmitBtn() &&(<> {isShowSubmitBtn() && (<>
<Tooltip title="提交当前的作业到集群,提交前请手动保存"> <Tooltip title="提交当前的作业到集群,提交前请手动保存">
<Button <Button
type="text" type="text"
...@@ -585,8 +590,8 @@ const StudioMenu = (props: any) => { ...@@ -585,8 +590,8 @@ const StudioMenu = (props: any) => {
<Tooltip title="停止"> <Tooltip title="停止">
<Button <Button
type="text" type="text"
icon={<PauseCircleTwoTone />} icon={<PauseCircleTwoTone/>}
onClick={()=>handleCancelTask('canceljob')} onClick={() => handleCancelTask('canceljob')}
/> />
</Tooltip> </Tooltip>
} }
...@@ -598,46 +603,46 @@ const StudioMenu = (props: any) => { ...@@ -598,46 +603,46 @@ const StudioMenu = (props: any) => {
icon={<CameraTwoTone/>} icon={<CameraTwoTone/>}
onClick={toReleaseTask} onClick={toReleaseTask}
/> />
</Tooltip>:undefined </Tooltip> : undefined
}{current.task.step == JOB_LIFE_CYCLE.RELEASE ? }{current.task.step == JOB_LIFE_CYCLE.RELEASE ?
<><Tooltip title="维护,点击进入编辑状态"> <><Tooltip title="维护,点击进入编辑状态">
<Button <Button
type="text" type="text"
icon={<EditTwoTone />} icon={<EditTwoTone/>}
onClick={toDevelopTask} onClick={toDevelopTask}
/> />
</Tooltip> </Tooltip>
<Tooltip title="上线,上线后自动恢复、告警等将生效"> <Tooltip title="上线,上线后自动恢复、告警等将生效">
<Button <Button
type="text" type="text"
icon={<CarryOutTwoTone />} icon={<CarryOutTwoTone/>}
onClick={toOnLineTask} onClick={toOnLineTask}
/> />
</Tooltip></>:undefined </Tooltip></> : undefined
}{current.task.step == JOB_LIFE_CYCLE.ONLINE ? }{current.task.step == JOB_LIFE_CYCLE.ONLINE ?
<Tooltip title="下线,将进入最新发布状态"> <Tooltip title="下线,将进入最新发布状态">
<Button <Button
type="text" type="text"
icon={<PauseCircleTwoTone />} icon={<PauseCircleTwoTone/>}
onClick={()=>toOffLineTask('cancel')} onClick={() => toOffLineTask('cancel')}
/> />
</Tooltip>:undefined </Tooltip> : undefined
}{(current.task.step != JOB_LIFE_CYCLE.ONLINE && current.task.step != JOB_LIFE_CYCLE.CANCEL) ? }{(current.task.step != JOB_LIFE_CYCLE.ONLINE && current.task.step != JOB_LIFE_CYCLE.CANCEL) ?
<Tooltip title="注销,将进入回收站"> <Tooltip title="注销,将进入回收站">
<Button <Button
type="text" type="text"
icon={<DeleteTwoTone />} icon={<DeleteTwoTone/>}
onClick={toCancelTask} onClick={toCancelTask}
/> />
</Tooltip>:undefined </Tooltip> : undefined
}{current.task.step == JOB_LIFE_CYCLE.CANCEL ? }{current.task.step == JOB_LIFE_CYCLE.CANCEL ?
<Tooltip title="恢复,将进入维护模式"> <Tooltip title="恢复,将进入维护模式">
<Button <Button
type="text" type="text"
icon={<RestTwoTone />} icon={<RestTwoTone/>}
onClick={toRecoveryTask} onClick={toRecoveryTask}
/> />
</Tooltip>:undefined </Tooltip> : undefined
} }
<Tooltip title="查看使用帮助"> <Tooltip title="查看使用帮助">
<Button <Button
...@@ -646,12 +651,14 @@ const StudioMenu = (props: any) => { ...@@ -646,12 +651,14 @@ const StudioMenu = (props: any) => {
onClick={showHelp} onClick={showHelp}
/> />
</Tooltip> </Tooltip>
</Col>:undefined} </Col> : undefined}
</Row> </Row>
</Col> </Col>
<StudioExplain <StudioExplain
modalVisible={modalVisible} modalVisible={modalVisible}
onClose={()=>{handleModalVisible(false)}} onClose={() => {
handleModalVisible(false)
}}
/> />
<Modal <Modal
width={1000} width={1000}
...@@ -661,16 +668,16 @@ const StudioMenu = (props: any) => { ...@@ -661,16 +668,16 @@ const StudioMenu = (props: any) => {
visible={graphModalVisible} visible={graphModalVisible}
onCancel={() => handleGraphModalVisible(false)} onCancel={() => handleGraphModalVisible(false)}
> >
<StudioGraph data={graphData} /> <StudioGraph data={graphData}/>
</Modal> </Modal>
{current?.task? {current?.task ?
<ModalForm <ModalForm
title={`${current.task.alias} 的 ${current.task.dialect} 导出`} title={`${current.task.alias} 的 ${current.task.dialect} 导出`}
visible={exportModalVisible} visible={exportModalVisible}
width={1000} width={1000}
modalProps={{ modalProps={{
maskClosable:false, maskClosable: false,
bodyStyle:{ bodyStyle: {
padding: '5px' padding: '5px'
} }
}} }}
...@@ -683,12 +690,12 @@ const StudioMenu = (props: any) => { ...@@ -683,12 +690,12 @@ const StudioMenu = (props: any) => {
}, },
}} }}
> >
<SqlExport id={current.task.id} /> <SqlExport id={current.task.id}/>
</ModalForm>:undefined} </ModalForm> : undefined}
{current && isFullScreen?<Modal {current && isFullScreen ? <Modal
width={width} width={width}
bodyStyle={{padding: 0}} bodyStyle={{padding: 0}}
style={{top:0,padding:0,margin:0,maxWidth:'100vw'}} style={{top: 0, padding: 0, margin: 0, maxWidth: '100vw'}}
destroyOnClose destroyOnClose
maskClosable={false} maskClosable={false}
closable={false} closable={false}
...@@ -698,31 +705,31 @@ const StudioMenu = (props: any) => { ...@@ -698,31 +705,31 @@ const StudioMenu = (props: any) => {
props.changeFullScreen(false); props.changeFullScreen(false);
}}> }}>
<StudioTabs width={width} height={height}/> <StudioTabs width={width} height={height}/>
</Modal>:undefined} </Modal> : undefined}
</Row> </Row>
); );
}; };
const mapDispatchToProps = (dispatch: Dispatch)=>({ const mapDispatchToProps = (dispatch: Dispatch) => ({
saveTask:(current: any)=>dispatch({ saveTask: (current: any) => dispatch({
type: "Studio/saveTask", type: "Studio/saveTask",
payload: current.task, payload: current.task,
}),saveTabs:(tabs: any)=>dispatch({ }), saveTabs: (tabs: any) => dispatch({
type: "Studio/saveTabs", type: "Studio/saveTabs",
payload: tabs, payload: tabs,
}),changeFullScreen:(isFull: boolean)=>dispatch({ }), changeFullScreen: (isFull: boolean) => dispatch({
type: "Studio/changeFullScreen", type: "Studio/changeFullScreen",
payload: isFull, payload: isFull,
}),changeTaskStep:(id: number, step: number)=>dispatch({ }), changeTaskStep: (id: number, step: number) => dispatch({
type: "Studio/changeTaskStep", type: "Studio/changeTaskStep",
payload: { payload: {
id,step id, step
}, },
}),changeTaskJobInstance:(id: number, jobInstanceId: number)=>dispatch({ }), changeTaskJobInstance: (id: number, jobInstanceId: number) => dispatch({
type: "Studio/changeTaskJobInstance", type: "Studio/changeTaskJobInstance",
payload: { payload: {
id,jobInstanceId id, jobInstanceId
}, },
}), }),
}); });
...@@ -734,4 +741,4 @@ export default connect(({Studio}: { Studio: StateType }) => ({ ...@@ -734,4 +741,4 @@ export default connect(({Studio}: { Studio: StateType }) => ({
tabs: Studio.tabs, tabs: Studio.tabs,
refs: Studio.refs, refs: Studio.refs,
currentSession: Studio.currentSession, currentSession: Studio.currentSession,
}),mapDispatchToProps)(StudioMenu); }), mapDispatchToProps)(StudioMenu);
import React, {useEffect, useState,Key} from "react"; import React, {useEffect, useState, Key} from "react";
import {connect} from "umi"; import {connect} from "umi";
import {DownOutlined, SwitcherOutlined, FolderAddOutlined} from "@ant-design/icons"; import {DownOutlined, SwitcherOutlined, FolderAddOutlined} from "@ant-design/icons";
import {Tree, Menu, Empty, Button, message, Modal,Tooltip,Row,Col,Input} from 'antd'; import {Tree, Menu, Empty, Button, message, Modal, Tooltip, Row, Col, Input} from 'antd';
import {getCatalogueTreeData} from "@/pages/FlinkSqlStudio/service"; import {getCatalogueTreeData} from "@/pages/FlinkSqlStudio/service";
import {convertToTreeData, getTreeNodeByKey, TreeDataNode} from "@/components/Studio/StudioTree/Function"; import {convertToTreeData, getTreeNodeByKey, TreeDataNode} from "@/components/Studio/StudioTree/Function";
import style from "./index.less"; import style from "./index.less";
...@@ -11,18 +11,18 @@ import { ...@@ -11,18 +11,18 @@ import {
} from "@/components/Common/crud"; } from "@/components/Common/crud";
import UpdateCatalogueForm from './components/UpdateCatalogueForm'; import UpdateCatalogueForm from './components/UpdateCatalogueForm';
import SimpleTaskForm from "@/components/Studio/StudioTree/components/SimpleTaskForm"; import SimpleTaskForm from "@/components/Studio/StudioTree/components/SimpleTaskForm";
import { Scrollbars } from "react-custom-scrollbars"; import {Scrollbars} from "react-custom-scrollbars";
import {getIcon} from "@/components/Studio/icon"; import {getIcon} from "@/components/Studio/icon";
import {showEnv} from "@/components/Studio/StudioEvent/DDL"; import {showEnv} from "@/components/Studio/StudioEvent/DDL";
import UploadModal from "@/components/Studio/StudioTree/components/UploadModal"; import UploadModal from "@/components/Studio/StudioTree/components/UploadModal";
type StudioTreeProps = { type StudioTreeProps = {
rightClickMenu:StateType['rightClickMenu']; rightClickMenu: StateType['rightClickMenu'];
dispatch:any; dispatch: any;
tabs:StateType['tabs']; tabs: StateType['tabs'];
current:StateType['current']; current: StateType['current'];
toolHeight:number; toolHeight: number;
refs:any; refs: any;
}; };
type RightClickMenu = { type RightClickMenu = {
...@@ -36,18 +36,18 @@ type RightClickMenu = { ...@@ -36,18 +36,18 @@ type RightClickMenu = {
const generateList = (data: any, list: any[]) => { const generateList = (data: any, list: any[]) => {
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const node = data[i]; const node = data[i];
const { name, id, parentId,level} = node; const {name, id, parentId, level} = node;
list.push({ name, id, key: id, title: name, parentId,level }); list.push({name, id, key: id, title: name, parentId, level});
if (node.children) { if (node.children) {
generateList(node.children, list); generateList(node.children, list);
} }
} }
return list return list
} };
// tree树 匹配方法 // tree树 匹配方法
const getParentKey = (key: number | string, tree: any): any => { const getParentKey = (key: number | string, tree: any): any => {
let parentKey let parentKey;
for (let i = 0; i < tree.length; i++) { for (let i = 0; i < tree.length; i++) {
const node = tree[i]; const node = tree[i];
if (node.children) { if (node.children) {
...@@ -58,16 +58,18 @@ const getParentKey = (key: number | string, tree: any): any => { ...@@ -58,16 +58,18 @@ const getParentKey = (key: number | string, tree: any): any => {
} }
} }
} }
// console.log(key, parentKey, tree,)
return parentKey; return parentKey;
} };
const {DirectoryTree} = Tree;
const {Search} = Input;
const StudioTree: React.FC<StudioTreeProps> = (props) => { const StudioTree: React.FC<StudioTreeProps> = (props) => {
const {rightClickMenu,dispatch,tabs,refs,toolHeight} = props; const {rightClickMenu, dispatch, tabs, refs, toolHeight} = props;
const [treeData, setTreeData] = useState<TreeDataNode[]>(); const [treeData, setTreeData] = useState<TreeDataNode[]>();
const [expandedKeys, setExpandedKeys] = useState<Key[]>(); const [expandedKeys, setExpandedKeys] = useState<Key[]>();
const [defaultExpandedKeys, setDefaultExpandedKeys] = useState<any[]>([]); const [defaultExpandedKeys, setDefaultExpandedKeys] = useState<any[]>([]);
const [rightClickNodeTreeItem,setRightClickNodeTreeItem] = useState<RightClickMenu>(); const [rightClickNodeTreeItem, setRightClickNodeTreeItem] = useState<RightClickMenu>();
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);
...@@ -78,10 +80,9 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -78,10 +80,9 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
const [isUploadModalVisible, setIsUploadModalVisible] = useState(false); const [isUploadModalVisible, setIsUploadModalVisible] = useState(false);
const [uploadNodeId, setUploadNodeId] = useState(0); const [uploadNodeId, setUploadNodeId] = useState(0);
const sref: any = React.createRef<Scrollbars>(); const sref: any = React.createRef<Scrollbars>();
const { DirectoryTree } = Tree; const [searchValue, setSearchValue] = useState('');
const {Search} = Input;
const [searchValue, setSearchValue] = useState('')
const [autoExpandParent, setAutoExpandParent] = useState(true); const [autoExpandParent, setAutoExpandParent] = useState(true);
const [cutId, setCutId] = useState<number | undefined>(undefined);
const getTreeData = async () => { const getTreeData = async () => {
const result = await getCatalogueTreeData(); const result = await getCatalogueTreeData();
...@@ -95,23 +96,23 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -95,23 +96,23 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
expendList.push(item.id); expendList.push(item.id);
}) })
} }
}) });
data = convertToTreeData(list, 0); data = convertToTreeData(list, 0);
setTreeData(data); setTreeData(data);
//默认展开所有 //默认展开所有
setExpandedKeys(expendList|| []); setExpandedKeys(expendList || []);
setDefaultExpandedKeys(expendList || []); setDefaultExpandedKeys(expendList || []);
}; };
const onChange = (e: any) => { const onChange = (e: any) => {
let { value } = e.target let {value} = e.target;
if (!value) { if (!value) {
setExpandedKeys(defaultExpandedKeys); setExpandedKeys(defaultExpandedKeys);
setSearchValue(value) setSearchValue(value);
return return
} }
value = String(value).trim() value = String(value).trim();
const expandList: any[] = generateList(treeData, []) const expandList: any[] = generateList(treeData, []);
let expandedKeys: any = expandList.map((item: any) => { let expandedKeys: any = expandList.map((item: any) => {
if (item && item.name.indexOf(value) > -1) { if (item && item.name.indexOf(value) > -1) {
let key = getParentKey(item.key, treeData); let key = getParentKey(item.key, treeData);
...@@ -125,21 +126,21 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -125,21 +126,21 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
setAutoExpandParent(true) setAutoExpandParent(true)
} }
const openByKey = async (key:any)=>{ const openByKey = async (key: any) => {
const result = await getCatalogueTreeData(); const result = await getCatalogueTreeData();
let data = result.datas; let data = result.datas;
let list = data; let list = data;
for(let i=0;i<list.length;i++){ for (let i = 0; i < list.length; i++) {
list[i].title=list[i].name; list[i].title = list[i].name;
list[i].key=list[i].id; list[i].key = list[i].id;
if(list[i].isLeaf){ if (list[i].isLeaf) {
list[i].icon = getIcon(list[i].type); list[i].icon = getIcon(list[i].type);
} }
} }
data = convertToTreeData(list, 0); data = convertToTreeData(list, 0);
setTreeData(data); setTreeData(data);
let node = getTreeNodeByKey(data,key); let node = getTreeNodeByKey(data, key);
onSelect([],{node:node}); onSelect([], {node: node});
}; };
useEffect(() => { useEffect(() => {
...@@ -147,74 +148,80 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -147,74 +148,80 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
}, []); }, []);
const handleMenuClick=(key:string)=>{ const handleMenuClick = (key: string) => {
if(key=='Open'){ if (key == 'Open') {
toOpen(rightClickNode); toOpen(rightClickNode);
}else if(key=='Submit'){ } else if (key == 'Submit') {
toSubmit(rightClickNode); toSubmit(rightClickNode);
}else if(key=='CreateCatalogue'){ } else if (key == 'CreateCatalogue') {
createCatalogue(rightClickNode); createCatalogue(rightClickNode);
}else if(key=='CreateRootCatalogue'){ } else if (key == 'CreateRootCatalogue') {
createRootCatalogue(); createRootCatalogue();
} else if(key == 'ShowUploadModal'){ } else if (key == 'ShowUploadModal') {
showUploadModal(rightClickNode); showUploadModal(rightClickNode);
}else if(key=='CreateTask'){ } else if (key == 'CreateTask') {
createTask(rightClickNode); createTask(rightClickNode);
}else if(key=='Rename'){ } else if (key == 'Rename') {
toRename(rightClickNode); toRename(rightClickNode);
}else if(key=='Delete'){ } else if (key == 'Delete') {
toDelete(rightClickNode); toDelete(rightClickNode);
} else if (key == 'Cut') {
toCut(rightClickNode);
} else if (key == 'Paste') {
toPaste(rightClickNode);
} }
}; };
const showUploadModal=(node:TreeDataNode|undefined)=>{ const showUploadModal = (node: TreeDataNode | undefined) => {
if(node == undefined) return; if (node == undefined) return;
setUploadNodeId(node.id); setUploadNodeId(node.id);
setIsUploadModalVisible(true); setIsUploadModalVisible(true);
} };
const toOpen=(node:TreeDataNode|undefined)=>{ const toOpen = (node: TreeDataNode | undefined) => {
if(!available){return} if (!available) {
return
}
setAvailable(false); setAvailable(false);
setTimeout(()=>{ setTimeout(() => {
setAvailable(true); setAvailable(true);
},200); }, 200);
if(node?.isLeaf&&node.taskId) { if (node?.isLeaf && node.taskId) {
for(let item of tabs.panes){ for (let item of tabs.panes) {
if(item.key==node.taskId){ if (item.key == node.taskId) {
dispatch&&dispatch({ dispatch && dispatch({
type: "Studio/saveToolHeight", type: "Studio/saveToolHeight",
payload: toolHeight-0.0001, payload: toolHeight - 0.0001,
}); });
dispatch&&dispatch({ dispatch && dispatch({
type: "Studio/changeActiveKey", type: "Studio/changeActiveKey",
payload: node.taskId, payload: node.taskId,
}); });
return; return;
} }
} }
const result = getInfoById('/api/task',node.taskId); const result = getInfoById('/api/task', node.taskId);
result.then(result=>{ result.then(result => {
let newTabs = tabs; let newTabs = tabs;
let newPane:any = { let newPane: any = {
title: <>{node!.icon} {node!.name}</>, title: <>{node!.icon} {node!.name}</>,
key: node!.taskId, key: node!.taskId,
value:(result.datas.statement?result.datas.statement:''), value: (result.datas.statement ? result.datas.statement : ''),
closable: true, closable: true,
path: node!.path, path: node!.path,
task:{ task: {
session:'', session: '',
maxRowNum: 100, maxRowNum: 100,
jobName:node!.name, jobName: node!.name,
useResult:true, useResult: true,
useChangeLog:false, useChangeLog: false,
useAutoCancel:false, useAutoCancel: false,
useSession:false, useSession: false,
useRemote:true, useRemote: true,
...result.datas, ...result.datas,
}, },
console:{ console: {
result: {}, result: {},
chart: {}, chart: {},
}, },
...@@ -222,7 +229,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -222,7 +229,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
}; };
newTabs!.activeKey = node!.taskId; newTabs!.activeKey = node!.taskId;
newTabs!.panes!.push(newPane); newTabs!.panes!.push(newPane);
dispatch&&dispatch({ dispatch && dispatch({
type: "Studio/saveTabs", type: "Studio/saveTabs",
payload: newTabs, payload: newTabs,
}); });
...@@ -230,8 +237,8 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -230,8 +237,8 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
} }
}; };
const createCatalogue=(node:TreeDataNode|undefined)=>{ const createCatalogue = (node: TreeDataNode | undefined) => {
if(!node?.isLeaf) { if (!node?.isLeaf) {
handleUpdateCatalogueModalVisible(true); handleUpdateCatalogueModalVisible(true);
setIsCreate(true); setIsCreate(true);
setCatalogueFormValues({ setCatalogueFormValues({
...@@ -239,12 +246,12 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -239,12 +246,12 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
parentId: node?.id, parentId: node?.id,
}); });
getTreeData(); getTreeData();
}else{ } else {
message.error('只能在目录上创建目录'); message.error('只能在目录上创建目录');
} }
}; };
const createRootCatalogue=()=>{ const createRootCatalogue = () => {
handleUpdateCatalogueModalVisible(true); handleUpdateCatalogueModalVisible(true);
setIsCreate(true); setIsCreate(true);
setCatalogueFormValues({ setCatalogueFormValues({
...@@ -254,25 +261,25 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -254,25 +261,25 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
getTreeData(); getTreeData();
}; };
const toSubmit=(node:TreeDataNode|undefined)=>{ const toSubmit = (node: TreeDataNode | undefined) => {
Modal.confirm({ Modal.confirm({
title: '提交作业', title: '提交作业',
content: '确定提交该作业到其配置的集群吗?', content: '确定提交该作业到其配置的集群吗?',
okText: '确认', okText: '确认',
cancelText: '取消', cancelText: '取消',
onOk:async () => { onOk: async () => {
let task = { let task = {
id:node?.taskId, id: node?.taskId,
}; };
setTimeout(()=>{ setTimeout(() => {
refs?.history?.current?.reload(); refs?.history?.current?.reload();
},2000); }, 2000);
handleSubmit('/api/task/submit','作业',[task]); handleSubmit('/api/task/submit', '作业', [task]);
} }
}); });
}; };
const toRename=(node:TreeDataNode|undefined)=>{ const toRename = (node: TreeDataNode | undefined) => {
handleUpdateCatalogueModalVisible(true); handleUpdateCatalogueModalVisible(true);
setIsCreate(false); setIsCreate(false);
setCatalogueFormValues({ setCatalogueFormValues({
...@@ -282,29 +289,45 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -282,29 +289,45 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
getTreeData(); getTreeData();
}; };
const createTask=(node:TreeDataNode|undefined)=>{ const toCut = (node: TreeDataNode | undefined) => {
if(!node?.isLeaf) { setCutId(node?.id);
message.success('剪切成功');
};
const toPaste = async (node: TreeDataNode | undefined) => {
if (cutId == 0) {
return;
}
const datas = await handleAddOrUpdateWithResult('/api/catalogue/moveCatalogue', {id: cutId, parentId: node?.id});
if (datas) {
setCutId(undefined);
getTreeData();
}
};
const createTask = (node: TreeDataNode | undefined) => {
if (!node?.isLeaf) {
handleUpdateTaskModalVisible(true); handleUpdateTaskModalVisible(true);
setIsCreate(true); setIsCreate(true);
setTaskFormValues({ setTaskFormValues({
parentId: node?.id, parentId: node?.id,
}); });
//getTreeData(); //getTreeData();
}else{ } else {
message.error('只能在目录上创建作业'); message.error('只能在目录上创建作业');
} }
}; };
const toDelete= (node: TreeDataNode|undefined)=>{ const toDelete = (node: TreeDataNode | undefined) => {
let label = (node?.taskId==null)?'目录':'作业'; let label = (node?.taskId == null) ? '目录' : '作业';
Modal.confirm({ Modal.confirm({
title: `删除${label}`, title: `删除${label}`,
content: `确定删除该${label}${node?.name}】吗?`, content: `确定删除该${label}${node?.name}】吗?`,
okText: '确认', okText: '确认',
cancelText: '取消', cancelText: '取消',
onOk:async () => { onOk: async () => {
await handleRemoveById('/api/catalogue',node!.id); await handleRemoveById('/api/catalogue', node!.id);
if(node?.taskId) { if (node?.taskId) {
dispatch({ dispatch({
type: "Studio/deleteTabByKey", type: "Studio/deleteTabByKey",
payload: node?.taskId, payload: node?.taskId,
...@@ -317,33 +340,39 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -317,33 +340,39 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
const getNodeTreeRightClickMenu = () => { const getNodeTreeRightClickMenu = () => {
const {pageX, pageY} = {...rightClickNodeTreeItem}; const {pageX, pageY} = {...rightClickNodeTreeItem};
const tmpStyle:any = { const tmpStyle: any = {
position: 'absolute', position: 'absolute',
left: pageX, left: pageX,
top: pageY, top: pageY,
}; };
let menuItems; let menuItems;
if(rightClickNode&&rightClickNode.isLeaf){ if (rightClickNode && rightClickNode.isLeaf) {
menuItems=(<> menuItems = (<>
<Menu.Item key='Open'>{'打开'}</Menu.Item> <Menu.Item key='Open'>{'打开'}</Menu.Item>
<Menu.Item key='Submit'>{'异步提交'}</Menu.Item> <Menu.Item key='Submit'>{'异步提交'}</Menu.Item>
<Menu.Item key='Rename'>{'重命名'}</Menu.Item> <Menu.Item key='Rename'>{'重命名'}</Menu.Item>
<Menu.Item key='Cut'>{'剪切'}</Menu.Item>
{cutId && <Menu.Item key='Paste'>{'粘贴'}</Menu.Item>}
<Menu.Item key='Delete'>{'删除'}</Menu.Item> <Menu.Item key='Delete'>{'删除'}</Menu.Item>
</>) </>)
}else if(rightClickNode&&rightClickNode.children&&rightClickNode.children.length>0){ } else if (rightClickNode && rightClickNode.children && rightClickNode.children.length > 0) {
menuItems=(<> menuItems = (<>
<Menu.Item key='CreateCatalogue'>{'创建目录'}</Menu.Item> <Menu.Item key='CreateCatalogue'>{'创建目录'}</Menu.Item>
<Menu.Item key='CreateRootCatalogue'>{'创建根目录'}</Menu.Item> <Menu.Item key='CreateRootCatalogue'>{'创建根目录'}</Menu.Item>
<Menu.Item key='ShowUploadModal'>{'上传zip包创建工程'}</Menu.Item> <Menu.Item key='ShowUploadModal'>{'上传zip包创建工程'}</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>
<Menu.Item key='Cut'>{'剪切'}</Menu.Item>
{cutId && <Menu.Item key='Paste'>{'粘贴'}</Menu.Item>}
<Menu.Item disabled>{'删除'}</Menu.Item> <Menu.Item disabled>{'删除'}</Menu.Item>
</>) </>)
}else{ } else {
menuItems=(<> menuItems = (<>
<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>
<Menu.Item key='Cut'>{'剪切'}</Menu.Item>
{cutId && <Menu.Item key='Paste'>{'粘贴'}</Menu.Item>}
<Menu.Item key='Delete'>{'删除'}</Menu.Item> <Menu.Item key='Delete'>{'删除'}</Menu.Item>
</>) </>)
} }
...@@ -356,40 +385,40 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -356,40 +385,40 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
{menuItems} {menuItems}
</Menu> </Menu>
); );
return rightClickMenu? menu: ''; return rightClickMenu ? menu : '';
}; };
const getEmpty = () =>{ const getEmpty = () => {
const empty = (<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} ><Button type="primary" onClick={() => { const empty = (<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}><Button type="primary" onClick={() => {
handleUpdateCatalogueModalVisible(true); handleUpdateCatalogueModalVisible(true);
setIsCreate(true); setIsCreate(true);
setCatalogueFormValues({ setCatalogueFormValues({
isLeaf:false, isLeaf: false,
parentId:0, parentId: 0,
}); });
}}>创建目录</Button></Empty>); }}>创建目录</Button></Empty>);
return (treeData&&treeData.length==0)?empty:''; return (treeData && treeData.length == 0) ? empty : '';
}; };
const handleContextMenu = (e:any) => { const handleContextMenu = (e: any) => {
let position = e.event.currentTarget.getBoundingClientRect(); let position = e.event.currentTarget.getBoundingClientRect();
let scrollTop = document.documentElement.scrollTop; let scrollTop = document.documentElement.scrollTop;
setRightClickNode(e.node); setRightClickNode(e.node);
setRightClickNodeTreeItem({ setRightClickNodeTreeItem({
pageX: e.event.pageX-40, pageX: e.event.pageX - 40,
pageY: position.y+sref.current.getScrollTop()+scrollTop-145-position.height, pageY: position.y + sref.current.getScrollTop() + scrollTop - 145 - position.height,
id: e.node.id, id: e.node.id,
categoryName: e.node.name categoryName: e.node.name
}); });
dispatch&&dispatch({ dispatch && dispatch({
type: "Studio/showRightClickMenu", type: "Studio/showRightClickMenu",
payload: true, payload: true,
}); });
}; };
//选中节点时触发 //选中节点时触发
const onSelect = (selectedKeys:Key[], e:any) => { const onSelect = (selectedKeys: Key[], e: any) => {
if(e.node&&e.node.isLeaf) { if (e.node && e.node.isLeaf) {
dispatch({ dispatch({
type: "Studio/saveCurrentPath", type: "Studio/saveCurrentPath",
payload: e.node.path, payload: e.node.path,
...@@ -398,18 +427,18 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -398,18 +427,18 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
} }
}; };
const offExpandAll = ()=>{ const offExpandAll = () => {
setExpandedKeys([]); setExpandedKeys([]);
}; };
// 树节点展开/收缩 // 树节点展开/收缩
const onExpand=(expandedKeys:Key[])=>{ const onExpand = (expandedKeys: Key[]) => {
setExpandedKeys(expandedKeys); setExpandedKeys(expandedKeys);
setAutoExpandParent(false) setAutoExpandParent(false)
}; };
const loop = (data:any) => const loop = (data: any) =>
data?.map((item:any) => { data?.map((item: any) => {
const index = item.title.indexOf(searchValue); const index = item.title.indexOf(searchValue);
const beforeStr = item.title.substr(0, index); const beforeStr = item.title.substr(0, index);
const afterStr = item.title.substr(index + searchValue.length); const afterStr = item.title.substr(index + searchValue.length);
...@@ -425,61 +454,72 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -425,61 +454,72 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
<span>{item.title}</span> <span>{item.title}</span>
); );
if (item.children) { if (item.children) {
return {isLeaf:item.isLeaf,name:item.name,id:item.id,taskId:item.taskId,parentId:item.parentId,path:item.path,icon:item.isLeaf?item.icon:'', title, key: item.key, children: loop(item.children) }; return {
isLeaf: item.isLeaf,
name: item.name,
id: item.id,
taskId: item.taskId,
parentId: item.parentId,
path: item.path,
icon: item.isLeaf ? item.icon : '',
title,
key: item.key,
children: loop(item.children)
};
} }
return { return {
isLeaf:item.isLeaf, isLeaf: item.isLeaf,
name:item.name, name: item.name,
id:item.id, id: item.id,
taskId:item.taskId, taskId: item.taskId,
parentId:item.parentId, parentId: item.parentId,
path:item.path, path: item.path,
icon:item.isLeaf?item.icon:'', icon: item.isLeaf ? item.icon : '',
title, title,
key: item.key, key: item.key,
}; };
}); });
return ( return (
<div className={style.tree_div} > <div className={style.tree_div}>
<Row> <Row>
<Col span={24}> <Col span={24}>
<Tooltip title="创建根目录"> <Tooltip title="创建根目录">
<Button <Button
type="text" type="text"
icon={<FolderAddOutlined />} icon={<FolderAddOutlined/>}
onClick={createRootCatalogue} onClick={createRootCatalogue}
/> />
</Tooltip> </Tooltip>
<Tooltip title="折叠目录"> <Tooltip title="折叠目录">
<Button <Button
type="text" type="text"
icon={<SwitcherOutlined />} icon={<SwitcherOutlined/>}
onClick={offExpandAll} onClick={offExpandAll}
/> />
</Tooltip> </Tooltip>
</Col> </Col>
</Row> </Row>
<Search style={{marginBottom: 8}} placeholder="Search" onChange={onChange} allowClear={true}/> <Search style={{marginBottom: 8}} placeholder="Search" onChange={onChange} allowClear={true}/>
<Scrollbars style={{height:(toolHeight-72)}} ref={sref}> <Scrollbars style={{height: (toolHeight - 72)}} ref={sref}>
<DirectoryTree <DirectoryTree
multiple multiple
onRightClick={handleContextMenu} onRightClick={handleContextMenu}
onSelect={onSelect} onSelect={onSelect}
switcherIcon={<DownOutlined/>} switcherIcon={<DownOutlined/>}
treeData={loop(treeData)} treeData={loop(treeData)}
onExpand ={onExpand} onExpand={onExpand}
autoExpandParent={autoExpandParent} autoExpandParent={autoExpandParent}
defaultExpandAll defaultExpandAll
expandedKeys={expandedKeys} expandedKeys={expandedKeys}
/> />
{getNodeTreeRightClickMenu()} {getNodeTreeRightClickMenu()}
{getEmpty()} {getEmpty()}
{updateCatalogueModalVisible? ( {updateCatalogueModalVisible ? (
<UpdateCatalogueForm <UpdateCatalogueForm
onSubmit={async (value) => { onSubmit={async (value) => {
const success = await handleAddOrUpdate( const success = await handleAddOrUpdate(
isCreate?'/api/catalogue':'/api/catalogue/toRename',value); isCreate ? '/api/catalogue' : '/api/catalogue/toRename', value);
if (success) { if (success) {
handleUpdateCatalogueModalVisible(false); handleUpdateCatalogueModalVisible(false);
setCatalogueFormValues({}); setCatalogueFormValues({});
...@@ -495,10 +535,10 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -495,10 +535,10 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
isCreate={isCreate} isCreate={isCreate}
/> />
) : null} ) : null}
{updateTaskModalVisible? ( {updateTaskModalVisible ? (
<SimpleTaskForm <SimpleTaskForm
onSubmit={async (value) => { onSubmit={async (value) => {
const datas = await handleAddOrUpdateWithResult('/api/catalogue/createTask',value); const datas = await handleAddOrUpdateWithResult('/api/catalogue/createTask', value);
if (datas) { if (datas) {
handleUpdateTaskModalVisible(false); handleUpdateTaskModalVisible(false);
setTaskFormValues({}); setTaskFormValues({});
...@@ -516,18 +556,20 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -516,18 +556,20 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
/> />
) : null} ) : null}
</Scrollbars> </Scrollbars>
<UploadModal visible={isUploadModalVisible} action={`/api/catalogue/upload/${uploadNodeId}`} handleOk={()=>{ <UploadModal visible={isUploadModalVisible} action={`/api/catalogue/upload/${uploadNodeId}`} handleOk={() => {
setIsUploadModalVisible(false); setIsUploadModalVisible(false);
setExpandedKeys(defaultExpandedKeys); setExpandedKeys(defaultExpandedKeys);
getTreeData(); getTreeData();
}} onCancel={()=>{setIsUploadModalVisible(false)}} buttonTitle="上传zip包并创建工程" /> }} onCancel={() => {
setIsUploadModalVisible(false)
}} buttonTitle="上传zip包并创建工程"/>
</div> </div>
); );
}; };
export default connect(({Studio}: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
currentPath:Studio.currentPath, currentPath: Studio.currentPath,
tabs: Studio.tabs, tabs: Studio.tabs,
rightClickMenu: Studio.rightClickMenu, rightClickMenu: Studio.rightClickMenu,
refs: Studio.refs, refs: Studio.refs,
......
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