Commit eeab42f6 authored by coderTomato's avatar coderTomato

monacoEditor实现快捷键保存、校验sql、代码格式化

parent e5e438d7
...@@ -206,7 +206,7 @@ public class CatalogueController { ...@@ -206,7 +206,7 @@ public class CatalogueController {
} }
/** /**
* 创建节点和作业 * 重命名节点和作业
*/ */
@PutMapping("/toRename") @PutMapping("/toRename")
public Result toRename(@RequestBody Catalogue catalogue) throws Exception { public Result toRename(@RequestBody Catalogue catalogue) throws Exception {
......
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
"react-helmet-async": "^1.0.4", "react-helmet-async": "^1.0.4",
"react-highlight-words": "^0.17.0", "react-highlight-words": "^0.17.0",
"react-monaco-editor": "^0.43.0", "react-monaco-editor": "^0.43.0",
"sql-formatter": "^4.0.2",
"umi": "^3.5.0", "umi": "^3.5.0",
"umi-request": "^1.0.8" "umi-request": "^1.0.8"
}, },
......
...@@ -3,7 +3,8 @@ import {connect} from "umi"; ...@@ -3,7 +3,8 @@ import {connect} from "umi";
import {Button, Tag, Space, Typography, Modal,} from 'antd'; import {Button, Tag, Space, Typography, Modal,} from 'antd';
import {ConsoleSqlOutlined} from "@ant-design/icons"; import {ConsoleSqlOutlined} from "@ant-design/icons";
import ProList from '@ant-design/pro-list'; import ProList from '@ant-design/pro-list';
import React, {useRef, useState} from "react"; import {explainSql} from "@/pages/FlinkSqlStudio/service";
import {useRef, useState, useEffect} from "react";
const {Paragraph} = Typography; const {Paragraph} = Typography;
...@@ -25,17 +26,41 @@ export type StudioExplainProps = { ...@@ -25,17 +26,41 @@ export type StudioExplainProps = {
data: Partial<ExplainItem>; data: Partial<ExplainItem>;
} }
const StudioExplain = (props: any) => { const StudioExplain = (props: any) => {
const [explainData, setExplainData] = useState([]);
const { const {
onCancel: handleModalVisible, onClose,
modalVisible, modalVisible,
data, current,
currentSession,
} = props; } = props;
useEffect(() => {
let selectsql = null;
if (current.monaco.current) {
let selection = current.monaco.current.editor.getSelection();
selectsql = current.monaco.current.editor.getModel().getValueInRange(selection);
}
if (selectsql == null || selectsql == '') {
selectsql = current.value;
}
let useSession = !!currentSession.session;
let param = {
...current.task,
useSession: useSession,
session: currentSession.session,
configJson: JSON.stringify(current.task.config),
statement: selectsql,
};
const result = explainSql(param);
result.then(res => {
setExplainData(res.datas);
})
}, [])
const renderFooter = () => { const renderFooter = () => {
return ( return (
<> <>
<Button onClick={() => handleModalVisible(false)}>关闭</Button> <Button onClick={onClose}>关闭</Button>
</> </>
); );
}; };
...@@ -49,7 +74,7 @@ const StudioExplain = (props: any) => { ...@@ -49,7 +74,7 @@ const StudioExplain = (props: any) => {
filterType: 'light', filterType: 'light',
}} }}
rowKey="id" rowKey="id"
dataSource={data} dataSource={explainData}
pagination={{ pagination={{
pageSize: 5, pageSize: 5,
}} }}
...@@ -66,7 +91,7 @@ const StudioExplain = (props: any) => { ...@@ -66,7 +91,7 @@ const StudioExplain = (props: any) => {
return ( return (
<Space size={0}> <Space size={0}>
<Tag color="blue" key={row.type}> <Tag color="blue" key={row.type}>
<ConsoleSqlOutlined /> {row.type} <ConsoleSqlOutlined/> {row.type}
</Tag> </Tag>
</Space> </Space>
); );
...@@ -125,7 +150,6 @@ const StudioExplain = (props: any) => { ...@@ -125,7 +150,6 @@ const StudioExplain = (props: any) => {
</>) </>)
}; };
return ( return (
<Modal <Modal
width={800} width={800}
...@@ -133,13 +157,14 @@ const StudioExplain = (props: any) => { ...@@ -133,13 +157,14 @@ const StudioExplain = (props: any) => {
title="FlinkSql 语法和逻辑检查" title="FlinkSql 语法和逻辑检查"
visible={modalVisible} visible={modalVisible}
footer={renderFooter()} footer={renderFooter()}
onCancel={() => handleModalVisible()} onCancel={onClose}
> >
{renderContent()} {renderContent()}
</Modal> </Modal>
); );
}; };
export default connect(({Studio}: {Studio: StateType}) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
current: Studio.current, current: Studio.current,
}))(StudioExplain); currentSession: Studio.currentSession,
}))(StudioExplain);
import React, {useEffect, useImperativeHandle, useRef} from 'react'; import React, {useEffect, useImperativeHandle, useRef,useState} from 'react';
import * as _monaco from "monaco-editor"; import * as _monaco from "monaco-editor";
import MonacoEditor from "react-monaco-editor"; import MonacoEditor from "react-monaco-editor";
import {BaseDataSourceField, BaseDataSourceHeader, CompletionItem} from "./data";
import styles from './index.less';
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi"; import {connect,Dispatch} from "umi";
import {DocumentStateType} from "@/pages/Document/model"; import {DocumentStateType} from "@/pages/Document/model";
import {DocumentTableListItem} from "@/pages/Document/data"; import {DocumentTableListItem} from "@/pages/Document/data";
import {parseSqlMetaData} from "@/components/Studio/StudioEvent/Utils"; import {parseSqlMetaData} from "@/components/Studio/StudioEvent/Utils";
import {Column, MetaData} from "@/components/Studio/StudioEvent/data"; import {Column, MetaData} from "@/components/Studio/StudioEvent/data";
import StudioExplain from "@/components/Studio/StudioConsole/StudioExplain";
import {format} from "sql-formatter";
let provider = { let provider = {
dispose: () => {}, dispose: () => {},
...@@ -34,11 +34,11 @@ const FlinkSqlEditor = (props:any) => { ...@@ -34,11 +34,11 @@ const FlinkSqlEditor = (props:any) => {
}, },
tabs, tabs,
fillDocuments, fillDocuments,
dispatch,
} = props; } = props;
const editorInstance:any = useRef<any>(); const editorInstance:any = useRef<any>();
const monacoInstance: any = useRef(); const monacoInstance: any = useRef();
const [modalVisible, handleModalVisible] = useState<boolean>(false);
const getTabIndex = ():number=>{ const getTabIndex = ():number=>{
for(let i=0;i<tabs.panes.length;i++){ for(let i=0;i<tabs.panes.length;i++){
...@@ -84,14 +84,7 @@ const FlinkSqlEditor = (props:any) => { ...@@ -84,14 +84,7 @@ const FlinkSqlEditor = (props:any) => {
const onChangeHandle = (val: string, event: { changes: { text: any }[] }) => { const onChangeHandle = (val: string, event: { changes: { text: any }[] }) => {
let sqlMetaData = parseSqlMetaData(val); let sqlMetaData = parseSqlMetaData(val);
dispatch({ props.saveMetaData(sqlMetaData,tabs,tabIndex);
type: "Studio/saveSqlMetaData",
payload: {
activeKey:tabs.panes[tabIndex].key,
sqlMetaData,
isModified: true,
},
});
onChange(val,event); onChange(val,event);
/*const curWord = event.changes[0].text; /*const curWord = event.changes[0].text;
if (curWord === ';') { if (curWord === ';') {
...@@ -100,11 +93,7 @@ const FlinkSqlEditor = (props:any) => { ...@@ -100,11 +93,7 @@ const FlinkSqlEditor = (props:any) => {
return; return;
} }
cache.current = val;*/ cache.current = val;*/
dispatch({ props.saveSql(val);
type: "Studio/saveSql",
payload: val,
});
}; };
const buildSuggestions = () => { const buildSuggestions = () => {
...@@ -152,6 +141,16 @@ const FlinkSqlEditor = (props:any) => { ...@@ -152,6 +141,16 @@ const FlinkSqlEditor = (props:any) => {
const editorDidMountHandle = (editor: any, monaco: any) => { const editorDidMountHandle = (editor: any, monaco: any) => {
monacoInstance.current = monaco; monacoInstance.current = monaco;
editorInstance.current = editor; editorInstance.current = editor;
editor.addCommand(monaco.KeyMod.CtrlCmd|monaco.KeyCode.KEY_1,function (){
props.saveText(tabs,tabIndex);
})
editor.addCommand(monaco.KeyMod.CtrlCmd|monaco.KeyCode.KEY_2,function (){
handleModalVisible(true);
})
editor.addCommand(monaco.KeyMod.CtrlCmd|monaco.KeyCode.KEY_3,function (){
editor.getAction(['editor.action.formatDocument'])._run();
})
provider.dispose();// 清空提示项 provider.dispose();// 清空提示项
// 提示项设值 // 提示项设值
provider = monaco.languages.registerCompletionItemProvider('sql', { provider = monaco.languages.registerCompletionItemProvider('sql', {
...@@ -163,10 +162,23 @@ const FlinkSqlEditor = (props:any) => { ...@@ -163,10 +162,23 @@ const FlinkSqlEditor = (props:any) => {
// quickSuggestions: false, // quickSuggestions: false,
// triggerCharacters: ['$', '.', '='], // triggerCharacters: ['$', '.', '='],
}); });
monaco.languages.registerDocumentRangeFormattingEditProvider('sql', {
provideDocumentRangeFormattingEdits(model, range, options) {
var formatted = format(model.getValueInRange(range), {
indent: ' '.repeat(options.tabSize)
});
return [
{
range: range,
text: formatted
}
];
}
});
editor.focus(); editor.focus();
}; };
return ( return (
<React.Fragment> <React.Fragment>
<MonacoEditor <MonacoEditor
ref={tabs.panes[tabIndex].monaco} ref={tabs.panes[tabIndex].monaco}
...@@ -179,9 +191,33 @@ return ( ...@@ -179,9 +191,33 @@ return (
theme="vs-dark" theme="vs-dark"
editorDidMount={editorDidMountHandle} editorDidMount={editorDidMountHandle}
/> />
<StudioExplain
modalVisible={modalVisible}
onClose={()=>{handleModalVisible(false)}}
visible={modalVisible}
/>
</React.Fragment> </React.Fragment>
); )
}; }
const mapDispatchToProps = (dispatch:Dispatch)=>({
saveText:(tabs:any,tabIndex:any)=>dispatch({
type: "Studio/saveTask",
payload: tabs.panes[tabIndex].task,
}),
saveSql:(val:any)=>dispatch({
type: "Studio/saveSql",
payload: val,
}),
saveMetaData:(sqlMetaData:any,tabs:any,tabIndex:any)=>dispatch({
type: "Studio/saveSqlMetaData",
payload: {
activeKey:tabs.panes[tabIndex].key,
sqlMetaData,
isModified: true,
}
})
})
export default connect(({ Studio,Document }: { Studio: StateType,Document: DocumentStateType }) => ({ export default connect(({ Studio,Document }: { Studio: StateType,Document: DocumentStateType }) => ({
current: Studio.current, current: Studio.current,
...@@ -189,4 +225,4 @@ export default connect(({ Studio,Document }: { Studio: StateType,Document: Docum ...@@ -189,4 +225,4 @@ export default connect(({ Studio,Document }: { Studio: StateType,Document: Docum
tabs: Studio.tabs, tabs: Studio.tabs,
monaco: Studio.monaco, monaco: Studio.monaco,
fillDocuments: Document.fillDocuments, fillDocuments: Document.fillDocuments,
}))(FlinkSqlEditor); }),mapDispatchToProps)(FlinkSqlEditor);
...@@ -130,36 +130,7 @@ const StudioMenu = (props: any) => { ...@@ -130,36 +130,7 @@ const StudioMenu = (props: any) => {
}; };
const onCheckSql = () => { const onCheckSql = () => {
let selectsql = null;
if (current.monaco.current) {
let selection = current.monaco.current.editor.getSelection();
selectsql = current.monaco.current.editor.getModel().getValueInRange(selection);
}
if (selectsql == null || selectsql == '') {
selectsql = current.value;
}
let useSession = !!currentSession.session;
let param = {
...current.task,
useSession: useSession,
session: currentSession.session,
configJson: JSON.stringify(current.task.config),
statement: selectsql,
};
const taskKey = (Math.random() * 1000) + '';
notification.success({
message: `新任务【${param.jobName}】正在检查`,
description: param.statement.substring(0, 40) + '...',
duration: null,
key: taskKey,
icon: <SmileOutlined style={{color: '#108ee9'}}/>,
});
const result = explainSql(param);
handleModalVisible(true); handleModalVisible(true);
result.then(res => {
notification.close(taskKey);
setExplainData(res.datas);
})
}; };
const onGetStreamGraph=()=>{ const onGetStreamGraph=()=>{
...@@ -431,12 +402,8 @@ const StudioMenu = (props: any) => { ...@@ -431,12 +402,8 @@ const StudioMenu = (props: any) => {
</Row> </Row>
</Col> </Col>
<StudioExplain <StudioExplain
onCancel={() => {
handleModalVisible(false);
setExplainData([]);
}}
modalVisible={modalVisible} modalVisible={modalVisible}
data={explainData} onClose={()=>{handleModalVisible(false)}}
/> />
<Modal <Modal
width={1000} width={1000}
......
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