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
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>
|
|
|