Jelajahi Sumber

feat: 添加react-dnd

xieyonghong 3 tahun lalu
induk
melakukan
6bac1d0d71

+ 1 - 0
config/config.ts

@@ -91,5 +91,6 @@ export default defineConfig({
         languages: ['json', 'javascript', 'typescript', 'sql'],
       }),
     );
+    memo.module.rule('mjs-rule').test(/.m?js/).resolve.set('fullySpecified', false);
   },
 });

+ 2 - 0
package.json

@@ -97,6 +97,8 @@
     "react-beautiful-dnd": "^13.1.0",
     "react-custom-scrollbars": "^4.2.1",
     "react-dev-inspector": "^1.1.1",
+    "react-dnd": "^16.0.1",
+    "react-dnd-html5-backend": "^16.0.1",
     "react-dom": "^17.0.0",
     "react-helmet-async": "^1.0.4",
     "react-json-view": "^1.21.3",

+ 13 - 0
src/pages/system/Menu/Setting/dnd.tsx

@@ -0,0 +1,13 @@
+import { HTML5Backend } from 'react-dnd-html5-backend';
+import { DndProvider } from 'react-dnd';
+import { Tree } from 'antd';
+
+const Dnd = () => {
+  return (
+    <DndProvider backend={HTML5Backend}>
+      <Tree />
+    </DndProvider>
+  );
+};
+
+export default Dnd;

+ 33 - 12
src/pages/system/Menu/Setting/dragItem.tsx

