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 {
GroupPanelType,
useGroupInfo,
GroupPanel as GroupPanelInfo,
showToasts,
} from 'tailchat-shared';
import { Tree } from 'antd';
import type { NodeDragEventParams } from 'rc-tree/lib/contextTypes';
import type { DataNode, EventDataNode } from 'antd/lib/tree';
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;
const groupInfo = useGroupInfo(groupId);
const groupPanels = groupInfo?.panels ?? [];
/**
*
*/
function rebuildGroupPanelOrder(
groupPanels: GroupPanelInfo[]
): 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(
(
@ -47,25 +102,84 @@ export const GroupPanel: React.FC<{
dropToGap: boolean;
}
) => {
// TODO
console.log(info);
const newGroupPanels = _cloneDeep(props.groupPanels);
const dropNodePos = newGroupPanels.findIndex(
(panel) => panel.id === info.node.key
);
const dropGroupPanel = newGroupPanels[dropNodePos];
if (dropNodePos === -1) {
showToasts('异常, 目标节点未找到', 'error');
}
const dragPanelPos = newGroupPanels.findIndex(
(panel) => panel.id === info.dragNode.key
);
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]
);
const treeData: DataNode[] = useMemo(
() => buildTreeDataWithGroupPanel(groupPanels),
[groupPanels]
return (
<Tree
treeData={treeData}
defaultExpandAll={true}
draggable={true}
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>
<Tree
treeData={treeData}
defaultExpandAll={true}
draggable={true}
onDrop={handleDrop}
/>
<GroupPanelTree groupPanels={groupPanels} onChange={handleChange} />
</div>
);
});

Loading…
Cancel
Save