refactor(web): 面板管理拖拽管理

pull/13/head
moonrailgun 4 years ago
parent 770ba62630
commit 1c81bfb5e6

@ -1,13 +1,17 @@
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo, useRef } from 'react';
import { import {
GroupPanelType, GroupPanelType,
useGroupInfo, useGroupInfo,
GroupPanel as GroupPanelInfo, GroupPanel as GroupPanelInfo,
showToasts,
} from 'tailchat-shared'; } from 'tailchat-shared';
import { Tree } from 'antd'; import { Tree } from 'antd';
import type { NodeDragEventParams } from 'rc-tree/lib/contextTypes'; import type { NodeDragEventParams } from 'rc-tree/lib/contextTypes';
import type { DataNode, EventDataNode } from 'antd/lib/tree'; import type { DataNode, EventDataNode } from 'antd/lib/tree';
import type { Key } from 'rc-tree/lib/interface'; import type { Key } from 'rc-tree/lib/interface';
import type { AllowDrop } from 'rc-tree/lib/Tree';
import _cloneDeep from 'lodash/cloneDeep';
import _isNil from 'lodash/isNil';
/** /**
* *
@ -31,12 +35,63 @@ function buildTreeDataWithGroupPanel(
})); }));
} }
export const GroupPanel: React.FC<{ /**
groupId: string; *
}> = React.memo((props) => { */
const groupId = props.groupId; function rebuildGroupPanelOrder(
const groupInfo = useGroupInfo(groupId); groupPanels: GroupPanelInfo[]
const groupPanels = groupInfo?.panels ?? []; ): GroupPanelInfo[] {
const originGroupPanels = _cloneDeep(groupPanels);
const newPanel = originGroupPanels.filter((panel) => _isNil(panel.parentId)); // 第一层
const len = newPanel.length;
for (let i = len - 1; i >= 0; i--) {
const currentId = newPanel[i].id;
newPanel.splice(
i + 1,
0,
...originGroupPanels.filter((p) => p.parentId === currentId)
);
}
return newPanel;
}
interface GroupPanelTree {
groupPanels: GroupPanelInfo[];
onChange: (newGroupPanels: GroupPanelInfo[]) => void;
}
/**
*
*/
const GroupPanelTree: React.FC<GroupPanelTree> = React.memo((props) => {
const draggingNode = useRef<DataNode | null>(null);
const treeData: DataNode[] = useMemo(
() => buildTreeDataWithGroupPanel(props.groupPanels),
[props.groupPanels]
);
const handleDragStart = useCallback(
(info: NodeDragEventParams<HTMLDivElement>) => {
draggingNode.current = info.node;
},
[]
);
const handleDragEnd = useCallback(() => {
draggingNode.current = null;
}, []);
const handleAllowDrop = useCallback(
({ dropNode, dropPosition }: Parameters<AllowDrop>[0]) => {
if (dropPosition === 0 && draggingNode.current?.isLeaf === false) {
// 不允许容器之间产生父子节点
return false;
}
return dropNode.isLeaf === draggingNode.current?.isLeaf;
},
[]
);
const handleDrop = useCallback( const handleDrop = useCallback(
( (
@ -47,25 +102,84 @@ export const GroupPanel: React.FC<{
dropToGap: boolean; dropToGap: boolean;
} }
) => { ) => {
// TODO const newGroupPanels = _cloneDeep(props.groupPanels);
console.log(info); const dropNodePos = newGroupPanels.findIndex(
}, (panel) => panel.id === info.node.key
[]
); );
const dropGroupPanel = newGroupPanels[dropNodePos];
if (dropNodePos === -1) {
showToasts('异常, 目标节点未找到', 'error');
}
const treeData: DataNode[] = useMemo( const dragPanelPos = newGroupPanels.findIndex(
() => buildTreeDataWithGroupPanel(groupPanels), (panel) => panel.id === info.dragNode.key
[groupPanels] );
if (draggingNode.current?.isLeaf === true && info.node.isLeaf === true) {
// 如果是面板且目标也是面板
// 则更新它的父节点id
info.dragNodesKeys
// 获取所有的移动节点的位置
.map((key) => newGroupPanels.findIndex((panel) => panel.id === key))
// 过滤掉没找到的
.filter((index) => index !== -1)
.forEach((pos) => {
newGroupPanels[pos].parentId = dropGroupPanel.parentId;
});
}
if (info.node.dragOverGapTop === true) {
// 移动到目标节点之前
newGroupPanels.splice(
dropNodePos,
0,
newGroupPanels.splice(dragPanelPos, 1)[0]
);
} else if (info.node.dragOverGapBottom === true) {
// 移动到目标节点之后
newGroupPanels.splice(
dragPanelPos,
0,
newGroupPanels.splice(dropNodePos, 1)[0]
);
}
if (typeof props.onChange === 'function') {
props.onChange(rebuildGroupPanelOrder(newGroupPanels));
}
},
[props.groupPanels, props.onChange]
); );
return ( return (
<div>
<Tree <Tree
treeData={treeData} treeData={treeData}
defaultExpandAll={true} defaultExpandAll={true}
draggable={true} draggable={true}
onDrop={handleDrop} onDrop={handleDrop}
// TODO: 待简化 https://github.com/react-component/tree/pull/482
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
allowDrop={handleAllowDrop}
/> />
);
});
GroupPanelTree.displayName = 'GroupPanelTree';
export const GroupPanel: React.FC<{
groupId: string;
}> = React.memo((props) => {
const groupId = props.groupId;
const groupInfo = useGroupInfo(groupId);
const groupPanels = groupInfo?.panels ?? [];
const handleChange = useCallback((newGroupPanels: GroupPanelInfo[]) => {
console.log('newGroupPanels', newGroupPanels);
}, []);
return (
<div>
<GroupPanelTree groupPanels={groupPanels} onChange={handleChange} />
</div> </div>
); );
}); });

Loading…
Cancel
Save