feat(editor): 支持配置自定义创建Monaco editor函数

This commit is contained in:
roymondchen 2025-06-06 16:03:56 +08:00
parent cd4656e54f
commit 3097e8eddb
6 changed files with 71 additions and 15 deletions

View File

@ -32,20 +32,20 @@
</FloatingBox> </FloatingBox>
<Teleport to="body"> <Teleport to="body">
<TMagicDialog title="查看修改" v-model="difVisible" fullscreen> <TMagicDialog title="查看修改" v-model="difVisible" fullscreen destroy-on-close>
<div style="display: flex; margin-bottom: 10px"> <div style="display: flex; margin-bottom: 10px">
<div style="flex: 1"><TMagicTag size="small" type="info">修改前</TMagicTag></div> <div style="flex: 1"><TMagicTag size="small" type="info">修改前</TMagicTag></div>
<div style="flex: 1"><TMagicTag size="small" type="success">修改后</TMagicTag></div> <div style="flex: 1"><TMagicTag size="small" type="success">修改后</TMagicTag></div>
</div> </div>
<CodeEditor <CodeEditor
v-if="difVisible"
ref="magicVsEditor" ref="magicVsEditor"
type="diff" type="diff"
language="json" language="json"
:disabled-full-screen="true"
:initValues="content.content" :initValues="content.content"
:modifiedValues="formBox?.form?.values.content" :modifiedValues="formBox?.form?.values.content"
:style="`height: ${windowRect.height - 150}px`" :height="`${windowRect.height - 150}px`"
></CodeEditor> ></CodeEditor>
<template #footer> <template #footer>

View File

