feat(editor): 数据源抽屉切floatbox

This commit is contained in:
moonszhang 2024-03-19 18:57:55 +08:00 committed by roymondchen
parent e2326ff4f6
commit 96149bd2ae
13 changed files with 250 additions and 193 deletions

View File

@ -9,59 +9,57 @@
:before-close="beforeClose" :before-close="beforeClose"
> >
<template #body> <template #body>
<div ref="floatingBoxBody" style="height: 100%"></div> <MFormBox
class="m-editor-code-block-editor"
ref="formBox"
label-width="80px"
:close-on-press-escape="false"
:title="content.name"
:config="functionConfig"
:values="content"
:disabled="disabled"
style="height: 100%"
@change="changeHandler"
@submit="submitForm"
@error="errorHandler"
@closed="closedHandler"
>
<template #left>
<TMagicButton v-if="!disabled" type="primary" link @click="difVisible = true">查看修改</TMagicButton>
</template>
</MFormBox>
</template> </template>
</FloatingBox> </FloatingBox>
<Teleport :to="floatingBoxBody" :disabled="slideType === 'box'" v-if="editVisible"> <Teleport to="body">
<MFormBox <TMagicDialog title="查看修改" v-model="difVisible" fullscreen>
class="m-editor-code-block-editor" <div style="display: flex; margin-bottom: 10px">
ref="formBox" <div style="flex: 1"><TMagicTag size="small" type="info">修改前</TMagicTag></div>
label-width="80px" <div style="flex: 1"><TMagicTag size="small" type="success">修改后</TMagicTag></div>
:close-on-press-escape="false" </div>
:title="content.name"
:config="functionConfig" <CodeEditor
:values="content" v-if="difVisible"
:disabled="disabled" ref="magicVsEditor"
:height="floatingBoxBody?.clientHeight" type="diff"
@change="changeHandler" language="json"
@submit="submitForm" :initValues="content.content"
@error="errorHandler" :modifiedValues="formBox?.form?.values.content"
@closed="closedHandler" :style="`height: ${windowRect.height - 150}px`"
> ></CodeEditor>
<template #left>
<TMagicButton v-if="!disabled" type="primary" link @click="difVisible = true">查看修改</TMagicButton> <template #footer>
<span class="dialog-footer">
<TMagicButton size="small" @click="difVisible = false">取消</TMagicButton>
<TMagicButton size="small" type="primary" @click="diffChange">确定</TMagicButton>
</span>
</template> </template>
</MFormBox> </TMagicDialog>
</Teleport> </Teleport>
<TMagicDialog v-model="difVisible" title="查看修改" fullscreen>
<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="success">修改后</TMagicTag></div>
</div>
<CodeEditor
v-if="difVisible"
ref="magicVsEditor"
type="diff"
language="json"
:initValues="content.content"
:modifiedValues="formBox?.form?.values.content"
:style="`height: ${windowRect.height - 150}px`"
></CodeEditor>
<template #footer>
<span class="dialog-footer">
<TMagicButton size="small" @click="difVisible = false">取消</TMagicButton>
<TMagicButton size="small" type="primary" @click="diffChange">确定</TMagicButton>
</span>
</template>
</TMagicDialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, inject, nextTick, ref } from 'vue'; import { computed, inject, Ref, 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 } from '@tmagic/form'; import { ColumnConfig, FormConfig, FormState, MFormBox } from '@tmagic/form';
@ -69,9 +67,10 @@ import type { CodeBlockContent } from '@tmagic/schema';
import FloatingBox from '@editor/components/FloatingBox.vue'; import FloatingBox from '@editor/components/FloatingBox.vue';
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height'; import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
import { useWindowRect } from '@editor/hooks/use-window-rect'; import { useWindowRect } from '@editor/hooks/use-window-rect';
import CodeEditor from '@editor/layouts/CodeEditor.vue'; import CodeEditor from '@editor/layouts/CodeEditor.vue';
import type { Services, SlideType } from '@editor/type'; import type { Services } from '@editor/type';
import { getConfig } from '@editor/utils/config'; import { getConfig } from '@editor/utils/config';
defineOptions({ defineOptions({
@ -86,7 +85,6 @@ const props = defineProps<{
disabled?: boolean; disabled?: boolean;
isDataSource?: boolean; isDataSource?: boolean;
dataSourceType?: string; dataSourceType?: string;
slideType?: SlideType;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
@ -229,7 +227,6 @@ const changeHandler = (values: CodeBlockContent) => {
const beforeClose = (done: (cancel?: boolean) => void) => { const beforeClose = (done: (cancel?: boolean) => void) => {
if (!changedValue.value) { if (!changedValue.value) {
editVisible.value = false;
done(); done();
return; return;
} }
@ -242,12 +239,10 @@ const beforeClose = (done: (cancel?: boolean) => void) => {
}) })
.then(() => { .then(() => {
changedValue.value && submitForm(changedValue.value); changedValue.value && submitForm(changedValue.value);
editVisible.value = false;
done(); done();
}) })
.catch((action: string) => { .catch((action: string) => {
if (action === 'cancel') { if (action === 'cancel') {
editVisible.value = false;
} }
done(action === 'cancel'); done(action === 'cancel');
}); });
@ -257,35 +252,17 @@ const closedHandler = () => {
changedValue.value = undefined; changedValue.value = undefined;
}; };
const editVisible = ref<boolean>(false); const parentFloating = inject<Ref<HTMLDivElement>>('parentFloating');
const floatingBoxBody = ref<HTMLDivElement>(); const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
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({
async show() { async show() {
if (props.slideType !== 'box') { calcBoxPosition();
boxVisible.value = true; boxVisible.value = true;
await nextTick();
}
editVisible.value = true;
}, },
async hide() { async hide() {
editVisible.value = false; boxVisible.value = false;
if (props.slideType !== 'box') {
await nextTick();
boxVisible.value = false;
}
}, },
}); });
</script> </script>

View File

@ -17,13 +17,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue'; import { computed, inject, nextTick, onBeforeUnmount, provide, ref, watch } from 'vue';
import { Close } from '@element-plus/icons-vue'; import { Close } from '@element-plus/icons-vue';
import VanillaMoveable from 'moveable'; import VanillaMoveable from 'moveable';
import { TMagicButton, useZIndex } from '@tmagic/design'; import { TMagicButton, useZIndex } from '@tmagic/design';
import MIcon from '@editor/components/Icon.vue'; import MIcon from '@editor/components/Icon.vue';
import type { Services } from '@editor/type';
interface Position { interface Position {
left: number; left: number;
@ -50,7 +51,7 @@ const target = ref<HTMLDivElement>();
const titleEl = ref<HTMLDivElement>(); const titleEl = ref<HTMLDivElement>();
const zIndex = useZIndex(); const zIndex = useZIndex();
const curZIndex = ref<number>(zIndex.nextZIndex()); const curZIndex = ref<number>(0);
const titleHeight = ref(0); const titleHeight = ref(0);
const bodyHeight = computed(() => { const bodyHeight = computed(() => {
@ -65,12 +66,21 @@ const bodyHeight = computed(() => {
return 'auto'; return 'auto';
}); });
const style = computed(() => ({ const services = inject<Services>('services');
left: `${props.position.left}px`, const frameworkWidth = computed(() => services?.uiService.get('frameworkRect').width || 0);
top: `${props.position.top}px`, const style = computed(() => {
width: width.value ? `${width.value}px` : 'auto', let { left } = props.position;
height: height.value ? `${height.value}px` : 'auto', if (width.value) {
})); left = left + width.value > frameworkWidth.value ? frameworkWidth.value - width.value : left;
}
return {
left: `${left}px`,
top: `${props.position.top}px`,
width: width.value ? `${width.value}px` : 'auto',
height: height.value ? `${height.value}px` : 'auto',
};
});
let moveable: VanillaMoveable | null = null; let moveable: VanillaMoveable | null = null;
@ -114,6 +124,7 @@ watch(
async (visible) => { async (visible) => {
if (visible) { if (visible) {
await nextTick(); await nextTick();
curZIndex.value = zIndex.nextZIndex();
const targetRect = target.value?.getBoundingClientRect(); const targetRect = target.value?.getBoundingClientRect();
if (targetRect) { if (targetRect) {
@ -157,6 +168,8 @@ const nextZIndex = () => {
curZIndex.value = zIndex.nextZIndex(); curZIndex.value = zIndex.nextZIndex();
}; };
provide('parentFloating', target);
defineExpose({ defineExpose({
bodyHeight, bodyHeight,
target, target,

View File

@ -7,39 +7,57 @@
<TMagicButton size="small" type="primary" :disabled="disabled" plain @click="newHandler()">添加</TMagicButton> <TMagicButton size="small" type="primary" :disabled="disabled" plain @click="newHandler()">添加</TMagicButton>
</div> </div>
<MFormDrawer <FloatingBox
ref="addDialog" v-model:visible="addDialogVisible"
label-width="80px" v-model:width="width"
v-model:height="editorHeight"
:title="fieldTitle" :title="fieldTitle"
:config="dataSourceFieldsConfig" :position="boxPosition"
:values="fieldValues" >
:parentValues="model[name]" <template #body>
:disabled="disabled" <MFormBox
:width="width" label-width="80px"
@submit="fieldChange" :title="fieldTitle"
></MFormDrawer> :config="dataSourceFieldsConfig"
:values="fieldValues"
:parentValues="model[name]"
:disabled="disabled"
@submit="fieldChange"
></MFormBox>
</template>
</FloatingBox>
<MFormDrawer <FloatingBox
ref="addFromJsonDialog" v-model:visible="addFromJsonDialogVisible"
v-model:width="width"
v-model:height="editorHeight"
title="快速添加数据定义" title="快速添加数据定义"
:config="jsonFromConfig" :position="boxPosition"
:values="jsonFromValues" >
:disabled="disabled" <template #body>
:width="width" <MFormBox
@submit="addFromJsonFromChange" :config="jsonFromConfig"
></MFormDrawer> :values="jsonFromValues"
:disabled="disabled"
@submit="addFromJsonFromChange"
></MFormBox>
</template>
</FloatingBox>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, inject, ref } from 'vue'; import { inject, Ref, ref } from 'vue';
import { TMagicButton, tMagicMessage, tMagicMessageBox } from '@tmagic/design'; import { TMagicButton, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
import { type FieldProps, type FormConfig, type FormState, MFormDrawer } from '@tmagic/form'; import { type FieldProps, type FormConfig, type FormState, MFormBox } from '@tmagic/form';
import type { DataSchema } from '@tmagic/schema'; import type { DataSchema } from '@tmagic/schema';
import { type ColumnConfig, MagicTable } from '@tmagic/table'; import { type ColumnConfig, MagicTable } from '@tmagic/table';
import { getDefaultValueFromFields } from '@tmagic/utils'; import { getDefaultValueFromFields } from '@tmagic/utils';
import FloatingBox from '@editor/components/FloatingBox.vue';
import { useEditorContentHeight } from '@editor/hooks';
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
import type { Services } from '@editor/type'; import type { Services } from '@editor/type';
defineOptions({ defineOptions({
@ -61,17 +79,16 @@ const emit = defineEmits(['change']);
const services = inject<Services>('services'); const services = inject<Services>('services');
const addDialog = ref<InstanceType<typeof MFormDrawer>>();
const fieldValues = ref<Record<string, any>>({}); const fieldValues = ref<Record<string, any>>({});
const fieldTitle = ref(''); const fieldTitle = ref('');
const width = computed(() => globalThis.document.body.clientWidth - (services?.uiService.get('columnWidth').left || 0)); const width = defineModel<number>('width', { default: 670 });
const newHandler = () => { const newHandler = () => {
fieldValues.value = {}; fieldValues.value = {};
fieldTitle.value = '新增属性'; fieldTitle.value = '新增属性';
addDialog.value?.show(); calcBoxPosition();
addDialogVisible.value = true;
}; };
const fieldChange = ({ index, ...value }: Record<string, any>) => { const fieldChange = ({ index, ...value }: Record<string, any>) => {
@ -81,7 +98,7 @@ const fieldChange = ({ index, ...value }: Record<string, any>) => {
props.model[props.name].push(value); props.model[props.name].push(value);
} }
addDialog.value?.hide(); addDialogVisible.value = false;
emit('change', props.model[props.name]); emit('change', props.model[props.name]);
}; };
@ -122,7 +139,8 @@ const fieldColumns: ColumnConfig[] = [
index, index,
}; };
fieldTitle.value = `编辑${row.title}`; fieldTitle.value = `编辑${row.title}`;
addDialog.value?.show(); calcBoxPosition();
addDialogVisible.value = true;
}, },
}, },
{ {
@ -220,7 +238,6 @@ const dataSourceFieldsConfig: FormConfig = [
}, },
]; ];
const addFromJsonDialog = ref<InstanceType<typeof MFormDrawer>>();
const jsonFromConfig: FormConfig = [ const jsonFromConfig: FormConfig = [
{ {
name: 'data', name: 'data',
@ -238,7 +255,8 @@ const jsonFromValues = ref({
const newFromJsonHandler = () => { const newFromJsonHandler = () => {
jsonFromValues.value.data = getDefaultValueFromFields(props.model[props.name]); jsonFromValues.value.data = getDefaultValueFromFields(props.model[props.name]);
addFromJsonDialog.value?.show(); calcBoxPosition();
addFromJsonDialogVisible.value = true;
}; };
const getValueType = (value: any) => { const getValueType = (value: any) => {
@ -288,11 +306,18 @@ const addFromJsonFromChange = ({ data }: { data: string }) => {
props.model[props.name] = getFieldsConfig(value, props.model[props.name]); props.model[props.name] = getFieldsConfig(value, props.model[props.name]);
addFromJsonDialog.value?.hide(); addFromJsonDialogVisible.value = false;
emit('change', props.model[props.name]); emit('change', props.model[props.name]);
} catch (e: any) { } catch (e: any) {
tMagicMessage.error(e.message); tMagicMessage.error(e.message);
} }
}; };
const addDialogVisible = defineModel<boolean>('visible', { default: false });
const addFromJsonDialogVisible = defineModel<boolean>('visible1', { default: false });
const { height: editorHeight } = useEditorContentHeight();
const parentFloating = inject<Ref<HTMLDivElement>>('parentFloating');
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
</script> </script>

View File

@ -6,32 +6,44 @@
<TMagicButton size="small" type="primary" :disabled="disabled" plain @click="newHandler()">添加</TMagicButton> <TMagicButton size="small" type="primary" :disabled="disabled" plain @click="newHandler()">添加</TMagicButton>
</div> </div>
<MFormDrawer <FloatingBox
ref="addDialog" v-model:visible="addDialogVisible"
label-width="120px" v-model:width="width"
v-model:height="editorHeight"
:title="drawerTitle" :title="drawerTitle"
:config="formConfig" :position="boxPosition"
:values="formValues" >
:parentValues="model[name]" <template #body>
:disabled="disabled" <MFormBox
:width="width" ref="addDialog"
@submit="formChangeHandler" label-width="120px"
></MFormDrawer> :config="formConfig"
:values="formValues"
:parentValues="model[name]"
:disabled="disabled"
@submit="formChangeHandler"
></MFormBox>
</template>
</FloatingBox>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, inject, ref } from 'vue'; import { inject, Ref, ref } from 'vue';
import { TMagicButton, tMagicMessageBox, TMagicSwitch } from '@tmagic/design'; import { TMagicButton, tMagicMessageBox, TMagicSwitch } from '@tmagic/design';
import { type FieldProps, type FormConfig, type FormState, MFormDrawer } from '@tmagic/form'; import { type FieldProps, type FormConfig, type FormState, MFormBox } from '@tmagic/form';
import type { MockSchema } from '@tmagic/schema'; import type { MockSchema } from '@tmagic/schema';
import { type ColumnConfig, MagicTable } from '@tmagic/table'; import { type ColumnConfig, MagicTable } from '@tmagic/table';
import { getDefaultValueFromFields } from '@tmagic/utils'; import { getDefaultValueFromFields } from '@tmagic/utils';
import FloatingBox from '@editor/components/FloatingBox.vue';
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
import CodeEditor from '@editor/layouts/CodeEditor.vue'; import CodeEditor from '@editor/layouts/CodeEditor.vue';
import { Services } from '@editor/type'; import { Services } from '@editor/type';
import { useEditorContentHeight } from '..';
defineOptions({ defineOptions({
name: 'MFieldsDataSourceMocks', name: 'MFieldsDataSourceMocks',
}); });
@ -50,9 +62,8 @@ const props = withDefaults(
const emit = defineEmits(['change']); const emit = defineEmits(['change']);
const services = inject<Services>('services'); const services = inject<Services>('services');
const width = computed(() => globalThis.document.body.clientWidth - (services?.uiService.get('columnWidth').left || 0)); const width = defineModel<number>('width', { default: 670 });
const addDialog = ref<InstanceType<typeof MFormDrawer>>();
const drawerTitle = ref(''); const drawerTitle = ref('');
const formValues = ref<Record<string, any>>({}); const formValues = ref<Record<string, any>>({});
@ -182,7 +193,8 @@ const columns: ColumnConfig[] = [
index, index,
}; };
drawerTitle.value = `编辑${row.title}`; drawerTitle.value = `编辑${row.title}`;
addDialog.value?.show(); calcBoxPosition();
addDialogVisible.value = true;
}, },
}, },
{ {
@ -206,7 +218,8 @@ const newHandler = () => {
enable: isFirstRow, enable: isFirstRow,
}; };
drawerTitle.value = '新增Mock'; drawerTitle.value = '新增Mock';
addDialog.value?.show(); calcBoxPosition();
addDialogVisible.value = true;
}; };
const formChangeHandler = ({ index, ...value }: Record<string, any>) => { const formChangeHandler = ({ index, ...value }: Record<string, any>) => {
@ -216,7 +229,7 @@ const formChangeHandler = ({ index, ...value }: Record<string, any>) => {
props.model[props.name].push(value); props.model[props.name].push(value);
} }
addDialog.value?.hide(); addDialogVisible.value = false;
emit('change', props.model[props.name]); emit('change', props.model[props.name]);
}; };
@ -234,4 +247,9 @@ const toggleValue = (row: MockSchema, key: 'enable' | 'useInEditor', value: bool
index, index,
}); });
}; };
const addDialogVisible = defineModel<boolean>('visible', { default: false });
const { height: editorHeight } = useEditorContentHeight();
const parentFloating = inject<Ref<HTMLDivElement>>('parentFloating');
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
</script> </script>

View File

@ -10,7 +10,7 @@ export const useEditorContentHeight = () => {
const height = ref(0); const height = ref(0);
watchEffect(() => { watchEffect(() => {
if (height.value > 0) return; if (height.value > 0 && height.value === editorContentHeight.value) return;
height.value = editorContentHeight.value; height.value = editorContentHeight.value;
}); });

View File

@ -1,4 +1,6 @@
import { computed, ComputedRef, ref, watch } from 'vue'; import { computed, ComputedRef, inject, ref, watch } from 'vue';
import type { Services } from '@editor/type';
interface State { interface State {
status: boolean; status: boolean;
@ -7,6 +9,8 @@ interface State {
} }
export const useFloatBox = (slideKeys: ComputedRef<string[]>) => { export const useFloatBox = (slideKeys: ComputedRef<string[]>) => {
const services = inject<Services>('services');
const floatBoxStates = ref<{ const floatBoxStates = ref<{
[key in (typeof slideKeys.value)[number]]: State; [key in (typeof slideKeys.value)[number]]: State;
}>( }>(
@ -30,9 +34,10 @@ export const useFloatBox = (slideKeys: ComputedRef<string[]>) => {
const dragstartHandler = () => (isDragging.value = true); const dragstartHandler = () => (isDragging.value = true);
const dragendHandler = (key: string, e: DragEvent) => { const dragendHandler = (key: string, e: DragEvent) => {
const navMenuRect = services?.uiService?.get('navMenuRect');
floatBoxStates.value[key] = { floatBoxStates.value[key] = {
left: e.clientX, left: e.clientX,
top: e.clientY, top: (navMenuRect?.top ?? 0) + (navMenuRect?.height ?? 0),
status: true, status: true,
}; };
isDragging.value = false; isDragging.value = false;
@ -47,12 +52,13 @@ export const useFloatBox = (slideKeys: ComputedRef<string[]>) => {
() => slideKeys.value, () => slideKeys.value,
(slideKeys) => { (slideKeys) => {
slideKeys.forEach((key) => { slideKeys.forEach((key) => {
if (floatBoxStates.value[key]) return; if (!floatBoxStates.value[key]) {
floatBoxStates.value[key] = { floatBoxStates.value[key] = {
status: false, status: false,
top: 0, top: 0,
left: 0, left: 0,
}; };
}
}); });
}, },
{ {

View File

@ -0,0 +1,29 @@
import { Ref, ref } from 'vue';
import { UiService } from '@editor/services/ui';
export const useNextFloatBoxPosition = (uiService?: UiService, parent?: Ref<HTMLDivElement>) => {
const boxPosition = ref({
left: 0,
top: 0,
});
const calcBoxPosition = () => {
const columnWidth = uiService?.get('columnWidth');
const navMenuRect = uiService?.get('navMenuRect');
let left = columnWidth?.left ?? 0;
if (parent?.value) {
const rect = parent?.value?.getBoundingClientRect();
left = (rect?.left ?? 0) + (rect?.width ?? 0);
}
boxPosition.value = {
left,
top: (navMenuRect?.top ?? 0) + (navMenuRect?.height ?? 0),
};
};
return {
boxPosition,
calcBoxPosition,
};
};

View File

@ -111,8 +111,8 @@
:key="config.$key ?? index" :key="config.$key ?? index"
v-if="floatBoxStates[config.$key]?.status" v-if="floatBoxStates[config.$key]?.status"
v-model:visible="floatBoxStates[config.$key].status" v-model:visible="floatBoxStates[config.$key].status"
:width="columnLeftWitch" v-model:width="columnLeftWidth"
:height="600" v-model:height="columnLeftHeight"
:title="config.text" :title="config.text"
:position="{ :position="{
left: floatBoxStates[config.$key].left, left: floatBoxStates[config.$key].left,
@ -123,8 +123,8 @@
<div class="m-editor-slide-list-box"> <div class="m-editor-slide-list-box">
<component <component
v-if="config && floatBoxStates[config.$key].status" v-if="config && floatBoxStates[config.$key].status"
:is="config.boxComponentConfig?.component || config.component" :is="config.component"
v-bind="config.boxComponentConfig?.props || config.props || {}" v-bind="config.props || {}"
v-on="config?.listeners || {}" v-on="config?.listeners || {}"
/> />
</div> </div>
@ -140,6 +140,7 @@ import { Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
import FloatingBox from '@editor/components/FloatingBox.vue'; import FloatingBox from '@editor/components/FloatingBox.vue';
import MIcon from '@editor/components/Icon.vue'; import MIcon from '@editor/components/Icon.vue';
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
import { useFloatBox } from '@editor/hooks/use-float-box'; import { useFloatBox } from '@editor/hooks/use-float-box';
import { import {
ColumnLayout, ColumnLayout,
@ -176,7 +177,8 @@ const props = withDefaults(
const services = inject<Services>('services'); const services = inject<Services>('services');
const columnLeftWitch = computed(() => services?.uiService.get('columnWidth')[ColumnLayout.LEFT] || 0); const columnLeftWidth = computed(() => services?.uiService.get('columnWidth')[ColumnLayout.LEFT] || 0);
const { height: columnLeftHeight } = useEditorContentHeight();
const activeTabName = ref(props.data?.status); const activeTabName = ref(props.data?.status);
@ -209,11 +211,6 @@ const getItemConfig = (data: SideItem): SideComponent => {
text: '代码编辑', text: '代码编辑',
component: CodeBlockListPanel, component: CodeBlockListPanel,
slots: {}, slots: {},
boxComponentConfig: {
props: {
slideType: 'box',
},
},
}, },
'data-source': { 'data-source': {
$key: 'data-source', $key: 'data-source',

View File

@ -23,7 +23,6 @@
ref="codeBlockEditor" ref="codeBlockEditor"
:disabled="!editable" :disabled="!editable"
:content="codeConfig" :content="codeConfig"
:slideType="slideType"
@submit="submitCodeBlockHandler" @submit="submitCodeBlockHandler"
></CodeBlockEditor> ></CodeBlockEditor>
</template> </template>
@ -37,7 +36,7 @@ import type { Id } from '@tmagic/schema';
import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue'; import CodeBlockEditor from '@editor/components/CodeBlockEditor.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 } from '@editor/type';
import CodeBlockList from './CodeBlockList.vue'; import CodeBlockList from './CodeBlockList.vue';
@ -49,7 +48,6 @@ defineOptions({
defineProps<{ defineProps<{
customError?: (id: Id, errorType: CodeDeleteErrorType) => any; customError?: (id: Id, errorType: CodeDeleteErrorType) => any;
slideType?: SlideType;
}>(); }>();
const { codeBlockService } = inject<Services>('services') || {}; const { codeBlockService } = inject<Services>('services') || {};

View File

@ -1,27 +1,37 @@
<template> <template>
<component <FloatingBox
:is="slideType === 'box' ? MFormBox : MFormDrawer" v-model:visible="boxVisible"
ref="fomDrawer" v-model:width="width"
label-width="80px" v-model:height="editorHeight"
:close-on-press-escape="false"
:title="title" :title="title"
:width="size" :position="boxPosition"
:config="dataSourceConfig" >
:values="initValues" <template #body>
:disabled="disabled" <MFormBox
@submit="submitHandler" label-width="80px"
@error="errorHandler" :title="title"
></component> :config="dataSourceConfig"
:values="initValues"
:disabled="disabled"
style="height: 100%"
@submit="submitHandler"
@error="errorHandler"
></MFormBox>
</template>
</FloatingBox>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, inject, ref, watchEffect } from 'vue'; import { inject, Ref, ref, watchEffect } from 'vue';
import { tMagicMessage } from '@tmagic/design'; import { tMagicMessage } from '@tmagic/design';
import { FormConfig, MFormBox, MFormDrawer } from '@tmagic/form'; import { FormConfig, MFormBox } from '@tmagic/form';
import { DataSourceSchema } from '@tmagic/schema'; import { DataSourceSchema } from '@tmagic/schema';
import type { Services, SlideType } from '@editor/type'; import FloatingBox from '@editor/components/FloatingBox.vue';
import { useEditorContentHeight } from '@editor/hooks';
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
import type { Services } from '@editor/type';
defineOptions({ defineOptions({
name: 'MEditorDataSourceConfigPanel', name: 'MEditorDataSourceConfigPanel',
@ -31,23 +41,27 @@ const props = defineProps<{
title?: string; title?: string;
values: any; values: any;
disabled: boolean; disabled: boolean;
slideType?: SlideType;
}>(); }>();
const boxVisible = defineModel<boolean>('visible', { default: false });
const width = defineModel<number>('width', { default: 670 });
const emit = defineEmits(['submit']); const emit = defineEmits(['submit']);
const services = inject<Services>('services'); const services = inject<Services>('services');
const size = computed(() => globalThis.document.body.clientWidth - (services?.uiService.get('columnWidth').left || 0));
const fomDrawer = ref<InstanceType<typeof MFormDrawer>>();
const initValues = ref<Partial<DataSourceSchema>>({}); const initValues = ref<Partial<DataSourceSchema>>({});
const dataSourceConfig = ref<FormConfig>([]); const dataSourceConfig = ref<FormConfig>([]);
const { height: editorHeight } = useEditorContentHeight();
const parentFloating = inject<Ref<HTMLDivElement>>('parentFloating');
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
watchEffect(() => { watchEffect(() => {
initValues.value = props.values; initValues.value = props.values;
dataSourceConfig.value = services?.dataSourceService.getFormConfig(initValues.value.type) || []; dataSourceConfig.value = services?.dataSourceService.getFormConfig(initValues.value.type) || [];
console.log(dataSourceConfig.value);
}); });
const submitHandler = (values: any) => { const submitHandler = (values: any) => {
@ -60,11 +74,12 @@ const errorHandler = (error: any) => {
defineExpose({ defineExpose({
show() { show() {
fomDrawer.value?.show(); calcBoxPosition();
boxVisible.value = true;
}, },
hide() { hide() {
fomDrawer.value?.hide(); boxVisible.value = false;
}, },
}); });
</script> </script>

View File

@ -33,7 +33,6 @@
:disabled="!editable" :disabled="!editable"
:values="dataSourceValues" :values="dataSourceValues"
:title="dialogTitle" :title="dialogTitle"
:slideType="slideType"
@submit="submitDataSourceHandler" @submit="submitDataSourceHandler"
></DataSourceConfigPanel> ></DataSourceConfigPanel>
</template> </template>
@ -47,7 +46,7 @@ import type { DataSourceSchema } from '@tmagic/schema';
import SearchInput from '@editor/components/SearchInput.vue'; import SearchInput from '@editor/components/SearchInput.vue';
import ToolButton from '@editor/components/ToolButton.vue'; import ToolButton from '@editor/components/ToolButton.vue';
import type { DataSourceListSlots, Services, SlideType } from '@editor/type'; import type { DataSourceListSlots, Services } from '@editor/type';
import DataSourceConfigPanel from './DataSourceConfigPanel.vue'; import DataSourceConfigPanel from './DataSourceConfigPanel.vue';
import DataSourceList from './DataSourceList.vue'; import DataSourceList from './DataSourceList.vue';
@ -58,10 +57,6 @@ defineOptions({
name: 'MEditorDataSourceListPanel', name: 'MEditorDataSourceListPanel',
}); });
defineProps<{
slideType?: SlideType;
}>();
const { dataSourceService } = inject<Services>('services') || {}; const { dataSourceService } = inject<Services>('services') || {};
const editDialog = ref<InstanceType<typeof DataSourceConfigPanel>>(); const editDialog = ref<InstanceType<typeof DataSourceConfigPanel>>();

View File

@ -4,13 +4,3 @@
display: none; display: none;
} }
} }
.m-editor-code-block-editor {
.tmagic-design-table {
height: 180px;
}
.el-drawer__body {
padding: 10px 20px;
}
}

View File

@ -401,12 +401,6 @@ export interface SideBarData {
items: SideItem[]; items: SideItem[];
} }
/**
* drawer
* box
*/
export type SlideType = 'drawer' | 'box';
export interface ComponentItem { export interface ComponentItem {
/** 显示文案 */ /** 显示文案 */
text: string; text: string;