git-proxy / src /components /MonacoEditor.vue
github-actions[bot]
Update from GitHub Actions
15ff6c7
raw
history blame
4.13 kB
<template>
<div ref="editorContainer" class="h-full"></div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, onBeforeUnmount } from 'vue';
import monaco from '@monaco-editor/loader';
const props = defineProps<{
value: string,
originalValue?: string,
language?: string,
options?: Record<string, any>,
}>();
const emit = defineEmits(['update:value']);
const editorContainer = ref<HTMLElement>();
let editorInstance: any = null;
let monacoInstance: any = null;
let editorModel: any = null;
// 创建编辑器的函数
const createEditor = () => {
if (!editorContainer.value || !monacoInstance) return;
// 如果已存在编辑器实例,先销毁
if (editorInstance) {
editorInstance.dispose();
editorInstance = null;
}
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
const commonOptions = {
language: props.language || 'json',
minimap: { enabled: !isMobile },
fontSize: isMobile ? 16 : 14,
lineNumbers: isMobile ? 'off' as const : 'on' as const,
scrollBeyondLastLine: false,
automaticLayout: true,
...props.options
};
// 每次都创建新模型,确保内容刷新
if (editorModel) {
editorModel.dispose();
}
editorModel = monacoInstance.editor.createModel(props.value, props.language);
if (props.originalValue !== undefined) {
// 创建差异编辑器
const originalModel = monacoInstance.editor.createModel(props.originalValue, props.language);
editorInstance = monacoInstance.editor.createDiffEditor(editorContainer.value, {
...commonOptions,
readOnly: false,
renderSideBySide: true,
ignoreTrimWhitespace: false,
renderOverviewRuler: true,
diffWordWrap: 'on',
});
editorInstance.setModel({
original: originalModel,
modified: editorModel
});
const modifiedEditor = editorInstance.getModifiedEditor();
modifiedEditor.onDidChangeModelContent(() => {
emit('update:value', modifiedEditor.getValue());
});
} else {
// 创建普通编辑器
editorInstance = monacoInstance.editor.create(editorContainer.value, {
...commonOptions,
model: editorModel
});
editorInstance.onDidChangeModelContent(() => {
emit('update:value', editorInstance.getValue());
});
}
};
onMounted(() => {
monaco.init().then(instance => {
monacoInstance = instance;
createEditor();
});
});
// 监听 value, originalValue 和 language 的变化
watch([() => props.value, () => props.originalValue, () => props.language], ([newVal, newOriginalVal, newLanguage], [oldVal, oldOriginalVal]) => {
// 判断是否需要重建编辑器
const modeChanged =
(oldOriginalVal === undefined && newOriginalVal !== undefined) ||
(oldOriginalVal !== undefined && newOriginalVal === undefined);
if (modeChanged || oldVal === undefined) {
// 编辑器模式变化或首次加载,重新创建
createEditor();
} else if (props.language && editorModel && editorModel.getLanguageId() !== props.language) {
// 语言改变时,更新模型的语言
monacoInstance.editor.setModelLanguage(editorModel, props.language);
} else if (editorInstance) {
if (props.originalValue !== undefined) {
// 差异模式下更新内容
const model = editorInstance.getModel();
if (model && model.original && model.original.getValue() !== newOriginalVal) {
model.original.setValue(newOriginalVal || '');
}
if (model && model.modified && model.modified.getValue() !== newVal) {
model.modified.setValue(newVal || '');
}
} else {
// 普通模式下更新内容
if (editorInstance.getValue() !== newVal) {
editorInstance.setValue(newVal || '');
}
}
}
}, { deep: true });
onBeforeUnmount(() => {
if (editorInstance) {
editorInstance.dispose();
}
if (editorModel) {
editorModel.dispose();
}
editorInstance = null;
editorModel = null;
});
</script>
<style scoped>
:deep(.monaco-diff-editor),
:deep(.monaco-editor) {
height: 100%;
}
</style>