108 lines
2.4 KiB
Vue
108 lines
2.4 KiB
Vue
<script setup lang="ts">
|
|
import type * as Monaco from "monaco-editor"
|
|
import loader from "@monaco-editor/loader"
|
|
import { LANGUAGE_VALUE } from "../../utils/constants"
|
|
import { LANGUAGE } from "../../utils/types"
|
|
import { isMobile } from "../../utils/breakpoints"
|
|
|
|
interface Props {
|
|
value: string
|
|
language?: LANGUAGE
|
|
height?: string
|
|
fontSize?: number
|
|
class?: string
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
language: "C",
|
|
height: "calc(100vh - 100px)",
|
|
fontSize: 20,
|
|
class: "",
|
|
})
|
|
|
|
const emit = defineEmits<{
|
|
(e: "change", value: string): void
|
|
}>()
|
|
|
|
const monacoEditorRef = ref()
|
|
let editor: Monaco.editor.IStandaloneCodeEditor | null
|
|
|
|
onMounted(async function () {
|
|
const monaco = await loader.init()
|
|
|
|
const model = monaco.editor.createModel(
|
|
props.value,
|
|
LANGUAGE_VALUE[props.language],
|
|
monaco.Uri.parse(`file:///root/${Date.now()}.${ext()}`)
|
|
)
|
|
|
|
editor = monaco.editor.create(monacoEditorRef.value, {
|
|
model,
|
|
theme: "vs-dark", // 官方自带三种主题vs, hc-black, or vs-dark
|
|
minimap: {
|
|
enabled: false,
|
|
},
|
|
lineNumbersMinChars: 3,
|
|
automaticLayout: true, // 自适应布局
|
|
tabSize: 4,
|
|
fontSize: isMobile.value ? 20 : 24, // 字体大小
|
|
})
|
|
|
|
model.onDidChangeContent(() => {
|
|
const value = model.getValue().toString()
|
|
emit("change", value)
|
|
})
|
|
|
|
editor.onKeyDown((e) => {
|
|
if ((e.ctrlKey || e.metaKey) && e.code === "KeyS") {
|
|
e.preventDefault()
|
|
}
|
|
if ((e.ctrlKey || e.metaKey) && e.code === "KeyR") {
|
|
e.preventDefault()
|
|
}
|
|
})
|
|
|
|
watchEffect(() => {
|
|
monaco.editor.setModelLanguage(model, LANGUAGE_VALUE[props.language])
|
|
})
|
|
|
|
watchEffect(() => {
|
|
if (props.value !== model.getValue()) {
|
|
console.log(666)
|
|
model.setValue(props.value)
|
|
}
|
|
})
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
editor && editor.dispose()
|
|
})
|
|
|
|
function ext() {
|
|
switch (props.language) {
|
|
case "C":
|
|
return "c"
|
|
case "C++":
|
|
return "cpp"
|
|
case "Java":
|
|
return "java"
|
|
case "JavaScript":
|
|
return "js"
|
|
case "Python2":
|
|
return "py"
|
|
case "Python3":
|
|
return "py"
|
|
case "Golang":
|
|
return "go"
|
|
}
|
|
}
|
|
</script>
|
|
<template>
|
|
<div
|
|
ref="monacoEditorRef"
|
|
:class="props.class"
|
|
:style="{ height: props.height }"
|
|
></div>
|
|
</template>
|
|
<style scoped></style>
|