Merge pull request #467 from lt5227/feat/CodeEditor
feat: Add a new component CodeEditor (#466)
This commit is contained in:
commit
01ab895667
|
@ -202,6 +202,14 @@ const adminList = [
|
||||||
meta: {
|
meta: {
|
||||||
title: 'router.jsonEditor'
|
title: 'router.jsonEditor'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'code-editor',
|
||||||
|
component: 'views/Components/Editor/CodeEditor',
|
||||||
|
name: 'CodeEditor',
|
||||||
|
meta: {
|
||||||
|
title: 'router.codeEditor'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -687,6 +695,7 @@ const testList: string[] = [
|
||||||
'/components/editor-demo',
|
'/components/editor-demo',
|
||||||
'/components/editor-demo/editor',
|
'/components/editor-demo/editor',
|
||||||
'/components/editor-demo/json-editor',
|
'/components/editor-demo/json-editor',
|
||||||
|
'/components/editor-demo/code-editor',
|
||||||
'/components/search',
|
'/components/search',
|
||||||
'/components/descriptions',
|
'/components/descriptions',
|
||||||
'/components/image-viewer',
|
'/components/image-viewer',
|
||||||
|
|
|
@ -55,7 +55,8 @@
|
||||||
"vue-json-pretty": "^2.4.0",
|
"vue-json-pretty": "^2.4.0",
|
||||||
"vue-router": "^4.3.0",
|
"vue-router": "^4.3.0",
|
||||||
"vue-types": "^5.1.1",
|
"vue-types": "^5.1.1",
|
||||||
"xgplayer": "^3.0.14"
|
"xgplayer": "^3.0.14",
|
||||||
|
"monaco-editor": "^0.48.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^19.2.1",
|
"@commitlint/cli": "^19.2.1",
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import CodeEditor from './src/CodeEditor.vue'
|
||||||
|
|
||||||
|
export { CodeEditor }
|
|
@ -0,0 +1,119 @@
|
||||||
|
<script setup lang="tsx">
|
||||||
|
import { useMonacoEditor } from '@/hooks/web/useMonacoEditor'
|
||||||
|
import { onMounted, computed, watch, ref } from 'vue'
|
||||||
|
import { ElSelect, ElOption, ElFormItem, ElForm } from 'element-plus'
|
||||||
|
import { languageOptions, themeOptions } from './config/config'
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
width?: string | number
|
||||||
|
height?: string | number
|
||||||
|
languageSelector?: boolean
|
||||||
|
language?: string
|
||||||
|
themeSelector?: boolean
|
||||||
|
theme?: string
|
||||||
|
editorOption?: Object
|
||||||
|
modelValue: string
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
languageSelector: true,
|
||||||
|
language: 'javascript',
|
||||||
|
themeSelector: true,
|
||||||
|
theme: 'vs-dark',
|
||||||
|
editorOption: () => ({}),
|
||||||
|
modelValue: ''
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'blur'): void
|
||||||
|
(e: 'update:modelValue', val: string): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const monacoEditorStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
width: typeof props.width === 'string' ? props.width : props.width + 'px',
|
||||||
|
height: typeof props.height === 'string' ? props.height : props.height + 'px'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const {
|
||||||
|
monacoEditorRef,
|
||||||
|
createEditor,
|
||||||
|
updateVal,
|
||||||
|
updateOptions,
|
||||||
|
getEditor,
|
||||||
|
changeLanguage,
|
||||||
|
changeTheme
|
||||||
|
} = useMonacoEditor(props.language)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const monacoEditor = createEditor(props.editorOption)
|
||||||
|
updateMonacoVal(props.modelValue)
|
||||||
|
monacoEditor?.onDidChangeModelContent(() => {
|
||||||
|
emits('update:modelValue', monacoEditor!.getValue())
|
||||||
|
})
|
||||||
|
monacoEditor?.onDidBlurEditorText(() => {
|
||||||
|
emits('blur')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
() => {
|
||||||
|
updateMonacoVal(props.modelValue)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const localLanguage = ref(props.language)
|
||||||
|
|
||||||
|
watch(localLanguage, (newLanguage) => {
|
||||||
|
changeLanguage(newLanguage)
|
||||||
|
})
|
||||||
|
|
||||||
|
const localTheme = ref(props.theme)
|
||||||
|
watch(localTheme, (newTheme) => {
|
||||||
|
changeTheme(newTheme)
|
||||||
|
})
|
||||||
|
|
||||||
|
function updateMonacoVal(val: string) {
|
||||||
|
if (val !== getEditor()?.getValue()) {
|
||||||
|
updateVal(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ updateOptions })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ElForm :inline="true">
|
||||||
|
<ElFormItem v-if="languageSelector" label="language" class="w-30% mb-5px!">
|
||||||
|
<ElSelect
|
||||||
|
v-model="localLanguage"
|
||||||
|
placeholder="Please select language"
|
||||||
|
size="small"
|
||||||
|
filterable
|
||||||
|
>
|
||||||
|
<ElOption
|
||||||
|
v-for="item in languageOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</ElFormItem>
|
||||||
|
<ElFormItem v-if="themeSelector" label="theme" class="w-30% mb-5px!">
|
||||||
|
<ElSelect v-model="localTheme" placeholder="Please select language" size="small" filterable>
|
||||||
|
<ElOption
|
||||||
|
v-for="item in themeOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</ElFormItem>
|
||||||
|
</ElForm>
|
||||||
|
<div ref="monacoEditorRef" :style="monacoEditorStyle"></div>
|
||||||
|
</template>
|
|
@ -0,0 +1,129 @@
|
||||||
|
export const languageOptions = [
|
||||||
|
{ label: 'plaintext', value: 'plaintext' },
|
||||||
|
{ label: 'abap', value: 'abap' },
|
||||||
|
{ label: 'apex', value: 'apex' },
|
||||||
|
{ label: 'azcli', value: 'azcli' },
|
||||||
|
{ label: 'bat', value: 'bat' },
|
||||||
|
{ label: 'bicep', value: 'bicep' },
|
||||||
|
{ label: 'cameligo', value: 'cameligo' },
|
||||||
|
{ label: 'clojure', value: 'clojure' },
|
||||||
|
{ label: 'coffeescript', value: 'coffeescript' },
|
||||||
|
{ label: 'c', value: 'c' },
|
||||||
|
{ label: 'cpp', value: 'cpp' },
|
||||||
|
{ label: 'csharp', value: 'csharp' },
|
||||||
|
{ label: 'csp', value: 'csp' },
|
||||||
|
{ label: 'css', value: 'css' },
|
||||||
|
{ label: 'cypher', value: 'cypher' },
|
||||||
|
{ label: 'dart', value: 'dart' },
|
||||||
|
{ label: 'dockerfile', value: 'dockerfile' },
|
||||||
|
{ label: 'ecl', value: 'ecl' },
|
||||||
|
{ label: 'elixir', value: 'elixir' },
|
||||||
|
{ label: 'flow9', value: 'flow9' },
|
||||||
|
{ label: 'fsharp', value: 'fsharp' },
|
||||||
|
{ label: 'freemarker2', value: 'freemarker2' },
|
||||||
|
{
|
||||||
|
label: 'freemarker2.tag-angle.interpolation-dollar',
|
||||||
|
value: 'freemarker2.tag-angle.interpolation-dollar'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'freemarker2.tag-bracket.interpolation-dollar',
|
||||||
|
value: 'freemarker2.tag-bracket.interpolation-dollar'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'freemarker2.tag-angle.interpolation-bracket',
|
||||||
|
value: 'freemarker2.tag-angle.interpolation-bracket'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'freemarker2.tag-bracket.interpolation-bracket',
|
||||||
|
value: 'freemarker2.tag-bracket.interpolation-bracket'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'freemarker2.tag-auto.interpolation-dollar',
|
||||||
|
value: 'freemarker2.tag-auto.interpolation-dollar'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'freemarker2.tag-auto.interpolation-bracket',
|
||||||
|
value: 'freemarker2.tag-auto.interpolation-bracket'
|
||||||
|
},
|
||||||
|
{ label: 'go', value: 'go' },
|
||||||
|
{ label: 'graphql', value: 'graphql' },
|
||||||
|
{ label: 'handlebars', value: 'handlebars' },
|
||||||
|
{ label: 'hcl', value: 'hcl' },
|
||||||
|
{ label: 'html', value: 'html' },
|
||||||
|
{ label: 'ini', value: 'ini' },
|
||||||
|
{ label: 'java', value: 'java' },
|
||||||
|
{ label: 'javascript', value: 'javascript' },
|
||||||
|
{ label: 'julia', value: 'julia' },
|
||||||
|
{ label: 'kotlin', value: 'kotlin' },
|
||||||
|
{ label: 'less', value: 'less' },
|
||||||
|
{ label: 'lexon', value: 'lexon' },
|
||||||
|
{ label: 'lua', value: 'lua' },
|
||||||
|
{ label: 'liquid', value: 'liquid' },
|
||||||
|
{ label: 'm3', value: 'm3' },
|
||||||
|
{ label: 'markdown', value: 'markdown' },
|
||||||
|
{ label: 'mdx', value: 'mdx' },
|
||||||
|
{ label: 'mips', value: 'mips' },
|
||||||
|
{ label: 'msdax', value: 'msdax' },
|
||||||
|
{ label: 'mysql', value: 'mysql' },
|
||||||
|
{ label: 'objective-c', value: 'objective-c' },
|
||||||
|
{ label: 'pascal', value: 'pascal' },
|
||||||
|
{ label: 'pascaligo', value: 'pascaligo' },
|
||||||
|
{ label: 'perl', value: 'perl' },
|
||||||
|
{ label: 'pgsql', value: 'pgsql' },
|
||||||
|
{ label: 'php', value: 'php' },
|
||||||
|
{ label: 'pla', value: 'pla' },
|
||||||
|
{ label: 'postiats', value: 'postiats' },
|
||||||
|
{ label: 'powerquery', value: 'powerquery' },
|
||||||
|
{ label: 'powershell', value: 'powershell' },
|
||||||
|
{ label: 'proto', value: 'proto' },
|
||||||
|
{ label: 'pug', value: 'pug' },
|
||||||
|
{ label: 'python', value: 'python' },
|
||||||
|
{ label: 'qsharp', value: 'qsharp' },
|
||||||
|
{ label: 'r', value: 'r' },
|
||||||
|
{ label: 'razor', value: 'razor' },
|
||||||
|
{ label: 'redis', value: 'redis' },
|
||||||
|
{ label: 'redshift', value: 'redshift' },
|
||||||
|
{ label: 'restructuredtext', value: 'restructuredtext' },
|
||||||
|
{ label: 'ruby', value: 'ruby' },
|
||||||
|
{ label: 'rust', value: 'rust' },
|
||||||
|
{ label: 'sb', value: 'sb' },
|
||||||
|
{ label: 'scala', value: 'scala' },
|
||||||
|
{ label: 'scheme', value: 'scheme' },
|
||||||
|
{ label: 'scss', value: 'scss' },
|
||||||
|
{ label: 'shell', value: 'shell' },
|
||||||
|
{ label: 'sol', value: 'sol' },
|
||||||
|
{ label: 'aes', value: 'aes' },
|
||||||
|
{ label: 'sparql', value: 'sparql' },
|
||||||
|
{ label: 'sql', value: 'sql' },
|
||||||
|
{ label: 'st', value: 'st' },
|
||||||
|
{ label: 'swift', value: 'swift' },
|
||||||
|
{ label: 'systemverilog', value: 'systemverilog' },
|
||||||
|
{ label: 'verilog', value: 'verilog' },
|
||||||
|
{ label: 'tcl', value: 'tcl' },
|
||||||
|
{ label: 'twig', value: 'twig' },
|
||||||
|
{ label: 'typescript', value: 'typescript' },
|
||||||
|
{ label: 'vb', value: 'vb' },
|
||||||
|
{ label: 'wgsl', value: 'wgsl' },
|
||||||
|
{ label: 'xml', value: 'xml' },
|
||||||
|
{ label: 'yaml', value: 'yaml' },
|
||||||
|
{ label: 'json', value: 'json' }
|
||||||
|
]
|
||||||
|
|
||||||
|
export const themeOptions = [
|
||||||
|
{
|
||||||
|
label: 'vs',
|
||||||
|
value: 'vs'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'vs-dark',
|
||||||
|
value: 'vs-dark'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'hc-black',
|
||||||
|
value: 'hc-black'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'hc-light',
|
||||||
|
value: 'hc-light'
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,129 @@
|
||||||
|
import * as monaco from 'monaco-editor'
|
||||||
|
import { ref, nextTick, onBeforeUnmount } from 'vue'
|
||||||
|
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
|
||||||
|
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
|
||||||
|
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
|
||||||
|
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
|
||||||
|
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
|
||||||
|
|
||||||
|
self.MonacoEnvironment = {
|
||||||
|
getWorker(_, label) {
|
||||||
|
if (label === 'json') {
|
||||||
|
return new jsonWorker()
|
||||||
|
}
|
||||||
|
if (label === 'css' || label === 'scss' || label === 'less') {
|
||||||
|
return new cssWorker()
|
||||||
|
}
|
||||||
|
if (label === 'html' || label === 'handlebars' || label === 'razor') {
|
||||||
|
return new htmlWorker()
|
||||||
|
}
|
||||||
|
if (label === 'typescript' || label === 'javascript') {
|
||||||
|
return new tsWorker()
|
||||||
|
}
|
||||||
|
return new editorWorker()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useMonacoEditor(language: string = 'javascript') {
|
||||||
|
// 编辑器示例
|
||||||
|
let monacoEditor: monaco.editor.IStandaloneCodeEditor | null = null
|
||||||
|
// 目标元素
|
||||||
|
const monacoEditorRef = ref<HTMLElement>()
|
||||||
|
|
||||||
|
// 创建实例
|
||||||
|
function createEditor(editorOption: monaco.editor.IStandaloneEditorConstructionOptions = {}) {
|
||||||
|
if (!monacoEditorRef.value) return
|
||||||
|
monacoEditor = monaco.editor.create(monacoEditorRef.value, {
|
||||||
|
// 初始模型
|
||||||
|
model: monaco.editor.createModel('', language),
|
||||||
|
// 是否启用预览图
|
||||||
|
minimap: { enabled: true },
|
||||||
|
// 圆角
|
||||||
|
roundedSelection: true,
|
||||||
|
// 主题
|
||||||
|
theme: 'vs-dark',
|
||||||
|
// 主键
|
||||||
|
multiCursorModifier: 'ctrlCmd',
|
||||||
|
// 滚动条
|
||||||
|
scrollbar: {
|
||||||
|
verticalScrollbarSize: 8,
|
||||||
|
horizontalScrollbarSize: 8
|
||||||
|
},
|
||||||
|
// 行号
|
||||||
|
lineNumbers: 'on',
|
||||||
|
// tab大小
|
||||||
|
tabSize: 2,
|
||||||
|
//字体大小
|
||||||
|
fontSize: 14,
|
||||||
|
// 控制编辑器在用户键入、粘贴、移动或缩进行时是否应自动调整缩进
|
||||||
|
autoIndent: 'advanced',
|
||||||
|
// 自动布局
|
||||||
|
automaticLayout: true,
|
||||||
|
...editorOption
|
||||||
|
})
|
||||||
|
return monacoEditor
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化
|
||||||
|
async function formatDoc() {
|
||||||
|
await monacoEditor?.getAction('editor.action.formatDocument')?.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据更新
|
||||||
|
function updateVal(val: string) {
|
||||||
|
nextTick(() => {
|
||||||
|
if (getOption(monaco.editor.EditorOption.readOnly)) {
|
||||||
|
updateOptions({ readOnly: false })
|
||||||
|
}
|
||||||
|
monacoEditor?.setValue(val)
|
||||||
|
setTimeout(async () => {
|
||||||
|
await formatDoc()
|
||||||
|
}, 10)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置更新
|
||||||
|
function updateOptions(opt: monaco.editor.IStandaloneEditorConstructionOptions) {
|
||||||
|
monacoEditor?.updateOptions(opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取配置
|
||||||
|
function getOption(name: monaco.editor.EditorOption) {
|
||||||
|
return monacoEditor?.getOption(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取实例
|
||||||
|
function getEditor() {
|
||||||
|
return monacoEditor
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeLanguage(newLanguage: string) {
|
||||||
|
const model = monacoEditor?.getModel()
|
||||||
|
if (model) {
|
||||||
|
monaco.editor.setModelLanguage(model, newLanguage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeTheme(newTheme: string) {
|
||||||
|
monaco.editor.setTheme(newTheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面离开 销毁
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (monacoEditor) {
|
||||||
|
monacoEditor.dispose()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
monacoEditorRef,
|
||||||
|
createEditor,
|
||||||
|
getEditor,
|
||||||
|
updateVal,
|
||||||
|
updateOptions,
|
||||||
|
getOption,
|
||||||
|
formatDoc,
|
||||||
|
changeLanguage,
|
||||||
|
changeTheme
|
||||||
|
}
|
||||||
|
}
|
|
@ -153,6 +153,7 @@ export default {
|
||||||
editor: 'Editor',
|
editor: 'Editor',
|
||||||
richText: 'Rich text',
|
richText: 'Rich text',
|
||||||
jsonEditor: 'JSON Editor',
|
jsonEditor: 'JSON Editor',
|
||||||
|
codeEditor: 'Code Editor',
|
||||||
dialog: 'Dialog',
|
dialog: 'Dialog',
|
||||||
imageViewer: 'Image viewer',
|
imageViewer: 'Image viewer',
|
||||||
descriptions: 'Descriptions',
|
descriptions: 'Descriptions',
|
||||||
|
@ -473,7 +474,9 @@ export default {
|
||||||
richText: 'Rich text',
|
richText: 'Rich text',
|
||||||
richTextDes: 'Secondary packaging based on wangeditor',
|
richTextDes: 'Secondary packaging based on wangeditor',
|
||||||
jsonEditor: 'JSON Editor',
|
jsonEditor: 'JSON Editor',
|
||||||
jsonEditorDes: 'Secondary packaging based on vue-json-pretty'
|
jsonEditorDes: 'Secondary packaging based on vue-json-pretty',
|
||||||
|
codeEditor: 'Code Editor',
|
||||||
|
codeEditorDes: 'Secondary packaging based on monaco-editor'
|
||||||
},
|
},
|
||||||
dialogDemo: {
|
dialogDemo: {
|
||||||
dialog: 'Dialog',
|
dialog: 'Dialog',
|
||||||
|
|
|
@ -151,6 +151,7 @@ export default {
|
||||||
editor: '编辑器',
|
editor: '编辑器',
|
||||||
richText: '富文本',
|
richText: '富文本',
|
||||||
jsonEditor: 'JSON编辑器',
|
jsonEditor: 'JSON编辑器',
|
||||||
|
codeEditor: '代码编辑器',
|
||||||
dialog: '弹窗',
|
dialog: '弹窗',
|
||||||
imageViewer: '图片预览',
|
imageViewer: '图片预览',
|
||||||
descriptions: '描述',
|
descriptions: '描述',
|
||||||
|
@ -464,7 +465,9 @@ export default {
|
||||||
richText: '富文本',
|
richText: '富文本',
|
||||||
richTextDes: '基于 wangeditor 二次封装',
|
richTextDes: '基于 wangeditor 二次封装',
|
||||||
jsonEditor: 'JSON编辑器',
|
jsonEditor: 'JSON编辑器',
|
||||||
jsonEditorDes: '基于 vue-json-pretty 二次封装'
|
jsonEditorDes: '基于 vue-json-pretty 二次封装',
|
||||||
|
codeEditor: '代码编辑器',
|
||||||
|
codeEditorDes: '基于 monaco-editor 二次封装'
|
||||||
},
|
},
|
||||||
dialogDemo: {
|
dialogDemo: {
|
||||||
dialog: '弹窗',
|
dialog: '弹窗',
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script setup lang="tsx">
|
||||||
|
import { CodeEditor } from '@/components/CodeEditor'
|
||||||
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { BaseButton } from '@/components/Button'
|
||||||
|
import { ElDivider } from 'element-plus'
|
||||||
|
const content = ref(
|
||||||
|
'public class HelloWorld {\n public static void main(String[] args) {\n System.out.println("Hello, World!");\n }\n}'
|
||||||
|
)
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const MonacoEditRef = ref<InstanceType<typeof CodeEditor>>()
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<ContentWrap :title="t('richText.codeEditor')" :message="t('richText.codeEditorDes')">
|
||||||
|
<BaseButton @click="console.log(content)">控制台打印内容</BaseButton>
|
||||||
|
<ElDivider />
|
||||||
|
<div class="edit-container h-60vh">
|
||||||
|
<CodeEditor ref="MonacoEditRef" v-model="content" language="java" />
|
||||||
|
</div>
|
||||||
|
</ContentWrap>
|
||||||
|
</template>
|
Loading…
Reference in New Issue