mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-04-06 03:57:56 +08:00
feat(stage,editor): 拖入指定容器支持配置成按住alt才开启
This commit is contained in:
parent
b1ce0be682
commit
4f8ea94ee8
@ -360,6 +360,22 @@ icon使用的是[element-plus icon](https://element-plus.org/zh-CN/component/ico
|
|||||||
|
|
||||||
识别到容器后,会给其dom上添加的class
|
识别到容器后,会给其dom上添加的class
|
||||||
|
|
||||||
|
### containerHighlightType
|
||||||
|
|
||||||
|
- **类型:** 'default' | 'alt' | '';
|
||||||
|
|
||||||
|
- **默认值:** 'default'
|
||||||
|
|
||||||
|
- **详情:**
|
||||||
|
|
||||||
|
启动方式
|
||||||
|
|
||||||
|
default: 停留在画布上启动识别
|
||||||
|
|
||||||
|
alt: 按住alt键启动识别
|
||||||
|
|
||||||
|
其他值:不启动
|
||||||
|
|
||||||
|
|
||||||
## slots
|
## slots
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
<template #props-panel>
|
<template #props-panel>
|
||||||
<slot name="props-panel">
|
<slot name="props-panel">
|
||||||
<props-panel ref="propsPanel" @mounted="(instance) => $emit('props-panel-mounted', instance)">
|
<props-panel ref="propsPanel" @mounted="(instance: any) => $emit('props-panel-mounted', instance)">
|
||||||
<template #props-panel-header>
|
<template #props-panel-header>
|
||||||
<slot name="props-panel-header"></slot>
|
<slot name="props-panel-header"></slot>
|
||||||
</template>
|
</template>
|
||||||
@ -49,7 +49,7 @@ import { EventOption } from '@tmagic/core';
|
|||||||
import type { FormConfig } from '@tmagic/form';
|
import type { FormConfig } from '@tmagic/form';
|
||||||
import type { MApp, MNode } from '@tmagic/schema';
|
import type { MApp, MNode } from '@tmagic/schema';
|
||||||
import type StageCore from '@tmagic/stage';
|
import type StageCore from '@tmagic/stage';
|
||||||
import { CONTAINER_HIGHLIGHT_CLASS, MoveableOptions } from '@tmagic/stage';
|
import { CONTAINER_HIGHLIGHT_CLASS, ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
|
||||||
|
|
||||||
import Framework from './layouts/Framework.vue';
|
import Framework from './layouts/Framework.vue';
|
||||||
import NavMenu from './layouts/NavMenu.vue';
|
import NavMenu from './layouts/NavMenu.vue';
|
||||||
@ -170,6 +170,11 @@ export default defineComponent({
|
|||||||
default: 800,
|
default: 800,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
containerHighlightType: {
|
||||||
|
type: String as PropType<ContainerHighlightType>,
|
||||||
|
default: ContainerHighlightType.DEFAULT,
|
||||||
|
},
|
||||||
|
|
||||||
stageRect: {
|
stageRect: {
|
||||||
type: [String, Object] as PropType<StageRect>,
|
type: [String, Object] as PropType<StageRect>,
|
||||||
},
|
},
|
||||||
@ -289,6 +294,7 @@ export default defineComponent({
|
|||||||
isContainer: props.isContainer,
|
isContainer: props.isContainer,
|
||||||
containerHighlightClassName: props.containerHighlightClassName,
|
containerHighlightClassName: props.containerHighlightClassName,
|
||||||
containerHighlightDuration: props.containerHighlightDuration,
|
containerHighlightDuration: props.containerHighlightDuration,
|
||||||
|
containerHighlightType: props.containerHighlightType,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ watchEffect(() => {
|
|||||||
isContainer: stageOptions.isContainer,
|
isContainer: stageOptions.isContainer,
|
||||||
containerHighlightClassName: stageOptions.containerHighlightClassName,
|
containerHighlightClassName: stageOptions.containerHighlightClassName,
|
||||||
containerHighlightDuration: stageOptions.containerHighlightDuration,
|
containerHighlightDuration: stageOptions.containerHighlightDuration,
|
||||||
|
containerHighlightType: stageOptions.containerHighlightType,
|
||||||
canSelect: (el, event, stop) => {
|
canSelect: (el, event, stop) => {
|
||||||
const elCanSelect = stageOptions.canSelect(el);
|
const elCanSelect = stageOptions.canSelect(el);
|
||||||
// 在组件联动过程中不能再往下选择,返回并触发 ui-select
|
// 在组件联动过程中不能再往下选择,返回并触发 ui-select
|
||||||
|
@ -21,7 +21,7 @@ import type { Component } from 'vue';
|
|||||||
import type { FormConfig } from '@tmagic/form';
|
import type { FormConfig } from '@tmagic/form';
|
||||||
import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
||||||
import type StageCore from '@tmagic/stage';
|
import type StageCore from '@tmagic/stage';
|
||||||
import type { MoveableOptions } from '@tmagic/stage';
|
import type { ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
|
||||||
|
|
||||||
import type { ComponentListService } from './services/componentList';
|
import type { ComponentListService } from './services/componentList';
|
||||||
import type { EditorService } from './services/editor';
|
import type { EditorService } from './services/editor';
|
||||||
@ -53,6 +53,7 @@ export interface StageOptions {
|
|||||||
autoScrollIntoView: boolean;
|
autoScrollIntoView: boolean;
|
||||||
containerHighlightClassName: string;
|
containerHighlightClassName: string;
|
||||||
containerHighlightDuration: number;
|
containerHighlightDuration: number;
|
||||||
|
containerHighlightType: ContainerHighlightType;
|
||||||
render: () => HTMLDivElement;
|
render: () => HTMLDivElement;
|
||||||
moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
|
moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
|
||||||
canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
|
canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
|
||||||
|
@ -21,7 +21,7 @@ import { EventEmitter } from 'events';
|
|||||||
import type { Id } from '@tmagic/schema';
|
import type { Id } from '@tmagic/schema';
|
||||||
import { addClassName } from '@tmagic/utils';
|
import { addClassName } from '@tmagic/utils';
|
||||||
|
|
||||||
import { DEFAULT_ZOOM, GHOST_EL_ID_PREFIX, PAGE_CLASS } from './const';
|
import { CONTAINER_HIGHLIGHT_CLASS, DEFAULT_ZOOM, GHOST_EL_ID_PREFIX, PAGE_CLASS } from './const';
|
||||||
import StageDragResize from './StageDragResize';
|
import StageDragResize from './StageDragResize';
|
||||||
import StageHighlight from './StageHighlight';
|
import StageHighlight from './StageHighlight';
|
||||||
import StageMask from './StageMask';
|
import StageMask from './StageMask';
|
||||||
@ -29,6 +29,7 @@ import StageMultiDragResize from './StageMultiDragResize';
|
|||||||
import StageRender from './StageRender';
|
import StageRender from './StageRender';
|
||||||
import {
|
import {
|
||||||
CanSelect,
|
CanSelect,
|
||||||
|
ContainerHighlightType,
|
||||||
GuidesEventData,
|
GuidesEventData,
|
||||||
IsContainer,
|
IsContainer,
|
||||||
RemoveData,
|
RemoveData,
|
||||||
@ -57,6 +58,7 @@ export default class StageCore extends EventEmitter {
|
|||||||
public zoom = DEFAULT_ZOOM;
|
public zoom = DEFAULT_ZOOM;
|
||||||
public containerHighlightClassName: string;
|
public containerHighlightClassName: string;
|
||||||
public containerHighlightDuration: number;
|
public containerHighlightDuration: number;
|
||||||
|
public containerHighlightType?: ContainerHighlightType;
|
||||||
public isContainer: IsContainer;
|
public isContainer: IsContainer;
|
||||||
|
|
||||||
private canSelect: CanSelect;
|
private canSelect: CanSelect;
|
||||||
@ -69,8 +71,9 @@ export default class StageCore extends EventEmitter {
|
|||||||
this.setZoom(config.zoom);
|
this.setZoom(config.zoom);
|
||||||
this.canSelect = config.canSelect || ((el: HTMLElement) => !!el.id);
|
this.canSelect = config.canSelect || ((el: HTMLElement) => !!el.id);
|
||||||
this.isContainer = config.isContainer;
|
this.isContainer = config.isContainer;
|
||||||
this.containerHighlightClassName = config.containerHighlightClassName;
|
this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS;
|
||||||
this.containerHighlightDuration = config.containerHighlightDuration;
|
this.containerHighlightDuration = config.containerHighlightDuration || 800;
|
||||||
|
this.containerHighlightType = config.containerHighlightType;
|
||||||
|
|
||||||
this.renderer = new StageRender({ core: this });
|
this.renderer = new StageRender({ core: this });
|
||||||
this.mask = new StageMask({ core: this });
|
this.mask = new StageMask({ core: this });
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
|
import KeyController from 'keycon';
|
||||||
import type { MoveableOptions } from 'moveable';
|
import type { MoveableOptions } from 'moveable';
|
||||||
import Moveable from 'moveable';
|
import Moveable from 'moveable';
|
||||||
import MoveableHelper from 'moveable-helper';
|
import MoveableHelper from 'moveable-helper';
|
||||||
@ -29,7 +30,7 @@ import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode, ZIndex } from
|
|||||||
import StageCore from './StageCore';
|
import StageCore from './StageCore';
|
||||||
import StageMask from './StageMask';
|
import StageMask from './StageMask';
|
||||||
import type { StageDragResizeConfig } from './types';
|
import type { StageDragResizeConfig } from './types';
|
||||||
import { StageDragStatus } from './types';
|
import { ContainerHighlightType, StageDragStatus } from './types';
|
||||||
import { calcValueByFontsize, down, getAbsolutePosition, getMode, getOffset, getTargetElStyle, up } from './util';
|
import { calcValueByFontsize, down, getAbsolutePosition, getMode, getOffset, getTargetElStyle, up } from './util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,6 +62,7 @@ export default class StageDragResize extends EventEmitter {
|
|||||||
/** 流式布局下,目标节点的镜像节点 */
|
/** 流式布局下,目标节点的镜像节点 */
|
||||||
private ghostEl: HTMLElement | undefined;
|
private ghostEl: HTMLElement | undefined;
|
||||||
private moveableHelper?: MoveableHelper;
|
private moveableHelper?: MoveableHelper;
|
||||||
|
private isContainerHighlight: Boolean = false;
|
||||||
|
|
||||||
constructor(config: StageDragResizeConfig) {
|
constructor(config: StageDragResizeConfig) {
|
||||||
super();
|
super();
|
||||||
@ -68,6 +70,20 @@ export default class StageDragResize extends EventEmitter {
|
|||||||
this.core = config.core;
|
this.core = config.core;
|
||||||
this.container = config.container;
|
this.container = config.container;
|
||||||
this.mask = config.mask;
|
this.mask = config.mask;
|
||||||
|
|
||||||
|
KeyController.global.keydown('alt', (e) => {
|
||||||
|
e.inputEvent.preventDefault();
|
||||||
|
this.isContainerHighlight = true;
|
||||||
|
});
|
||||||
|
KeyController.global.keyup('alt', (e) => {
|
||||||
|
e.inputEvent.preventDefault();
|
||||||
|
|
||||||
|
const doc = this.core.renderer.contentWindow?.document;
|
||||||
|
if (doc && this.canContainerHighlight()) {
|
||||||
|
removeClassNameByClassName(doc, this.core.containerHighlightClassName);
|
||||||
|
}
|
||||||
|
this.isContainerHighlight = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -302,7 +318,9 @@ export default class StageDragResize extends EventEmitter {
|
|||||||
timeout = undefined;
|
timeout = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]);
|
if (this.canContainerHighlight()) {
|
||||||
|
timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]);
|
||||||
|
}
|
||||||
|
|
||||||
this.dragStatus = StageDragStatus.ING;
|
this.dragStatus = StageDragStatus.ING;
|
||||||
|
|
||||||
@ -325,7 +343,7 @@ export default class StageDragResize extends EventEmitter {
|
|||||||
|
|
||||||
let parentEl: HTMLElement | null = null;
|
let parentEl: HTMLElement | null = null;
|
||||||
|
|
||||||
if (doc) {
|
if (doc && this.canContainerHighlight()) {
|
||||||
parentEl = removeClassNameByClassName(doc, this.core.containerHighlightClassName);
|
parentEl = removeClassNameByClassName(doc, this.core.containerHighlightClassName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,4 +579,11 @@ export default class StageDragResize extends EventEmitter {
|
|||||||
...moveableOptions,
|
...moveableOptions,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private canContainerHighlight() {
|
||||||
|
return (
|
||||||
|
this.core.containerHighlightType === ContainerHighlightType.DEFAULT ||
|
||||||
|
(this.core.containerHighlightType === ContainerHighlightType.ALT && this.isContainerHighlight)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,11 @@ import StageMask from './StageMask';
|
|||||||
export type CanSelect = (el: HTMLElement, event: MouseEvent, stop: () => boolean) => boolean | Promise<boolean>;
|
export type CanSelect = (el: HTMLElement, event: MouseEvent, stop: () => boolean) => boolean | Promise<boolean>;
|
||||||
export type IsContainer = (el: HTMLElement) => boolean | Promise<boolean>;
|
export type IsContainer = (el: HTMLElement) => boolean | Promise<boolean>;
|
||||||
|
|
||||||
|
export enum ContainerHighlightType {
|
||||||
|
DEFAULT = 'default',
|
||||||
|
ALT = 'alt',
|
||||||
|
}
|
||||||
|
|
||||||
export type StageCoreConfig = {
|
export type StageCoreConfig = {
|
||||||
/** 需要对齐的dom节点的CSS选择器字符串 */
|
/** 需要对齐的dom节点的CSS选择器字符串 */
|
||||||
snapElementQuerySelector?: string;
|
snapElementQuerySelector?: string;
|
||||||
@ -36,8 +41,9 @@ export type StageCoreConfig = {
|
|||||||
zoom?: number;
|
zoom?: number;
|
||||||
canSelect?: CanSelect;
|
canSelect?: CanSelect;
|
||||||
isContainer: IsContainer;
|
isContainer: IsContainer;
|
||||||
containerHighlightClassName: string;
|
containerHighlightClassName?: string;
|
||||||
containerHighlightDuration: number;
|
containerHighlightDuration?: number;
|
||||||
|
containerHighlightType?: ContainerHighlightType;
|
||||||
moveableOptions?: ((core?: StageCore) => MoveableOptions) | MoveableOptions;
|
moveableOptions?: ((core?: StageCore) => MoveableOptions) | MoveableOptions;
|
||||||
multiMoveableOptions?: ((core?: StageCore) => MoveableOptions) | MoveableOptions;
|
multiMoveableOptions?: ((core?: StageCore) => MoveableOptions) | MoveableOptions;
|
||||||
/** runtime 的HTML地址,可以是一个HTTP地址,如果和编辑器不同域,需要设置跨域,也可以是一个相对或绝对路径 */
|
/** runtime 的HTML地址,可以是一个HTTP地址,如果和编辑器不同域,需要设置跨域,也可以是一个相对或绝对路径 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user