From 1c6c9ab3e86420fcf17ae00c4ec4ec65c6015e19 Mon Sep 17 00:00:00 2001 From: roymondchen Date: Tue, 19 Sep 2023 17:39:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(editor,stage):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E9=BC=A0=E6=A0=87=E6=82=AC=E5=81=9C=E5=9C=A8=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E4=B8=8A=E6=98=BE=E7=A4=BA=E5=BD=93=E5=89=8D=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E4=B8=8B=E6=89=80=E6=9C=89=E7=BB=84=E4=BB=B6=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../editor/src/components/ContentMenu.vue | 130 +++++++++----- packages/editor/src/components/Resizer.vue | 38 +---- packages/editor/src/components/SplitView.vue | 5 +- packages/editor/src/hooks/use-getso.ts | 35 ++++ packages/editor/src/icons/PinIcon.vue | 25 +++ packages/editor/src/icons/PinnedIcon.vue | 25 +++ packages/editor/src/index.ts | 2 + .../src/layouts/workspace/Workspace.vue | 2 +- .../layouts/workspace/viewer/NodeListMenu.vue | 159 ++++++++++++++++++ .../workspace/viewer/NodeListMenuTitle.vue | 68 ++++++++ .../layouts/workspace/{ => viewer}/Stage.vue | 2 + .../workspace/{ => viewer}/ViewerMenu.vue | 0 packages/editor/src/theme/content-menu.scss | 26 ++- packages/editor/src/theme/index.scss | 8 + packages/editor/src/type.ts | 2 + .../unit/layouts/workspace/Stage.spec.ts | 2 +- packages/stage/src/ActionManager.ts | 14 +- packages/stage/src/StageCore.ts | 23 ++- packages/stage/src/StageDragResize.ts | 5 + packages/stage/src/index.ts | 2 +- 20 files changed, 493 insertions(+), 80 deletions(-) create mode 100644 packages/editor/src/hooks/use-getso.ts create mode 100644 packages/editor/src/icons/PinIcon.vue create mode 100644 packages/editor/src/icons/PinnedIcon.vue create mode 100644 packages/editor/src/layouts/workspace/viewer/NodeListMenu.vue create mode 100644 packages/editor/src/layouts/workspace/viewer/NodeListMenuTitle.vue rename packages/editor/src/layouts/workspace/{ => viewer}/Stage.vue (97%) rename packages/editor/src/layouts/workspace/{ => viewer}/ViewerMenu.vue (100%) diff --git a/packages/editor/src/components/ContentMenu.vue b/packages/editor/src/components/ContentMenu.vue index 9b21b44e..79812e2f 100644 --- a/packages/editor/src/components/ContentMenu.vue +++ b/packages/editor/src/components/ContentMenu.vue @@ -1,31 +1,42 @@ diff --git a/packages/editor/src/components/Resizer.vue b/packages/editor/src/components/Resizer.vue index af9ce030..dd17d88c 100644 --- a/packages/editor/src/components/Resizer.vue +++ b/packages/editor/src/components/Resizer.vue @@ -5,41 +5,19 @@ diff --git a/packages/editor/src/components/SplitView.vue b/packages/editor/src/components/SplitView.vue index 6aa7abbb..83c5ae33 100644 --- a/packages/editor/src/components/SplitView.vue +++ b/packages/editor/src/components/SplitView.vue @@ -22,6 +22,7 @@ diff --git a/packages/editor/src/icons/PinnedIcon.vue b/packages/editor/src/icons/PinnedIcon.vue new file mode 100644 index 00000000..6659822d --- /dev/null +++ b/packages/editor/src/icons/PinnedIcon.vue @@ -0,0 +1,25 @@ + + + diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index 0bab250b..7989a8a2 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -37,6 +37,8 @@ import type { InstallOptions } from './type'; import './theme/index.scss'; +export type { OnDrag } from 'gesto'; + export type { MoveableOptions } from '@tmagic/stage'; export * from './type'; export * from './hooks'; diff --git a/packages/editor/src/layouts/workspace/Workspace.vue b/packages/editor/src/layouts/workspace/Workspace.vue index 2124d732..1501b864 100644 --- a/packages/editor/src/layouts/workspace/Workspace.vue +++ b/packages/editor/src/layouts/workspace/Workspace.vue @@ -20,9 +20,9 @@ import { computed, inject } from 'vue'; import { MenuButton, MenuComponent, Services } from '@editor/type'; +import MagicStage from './viewer/Stage.vue'; import Breadcrumb from './Breadcrumb.vue'; import PageBar from './PageBar.vue'; -import MagicStage from './Stage.vue'; defineOptions({ name: 'MEditorWorkspace', diff --git a/packages/editor/src/layouts/workspace/viewer/NodeListMenu.vue b/packages/editor/src/layouts/workspace/viewer/NodeListMenu.vue new file mode 100644 index 00000000..b08c3fa2 --- /dev/null +++ b/packages/editor/src/layouts/workspace/viewer/NodeListMenu.vue @@ -0,0 +1,159 @@ + + + diff --git a/packages/editor/src/layouts/workspace/viewer/NodeListMenuTitle.vue b/packages/editor/src/layouts/workspace/viewer/NodeListMenuTitle.vue new file mode 100644 index 00000000..226b96b1 --- /dev/null +++ b/packages/editor/src/layouts/workspace/viewer/NodeListMenuTitle.vue @@ -0,0 +1,68 @@ + + + diff --git a/packages/editor/src/layouts/workspace/Stage.vue b/packages/editor/src/layouts/workspace/viewer/Stage.vue similarity index 97% rename from packages/editor/src/layouts/workspace/Stage.vue rename to packages/editor/src/layouts/workspace/viewer/Stage.vue index 9ff4cdc2..3a64a445 100644 --- a/packages/editor/src/layouts/workspace/Stage.vue +++ b/packages/editor/src/layouts/workspace/viewer/Stage.vue @@ -24,6 +24,7 @@ > + @@ -40,6 +41,7 @@ import { useStage } from '@editor/hooks/use-stage'; import { Layout, MenuButton, MenuComponent, Services, StageOptions } from '@editor/type'; import { getConfig } from '@editor/utils/config'; +import NodeListMenu from './NodeListMenu.vue'; import ViewerMenu from './ViewerMenu.vue'; defineOptions({ diff --git a/packages/editor/src/layouts/workspace/ViewerMenu.vue b/packages/editor/src/layouts/workspace/viewer/ViewerMenu.vue similarity index 100% rename from packages/editor/src/layouts/workspace/ViewerMenu.vue rename to packages/editor/src/layouts/workspace/viewer/ViewerMenu.vue diff --git a/packages/editor/src/theme/content-menu.scss b/packages/editor/src/theme/content-menu.scss index e50db50e..93b8243b 100644 --- a/packages/editor/src/theme/content-menu.scss +++ b/packages/editor/src/theme/content-menu.scss @@ -3,12 +3,13 @@ font-size: 12px; background: #fff; box-shadow: 0 2px 8px 2px rgba(68, 73, 77, 0.16); - z-index: 9999; + z-index: 1000; transform-origin: 0% 0%; font-weight: 600; padding: 4px 0px; overflow: auto; max-height: 80%; + min-width: 180px; .menu-item { color: #333; @@ -43,8 +44,31 @@ } } + &.active { + background-color: $--theme-color; + .tmagic-design-button, + .tmagic-design-button:active, + .tmagic-design-button:focus { + color: #fff; + background-color: $--theme-color; + } + + &.menu-item i { + color: #fff; + } + } + &:hover { background-color: $--hover-color; + .tmagic-design-button, + .tmagic-design-button:active, + .tmagic-design-button:focus { + color: $--font-color; + } + + &.menu-item i { + color: $--font-color; + } } } } diff --git a/packages/editor/src/theme/index.scss b/packages/editor/src/theme/index.scss index b7f90e8a..d26c45c4 100644 --- a/packages/editor/src/theme/index.scss +++ b/packages/editor/src/theme/index.scss @@ -1,2 +1,10 @@ @import "./common/var.scss"; @import "./theme.scss"; + +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.5s; +} +.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { + opacity: 0; +} diff --git a/packages/editor/src/type.ts b/packages/editor/src/type.ts index c0cddfd3..6e2b4aef 100644 --- a/packages/editor/src/type.ts +++ b/packages/editor/src/type.ts @@ -201,6 +201,8 @@ export interface MenuButton { className?: string; /** type为dropdown时,下拉的菜单列表, 或者有子菜单时 */ items?: MenuButton[]; + /** 唯一标识,用于高亮 */ + id?: string | number; } export interface MenuComponent { diff --git a/packages/editor/tests/unit/layouts/workspace/Stage.spec.ts b/packages/editor/tests/unit/layouts/workspace/Stage.spec.ts index 8c767bf6..1ccea68e 100644 --- a/packages/editor/tests/unit/layouts/workspace/Stage.spec.ts +++ b/packages/editor/tests/unit/layouts/workspace/Stage.spec.ts @@ -20,7 +20,7 @@ import { mount } from '@vue/test-utils'; import { NodeType } from '@tmagic/schema'; -import Stage from '@editor/layouts/workspace/Stage.vue'; +import Stage from '@editor/layouts/workspace/viewer/Stage.vue'; globalThis.ResizeObserver = globalThis.ResizeObserver || diff --git a/packages/stage/src/ActionManager.ts b/packages/stage/src/ActionManager.ts index 1ec2b5e7..f97f2919 100644 --- a/packages/stage/src/ActionManager.ts +++ b/packages/stage/src/ActionManager.ts @@ -19,7 +19,7 @@ import EventEmitter from 'events'; import KeyController from 'keycon'; import { throttle } from 'lodash-es'; -import type { MoveableOptions } from 'moveable'; +import type { MoveableOptions, OnDragStart } from 'moveable'; import { Env } from '@tmagic/core'; import type { Id } from '@tmagic/schema'; @@ -88,6 +88,9 @@ export default class ActionManager extends EventEmitter { this.clearHighlight(); return; } + + this.emit('mousemove', event); + this.highlight(el); }, throttleTime); @@ -204,6 +207,8 @@ export default class ActionManager extends EventEmitter { public async getElementFromPoint(event: MouseEvent): Promise { const els = this.getElementsFromPoint(event as Point); + this.emit('get-elements-from-point', els); + let stopped = false; const stop = () => (stopped = true); for (const el of els) { @@ -343,6 +348,10 @@ export default class ActionManager extends EventEmitter { return undefined; } + public getDragStatus() { + return this.dr.getDragStatus(); + } + public destroy(): void { this.container.removeEventListener('mousedown', this.mouseDownHandler); this.container.removeEventListener('mousemove', this.mouseMoveHandler); @@ -484,6 +493,9 @@ export default class ActionManager extends EventEmitter { data: [{ el: drTarget }], }; this.emit('remove', data); + }) + .on('drag-start', (e: OnDragStart) => { + this.emit('drag-start', e); }); this.multiDr diff --git a/packages/stage/src/StageCore.ts b/packages/stage/src/StageCore.ts index 26627dd5..fd9fd211 100644 --- a/packages/stage/src/StageCore.ts +++ b/packages/stage/src/StageCore.ts @@ -18,7 +18,7 @@ import { EventEmitter } from 'events'; -import type { MoveableOptions } from 'moveable'; +import type { MoveableOptions, OnDragStart } from 'moveable'; import type { Id } from '@tmagic/schema'; @@ -217,6 +217,10 @@ export default class StageCore extends EventEmitter { return this.actionManager.getMoveableOption(key); } + public getDragStatus() { + return this.actionManager.getDragStatus(); + } + /** * 销毁实例 */ @@ -292,6 +296,7 @@ export default class StageCore extends EventEmitter { this.initDrEvent(); this.initMulDrEvent(); this.initHighlightEvent(); + this.initMouseEvent(); } /** @@ -356,4 +361,20 @@ export default class StageCore extends EventEmitter { this.emit('highlight', highlightEl); }); } + + /** + * 初始化Highlight类通过ActionManager抛出来的事件监听 + */ + private initMouseEvent(): void { + this.actionManager + .on('mousemove', async (event: MouseEvent) => { + this.emit('mousemove', event); + }) + .on('mouseleave', async (event: MouseEvent) => { + this.emit('mouseleave', event); + }) + .on('drag-start', (e: OnDragStart) => { + this.emit('drag-start', e); + }); + } } diff --git a/packages/stage/src/StageDragResize.ts b/packages/stage/src/StageDragResize.ts index 18615782..f5397eb2 100644 --- a/packages/stage/src/StageDragResize.ts +++ b/packages/stage/src/StageDragResize.ts @@ -105,6 +105,10 @@ export default class StageDragResize extends MoveableOptionsManager { this.moveable.updateRect(); } + public getDragStatus(): StageDragStatus { + return this.dragStatus; + } + /** * 销毁实例 */ @@ -187,6 +191,7 @@ export default class StageDragResize extends MoveableOptionsManager { this.dragStatus = StageDragStatus.START; this.dragResizeHelper.onDragStart(e); + this.emit('drag-start', e); }) .on('drag', (e) => { if (!this.target || !this.dragResizeHelper.getShadowEl()) return; diff --git a/packages/stage/src/index.ts b/packages/stage/src/index.ts index 80818688..0b49aa72 100644 --- a/packages/stage/src/index.ts +++ b/packages/stage/src/index.ts @@ -18,7 +18,7 @@ import StageCore from './StageCore'; -export type { MoveableOptions } from 'moveable'; +export type { MoveableOptions, OnDragStart } from 'moveable'; export { default as StageRender } from './StageRender'; export { default as StageMask } from './StageMask'; export { default as StageDragResize } from './StageDragResize';