zhemima/msmail
0
1<template>2 <div ref="editorContainer" class="h-full"></div>3</template>4 5<script setup lang="ts">6import { ref, onMounted, watch, onBeforeUnmount } from 'vue';7import monaco from '@monaco-editor/loader';8 9const props = defineProps<{10 value: string,11 originalValue?: string,12 language?: string,13 options?: Record<string, any>,14}>();15const emit = defineEmits(['update:value']);16 17const editorContainer = ref<HTMLElement>();18let editorInstance: any = null;19let monacoInstance: any = null;20let editorModel: any = null;21 22// 创建编辑器的函数23const createEditor = () => {24 if (!editorContainer.value || !monacoInstance) return;25 26 // 如果已存在编辑器实例,先销毁27 if (editorInstance) {28 editorInstance.dispose();29 editorInstance = null;30 }31 32 const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);33 const commonOptions = {34 language: props.language || 'json',35 minimap: { enabled: !isMobile },36 fontSize: isMobile ? 16 : 14,37 lineNumbers: isMobile ? 'off' as const : 'on' as const,38 scrollBeyondLastLine: false,39 automaticLayout: true,40 ...props.options41 };42 43 // 每次都创建新模型,确保内容刷新44 if (editorModel) {45 editorModel.dispose();46 }47 editorModel = monacoInstance.editor.createModel(props.value, props.language);48 49 if (props.originalValue !== undefined) {50 // 创建差异编辑器51 const originalModel = monacoInstance.editor.createModel(props.originalValue, props.language);52 editorInstance = monacoInstance.editor.createDiffEditor(editorContainer.value, {53 ...commonOptions,54 readOnly: false,55 renderSideBySide: true,56 ignoreTrimWhitespace: false,57 renderOverviewRuler: true,58 diffWordWrap: 'on',59 });60 61 editorInstance.setModel({62 original: originalModel,63 modified: editorModel64 });65 const modifiedEditor = editorInstance.getModifiedEditor();66 modifiedEditor.onDidChangeModelContent(() => {67 emit('update:value', modifiedEditor.getValue());68 });69 } else {70 // 创建普通编辑器71 editorInstance = monacoInstance.editor.create(editorContainer.value, {72 ...commonOptions,73 model: editorModel74 });75 editorInstance.onDidChangeModelContent(() => {76 emit('update:value', editorInstance.getValue());77 });78 }79};80 81onMounted(() => {82 monaco.init().then(instance => {83 monacoInstance = instance;84 createEditor();85 });86});87 88// 监听 value 和 originalValue 的变化89watch([() => props.value, () => props.originalValue], ([newVal, newOriginalVal], [oldVal, oldOriginalVal]) => {90 // 判断是否需要重建编辑器91 const modeChanged =92 (oldOriginalVal === undefined && newOriginalVal !== undefined) ||93 (oldOriginalVal !== undefined && newOriginalVal === undefined);94 95 if (modeChanged) {96 // 编辑器模式变化,重新创建97 createEditor();98 } else if (editorInstance) {99 if (props.originalValue !== undefined) {100 // 差异模式下更新内容101 const model = editorInstance.getModel();102 if (model && model.original && model.original.getValue() !== newOriginalVal) {103 model.original.setValue(newOriginalVal || '');104 }105 if (model && model.modified && model.modified.getValue() !== newVal) {106 model.modified.setValue(newVal || '');107 }108 } else {109 // 普通模式下更新内容110 if (editorInstance.getValue() !== newVal) {111 editorInstance.setValue(newVal || '');112 }113 }114 }115}, { deep: true });116 117onBeforeUnmount(() => {118 if (editorInstance) {119 editorInstance.dispose();120 }121 if (editorModel) {122 editorModel.dispose();123 }124 editorInstance = null;125 editorModel = null;126});127</script>128 129<style scoped>130:deep(.monaco-diff-editor),131:deep(.monaco-editor) {132 height: 100%;133}134</style>135 