<template>
|
<div
|
class="app-monaco-sql"
|
:style="`height:calc(50vh - ${complementHeight}px)`"
|
ref="monacoEditorRef"
|
/>
|
</template>
|
|
|
<script setup>
|
import * as monaco from 'monaco-editor';
|
import {language} from 'monaco-editor/esm/vs/basic-languages/sql/sql';
|
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
|
self.MonacoEnvironment = {
|
getWorker() {
|
return new editorWorker();
|
}
|
}
|
/**
|
* 定义从父组件接收的属性
|
*/
|
const props = defineProps({
|
complementHeight: {
|
type: Number,
|
default: 0
|
}
|
});
|
|
const monacoEditorRef = ref();
|
|
/**
|
* 代码
|
* @type {Ref<UnwrapRef<string>>}
|
*/
|
const code = ref('')
|
|
/**
|
* 获取 SQL 的关键字
|
*/
|
const {keywords} = language
|
|
let editor
|
|
/**
|
* 初始化 SQL 代码和表格数据
|
* @type {{当前月: *[]}}
|
*/
|
const tables = {
|
'当前月': []
|
}
|
|
/**
|
* 编辑器的主题设置
|
* @type {string}
|
*/
|
const theme = 'Light';
|
|
/**
|
* 组件挂载后创建编辑器实例
|
*/
|
const init = ({sql}) => {
|
onDispose();
|
initAutoCompletion();
|
editor = monaco.editor.create(
|
monacoEditorRef.value,
|
{
|
value: sql,
|
language: 'sql',
|
readOnly: false,
|
automaticLayout: true,
|
contextmenu: false,
|
/**
|
* 颜色装饰器
|
*/
|
colorDecorators: true,
|
theme,
|
minimap: {
|
enabled: false
|
},
|
tabSize: 2,
|
fontSize: 16
|
}
|
);
|
};
|
|
/**
|
* 组件卸载前销毁编辑器实例
|
*/
|
const onDispose = () => {
|
if (editor) {
|
editor.dispose();
|
}
|
}
|
|
/**
|
* @description: 获取编辑器中填写的值
|
*/
|
const getValue = () => {
|
return editor.getValue();
|
}
|
|
/**
|
* @description: 初始化自动补全
|
*/
|
const initAutoCompletion = () => {
|
monaco.languages.registerCompletionItemProvider('sql', {
|
triggerCharacters: ['.', ' ', ...keywords],
|
provideCompletionItems: (model, position) => {
|
let suggestions = []
|
const {lineNumber, column} = position
|
const textBeforePointer = model.getValueInRange({
|
startLineNumber: lineNumber,
|
startColumn: 0,
|
endLineNumber: lineNumber,
|
endColumn: column
|
})
|
const words = textBeforePointer.trim().split(/\s+/)
|
const lastWord = words[words.length - 1]
|
|
if (lastWord.endsWith('.')) {
|
const tableName = lastWord.slice(0, lastWord.length - 1)
|
if (Object.keys(tables).includes(tableName)) {
|
suggestions = [...getFieldsSuggest(tableName)]
|
}
|
} else if (lastWord === '.') {
|
suggestions = []
|
} else {
|
suggestions = [...getTableSuggest(), ...getKeywordsSuggest()]
|
}
|
|
return {
|
suggestions
|
}
|
}
|
})
|
}
|
|
/**
|
* @description: 获取关键字的补全列表
|
*
|
*/
|
const getKeywordsSuggest = () => {
|
return keywords.map((key) => ({
|
label: key,
|
kind: monaco.languages.CompletionItemKind.Keyword,
|
insertText: key
|
}))
|
}
|
|
/**
|
* @description: 获取表名的补全列表
|
*/
|
const getTableSuggest = () => {
|
return Object.keys(tables).map((key) => ({
|
label: key,
|
kind: monaco.languages.CompletionItemKind.Variable,
|
insertText: key
|
}))
|
}
|
|
/**
|
* @description: 根据表名获取字段补全列表
|
* @param {*} tableName
|
*/
|
const getFieldsSuggest = (tableName) => {
|
const fields = tables[tableName]
|
if (!fields) {
|
return []
|
}
|
return fields.map((name) => ({
|
label: name,
|
kind: monaco.languages.CompletionItemKind.Field,
|
insertText: name
|
}))
|
}
|
|
/**
|
* 暴露给父组件的参数和方法 (外部需要什么,都可以从这里暴露出去)
|
*/
|
defineExpose({
|
init,
|
getValue,
|
});
|
|
</script>
|
|
<style lang="scss">
|
.app-monaco-sql {
|
.margin {
|
background: var(--el-color-primary-light-9);
|
}
|
|
.monaco-editor-background {
|
background: var(--el-color-primary-light-9);
|
}
|
}
|
</style>
|