feat(editor): 代码编辑器支持配置自动高度

This commit is contained in:
roymondchen 2025-12-03 17:50:48 +08:00
parent 8d7c8fa725
commit 8d55d0cd8d
8 changed files with 92 additions and 12 deletions

View File

@ -201,7 +201,7 @@ const functionConfig = computed<FormConfig>(() => [
name: 'content',
type: 'vs-code',
options: inject('codeOptions', {}),
height: '500px',
autosize: { minRows: 10, maxRows: 30 },
onChange: (formState: FormState | undefined, code: string) => {
try {
// js

View File

@ -7,6 +7,7 @@
...config.options,
readOnly: disabled,
}"
:autosize="config.autosize"
:parse="config.parse"
@save="save"
></MagicCodeEditor>

View File

@ -233,7 +233,6 @@ const dataSourceFieldsConfig: FormConfig = [
{
name: 'defaultValue',
text: '默认值',
height: '200px',
parse: true,
type: (mForm: FormState | undefined, { model }: any) => {
if (model.type === 'number') return 'number';
@ -242,6 +241,7 @@ const dataSourceFieldsConfig: FormConfig = [
return 'vs-code';
},
autosize: { minRows: 1, maxRows: 30 },
options: [
{ text: 'true', value: true },
{ text: 'false', value: false },
@ -267,7 +267,7 @@ const jsonFromConfig: FormConfig = [
type: 'vs-code',
labelWidth: '0',
language: 'json',
height: '600px',
autosize: { minRows: 30, maxRows: 50 },
options: inject('codeOptions', {}),
},
];

View File

@ -96,7 +96,7 @@ const formConfig: FormConfig = [
language: 'json',
options: inject('codeOptions', {}),
defaultValue: '{}',
height: '400px',
autosize: { minRows: 30, maxRows: 50 },
onChange: (formState: FormState | undefined, v: string | any) => {
if (typeof v !== 'string') return v;
return JSON.parse(v);

View File

@ -37,12 +37,15 @@
<MagicCodeEditor
v-if="config.advanced && showCode"
height="200px"
:init-values="model[name]"
language="javascript"
:options="{
readOnly: disabled,
}"
:autosize="{
minRows: 1,
maxRows: 20,
}"
:parse="true"
@save="save"
></MagicCodeEditor>

View File

@ -1,10 +1,7 @@
<template>
<div :class="`magic-code-editor`">
<Teleport to="body" :disabled="!fullScreen">
<div
:class="`magic-code-editor-wrapper${fullScreen ? ' full-screen' : ''}`"
:style="!fullScreen && height ? `height: ${height}` : '100%'"
>
<div :class="{ 'magic-code-editor-wrapper': true, 'full-screen': fullScreen }" :style="{ height: computeHeight }">
<TMagicButton
v-if="!disabledFullScreen"
class="magic-code-editor-full-screen-icon"
@ -20,7 +17,7 @@
</template>
<script lang="ts" setup>
import { nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue';
import { computed, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue';
import { FullScreen } from '@element-plus/icons-vue';
import { throttle } from 'lodash-es';
import serialize from 'serialize-javascript';
@ -46,6 +43,10 @@ const props = withDefaults(
autoSave?: boolean;
parse?: boolean;
disabledFullScreen?: boolean;
autosize?: {
minRows?: number;
maxRows?: number;
};
}>(),
{
initValues: '',
@ -61,6 +62,58 @@ const props = withDefaults(
const emit = defineEmits(['initd', 'save']);
const autoHeight = ref<string>('');
const computeHeight = computed(() => {
if (fullScreen.value) {
return '100%';
}
if (props.height) {
return props.height;
}
if (props.autosize) {
return autoHeight.value;
}
return '100%';
});
const setAutoHeight = (v = '') => {
let lines = Math.max(v.split('\n').length, props.autosize?.minRows || 1);
if (v) {
if (props.autosize?.maxRows) {
lines = Math.min(lines, props.autosize.maxRows);
}
}
// 使
let lineHeight = 20;
if (vsEditor) {
const editorOptions = vsEditor.getOptions();
lineHeight = editorOptions.get(monaco.editor.EditorOption.lineHeight) || 20;
}
const newHeight = `${lines * lineHeight + 10}px`;
//
if (autoHeight.value !== newHeight) {
autoHeight.value = newHeight;
//
nextTick(() => {
vsEditor?.layout();
//
if (vsEditor) {
vsEditor.setScrollTop(0);
vsEditor.revealLine(1);
}
});
}
};
const toString = (v: string | any, language: string): string => {
let value: string;
if (typeof v !== 'string') {
@ -110,6 +163,8 @@ const resizeObserver = new globalThis.ResizeObserver(
const setEditorValue = (v: string | any, m: string | any) => {
values.value = toString(v, props.language.toLocaleLowerCase());
setAutoHeight(values.value);
if (props.type === 'diff') {
const originalModel = monaco.editor.createModel(values.value, 'text/javascript');
const modifiedModel = monaco.editor.createModel(toString(m, props.language), 'text/javascript');
@ -147,6 +202,7 @@ const handleKeyDown = (e: KeyboardEvent) => {
emit('save', props.parse ? parseCode(newValue, props.language) : newValue);
}
};
const init = async () => {
if (!codeEditorEl.value) return;
@ -163,8 +219,24 @@ const init = async () => {
if (props.type === 'diff') {
vsDiffEditor = getEditorConfig('customCreateMonacoDiffEditor')(monaco, codeEditorEl.value, options);
// diff
vsDiffEditor.getModifiedEditor().onDidChangeModelContent(() => {
// 使 autosize
if (props.autosize) {
setAutoHeight(getEditorValue());
}
});
} else {
vsEditor = getEditorConfig('customCreateMonacoEditor')(monaco, codeEditorEl.value, options);
//
vsEditor.onDidChangeModelContent(() => {
// 使 autosize
if (props.autosize) {
setAutoHeight(getEditorValue());
}
});
}
setEditorValue(props.initValues, props.modifiedValues);

View File

@ -64,7 +64,7 @@ const fillConfig = (config: FormConfig): FormConfig => [
name: 'beforeRequest',
type: 'vs-code',
parse: true,
height: '600px',
autosize: { minRows: 10, maxRows: 30 },
},
],
},
@ -76,7 +76,7 @@ const fillConfig = (config: FormConfig): FormConfig => [
name: 'afterResponse',
type: 'vs-code',
parse: true,
height: '600px',
autosize: { minRows: 10, maxRows: 30 },
},
],
},

View File

@ -39,6 +39,10 @@ export interface CodeConfig extends FormItem {
};
height?: string;
parse?: boolean;
autosize?: {
minRows?: number;
maxRows?: number;
};
}
export interface CodeLinkConfig extends FormItem {