feat(脑图): 脑图快捷键屏蔽&脑图拖拽拦截&部分样式调整 (#31248)
Co-authored-by: baiqi <qi.bai@fit2cloud.com>
This commit is contained in:
parent
fdafb1236a
commit
800fcdb2ad
|
@ -469,7 +469,6 @@
|
||||||
|
|
||||||
/** radio **/
|
/** radio **/
|
||||||
.arco-radio-group-button {
|
.arco-radio-group-button {
|
||||||
padding: 1px;
|
|
||||||
background-color: var(--color-text-n8);
|
background-color: var(--color-text-n8);
|
||||||
.arco-radio-button {
|
.arco-radio-button {
|
||||||
@apply bg-transparent;
|
@apply bg-transparent;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
@content-change="handleContentChange"
|
@content-change="handleContentChange"
|
||||||
@node-select="handleNodeSelect"
|
@node-select="handleNodeSelect"
|
||||||
@action="handleAction"
|
@action="handleAction"
|
||||||
|
@before-exec-command="handleBeforeExecCommand"
|
||||||
@save="handleMinderSave"
|
@save="handleMinderSave"
|
||||||
>
|
>
|
||||||
<template #extractTabContent>
|
<template #extractTabContent>
|
||||||
|
@ -44,7 +45,12 @@
|
||||||
|
|
||||||
import { FormItem } from '@/components/pure/ms-form-create/types';
|
import { FormItem } from '@/components/pure/ms-form-create/types';
|
||||||
import MsMinderEditor from '@/components/pure/ms-minder-editor/minderEditor.vue';
|
import MsMinderEditor from '@/components/pure/ms-minder-editor/minderEditor.vue';
|
||||||
import type { MinderJson, MinderJsonNode, MinderJsonNodeData } from '@/components/pure/ms-minder-editor/props';
|
import type {
|
||||||
|
MinderEvent,
|
||||||
|
MinderJson,
|
||||||
|
MinderJsonNode,
|
||||||
|
MinderJsonNodeData,
|
||||||
|
} from '@/components/pure/ms-minder-editor/props';
|
||||||
import { MsFileItem } from '@/components/pure/ms-upload/types';
|
import { MsFileItem } from '@/components/pure/ms-upload/types';
|
||||||
import attachment from './attachment.vue';
|
import attachment from './attachment.vue';
|
||||||
import baseInfo from './basInfo.vue';
|
import baseInfo from './basInfo.vue';
|
||||||
|
@ -60,7 +66,7 @@
|
||||||
} from '@/api/modules/case-management/featureCase';
|
} from '@/api/modules/case-management/featureCase';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { MinderEvent } from '@/store/modules/components/minder-editor/types';
|
import { MinderCustomEvent } from '@/store/modules/components/minder-editor/types';
|
||||||
import { filterTree, getGenerateId, mapTree } from '@/utils';
|
import { filterTree, getGenerateId, mapTree } from '@/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -805,7 +811,7 @@
|
||||||
* 处理脑图节点操作
|
* 处理脑图节点操作
|
||||||
* @param event 脑图事件对象
|
* @param event 脑图事件对象
|
||||||
*/
|
*/
|
||||||
function handleAction(event: MinderEvent) {
|
function handleAction(event: MinderCustomEvent) {
|
||||||
const { node, name } = event;
|
const { node, name } = event;
|
||||||
if (node) {
|
if (node) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
|
@ -831,6 +837,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleBeforeExecCommand(event: MinderEvent) {
|
||||||
|
if (event.commandName === 'movetoparent') {
|
||||||
|
// TODO:拖拽拦截
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|
|
@ -83,9 +83,8 @@
|
||||||
class="list-item-action flex flex-row items-center gap-[8px] opacity-0"
|
class="list-item-action flex flex-row items-center gap-[8px] opacity-0"
|
||||||
:class="{ '!opacity-100': element.id === currentId }"
|
:class="{ '!opacity-100': element.id === currentId }"
|
||||||
>
|
>
|
||||||
<div class="icon-button">
|
<div v-if="element.type === systemType" class="icon-button">
|
||||||
<MsIcon
|
<MsIcon
|
||||||
v-if="element.type === systemType"
|
|
||||||
v-permission="props.updatePermission"
|
v-permission="props.updatePermission"
|
||||||
type="icon-icon_add_outlined"
|
type="icon-icon_add_outlined"
|
||||||
size="16"
|
size="16"
|
||||||
|
@ -213,9 +212,8 @@
|
||||||
class="list-item-action flex flex-row items-center gap-[8px] opacity-0"
|
class="list-item-action flex flex-row items-center gap-[8px] opacity-0"
|
||||||
:class="{ '!opacity-100': element.id === currentId }"
|
:class="{ '!opacity-100': element.id === currentId }"
|
||||||
>
|
>
|
||||||
<div class="icon-button">
|
<div v-if="element.type === systemType" class="icon-button">
|
||||||
<MsIcon
|
<MsIcon
|
||||||
v-if="element.type === systemType"
|
|
||||||
v-permission="props.updatePermission"
|
v-permission="props.updatePermission"
|
||||||
type="icon-icon_add_outlined"
|
type="icon-icon_add_outlined"
|
||||||
size="16"
|
size="16"
|
||||||
|
@ -317,9 +315,8 @@
|
||||||
class="list-item-action flex flex-row items-center gap-[8px] opacity-0"
|
class="list-item-action flex flex-row items-center gap-[8px] opacity-0"
|
||||||
:class="{ '!opacity-100': element.id === currentId }"
|
:class="{ '!opacity-100': element.id === currentId }"
|
||||||
>
|
>
|
||||||
<div class="icon-button">
|
<div v-if="element.type === systemType" class="icon-button">
|
||||||
<MsIcon
|
<MsIcon
|
||||||
v-if="element.type === systemType"
|
|
||||||
v-permission="props.updatePermission"
|
v-permission="props.updatePermission"
|
||||||
type="icon-icon_add_outlined"
|
type="icon-icon_add_outlined"
|
||||||
size="16"
|
size="16"
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import { debounce } from 'lodash-es';
|
import { debounce } from 'lodash-es';
|
||||||
|
|
||||||
import useMinderStore from '@/store/modules/components/minder-editor/index';
|
import useMinderStore from '@/store/modules/components/minder-editor/index';
|
||||||
import type { MinderEvent } from '@/store/modules/components/minder-editor/types';
|
import type { MinderCustomEvent } from '@/store/modules/components/minder-editor/types';
|
||||||
|
|
||||||
import type { MinderJsonNode } from '../props';
|
import type { MinderEvent, MinderJsonNode } from '../props';
|
||||||
|
|
||||||
export interface UseEventListenerProps {
|
export interface UseEventListenerProps {
|
||||||
handleContentChange?: (node: MinderJsonNode) => void;
|
handleContentChange?: (node: MinderJsonNode) => void;
|
||||||
handleSelectionChange?: (node: MinderJsonNode) => void;
|
handleSelectionChange?: (node: MinderJsonNode) => void;
|
||||||
handleMinderEvent?: (event: MinderEvent) => void;
|
handleMinderEvent?: (event: MinderCustomEvent) => void;
|
||||||
|
handleBeforeExecCommand?: (event: MinderEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function useEventListener(listener: UseEventListenerProps) {
|
export default function useEventListener(listener: UseEventListenerProps) {
|
||||||
|
@ -34,6 +35,21 @@ export default function useEventListener(listener: UseEventListenerProps) {
|
||||||
}, 300)
|
}, 300)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// minder.on('dragStart', () => {
|
||||||
|
// const node: MinderJsonNode = minder.getSelectedNode();
|
||||||
|
// console.log('dragStart', node);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// minder.on('dragFinish', () => {
|
||||||
|
// console.log('dragFinish', minder.history);
|
||||||
|
// });
|
||||||
|
|
||||||
|
minder.on('beforeExecCommand', (e: any) => {
|
||||||
|
if (listener.handleBeforeExecCommand) {
|
||||||
|
listener.handleBeforeExecCommand(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 监听脑图自定义事件
|
// 监听脑图自定义事件
|
||||||
watch(
|
watch(
|
||||||
() => minderStore.event.timestamp,
|
() => minderStore.event.timestamp,
|
|
@ -67,15 +67,16 @@
|
||||||
import minderHeader from './main/header.vue';
|
import minderHeader from './main/header.vue';
|
||||||
import mainEditor from './main/mainEditor.vue';
|
import mainEditor from './main/mainEditor.vue';
|
||||||
|
|
||||||
import { MinderEvent } from '@/store/modules/components/minder-editor/types';
|
import { MinderCustomEvent } from '@/store/modules/components/minder-editor/types';
|
||||||
|
|
||||||
import useEventListener from './hooks/useEventListener';
|
import useMinderEventListener from './hooks/useMinderEventListener';
|
||||||
import {
|
import {
|
||||||
delProps,
|
delProps,
|
||||||
editMenuProps,
|
editMenuProps,
|
||||||
headerProps,
|
headerProps,
|
||||||
insertProps,
|
insertProps,
|
||||||
mainEditorProps,
|
mainEditorProps,
|
||||||
|
MinderEvent,
|
||||||
MinderJsonNode,
|
MinderJsonNode,
|
||||||
moleProps,
|
moleProps,
|
||||||
priorityProps,
|
priorityProps,
|
||||||
|
@ -90,7 +91,8 @@
|
||||||
(e: 'enterNode', data: MinderJsonNode): void;
|
(e: 'enterNode', data: MinderJsonNode): void;
|
||||||
(e: 'nodeSelect', data: MinderJsonNode): void;
|
(e: 'nodeSelect', data: MinderJsonNode): void;
|
||||||
(e: 'contentChange', data: MinderJsonNode): void;
|
(e: 'contentChange', data: MinderJsonNode): void;
|
||||||
(e: 'action', event: MinderEvent): void;
|
(e: 'action', event: MinderCustomEvent): void;
|
||||||
|
(e: 'beforeExecCommand', event: MinderEvent): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -132,7 +134,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
useEventListener({
|
useMinderEventListener({
|
||||||
handleSelectionChange: () => {
|
handleSelectionChange: () => {
|
||||||
const selectedNode: MinderJsonNode = window.minder.getSelectedNode();
|
const selectedNode: MinderJsonNode = window.minder.getSelectedNode();
|
||||||
if (Object.keys(window.minder).length > 0 && selectedNode) {
|
if (Object.keys(window.minder).length > 0 && selectedNode) {
|
||||||
|
@ -145,6 +147,9 @@
|
||||||
handleMinderEvent: (event) => {
|
handleMinderEvent: (event) => {
|
||||||
emit('action', event);
|
emit('action', event);
|
||||||
},
|
},
|
||||||
|
handleBeforeExecCommand: (event) => {
|
||||||
|
emit('beforeExecCommand', event);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -6,6 +6,19 @@ import type { MoveMode } from '@/models/common';
|
||||||
|
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
|
|
||||||
|
export interface MinderClass {
|
||||||
|
stopPropagation: () => void; // 阻止事件冒泡
|
||||||
|
stopPropagationImmediately: () => void; // 立即阻止事件冒泡
|
||||||
|
[key: string]: any; // TODO: 其他事件属性
|
||||||
|
}
|
||||||
|
// TODO:脑图事件类型补充
|
||||||
|
export interface MinderEvent extends MinderClass {
|
||||||
|
command: any;
|
||||||
|
commandArgs: Record<string, any>[];
|
||||||
|
commandName: string;
|
||||||
|
minder: any;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
export interface MinderIconButtonItem {
|
export interface MinderIconButtonItem {
|
||||||
icon: string;
|
icon: string;
|
||||||
tooltip: string;
|
tooltip: string;
|
||||||
|
|
|
@ -22,11 +22,13 @@ function createDragRuntime(this: DragRuntimeOptions) {
|
||||||
// when jumped to drag mode, enter
|
// when jumped to drag mode, enter
|
||||||
fsm.when('* -> drag', () => {
|
fsm.when('* -> drag', () => {
|
||||||
// now is drag mode
|
// now is drag mode
|
||||||
|
minder.fire('dragStart');
|
||||||
});
|
});
|
||||||
|
|
||||||
fsm.when('drag -> *', (exit: any, enter: any, reason: string) => {
|
fsm.when('drag -> *', (exit: any, enter: any, reason: string) => {
|
||||||
if (reason === 'drag-finish') {
|
if (reason === 'drag-finish') {
|
||||||
// now exit drag mode
|
// now exit drag mode
|
||||||
|
minder.fire('dragFinish');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,6 @@ function handlerConditionMatch(condition: any, when: string, exit: string, enter
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handler = () => void & {
|
|
||||||
condition: {
|
|
||||||
when: string;
|
|
||||||
exit: string;
|
|
||||||
enter: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
class FSM {
|
class FSM {
|
||||||
private currentState: string;
|
private currentState: string;
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,7 @@ export default function HistoryRuntime(this: { minder: any; hotbox: any; editTex
|
||||||
hasUndo,
|
hasUndo,
|
||||||
hasRedo,
|
hasRedo,
|
||||||
};
|
};
|
||||||
|
window.minderHistory = this.history;
|
||||||
reset();
|
reset();
|
||||||
minder.on('contentchange', changed);
|
minder.on('contentchange', changed);
|
||||||
minder.on('import', reset);
|
minder.on('import', reset);
|
||||||
|
|
|
@ -7,7 +7,7 @@ export interface MinderNodePosition {
|
||||||
y: number;
|
y: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MinderEvent {
|
export interface MinderCustomEvent {
|
||||||
name: MinderEventName;
|
name: MinderEventName;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
nodePosition?: MinderNodePosition;
|
nodePosition?: MinderNodePosition;
|
||||||
|
@ -16,6 +16,6 @@ export interface MinderEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MinderState {
|
export interface MinderState {
|
||||||
event: MinderEvent;
|
event: MinderCustomEvent;
|
||||||
mold: number;
|
mold: number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
class="mb-[16px] flex items-center"
|
class="mb-[16px] flex items-center"
|
||||||
:class="{ 'justify-between': hasAddPermission, 'justify-end': !hasAddPermission }"
|
:class="{ 'justify-between': hasAddPermission, 'justify-end': !hasAddPermission }"
|
||||||
>
|
>
|
||||||
<a-button v-permission="['ORGANIZATION_PROJECT:READ+ADD']" type="primary" @click="showAddProject">{{
|
<a-button v-permission="['ORGANIZATION_PROJECT:READ+ADD']" type="primary" @click="showAddProject">
|
||||||
t('system.organization.createProject')
|
{{ t('system.organization.createProject') }}
|
||||||
}}</a-button>
|
</a-button>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
:placeholder="t('system.organization.searchIndexPlaceholder')"
|
:placeholder="t('system.organization.searchIndexPlaceholder')"
|
||||||
|
@ -22,15 +22,16 @@
|
||||||
<a-tooltip class="tooltip-white">
|
<a-tooltip class="tooltip-white">
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="flex flex-row">
|
<div class="flex flex-row">
|
||||||
<span class="text-[var(--color-text-1)]">{{
|
<span class="text-[var(--color-text-1)]">
|
||||||
t('system.project.revokeDeleteToolTip', { count: record.remainDayCount })
|
{{ t('system.project.revokeDeleteToolTip', { count: record.remainDayCount }) }}
|
||||||
}}</span>
|
</span>
|
||||||
<MsButton
|
<MsButton
|
||||||
v-if="hasAnyPermission(['ORGANIZATION_PROJECT:READ+RECOVER'])"
|
v-if="hasAnyPermission(['ORGANIZATION_PROJECT:READ+RECOVER'])"
|
||||||
class="ml-[8px]"
|
class="ml-[8px]"
|
||||||
@click="handleRevokeDelete(record)"
|
@click="handleRevokeDelete(record)"
|
||||||
>{{ t('common.revokeDelete') }}</MsButton
|
|
||||||
>
|
>
|
||||||
|
{{ t('common.revokeDelete') }}
|
||||||
|
</MsButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<MsIcon v-if="record.deleted" type="icon-icon_alarm_clock" class="ml-[4px] text-[rgb(var(--danger-6))]" />
|
<MsIcon v-if="record.deleted" type="icon-icon_alarm_clock" class="ml-[4px] text-[rgb(var(--danger-6))]" />
|
||||||
|
@ -44,34 +45,35 @@
|
||||||
v-if="hasAnyPermission(['ORGANIZATION_PROJECT:READ+ADD_MEMBER', 'ORGANIZATION_PROJECT:READ'])"
|
v-if="hasAnyPermission(['ORGANIZATION_PROJECT:READ+ADD_MEMBER', 'ORGANIZATION_PROJECT:READ'])"
|
||||||
class="cursor-pointer text-[rgb(var(--primary-5))]"
|
class="cursor-pointer text-[rgb(var(--primary-5))]"
|
||||||
@click="showUserDrawer(record)"
|
@click="showUserDrawer(record)"
|
||||||
>{{ record.memberCount }}</span
|
|
||||||
>
|
>
|
||||||
|
{{ record.memberCount }}
|
||||||
|
</span>
|
||||||
<span v-else>{{ record.memberCount }}</span>
|
<span v-else>{{ record.memberCount }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template #operation="{ record }">
|
<template #operation="{ record }">
|
||||||
<template v-if="record.deleted">
|
<template v-if="record.deleted">
|
||||||
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+RECOVER']" @click="handleRevokeDelete(record)">{{
|
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+RECOVER']" @click="handleRevokeDelete(record)">
|
||||||
t('common.revokeDelete')
|
{{ t('common.revokeDelete') }}
|
||||||
}}</MsButton>
|
</MsButton>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="!record.enable">
|
<template v-else-if="!record.enable">
|
||||||
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+UPDATE']" @click="handleEnableOrDisableProject(record)">{{
|
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+UPDATE']" @click="handleEnableOrDisableProject(record)">
|
||||||
t('common.enable')
|
{{ t('common.enable') }}
|
||||||
}}</MsButton>
|
</MsButton>
|
||||||
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+DELETE']" @click="handleDelete(record)">{{
|
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+DELETE']" @click="handleDelete(record)">
|
||||||
t('common.delete')
|
{{ t('common.delete') }}
|
||||||
}}</MsButton>
|
</MsButton>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+UPDATE']" @click="showAddProjectModal(record)">{{
|
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+UPDATE']" @click="showAddProjectModal(record)">
|
||||||
t('common.edit')
|
{{ t('common.edit') }}
|
||||||
}}</MsButton>
|
</MsButton>
|
||||||
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+ADD_MEMBER']" @click="showAddUserModal(record)">{{
|
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+ADD_MEMBER']" @click="showAddUserModal(record)">
|
||||||
t('system.organization.addMember')
|
{{ t('system.organization.addMember') }}
|
||||||
}}</MsButton>
|
</MsButton>
|
||||||
<MsButton v-permission="['PROJECT_BASE_INFO:READ']" @click="enterProject(record.id)">{{
|
<MsButton v-permission="['PROJECT_BASE_INFO:READ']" @click="enterProject(record.id)">
|
||||||
t('system.project.enterProject')
|
{{ t('system.project.enterProject') }}
|
||||||
}}</MsButton>
|
</MsButton>
|
||||||
<MsTableMoreAction
|
<MsTableMoreAction
|
||||||
v-permission="['ORGANIZATION_PROJECT:READ+DELETE']"
|
v-permission="['ORGANIZATION_PROJECT:READ+DELETE']"
|
||||||
:list="tableActions"
|
:list="tableActions"
|
||||||
|
|
|
@ -46,6 +46,13 @@ declare interface Window {
|
||||||
minderEditor: Record<string, any>;
|
minderEditor: Record<string, any>;
|
||||||
km: Record<string, any>;
|
km: Record<string, any>;
|
||||||
canvg: (canvas: HTMLCanvasElement, xml: string, option: Record<string, any>) => void;
|
canvg: (canvas: HTMLCanvasElement, xml: string, option: Record<string, any>) => void;
|
||||||
|
minderHistory: {
|
||||||
|
reset: () => void;
|
||||||
|
undo: () => void;
|
||||||
|
redo: () => void;
|
||||||
|
hasUndo: () => boolean;
|
||||||
|
hasRedo: () => boolean;
|
||||||
|
};
|
||||||
DTFrameLogin: (
|
DTFrameLogin: (
|
||||||
frameParams: IDTLoginFrameParams, // DOM包裹容器相关参数
|
frameParams: IDTLoginFrameParams, // DOM包裹容器相关参数
|
||||||
loginParams: IDTLoginLoginParams, // 统一登录参数
|
loginParams: IDTLoginLoginParams, // 统一登录参数
|
||||||
|
|
Loading…
Reference in New Issue