@ -112,6 +112,9 @@ export { default as StyleSetter } from './fields/StyleSetter/Index.vue';
const defaultInstallOpt: EditorInstallOptions = { const defaultInstallOpt: EditorInstallOptions = {
// eslint-disable-next-line no-eval // eslint-disable-next-line no-eval
parseDSL: (dsl: string) => eval(dsl), parseDSL: (dsl: string) => eval(dsl),
customCreateMonacoEditor: (monaco, codeEditorEl, options) => monaco.editor.create(codeEditorEl, options),
customCreateMonacoDiffEditor: (monaco, codeEditorEl, options) =>
monaco.editor.createDiffEditor(codeEditorEl, options),
}; };
export default { export default {

View File

@ -5,7 +5,12 @@
:class="`magic-code-editor-wrapper${fullScreen ? ' full-screen' : ''}`" :class="`magic-code-editor-wrapper${fullScreen ? ' full-screen' : ''}`"
:style="!fullScreen && height ? `height: ${height}` : '100%'" :style="!fullScreen && height ? `height: ${height}` : '100%'"
> >
<TMagicButton class="magic-code-editor-full-screen-icon" circle size="small" @click="fullScreenHandler" <TMagicButton
v-if="!disabledFullScreen"
class="magic-code-editor-full-screen-icon"
circle
size="small"
@click="fullScreenHandler"
><MIcon :icon="FullScreen"></MIcon ><MIcon :icon="FullScreen"></MIcon
></TMagicButton> ></TMagicButton>
<div ref="codeEditor" class="magic-code-editor-content"></div> <div ref="codeEditor" class="magic-code-editor-content"></div>
@ -15,7 +20,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue'; import { nextTick, onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue';
import { FullScreen } from '@element-plus/icons-vue'; import { FullScreen } from '@element-plus/icons-vue';
import { throttle } from 'lodash-es'; import { throttle } from 'lodash-es';
import serialize from 'serialize-javascript'; import serialize from 'serialize-javascript';
@ -36,12 +41,11 @@ const props = withDefaults(
modifiedValues?: any; modifiedValues?: any;
type?: 'diff'; type?: 'diff';
language?: string; language?: string;
options?: { options?: monaco.editor.IStandaloneEditorConstructionOptions;
[key: string]: any;
};
height?: string; height?: string;
autoSave?: boolean; autoSave?: boolean;
parse?: boolean; parse?: boolean;
disabledFullScreen?: boolean;
}>(), }>(),
{ {
initValues: '', initValues: '',
@ -51,6 +55,7 @@ const props = withDefaults(
tabSize: 2, tabSize: 2,
}), }),
parse: false, parse: false,
disabledFullScreen: false,
}, },
); );
@ -124,6 +129,10 @@ const getEditorValue = () =>
const init = async () => { const init = async () => {
if (!codeEditorEl.value) return; if (!codeEditorEl.value) return;
if (codeEditorEl.value.clientHeight === 0) {
await nextTick();
}
const options = { const options = {
value: values.value, value: values.value,
language: props.language, language: props.language,
@ -132,15 +141,13 @@ const init = async () => {
}; };
if (props.type === 'diff') { if (props.type === 'diff') {
vsDiffEditor = monaco.editor.createDiffEditor(codeEditorEl.value, options); vsDiffEditor = getEditorConfig('customCreateMonacoDiffEditor')(monaco, codeEditorEl.value, options);
} else { } else {
vsEditor = monaco.editor.create(codeEditorEl.value, options); vsEditor = getEditorConfig('customCreateMonacoEditor')(monaco, codeEditorEl.value, options);
} }
setEditorValue(props.initValues, props.modifiedValues); setEditorValue(props.initValues, props.modifiedValues);
loading.value = false;
emit('initd', vsEditor); emit('initd', vsEditor);
codeEditorEl.value.addEventListener('keydown', (e) => { codeEditorEl.value.addEventListener('keydown', (e) => {
@ -179,14 +186,33 @@ watch(
}, },
); );
watch(
() => props.options,
(v) => {
vsEditor?.updateOptions(v);
vsDiffEditor?.updateOptions(v);
},
{
deep: true,
},
);
onMounted(async () => { onMounted(async () => {
loading.value = true; loading.value = true;
init(); await init();
loading.value = false;
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
resizeObserver.disconnect(); resizeObserver.disconnect();
vsEditor?.dispose();
vsDiffEditor?.dispose();
vsEditor = null;
vsDiffEditor = null;
}); });
const fullScreen = ref(false); const fullScreen = ref(false);

View File

@ -31,8 +31,13 @@
.magic-code-editor-full-screen-icon { .magic-code-editor-full-screen-icon {
position: absolute; position: absolute;
top: 5px; top: 20px;
right: 0; right: 10px;
z-index: 11; z-index: 11;
opacity: 0.3;
&:hover {
opacity: 1;
}
} }
} }

View File

@ -84,6 +84,11 @@
right: 15px; right: 15px;
bottom: 15px; bottom: 15px;
z-index: 30; z-index: 30;
opacity: 0.5;
&:hover {
opacity: 1;
}
} }
.m-editor-props-panel-style-icon { .m-editor-props-panel-style-icon {
@ -91,6 +96,11 @@
right: 15px; right: 15px;
bottom: 60px; bottom: 60px;
z-index: 30; z-index: 30;
opacity: 0.5;
&:hover {
opacity: 1;
}
} }
.m-editor-props-panel-src-code.magic-code-editor { .m-editor-props-panel-src-code.magic-code-editor {

View File

@ -33,6 +33,8 @@ import type {
UpdateDragEl, UpdateDragEl,
} from '@tmagic/stage'; } from '@tmagic/stage';
import Monaco from '@editor/utils/monaco-editor';
import type { CodeBlockService } from './services/codeBlock'; import type { CodeBlockService } from './services/codeBlock';
import type { ComponentListService } from './services/componentList'; import type { ComponentListService } from './services/componentList';
import type { DataSourceService } from './services/dataSource'; import type { DataSourceService } from './services/dataSource';
@ -119,6 +121,16 @@ export type GetConfig = (config: FormConfig) => Promise<FormConfig> | FormConfig
export interface EditorInstallOptions { export interface EditorInstallOptions {
parseDSL: <T = any>(dsl: string) => T; parseDSL: <T = any>(dsl: string) => T;
customCreateMonacoEditor: (
monaco: typeof Monaco,
codeEditorEl: HTMLElement,
options: Monaco.editor.IStandaloneEditorConstructionOptions,
) => Monaco.editor.IStandaloneCodeEditor;
customCreateMonacoDiffEditor: (
monaco: typeof Monaco,
codeEditorEl: HTMLElement,
options: Monaco.editor.IStandaloneEditorConstructionOptions,
) => Monaco.editor.IStandaloneDiffEditor;
[key: string]: any; [key: string]: any;
} }