You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

223 lines
5.3 KiB

<template>
<VueMonacoEditor
:options="options"
:defaultLanguage="language"
:onBeforeMount="onBeforeMount"
:onMount="onMount"
class="codeEditBox"
className="codeEditBox"
/>
</template>
<script>
import _ from 'lodash'
import { loader, VueMonacoEditor } from '@guolao/vue-monaco-editor'
import { setupMonacoEditor } from '@/core/script/ModelScript.js'
loader.config({
paths: {
vs: 'static/monaco-editor/min/vs'
},
'vs/nls': { availableLanguages: { '*': 'zh-cn' } }
})
export default {
props: {
modelValue: String,
language: String,
readonly: { defaults: false, required: false, type: Boolean },
lineNumbers: { defaults: true, required: false, type: Boolean },
expressMode: { defaults: false, required: false, type: Boolean }
},
components: {
VueMonacoEditor
},
emits: [
'update:modelValue',
'editor-mounted',
'change',
'editor-blur',
'editor-focus'
],
mounted() {
},
data() {
const option = {
value: this.modelValue,
language: this.language ?? 'javascript',
minimap: {
enabled: false
},
selectOnLineNumbers: true,
renderSideBySide: false,
automaticLayout: true,
// * 这个属性,允许悬浮的提示溢出到 dom 外
fixedOverflowWidgets: true,
allowEditorOverflow: false
}
if (!this.$props.lineNumbers) {
option.lineNumbers = 'off'
}
if (this.$props.expressMode === true) {
_.extend(option, {
lineNumbers: 'off',
hideCursorInOverviewRuler: true,
overviewRulerBorder: false,
glyphMargin: false,
lineDecorationsWidth: 0,
fontSize: '19px',
roundedSelection: false,
scrollBeyondLastLine: false,
disableMonospaceOptimizations: true,
readOnly: this.readonly
})
}
return {
options: option
// language: option.language,
}
},
watch: {
'modelValue': {
handler(newVal) {
if (!this.editor) {
return
}
if (newVal === this.editor.getValue()) {
// 防止递归
return
}
this.editor.setValue(newVal ?? '')
}
},
'language': {
handler(newVal) {
if (this.editor) {
this.setLanguage(newVal)
}
}
},
'loadTypeAction': {
handler(newVal) {
}
}
},
unmounted() {
if (this.editor) {
this.editor.dispose()
this.editor = null
}
},
methods: {
onBeforeMount(monaco) {
this.monaco = monaco
setupMonacoEditor(monaco)
},
onMount(editor, monaco) {
this.editor = editor
this.monaco = monaco
this.init()
},
focus() {
_.defer(() => {
this.editor?.focus()
})
},
insertText(text) {
if (!this.editor) {
return
}
const position = this.editor.getPosition()
this.editor.executeEdits('', [{
range: new this.monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column),
text: text,
forceMoveMarkers: true
}])
},
scrollToButtom() {
this.editor?.revealLine(this.editor.getModel().getLineCount())
},
appendText(text) {
this.editor?.getModel().pushEditOperations(
[],
[
{
range: new monaco.Range(1, 1, 1, 1),
text: text
}
],
() => null
)
},
clear(){
if (this.editor) {
this.editor.setValue('')
this.$emit('update:modelValue', '')
this.$emit('change', '')
}
},
init() {
// this.editor.updateOptions(option);
this.editor.setValue(this.modelValue ?? '')
// 监听值的变化
this.editor.onDidChangeModelContent(() => {
const value = this.editor.getValue() // 给父组件实时返回最新文本
this.$emit('update:modelValue', value)
this.$emit('change', value)
})
this.editor.onDidBlurEditorWidget((e) => {
this.$emit('editor-blur', e)
})
this.editor.onDidFocusEditorWidget((e) => {
this.$emit('editor-focus', e)
})
if (this.language === 'typescript' || this.language === 'javascript') {
this.editor.onDidFocusEditorWidget(() => {
window['editor'] = this.editor
window['monaco'] = this.monaco
})
const monaco = this.monaco
const editor = this.editor
editor.addCommand(
monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.KeyL,
() => editor.getAction('editor.action.formatDocument')?.run()
)
}
this.$emit('editor-mounted', this.editor)
// .monacoInitFinished()
},
updateOptions(options) {
if (this.editor && options) {
this.editor.updateOptions(options)
}
},
setLanguage(lang) {
if (this.editor && lang) {
this.monaco.editor.setModelLanguage(this.editor.getModel(), lang)
}
}
}
}
</script>
<style lang="less">
.codeEditBox {
width: 100%;
flex: 1;
overflow-y: auto;
border: 1px solid #ccc;
.monaco-editor .suggest-widget .monaco-list .monaco-list-row > .contents > .main {
flex-direction: row;
font-size: 14px;
}
.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon {
height: 18px;
}
}
</style>