mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-06-11 14:45:10 +08:00
feat(playground): 完善form editor
This commit is contained in:
parent
b72e487b58
commit
538f96c082
@ -2,6 +2,7 @@
|
||||
<div
|
||||
v-if="config"
|
||||
:id="config.id"
|
||||
:data-magic-id="config.id"
|
||||
:style="config.tip ? 'display: flex;align-items: baseline;' : ''"
|
||||
:class="`m-form-container m-container-${type || ''} ${config.className || ''}`"
|
||||
>
|
||||
|
@ -181,7 +181,7 @@ export default class ActionManager extends EventEmitter {
|
||||
return el.id === this.selectedEl?.id;
|
||||
}
|
||||
|
||||
public setSelectedEl(el: HTMLElement): void {
|
||||
public setSelectedEl(el?: HTMLElement): void {
|
||||
this.selectedEl = el;
|
||||
}
|
||||
|
||||
@ -258,7 +258,7 @@ export default class ActionManager extends EventEmitter {
|
||||
}
|
||||
|
||||
public select(el: HTMLElement, event: MouseEvent | undefined): void {
|
||||
this.selectedEl = el;
|
||||
this.setSelectedEl(el);
|
||||
this.clearSelectStatus(SelectStatus.MULTI_SELECT);
|
||||
this.dr.select(el, event);
|
||||
}
|
||||
@ -399,7 +399,7 @@ export default class ActionManager extends EventEmitter {
|
||||
// 如果已有单选选中元素,不是magic-ui-page就可以加入多选列表
|
||||
if (this.selectedEl && !this.selectedEl.className.includes(PAGE_CLASS)) {
|
||||
this.selectedElList.push(this.selectedEl as HTMLElement);
|
||||
this.selectedEl = undefined;
|
||||
this.setSelectedEl(undefined);
|
||||
}
|
||||
// 判断元素是否已在多选列表
|
||||
const existIndex = this.selectedElList.findIndex((selectedDom) => selectedDom.id === el.id);
|
||||
|
@ -156,12 +156,6 @@ export default class StageRender extends EventEmitter {
|
||||
x = x - rect.left;
|
||||
y = y - rect.top;
|
||||
}
|
||||
} else if (this.nativeContainer) {
|
||||
const rect = this.nativeContainer.getClientRects()[0];
|
||||
if (rect) {
|
||||
x = x - rect.left;
|
||||
y = y - rect.top;
|
||||
}
|
||||
}
|
||||
|
||||
return this.getDocument()?.elementsFromPoint(x / this.zoom, y / this.zoom) as HTMLElement[];
|
||||
|
3
playground/src/configs/form-config/checkbox.ts
Normal file
3
playground/src/configs/form-config/checkbox.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import type { FormConfig } from '@tmagic/form';
|
||||
|
||||
export default [] as FormConfig;
|
27
playground/src/configs/form-config/common.ts
Normal file
27
playground/src/configs/form-config/common.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import type { FormConfig } from '@tmagic/form';
|
||||
|
||||
export default [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'hidden',
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
type: 'hidden',
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
text: '表单key',
|
||||
extra: '字段名',
|
||||
},
|
||||
{
|
||||
name: 'text',
|
||||
text: '标签文本',
|
||||
extra: 'label 标签的文本',
|
||||
},
|
||||
{
|
||||
name: 'labelWidth',
|
||||
text: '标签宽度',
|
||||
extra: '表单域标签的的宽度,例如 "50px"。支持 auto。',
|
||||
},
|
||||
] as FormConfig;
|
3
playground/src/configs/form-config/display.ts
Normal file
3
playground/src/configs/form-config/display.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import type { FormConfig } from '@tmagic/form';
|
||||
|
||||
export default [] as FormConfig;
|
13
playground/src/configs/form-config/index.ts
Normal file
13
playground/src/configs/form-config/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import checkbox from './checkbox';
|
||||
import display from './display';
|
||||
import number from './number';
|
||||
import switchConfig from './switch';
|
||||
import text from './text';
|
||||
|
||||
export default {
|
||||
text,
|
||||
checkbox,
|
||||
display,
|
||||
number,
|
||||
switch: switchConfig,
|
||||
};
|
23
playground/src/configs/form-config/number.ts
Normal file
23
playground/src/configs/form-config/number.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import type { FormConfig } from '@tmagic/form';
|
||||
|
||||
export default [
|
||||
{
|
||||
type: 'number',
|
||||
name: 'min',
|
||||
text: '最小值',
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
name: 'max',
|
||||
text: '最大值',
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
name: 'step',
|
||||
text: '步数',
|
||||
},
|
||||
{
|
||||
name: 'placeholder',
|
||||
text: 'placeholder',
|
||||
},
|
||||
] as FormConfig;
|
3
playground/src/configs/form-config/switch.ts
Normal file
3
playground/src/configs/form-config/switch.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import type { FormConfig } from '@tmagic/form';
|
||||
|
||||
export default [] as FormConfig;
|
26
playground/src/configs/form-config/text.ts
Normal file
26
playground/src/configs/form-config/text.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import type { FormConfig } from '@tmagic/form';
|
||||
|
||||
export default [
|
||||
{
|
||||
name: 'placeholder',
|
||||
text: 'placeholder',
|
||||
},
|
||||
{
|
||||
name: 'append',
|
||||
legend: '后置按钮',
|
||||
type: 'fieldset',
|
||||
labelWidth: '80px',
|
||||
items: [
|
||||
{
|
||||
name: 'text',
|
||||
text: '按钮文案',
|
||||
},
|
||||
{
|
||||
name: 'handler',
|
||||
type: 'vs-code',
|
||||
height: '400px',
|
||||
text: '点击',
|
||||
},
|
||||
],
|
||||
},
|
||||
] as FormConfig;
|
@ -43,7 +43,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick, ref, toRaw } from 'vue';
|
||||
import { computed, nextTick, onBeforeUnmount, ref, toRaw } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Coin, Connection, Document } from '@element-plus/icons-vue';
|
||||
import serialize from 'serialize-javascript';
|
||||
@ -233,6 +233,10 @@ editorService.usePlugin({
|
||||
return [config, parent];
|
||||
},
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
editorService.removeAllPlugins();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
@ -4,11 +4,11 @@
|
||||
:menu="menu"
|
||||
:sidebar="sidebar"
|
||||
:component-group-list="componentGroupList"
|
||||
:render-type="RenderType.NATIVE"
|
||||
:props-configs="propsConfigs"
|
||||
:render="render"
|
||||
:can-select="canSelect"
|
||||
:update-drag-el="updateDragEl"
|
||||
:stage-rect="{ width: 'calc(100% - 70px)', height: '100%' }"
|
||||
:moveable-options="{ resizable: false }"
|
||||
>
|
||||
<template #layer-node-label="{ data }">
|
||||
{{ data.text || data.name || 'container' }}
|
||||
@ -17,21 +17,33 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { createApp, nextTick, ref } from 'vue';
|
||||
import { createApp, onBeforeUnmount, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Document } from '@element-plus/icons-vue';
|
||||
import cssStyle from 'element-plus/dist/index.css?raw';
|
||||
|
||||
import { ComponentGroup, MenuBarData, SideBarData, TMagicEditor, traverseNode, uiService } from '@tmagic/editor';
|
||||
import MagicForm, { MForm } from '@tmagic/form';
|
||||
import { MApp, MNode, NodeType } from '@tmagic/schema';
|
||||
import { getOffset, RenderType, RuntimeWindow, TargetElement } from '@tmagic/stage';
|
||||
import { guid } from '@tmagic/utils';
|
||||
import {
|
||||
ComponentGroup,
|
||||
MenuBarData,
|
||||
propsService,
|
||||
SideBarData,
|
||||
TMagicEditor,
|
||||
traverseNode,
|
||||
uiService,
|
||||
} from '@tmagic/editor';
|
||||
import MagicForm, { type FormConfig, MForm } from '@tmagic/form';
|
||||
import { type MApp, type MNode, NodeType } from '@tmagic/schema';
|
||||
import type StageCore from '@tmagic/stage';
|
||||
import { guid, injectStyle } from '@tmagic/utils';
|
||||
|
||||
import propsConfigs from '../configs/form-config';
|
||||
import commonConfig from '../configs/form-config/common';
|
||||
import formDsl from '../configs/formDsl';
|
||||
|
||||
formDsl.forEach((item) => {
|
||||
traverseNode<any>(item, (item) => {
|
||||
item.id = `${item.type}_${guid()}`;
|
||||
item.type = item.type || (item.items ? 'container' : 'text');
|
||||
item.style = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
@ -53,30 +65,43 @@ const config = ref<MApp>({
|
||||
],
|
||||
});
|
||||
|
||||
const render = () => {
|
||||
const el = globalThis.document.createElement('div');
|
||||
el.style.position = 'relative';
|
||||
const render = (stage: StageCore) => {
|
||||
injectStyle(stage.renderer.getDocument()!, cssStyle);
|
||||
injectStyle(
|
||||
stage.renderer.getDocument()!,
|
||||
`
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
`,
|
||||
);
|
||||
|
||||
const el: HTMLDivElement = globalThis.document.createElement('div');
|
||||
el.id = 'app';
|
||||
el.style.overflow = 'auto';
|
||||
createApp(MForm, {
|
||||
config: formDsl,
|
||||
config: config.value.items[0].items,
|
||||
initValues: {},
|
||||
})
|
||||
.use(MagicForm)
|
||||
.mount(el);
|
||||
|
||||
nextTick(() => {
|
||||
(globalThis as unknown as RuntimeWindow).magic.onPageElUpdate(el);
|
||||
stage.renderer.contentWindow?.magic?.onRuntimeReady({});
|
||||
setTimeout(() => {
|
||||
stage.renderer.contentWindow?.magic.onPageElUpdate(el.children[0] as HTMLElement);
|
||||
uiService.set('showRule', false);
|
||||
});
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
const updateDragEl = (el: TargetElement, target: TargetElement, container: HTMLElement) => {
|
||||
const { left, top } = getOffset(container);
|
||||
el.style.left = `${globalThis.parseFloat(el.style.left) - left}px`;
|
||||
el.style.top = `${globalThis.parseFloat(el.style.top) - top}px`;
|
||||
};
|
||||
|
||||
const componentGroupList: ComponentGroup[] = [
|
||||
{
|
||||
title: '容器',
|
||||
@ -162,5 +187,26 @@ const sidebar: SideBarData = {
|
||||
items: ['component-list', 'layer'],
|
||||
};
|
||||
|
||||
const canSelect = (el: HTMLElement) => el.classList.contains('m-form-container');
|
||||
const canSelect = (el: HTMLElement) => Boolean(el.dataset.magicId);
|
||||
|
||||
propsService.usePlugin({
|
||||
afterFillConfig(config: FormConfig, itemConfig: FormConfig) {
|
||||
return [
|
||||
{
|
||||
type: 'tab',
|
||||
items: [
|
||||
{
|
||||
title: '属性',
|
||||
labelWidth: '80px',
|
||||
items: [...commonConfig, ...itemConfig],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
propsService.removeAllPlugins();
|
||||
});
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user