115 lines
2.7 KiB
Vue
115 lines
2.7 KiB
Vue
<script lang="ts" setup>
|
|
import loader, { Monaco } from "@monaco-editor/loader"
|
|
import {
|
|
LANGUAGE_LABEL,
|
|
LANGUAGE_VALUE,
|
|
SOURCES,
|
|
} from "../../../utils/constants"
|
|
import { isMobile } from "../../../utils/breakpoints"
|
|
import { Problem } from "../../../utils/types"
|
|
import EditorExec from "./editor-exec.vue"
|
|
|
|
interface Props {
|
|
problem: Problem
|
|
}
|
|
|
|
const props = defineProps<Props>()
|
|
const code = reactive({
|
|
value: SOURCES[props.problem.languages[0] || "C"],
|
|
language: props.problem.languages[0] || "C",
|
|
})
|
|
provide("code", code)
|
|
|
|
const monacoEditorRef = ref()
|
|
|
|
let monaco: Monaco
|
|
|
|
onMounted(() => {
|
|
init()
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
monaco.editor.getModels().forEach((model) => model.dispose())
|
|
})
|
|
|
|
watch(
|
|
() => code.language,
|
|
() => {
|
|
if (monaco && monaco.editor) {
|
|
monaco.editor.setModelLanguage(
|
|
monaco.editor.getModels()[0],
|
|
LANGUAGE_VALUE[code.language]
|
|
)
|
|
reset()
|
|
}
|
|
}
|
|
)
|
|
|
|
function reset() {
|
|
code.value = props.problem.template[code.language] || SOURCES[code.language]
|
|
if (monaco && monaco.editor) {
|
|
monaco.editor.getModels()[0].setValue(code.value)
|
|
}
|
|
}
|
|
|
|
async function init() {
|
|
code.value = props.problem.template[code.language] || SOURCES[code.language]
|
|
monaco = await loader.init()
|
|
monaco.editor.create(monacoEditorRef.value, {
|
|
value: code.value, // 编辑器初始显示文字
|
|
language: LANGUAGE_VALUE[code.language],
|
|
theme: "vs-dark", // 官方自带三种主题vs, hc-black, or vs-dark
|
|
minimap: {
|
|
enabled: false,
|
|
},
|
|
lineNumbersMinChars: 3,
|
|
automaticLayout: true, // 自适应布局
|
|
tabSize: 4,
|
|
fontSize: isMobile.value ? 20 : 24, // 字体大小
|
|
scrollBeyondLastLine: false, // 取消代码后面一大段空白
|
|
})
|
|
monaco.editor.getModels()[0].onDidChangeContent(() => {
|
|
code.value = monaco.editor.getModels()[0].getValue()
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<el-form inline>
|
|
<el-form-item label="语言" label-width="60">
|
|
<el-select v-model="code.language" class="language">
|
|
<el-option
|
|
v-for="item in problem.languages"
|
|
:key="item"
|
|
:value="item"
|
|
:label="LANGUAGE_LABEL[item]"
|
|
>
|
|
</el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button @click="reset">重置</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
<section
|
|
ref="monacoEditorRef"
|
|
:class="isMobile ? 'editorMobile' : 'editor'"
|
|
></section>
|
|
<EditorExec />
|
|
</template>
|
|
|
|
<style scoped>
|
|
.language {
|
|
width: 100px;
|
|
}
|
|
|
|
.editor {
|
|
/* 141px+400 */
|
|
height: calc(100vh - 541px);
|
|
}
|
|
|
|
.editorMobile {
|
|
height: 500px;
|
|
}
|
|
</style>
|