|
| 1 | +<template> |
| 2 | + <div ref="containerRef" :style="{ width: width, height: height, border: '1px solid #ddd', borderRadius: '4px' }"></div> |
| 3 | +</template> |
| 4 | + |
| 5 | +<script setup lang="ts"> |
| 6 | +import { ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue' |
| 7 | +import loader from '@monaco-editor/loader' |
| 8 | +
|
| 9 | +const props = withDefaults(defineProps<{ |
| 10 | + modelValue?: string |
| 11 | + language?: string |
| 12 | + theme?: string |
| 13 | + width?: string |
| 14 | + height?: string |
| 15 | + readOnly?: boolean |
| 16 | +}>(), { |
| 17 | + modelValue: '', |
| 18 | + language: 'javascript', |
| 19 | + theme: 'vs-dark', |
| 20 | + width: '100%', |
| 21 | + height: '300px', |
| 22 | + readOnly: false |
| 23 | +}) |
| 24 | +
|
| 25 | +const emit = defineEmits<{ (e: 'update:modelValue', val: string): void }>() |
| 26 | +
|
| 27 | +const containerRef = ref<HTMLElement>() |
| 28 | +let monacoEditor: any = null |
| 29 | +
|
| 30 | +onMounted(async () => { |
| 31 | + // 配置 Monaco loader 使用 CDN(可自行更换为本地路径) |
| 32 | + loader.config({ paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs' } }) |
| 33 | +
|
| 34 | + await nextTick() |
| 35 | + const monaco = await loader.init() |
| 36 | +
|
| 37 | + monacoEditor = monaco.editor.create(containerRef.value!, { |
| 38 | + value: props.modelValue, |
| 39 | + language: props.language, |
| 40 | + theme: props.theme, |
| 41 | + readOnly: props.readOnly, |
| 42 | + automaticLayout: true, |
| 43 | + minimap: { enabled: false }, |
| 44 | + fontSize: 13, |
| 45 | + lineNumbers: 'on', |
| 46 | + scrollBeyondLastLine: false, |
| 47 | + wordWrap: 'on', |
| 48 | + tabSize: 2, |
| 49 | + // 代码提示:$var / $static 对象 |
| 50 | + suggestOnTriggerCharacters: true |
| 51 | + }) |
| 52 | +
|
| 53 | + // 注册 Juggle JS 变量提示 |
| 54 | + monaco.languages.registerCompletionItemProvider('javascript', { |
| 55 | + provideCompletionItems: (model: any, position: any) => { |
| 56 | + const word = model.getWordUntilPosition(position) |
| 57 | + const range = { |
| 58 | + startLineNumber: position.lineNumber, |
| 59 | + endLineNumber: position.lineNumber, |
| 60 | + startColumn: word.startColumn, |
| 61 | + endColumn: word.endColumn |
| 62 | + } |
| 63 | + return { |
| 64 | + suggestions: [ |
| 65 | + { label: '$var.getVariableValue', kind: monaco.languages.CompletionItemKind.Function, |
| 66 | + insertText: "$var.getVariableValue('${1:varName}')", insertTextRules: 4, |
| 67 | + documentation: '获取流程变量值', range }, |
| 68 | + { label: '$var.setVariableValue', kind: monaco.languages.CompletionItemKind.Function, |
| 69 | + insertText: "$var.setVariableValue('${1:varName}', ${2:value})", insertTextRules: 4, |
| 70 | + documentation: '设置流程变量值', range }, |
| 71 | + { label: '$static.getVariableValue', kind: monaco.languages.CompletionItemKind.Function, |
| 72 | + insertText: "$static.getVariableValue('${1:varCode}')", insertTextRules: 4, |
| 73 | + documentation: '获取全局静态变量', range }, |
| 74 | + { label: '$static.setVariableValue', kind: monaco.languages.CompletionItemKind.Function, |
| 75 | + insertText: "$static.setVariableValue('${1:varCode}', ${2:value})", insertTextRules: 4, |
| 76 | + documentation: '设置全局静态变量', range }, |
| 77 | + { label: 'JSON.parse', kind: monaco.languages.CompletionItemKind.Function, |
| 78 | + insertText: 'JSON.parse(${1:str})', insertTextRules: 4, range }, |
| 79 | + { label: 'JSON.stringify', kind: monaco.languages.CompletionItemKind.Function, |
| 80 | + insertText: 'JSON.stringify(${1:obj})', insertTextRules: 4, range } |
| 81 | + ] |
| 82 | + } |
| 83 | + } |
| 84 | + }) |
| 85 | +
|
| 86 | + monacoEditor.onDidChangeModelContent(() => { |
| 87 | + emit('update:modelValue', monacoEditor.getValue()) |
| 88 | + }) |
| 89 | +}) |
| 90 | +
|
| 91 | +watch(() => props.modelValue, (newVal) => { |
| 92 | + if (monacoEditor && monacoEditor.getValue() !== newVal) { |
| 93 | + monacoEditor.setValue(newVal) |
| 94 | + } |
| 95 | +}) |
| 96 | +
|
| 97 | +onBeforeUnmount(() => { |
| 98 | + monacoEditor?.dispose() |
| 99 | +}) |
| 100 | +</script> |
0 commit comments