@@ -6,73 +6,51 @@ import { language } from 'monaco-editor/esm/vs/basic-languages/sql/sql';
66const { keywords : SQLKeys } = language ;
77import { editorDefaultOptions , ThemeType } from '@/constants' ;
88import styles from './index.less' ;
9- import { monacoSqlAutocomplete } from './syntax-parser/plugin/monaco-plugin' ;
109
1110export type IEditorIns = monaco . editor . IStandaloneCodeEditor ;
1211export type IEditorOptions = monaco . editor . IStandaloneEditorConstructionOptions ;
1312export type IEditorContentChangeEvent = monaco . editor . IModelContentChangedEvent ;
14-
1513interface IProps {
1614 id : string | number ;
17- value ?: string ;
15+ isActive ?: boolean ;
1816 language ?: string ;
19- className : string ;
20- onChange ?: ( v : string , e ?: IEditorContentChangeEvent ) => void ;
21- didMount ?: ( editor : IEditorIns ) => any ;
17+ className ?: string ;
2218 options ?: IEditorOptions ;
2319 needDestroy ?: boolean ;
2420 addAction ?: Array < { id : string ; label : string ; action : ( selectedText : string ) => void } > ;
21+ // onChange?: (v: string, e?: IEditorContentChangeEvent) => void;
22+ didMount ?: ( editor : IEditorIns ) => any ;
23+ onSave ?: ( value : string ) => void ; // 快捷键保存的回调
24+ onExecute ?: ( value : string ) => void ; // 快捷键执行的回调
2525}
2626
2727export interface IExportRefFunction {
2828 getCurrentSelectContent : ( ) => string ;
2929 getAllContent : ( ) => string ;
30+ setValue : ( text : any , range ?: IRangeType ) => void ;
3031}
3132
3233function MonacoEditor ( props : IProps , ref : ForwardedRef < IExportRefFunction > ) {
33- const { id, className, value = '' , language = 'sql' , didMount, options } = props ;
34-
34+ const {
35+ id,
36+ className,
37+ language = 'sql' ,
38+ didMount,
39+ options,
40+ isActive,
41+ onSave,
42+ onExecute
43+ } = props ;
3544 const editorRef = useRef < IEditorIns > ( ) ;
36- const [ editorVal , setEditorVal ] = useState ( '' ) ;
37-
38- // 受控暂存value
39- const valRef = useRef < string > ( '' ) ;
40-
4145 const [ appTheme ] = useTheme ( ) ;
4246
43- useImperativeHandle ( ref , ( ) => ( {
44- getCurrentSelectContent,
45- getAllContent,
46- } ) ) ;
47-
48- /**
49- * 获取当前选中的内容
50- * @returns
51- */
52- const getCurrentSelectContent = ( ) => {
53- let selection = editorRef . current ?. getSelection ( ) ;
54- if ( ! selection || selection . isEmpty ( ) ) {
55- return '' ;
56- } else {
57- var selectedText = editorRef . current ?. getModel ( ) ?. getValueInRange ( selection ) ;
58- return selectedText || '' ;
59- }
60- } ;
61-
62- /** 获取文本所有内容 */
63- const getAllContent = ( ) => {
64- const model = editorRef . current ?. getModel ( ) ;
65- const value = model ?. getValue ( ) ;
66- return value || '' ;
67- } ;
68-
6947 // init
7048 useEffect ( ( ) => {
7149 const editorIns = monaco . editor . create ( document . getElementById ( `monaco-editor-${ id } ` ) ! , {
7250 ...editorDefaultOptions ,
7351 ...options ,
74- value,
75- language : 'sql' ,
52+ value : '' ,
53+ language : language ,
7654 theme : appTheme . backgroundColor === ThemeType . Light ? 'Default' : 'BlackTheme' ,
7755 } ) ;
7856 editorRef . current = editorIns ;
@@ -81,7 +59,7 @@ function MonacoEditor(props: IProps, ref: ForwardedRef<IExportRefFunction>) {
8159 monaco . editor . defineTheme ( 'BlackTheme' , {
8260 base : 'vs-dark' ,
8361 inherit : true ,
84- rules : [ { background : '#15161a' } ] ,
62+ rules : [ { background : '#15161a' } ] as any ,
8563 colors : {
8664 // 相关颜色属性配置
8765 'editor.foreground' : '#ffffff' ,
@@ -92,14 +70,13 @@ function MonacoEditor(props: IProps, ref: ForwardedRef<IExportRefFunction>) {
9270 monaco . editor . defineTheme ( 'Default' , {
9371 base : 'vs' ,
9472 inherit : true ,
95- rules : [ { background : '#15161a' } ] ,
73+ rules : [ { background : '#15161a' } ] as any ,
9674 colors : {
9775 'editor.foreground' : '#000000' ,
9876 'editor.background' : '#fff' , //背景色
9977 } ,
10078 } ) ;
10179
102- // monacoSqlAutocomplete(monaco, editorIns);
10380 handleRegisterTigger ( ) ;
10481
10582 createAction ( editorIns ) ;
@@ -108,56 +85,64 @@ function MonacoEditor(props: IProps, ref: ForwardedRef<IExportRefFunction>) {
10885 } ;
10986 } , [ ] ) ;
11087
111- // value 变了,直接设置editorValue
11288 useEffect ( ( ) => {
113- updateEditor ( value ) ;
114- valRef . current = value ;
115- } , [ value ] ) ;
89+ if ( isActive && editorRef . current ) {
90+ // 自定义快捷键
91+ editorRef . current . addCommand ( monaco . KeyMod . CtrlCmd | monaco . KeyCode . KeyS , ( ) => {
92+ const value = editorRef . current ?. getValue ( ) ;
93+ onSave ?.( value || '' ) ;
94+ } ) ;
11695
117- // editor 变了,val 没变,设置 editorValue 为 value
118- // useEffect(() => {
119- // if (editorVal !== valRef.current) {
120- // updateEditor(valRef.current );
121- // }
122- // }, [editorVal]);
96+ editorRef . current . addCommand ( monaco . KeyMod . CtrlCmd | monaco . KeyCode . Enter , ( event : Event ) => {
97+ const value = getCurrentSelectContent ( )
98+ onExecute ?. ( value ) ;
99+ } ) ;
100+ }
101+ } , [ editorRef . current , isActive ] )
123102
103+ // 监听主题色变化切换编辑器主题色
124104 useEffect ( ( ) => {
125- const _ref = editorRef . current ?. onDidChangeModelContent ( ( e ) => {
126- const curVal = editorRef . current ?. getValue ( ) ;
127- props . onChange ?.( curVal || '' , e ) ;
128- setEditorVal ( curVal || '' ) ;
129- } ) ;
105+ monaco . editor . setTheme ( appTheme . backgroundColor === ThemeType . Dark ? 'BlackTheme' : 'Default' ) ;
106+ } , [ appTheme . backgroundColor ] ) ;
130107
131- return ( ) => _ref && _ref . dispose ( ) ;
132- } , [ props . onChange ] ) ;
108+ // useEffect(() => {
109+ // const _ref = editorRef.current?.onDidChangeModelContent((e) => {
110+ // const curVal = editorRef.current?.getValue();
111+ // props.onChange?.(curVal || '', e);
112+ // });
113+ // return () => _ref && _ref.dispose();
114+ // }, [props.onChange]);
133115
134- const updateEditor = ( value : string ) => {
135- if ( editorRef . current ) {
136- if ( value === editorRef . current . getValue ( ) ) {
137- return ;
138- }
139- const model = editorRef . current . getModel ( ) ;
140- if ( ! model ) return ;
116+ useImperativeHandle ( ref , ( ) => ( {
117+ getCurrentSelectContent,
118+ getAllContent,
119+ setValue
120+ } ) ) ;
141121
142- editorRef . current . pushUndoStop ( ) ;
122+ const setValue = ( text : any , range ?: IRangeType ) => {
123+ appendMonacoValue ( editorRef . current , text , range )
124+ }
143125
144- model . pushEditOperations (
145- [ ] ,
146- [
147- {
148- range : model . getFullModelRange ( ) ,
149- text : value ,
150- } ,
151- ] ,
152- ( ) => [ editorRef . current . getSelection ( ) ] ,
153- ) ;
154- editorRef . current . pushUndoStop ( ) ;
126+ /**
127+ * 获取当前选中的内容
128+ * @returns
129+ */
130+ const getCurrentSelectContent = ( ) => {
131+ let selection = editorRef . current ?. getSelection ( ) ;
132+ if ( ! selection || selection . isEmpty ( ) ) {
133+ return '' ;
134+ } else {
135+ var selectedText = editorRef . current ?. getModel ( ) ?. getValueInRange ( selection ) ;
136+ return selectedText || '' ;
155137 }
156138 } ;
157139
158- useEffect ( ( ) => {
159- monaco . editor . setTheme ( appTheme . backgroundColor === ThemeType . Dark ? 'BlackTheme' : 'Default' ) ;
160- } , [ appTheme . backgroundColor ] ) ;
140+ /** 获取文本所有内容 */
141+ const getAllContent = ( ) => {
142+ const model = editorRef . current ?. getModel ( ) ;
143+ const value = model ?. getValue ( ) ;
144+ return value || '' ;
145+ } ;
161146
162147 const handleRegisterTigger = ( ) => {
163148 // SQL关键词、 数据库、 表 、列
@@ -253,7 +238,47 @@ function MonacoEditor(props: IProps, ref: ForwardedRef<IExportRefFunction>) {
253238 } ) ;
254239 } ;
255240
256- return < div ref = { ref } id = { `monaco-editor-${ id } ` } className = { cs ( className , styles . editorContainer ) } /> ;
241+ return < div ref = { ref as any } id = { `monaco-editor-${ id } ` } className = { cs ( className , styles . editorContainer ) } /> ;
242+ }
243+
244+ // text 需要添加的文本
245+ // range 添加到的位置
246+ // 'end' 末尾
247+ // 'front' 开头
248+ // 'cover' 覆盖掉原有的文字
249+ // 自定义位置数组 new monaco.Range []
250+ export type IRangeType = 'end' | 'front' | 'cover' | any ;
251+
252+ export const appendMonacoValue = ( editor : any , text : any , range : IRangeType = 'end' ) => {
253+ if ( ! editor ) {
254+ return
255+ }
256+ const model = editor ?. getModel && editor . getModel ( editor ) ;
257+ // 创建编辑操作,将当前文档内容替换为新内容
258+ let newRange : IRangeType = range ;
259+ text = `${ text } \n`
260+ switch ( range ) {
261+ case 'cover' :
262+ newRange = model . getFullModelRange ( ) ;
263+ break ;
264+ case 'front' :
265+ newRange = new monaco . Range ( 1 , 1 , 1 , 1 ) ;
266+ break ;
267+ case 'end' :
268+ const lastLine = editor . getModel ( ) . getLineCount ( ) ;
269+ const lastLineLength = editor . getModel ( ) . getLineMaxColumn ( lastLine ) ;
270+ newRange = new monaco . Range ( lastLine , lastLineLength , lastLine , lastLineLength ) ;
271+ break ;
272+ default :
273+ break ;
274+ }
275+ const op = {
276+ range : newRange ,
277+ text,
278+ } ;
279+ // decorations?: IModelDeltaDecoration[]: 一个数组类型的参数,用于指定插入的文本的装饰。可以用来设置文本的样式、颜色、背景色等。如果不需要设置装饰,可以忽略此参数。
280+ const decorations = [ { } ] ; // 解决新增的文本默认背景色为灰色
281+ editor . executeEdits ( 'setValue' , [ op ] , decorations ) ;
257282}
258283
259284export default forwardRef ( MonacoEditor ) ;
0 commit comments