@@ -1,4 +1,5 @@
-import { Draggable } from 'react-beautiful-dnd';
+import { useRef } from 'react';
+import { useDrag, useDrop } from 'react-dnd';
 
 interface DragItemProps {
   data: any;
@@ -6,18 +7,38 @@ interface DragItemProps {
 }
 
 const DragItem = (props: DragItemProps) => {
+  const ref = useRef<HTMLDivElement>(null);
+  const [{ isOver, dropClassName }, drop] = useDrop({
+    accept: props.type,
+    collect: (monitor) => {
+      console.log(monitor.getItem());
+      // const { index: dragIndex } = monitor.getItem() || {};
+      // if (dragIndex === index) {
+      //   return {};
+      // }
+      return {
+        isOver: monitor.isOver(),
+        dropClassName: 'dropping',
+      };
+    },
+    drop: (item: { index: React.Key }) => {
+      console.log(item);
+      // moveNode(item.index, index);
+    },
+  });
+  const [, drag] = useDrag({
+    type: props.type,
+    item: { index: props.data.id },
+    collect: (monitor) => ({
+      isDragging: monitor.isDragging(),
+    }),
+  });
+  drop(drag(ref));
+
   return (
-    <Draggable
-      draggableId={props.type + '&' + props.data.id}
-      index={props.type + '&' + props.data.id}
-      isCombineEnabled={true}
-    >
-      {(provided) => (
-        <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
-          {props.data.name}
-        </div>
-      )}
-    </Draggable>
+    <div ref={ref} className={isOver ? dropClassName : ''}>
+      {props.data.name}
+    </div>
   );
 };
 

+ 83 - 82
src/pages/system/Menu/Setting/index.tsx

@@ -9,12 +9,13 @@ import Tree from './tree';
 import './index.less';
 import { Button, Tooltip } from 'antd';
 import BaseTreeData from './baseMenu';
-import { useCallback, useEffect, useState } from 'react';
-import { DragDropContext } from 'react-beautiful-dnd';
+import { useEffect, useState } from 'react';
+import { HTML5Backend } from 'react-dnd-html5-backend';
+import { DndProvider } from 'react-dnd';
 
 export default () => {
   const { minHeight } = useDomFullHeight(`.menu-setting-warp`);
-  const [menuData, setMenuData] = useState<any[]>([]);
+  const [menuData] = useState<any[]>([]);
   const [baseMenu, setBaseMenu] = useState<any[]>([]);
 
   // const removeItem = (data: any[], id: string): any[] => {
@@ -30,85 +31,85 @@ export default () => {
   //   })
   // }
 
-  const findItem = (data: any[], id: string) => {
-    let object = null;
-    data.some((item) => {
-      if (item.id === id) {
-        object = item;
-        return true;
-      }
-
-      if (item.children) {
-        object = findItem(item.children, id);
-        return !!object;
-      }
-
-      return false;
-    });
-    return object;
-  };
-
-  const finedIndex = (data: any[], id: string): { index: number; menus: any[] } => {
-    let object = {
-      index: data.length,
-      menus: data,
-    };
-    data.some((item, index) => {
-      if (item.id === id) {
-        object = {
-          index,
-          menus: data,
-        };
-        return true;
-      }
-
-      if (item.children) {
-        object = finedIndex(item.children, id);
-        return !!object;
-      }
-
-      return false;
-    });
+  // const findItem = (data: any[], id: string) => {
+  //   let object = null;
+  //   data.some((item) => {
+  //     if (item.id === id) {
+  //       object = item;
+  //       return true;
+  //     }
+  //
+  //     if (item.children) {
+  //       object = findItem(item.children, id);
+  //       return !!object;
+  //     }
+  //
+  //     return false;
+  //   });
+  //   return object;
+  // };
 
-    return object;
-  };
+  // const finedIndex = (data: any[], id: string): { index: number; menus: any[] } => {
+  //   let object = {
+  //     index: data.length,
+  //     menus: data,
+  //   };
+  //   data.some((item, index) => {
+  //     if (item.id === id) {
+  //       object = {
+  //         index,
+  //         menus: data,
+  //       };
+  //       return true;
+  //     }
+  //
+  //     if (item.children) {
+  //       object = finedIndex(item.children, id);
+  //       return !!object;
+  //     }
+  //
+  //     return false;
+  //   });
+  //
+  //   return object;
+  // };
 
-  const onDragEnd = useCallback(
-    (result: any) => {
-      console.log(result);
-      if (result.source.droppableId.includes('source')) {
-        if (result.combine && result.combine.droppableId.includes('menu')) {
-          const sourceIndex = result.source.index.replace(/(source|menu)&/, '');
-          const draggableIdIndex = result.combine?.draggableId.replace(/(source|menu)&/, '');
-          const sourceItem = findItem(baseMenu, sourceIndex);
-          const newMenus = [...menuData];
-          const { index, menus } = finedIndex(newMenus, draggableIdIndex);
-          console.log(index, menus);
-          menus.splice(index + 1, 0, sourceItem);
-          console.log(newMenus);
-          setMenuData([...newMenus]);
-        } else if (result.destination && result.destination.includes('menu')) {
-          const sourceIndex = result.source.index.replace(/(source|menu)&/, '');
-          const sourceItem = findItem(baseMenu, sourceIndex);
-          const newMenus = [...menuData];
-          if (sourceItem) {
-            if (newMenus.length) {
-              const destinationIndex = result.destination?.index.replace(/(source|menu)&/, '');
-              // 获取右侧menu的位置
-              const { index, menus } = finedIndex(newMenus, destinationIndex);
-              console.log(index, menus);
-              menus.splice(index + 1, 0, sourceItem);
-            } else {
-              newMenus.push(sourceItem);
-            }
-            console.log(newMenus);
-            setMenuData([...newMenus]);
-          }
-        }
-      }
-    },
-    [menuData, baseMenu],
-  );
+  // const onDragEnd = useCallback(
+  //   (result: any) => {
+  //     console.log(result);
+  //     if (result.source.droppableId.includes('source')) {
+  //       if (result.combine && result.combine.droppableId.includes('menu')) {
+  //         const sourceIndex = result.source.index.replace(/(source|menu)&/, '');
+  //         const draggableIdIndex = result.combine?.draggableId.replace(/(source|menu)&/, '');
+  //         const sourceItem = findItem(baseMenu, sourceIndex);
+  //         const newMenus = [...menuData];
+  //         const { index, menus } = finedIndex(newMenus, draggableIdIndex);
+  //         console.log(index, menus);
+  //         menus.splice(index + 1, 0, sourceItem);
+  //         console.log(newMenus);
+  //         setMenuData([...newMenus]);
+  //       } else if (result.destination && result.destination.droppableId.includes('menu')) {
+  //         const sourceIndex = result.source.index.replace(/(source|menu)&/, '');
+  //         const sourceItem = findItem(baseMenu, sourceIndex);
+  //         const newMenus = [...menuData];
+  //         if (sourceItem) {
+  //           if (newMenus.length) {
+  //             const destinationIndex = result.destination?.index.replace(/(source|menu)&/, '');
+  //             // 获取右侧menu的位置
+  //             const { index, menus } = finedIndex(newMenus, destinationIndex);
+  //             console.log(index, menus);
+  //             menus.splice(index + 1, 0, sourceItem);
+  //           } else {
+  //             newMenus.push(sourceItem);
+  //           }
+  //           console.log(newMenus);
+  //           setMenuData([...newMenus]);
+  //         }
+  //       }
+  //     }
+  //   },
+  //   [menuData, baseMenu],
+  // );
 
   useEffect(() => {
     setBaseMenu(BaseTreeData);
@@ -122,7 +123,7 @@ export default () => {
           基于系统源代码中的菜单数据,配置系统菜单。
         </div>
         <div className={'menu-tree-content'}>
-          <DragDropContext onDragEnd={onDragEnd}>
+          <DndProvider backend={HTML5Backend}>
             <div className={'menu-tree left-tree'}>
               <div className={'menu-tree-title'}>
                 <div>
@@ -155,7 +156,7 @@ export default () => {
               </div>
               <Tree treeData={menuData} droppableId={'menu'} />
             </div>
-          </DragDropContext>
+          </DndProvider>
         </div>
         <div>
           <Button type={'primary'} style={{ marginTop: 24 }}>

+ 3 - 20
src/pages/system/Menu/Setting/tree.tsx

@@ -1,7 +1,6 @@
 import { Input, Tree } from 'antd';
 import { SearchOutlined } from '@ant-design/icons';
 import DragItem from '@/pages/system/Menu/Setting/dragItem';
-import { Droppable } from 'react-beautiful-dnd';
 
 interface TreeBodyProps {
   treeData: any[];
@@ -33,25 +32,9 @@ export default (props: TreeBodyProps) => {
         />
       </div>
       <div className={'tree-body'}>
-        <Droppable
-          droppableId={props.droppableId}
-          direction="horizontal"
-          type="COLUMN"
-          isCombineEnabled={true}
-        >
-          {(provided) => (
-            <div
-              className="columns"
-              {...provided.droppableProps}
-              ref={provided.innerRef}
-              style={{ height: '100%' }}
-            >
-              <Tree draggable={props.droppableId === 'menu'}>
-                {createTreeNode(props.treeData, props.droppableId)}
-              </Tree>
-            </div>
-          )}
-        </Droppable>
+        <Tree draggable={props.droppableId === 'menu'}>
+          {createTreeNode(props.treeData, props.droppableId)}
+        </Tree>
       </div>
     </div>
   );

+ 43 - 1
yarn.lock

@@ -3622,6 +3622,21 @@
   resolved "https://registry.yarnpkg.com/@qixian.cs/path-to-regexp/-/path-to-regexp-6.1.0.tgz#6b84ad01596332aba95fa29d2e70104698cd5c45"
   integrity sha512-2jIiLiVZB1jnY7IIRQKtoV8Gnr7XIhk4mC88ONGunZE3hYt5IHUG4BE/6+JiTBjjEWQLBeWnZB8hGpppkufiVw==
 
+"@react-dnd/asap@^5.0.1":
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/@react-dnd/asap/-/asap-5.0.2.tgz#1f81f124c1cd6f39511c11a881cfb0f715343488"
+  integrity sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==
+
+"@react-dnd/invariant@^4.0.1":
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/@react-dnd/invariant/-/invariant-4.0.2.tgz#b92edffca10a26466643349fac7cdfb8799769df"
+  integrity sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==
+
+"@react-dnd/shallowequal@^4.0.1":
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz#d1b4befa423f692fa4abf1c79209702e7d8ae4b4"
+  integrity sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==
+
 "@sindresorhus/is@^0.14.0":
   version "0.14.0"
   resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
@@ -8448,6 +8463,15 @@ discontinuous-range@1.0.0:
   resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
   integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=
 
+dnd-core@^16.0.1:
+  version "16.0.1"
+  resolved "https://registry.yarnpkg.com/dnd-core/-/dnd-core-16.0.1.tgz#a1c213ed08961f6bd1959a28bb76f1a868360d19"
+  integrity sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==
+  dependencies:
+    "@react-dnd/asap" "^5.0.1"
+    "@react-dnd/invariant" "^4.0.1"
+    redux "^4.2.0"
+
 doctrine@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
@@ -16919,6 +16943,24 @@ react-dev-utils@^11.0.0:
     strip-ansi "6.0.0"
     text-table "0.2.0"
 
+react-dnd-html5-backend@^16.0.1:
+  version "16.0.1"
+  resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz#87faef15845d512a23b3c08d29ecfd34871688b6"
+  integrity sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==
+  dependencies:
+    dnd-core "^16.0.1"
+
+react-dnd@^16.0.1:
+  version "16.0.1"
+  resolved "https://registry.yarnpkg.com/react-dnd/-/react-dnd-16.0.1.tgz#2442a3ec67892c60d40a1559eef45498ba26fa37"
+  integrity sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==
+  dependencies:
+    "@react-dnd/invariant" "^4.0.1"
+    "@react-dnd/shallowequal" "^4.0.1"
+    dnd-core "^16.0.1"
+    fast-deep-equal "^3.1.3"
+    hoist-non-react-statics "^3.3.2"
+
 react-docgen-typescript-dumi-tmp@^1.22.1-0:
   version "1.22.1-0"
   resolved "https://registry.yarnpkg.com/react-docgen-typescript-dumi-tmp/-/react-docgen-typescript-dumi-tmp-1.22.1-0.tgz#6f452de05c5c114a6e1dd60b34930afaa7ae39a0"
@@ -17468,7 +17510,7 @@ redux@^4.0.0, redux@^4.0.1:
   dependencies:
     "@babel/runtime" "^7.9.2"
 
-redux@^4.0.4:
+redux@^4.0.4, redux@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.0.tgz#46f10d6e29b6666df758780437651eeb2b969f13"
   integrity sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==