fix(editor): 修复高级中打开代码块没有floatbox嵌套的问题,floatbox支持beforeClose事件

This commit is contained in:
moonszhang 2024-03-12 16:06:18 +08:00 committed by roymondchen
parent 4f31eed71a
commit 5fc649607a
3 changed files with 91 additions and 84 deletions

View File

@ -1,25 +1,33 @@
<template> <template>
<MFormBox <!-- 代码块编辑区 -->
class="m-editor-code-block-editor" <FloatingBox v-model:visible="boxVisible" title="代码编辑" :position="boxPosition" :before-close="beforeClose">
ref="fomDrawer" <template #body>
label-width="80px" <div ref="floatingBoxBody"></div>
:close-on-press-escape="false"
:title="content.name"
:width="size"
:config="functionConfig"
:values="content"
:disabled="disabled"
:before-close="beforeClose"
@change="changeHandler"
@submit="submitForm"
@error="errorHandler"
@open="openHandler"
@closed="closedHandler"
>
<template #left>
<TMagicButton type="primary" link @click="difVisible = true">查看修改</TMagicButton>
</template> </template>
</MFormBox> </FloatingBox>
<Teleport :to="floatingBoxBody" :disabled="slideType === 'box'" v-if="editVisible">
<MFormBox
class="m-editor-code-block-editor"
ref="fomDrawer"
label-width="80px"
:close-on-press-escape="false"
:title="content.name"
:width="size"
:config="functionConfig"
:values="content"
:disabled="disabled"
@change="changeHandler"
@submit="submitForm"
@error="errorHandler"
@open="openHandler"
@closed="closedHandler"
>
<template #left>
<TMagicButton type="primary" link @click="difVisible = true">查看修改</TMagicButton>
</template>
</MFormBox>
</Teleport>
<TMagicDialog v-model="difVisible" title="查看修改" fullscreen> <TMagicDialog v-model="difVisible" title="查看修改" fullscreen>
<div style="display: flex; margin-bottom: 10px"> <div style="display: flex; margin-bottom: 10px">
@ -47,14 +55,15 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, inject, onBeforeUnmount, ref } from 'vue'; import { computed, inject, nextTick, onBeforeUnmount, ref } from 'vue';
import { TMagicButton, TMagicDialog, tMagicMessage, tMagicMessageBox, TMagicTag } from '@tmagic/design'; import { TMagicButton, TMagicDialog, tMagicMessage, tMagicMessageBox, TMagicTag } from '@tmagic/design';
import { ColumnConfig, FormConfig, FormState, MFormBox, MFormDrawer } from '@tmagic/form'; import { ColumnConfig, FormConfig, FormState, MFormBox, MFormDrawer } from '@tmagic/form';
import type { CodeBlockContent } from '@tmagic/schema'; import type { CodeBlockContent } from '@tmagic/schema';
import FloatingBox from '@editor/components/FloatingBox.vue';
import CodeEditor from '@editor/layouts/CodeEditor.vue'; import CodeEditor from '@editor/layouts/CodeEditor.vue';
import type { Services } from '@editor/type'; import type { Services, SlideType } from '@editor/type';
import { getConfig } from '@editor/utils/config'; import { getConfig } from '@editor/utils/config';
defineOptions({ defineOptions({
@ -66,6 +75,7 @@ const props = defineProps<{
disabled?: boolean; disabled?: boolean;
isDataSource?: boolean; isDataSource?: boolean;
dataSourceType?: string; dataSourceType?: string;
slideType?: SlideType;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
@ -246,7 +256,7 @@ const beforeClose = (done: (cancel?: boolean) => void) => {
done(); done();
}) })
.catch((action: string) => { .catch((action: string) => {
done(action === 'close'); done(action === 'cancel');
}); });
}; };
@ -254,8 +264,26 @@ const closedHandler = () => {
changedValue.value = undefined; changedValue.value = undefined;
}; };
const boxVisible = ref<boolean>(false);
const editVisible = ref<boolean>(false);
const floatingBoxBody = ref<HTMLDivElement>();
const boxPosition = computed(() => {
const columnWidth = services?.uiService?.get('columnWidth');
const navMenuRect = services?.uiService?.get('navMenuRect');
return {
left: columnWidth?.left ?? 0,
top: (navMenuRect?.top ?? 0) + (navMenuRect?.height ?? 0),
};
});
defineExpose({ defineExpose({
show() { async show() {
if (props.slideType !== 'box') {
boxVisible.value = true;
}
await nextTick();
editVisible.value = true;
fomDrawer.value?.show(); fomDrawer.value?.show();
}, },

View File

@ -33,12 +33,21 @@ interface Rect {
height: number | string; height: number | string;
} }
const props = withDefaults(defineProps<{ visible: boolean; position?: Position; rect?: Rect; title?: string }>(), { const props = withDefaults(
visible: false, defineProps<{
title: '', visible: boolean;
position: () => ({ left: 0, top: 0 }), position?: Position;
rect: () => ({ width: 'auto', height: 'auto' }), rect?: Rect;
}); title?: string;
beforeClose?: (done: (cancel?: boolean) => void) => void;
}>(),
{
visible: false,
title: '',
position: () => ({ left: 0, top: 0 }),
rect: () => ({ width: 'auto', height: 'auto' }),
},
);
const emit = defineEmits<{ const emit = defineEmits<{
'update:visible': [boolean]; 'update:visible': [boolean];
@ -112,8 +121,18 @@ onBeforeUnmount(() => {
destroyMoveable(); destroyMoveable();
}); });
const hide = (cancel?: boolean) => {
if (cancel !== false) {
emit('update:visible', false);
}
};
const closeHandler = () => { const closeHandler = () => {
emit('update:visible', false); if (typeof props.beforeClose === 'function') {
props.beforeClose(hide);
} else {
hide();
}
}; };
const nextZIndex = () => { const nextZIndex = () => {

View File

@ -3,7 +3,7 @@
<slot name="code-block-panel-header"> <slot name="code-block-panel-header">
<div class="search-wrapper"> <div class="search-wrapper">
<SearchInput @search="filterTextChangeHandler"></SearchInput> <SearchInput @search="filterTextChangeHandler"></SearchInput>
<TMagicButton v-if="editable" class="create-code-button" type="primary" size="small" @click="showCreate" <TMagicButton v-if="editable" class="create-code-button" type="primary" size="small" @click="createCodeBlock"
>新增</TMagicButton >新增</TMagicButton
> >
<slot name="code-block-panel-search"></slot> <slot name="code-block-panel-search"></slot>
@ -11,39 +11,30 @@
</slot> </slot>
<!-- 代码块列表 --> <!-- 代码块列表 -->
<CodeBlockList ref="codeBlockList" :custom-error="customError" @edit="showEdit" @remove="deleteCode"> <CodeBlockList ref="codeBlockList" :custom-error="customError" @edit="editCode" @remove="deleteCode">
<template #code-block-panel-tool="{ id, data }"> <template #code-block-panel-tool="{ id, data }">
<slot name="code-block-panel-tool" :id="id" :data="data"></slot> <slot name="code-block-panel-tool" :id="id" :data="data"></slot>
</template> </template>
</CodeBlockList> </CodeBlockList>
</TMagicScrollbar> </TMagicScrollbar>
<!-- 代码块编辑区 --> <CodeBlockEditor
<FloatingBox v-model:visible="popVisible" title="代码编辑" :position="boxPosition"> v-if="codeConfig"
<template #body> ref="codeBlockEditor"
<div ref="scrollBar"></div> :disabled="!editable"
</template> :content="codeConfig"
</FloatingBox> :slideType="slideType"
@submit="submitCodeBlockHandler"
<Teleport :to="scrollBar" :disabled="slideType === 'box'" v-if="editVisible"> ></CodeBlockEditor>
<CodeBlockEditor
v-if="codeConfig"
ref="codeBlockEditor"
:disabled="!editable"
:content="codeConfig"
@submit="submitCodeBlockHandler"
></CodeBlockEditor>
</Teleport>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, inject, nextTick, ref } from 'vue'; import { computed, inject, ref } from 'vue';
import { TMagicButton, TMagicScrollbar } from '@tmagic/design'; import { TMagicButton, TMagicScrollbar } from '@tmagic/design';
import type { Id } from '@tmagic/schema'; import type { Id } from '@tmagic/schema';
import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue'; import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
import FloatingBox from '@editor/components/FloatingBox.vue';
import SearchInput from '@editor/components/SearchInput.vue'; import SearchInput from '@editor/components/SearchInput.vue';
import { useCodeBlockEdit } from '@editor/hooks/use-code-block-edit'; import { useCodeBlockEdit } from '@editor/hooks/use-code-block-edit';
import type { CodeBlockListPanelSlots, CodeDeleteErrorType, Services, SlideType } from '@editor/type'; import type { CodeBlockListPanelSlots, CodeDeleteErrorType, Services, SlideType } from '@editor/type';
@ -56,12 +47,12 @@ defineOptions({
name: 'MEditorCodeBlockListPanel', name: 'MEditorCodeBlockListPanel',
}); });
const props = defineProps<{ defineProps<{
customError?: (id: Id, errorType: CodeDeleteErrorType) => any; customError?: (id: Id, errorType: CodeDeleteErrorType) => any;
slideType?: SlideType; slideType?: SlideType;
}>(); }>();
const { codeBlockService, uiService } = inject<Services>('services') || {}; const { codeBlockService } = inject<Services>('services') || {};
const editable = computed(() => codeBlockService?.getEditStatus()); const editable = computed(() => codeBlockService?.getEditStatus());
@ -73,35 +64,4 @@ const codeBlockList = ref<InstanceType<typeof CodeBlockList>>();
const filterTextChangeHandler = (val: string) => { const filterTextChangeHandler = (val: string) => {
codeBlockList.value?.filter(val); codeBlockList.value?.filter(val);
}; };
const boxPosition = computed(() => {
const columnWidth = uiService?.get('columnWidth');
const navMenuRect = uiService?.get('navMenuRect');
return {
left: columnWidth?.left ?? 0,
top: (navMenuRect?.top ?? 0) + (navMenuRect?.height ?? 0),
};
});
const scrollBar = ref<HTMLDivElement>();
const popVisible = ref<boolean>(false);
const editVisible = ref<boolean>(false);
const beforeShowEdit = async () => {
if (props.slideType !== 'box') {
popVisible.value = true;
}
await nextTick();
editVisible.value = true;
};
const showEdit = async (id: string) => {
await beforeShowEdit();
editCode(id);
};
const showCreate = async () => {
await beforeShowEdit();
createCodeBlock();
};
</script> </script>