Skip to content

Commit 52490ca

Browse files
committed
feat: add mouseMove
1 parent 0d81a56 commit 52490ca

File tree

6 files changed

+145
-110
lines changed

6 files changed

+145
-110
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import {
2+
DndContext,
3+
DragEndEvent,
4+
MouseSensor,
5+
closestCenter,
6+
useSensor,
7+
useSensors,
8+
} from '@dnd-kit/core'
9+
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'
10+
import { FC } from 'react'
11+
12+
interface PropsType {
13+
children: JSX.Element | JSX.Element[]
14+
items: Array<{ id: string; [key: string]: any }>
15+
onDragEnd: (oldIndex: number, newIndex: number) => void
16+
}
17+
18+
/** 拖拽容器 */
19+
const SortableContainer: FC<PropsType> = (props: PropsType) => {
20+
const { children, items, onDragEnd } = props
21+
22+
const sensors = useSensors(
23+
useSensor(MouseSensor, {
24+
activationConstraint: {
25+
// 活动限制
26+
distance: 8, // 8px
27+
},
28+
}),
29+
)
30+
31+
/** 拖拽结束事件 */
32+
const handleDragEnd = (event: DragEndEvent) => {
33+
const { active, over } = event
34+
if (over == null) return
35+
36+
if (active.id !== over.id) {
37+
const oldIndex = items.findIndex((c) => c.fe_id === active.id)
38+
const newIndex = items.findIndex((c) => c.fe_id === over.id)
39+
onDragEnd(oldIndex, newIndex)
40+
}
41+
}
42+
43+
return (
44+
<DndContext
45+
sensors={sensors}
46+
collisionDetection={closestCenter}
47+
onDragEnd={handleDragEnd}
48+
>
49+
<SortableContext items={items} strategy={verticalListSortingStrategy}>
50+
{children}
51+
</SortableContext>
52+
</DndContext>
53+
)
54+
}
55+
56+
export default SortableContainer

src/components/DragSortable/index.tsx

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,2 @@
1-
import {
2-
DndContext,
3-
DragEndEvent,
4-
MouseSensor,
5-
closestCenter,
6-
useSensor,
7-
useSensors,
8-
} from '@dnd-kit/core'
9-
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'
10-
import { FC } from 'react'
11-
12-
interface PropsType {
13-
children: JSX.Element | JSX.Element[]
14-
items: Array<{ id: string; [key: string]: any }>
15-
onDragEnd: (oldIndex: number, newIndex: number) => void
16-
}
17-
18-
const SortableContainer: FC<PropsType> = (props: PropsType) => {
19-
const { children, items, onDragEnd } = props
20-
21-
const sensors = useSensors(
22-
useSensor(MouseSensor, {
23-
activationConstraint: {
24-
distance: 8, // 8px
25-
},
26-
}),
27-
)
28-
29-
const handleDragEnd = (event: DragEndEvent) => {
30-
const { active, over } = event
31-
if (over == null) return
32-
33-
if (active.id !== over.id) {
34-
const oldIndex = items.findIndex((c) => c.fe_id === active.id)
35-
const newIndex = items.findIndex((c) => c.fe_id === over.id)
36-
onDragEnd(oldIndex, newIndex)
37-
}
38-
}
39-
return (
40-
<DndContext
41-
sensors={sensors}
42-
collisionDetection={closestCenter}
43-
onDragEnd={handleDragEnd}
44-
>
45-
<SortableContext items={items} strategy={verticalListSortingStrategy}>
46-
{children}
47-
</SortableContext>
48-
</DndContext>
49-
)
50-
}
51-
52-
export default SortableContainer
1+
export * from './components/SortableContainer'
2+
export * from './components/SortableItem'

src/pages/question/edit/component/centerPanel/index.tsx

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import SortableContainer from '@/components/DragSortable/components/SortableContainer'
2+
import SortableItem from '@/components/DragSortable/components/SortableItem'
13
import { getComponentConfByType } from '@/components/QuestionComponents'
24
import { useBindKeyPress, useGetComponentInfo } from '@/hooks'
35
import {
46
ComponentInfoType,
57
changeSelectedId,
8+
moveComponent,
69
} from '@/store/modules/componentsReducer'
710
import { Spin } from 'antd'
811
import classNames from 'classnames'
@@ -44,26 +47,39 @@ const EditCenterPanel: FC<PropsType> = ({ loading }) => {
4447
return <Component {...props} />
4548
}
4649

50+
/** 添加拖拽,组件需要 id */
51+
const componentListWithId = componentList.map((item) => {
52+
return { ...item, id: item.fe_id }
53+
})
54+
55+
/** 拖拽结束 */
56+
const onDragEnd = (oldIndex: number, newIndex: number) => {
57+
dispatch(moveComponent({ oldIndex, newIndex })) // 更新序列
58+
}
59+
4760
return (
48-
<div className="min-h-[100%] overflow-hidden bg-white">
49-
{componentList.map((item) => {
50-
const { fe_id } = item
61+
<SortableContainer items={componentListWithId} onDragEnd={onDragEnd}>
62+
<div className="min-h-[100%] overflow-hidden bg-white">
63+
{componentList.map((item) => {
64+
const { fe_id } = item
5165

52-
const wrapperDefaultClassName =
53-
'm-3 border border-white rounded-sm border-solid p-3 hover:border-gray-200'
54-
const wrapperName = classNames({ [wrapperDefaultClassName]: true })
66+
const wrapperDefaultClassName =
67+
'm-3 border border-white rounded-sm border-solid p-3 hover:border-gray-200'
68+
const wrapperName = classNames({ [wrapperDefaultClassName]: true })
5569

56-
return (
57-
<div
58-
key={fe_id}
59-
className={wrapperName}
60-
onClick={(e) => handleClick(e, fe_id)}
61-
>
62-
<div className="pointer-events-none">{genComponent(item)}</div>
63-
</div>
64-
)
65-
})}
66-
</div>
70+
return (
71+
<SortableItem key={fe_id} id={fe_id}>
72+
<div
73+
className={wrapperName}
74+
onClick={(e) => handleClick(e, fe_id)}
75+
>
76+
<div className="pointer-events-none">{genComponent(item)}</div>
77+
</div>
78+
</SortableItem>
79+
)
80+
})}
81+
</div>
82+
</SortableContainer>
6783
)
6884
}
6985

src/pages/question/edit/component/leftPanel/LeftLayers.tsx

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import SortableContainer from '@/components/DragSortable/components/SortableContainer'
2+
import SortableItem from '@/components/DragSortable/components/SortableItem'
13
import { useGetComponentInfo } from '@/hooks'
24
import {
35
changeComponentHidden,
46
changeComponentTitle,
57
changeSelectedId,
8+
moveComponent,
69
toggleComponentLocked,
710
} from '@/store/modules/componentsReducer'
811
import { EyeInvisibleOutlined, LockOutlined } from '@ant-design/icons'
@@ -52,8 +55,18 @@ const LeftLayers: FC = () => {
5255
dispatch(toggleComponentLocked({ fe_id }))
5356
}
5457

58+
/** 添加拖拽,组件需要 id */
59+
const componentListWithId = componentList.map((item) => {
60+
return { ...item, id: item.fe_id }
61+
})
62+
63+
/** 拖拽结束 */
64+
const onDragEnd = (oldIndex: number, newIndex: number) => {
65+
dispatch(moveComponent({ oldIndex, newIndex })) // 更新序列
66+
}
67+
5568
return (
56-
<>
69+
<SortableContainer items={componentListWithId} onDragEnd={onDragEnd}>
5770
{componentList.map((c) => {
5871
const { fe_id, title, isHidden, isLocked } = c
5972
const titleDefaultClassName = 'flex-auto line-height-loose'
@@ -71,48 +84,47 @@ const LeftLayers: FC = () => {
7184
})
7285

7386
return (
74-
<div
75-
key={fe_id}
76-
className="flex border-b border-b-green-200 border-b-solid py-2"
77-
>
78-
<div
79-
className={titleClassName}
80-
onClick={() => handleTitleClick(fe_id)}
81-
>
82-
{fe_id === changingTitleId && (
83-
<Input
84-
value={title}
85-
onChange={changeTitle}
86-
onPressEnter={() => setChangingTitleId('')}
87-
onBlur={() => setChangingTitleId('')}
88-
/>
89-
)}
90-
{fe_id !== changingTitleId && title}
91-
</div>
92-
<div className="w-12 text-end">
93-
<Space>
94-
<Button
95-
size="small"
96-
shape="circle"
97-
className={hiddenButtonClassName}
98-
icon={<EyeInvisibleOutlined />}
99-
type={isHidden ? 'primary' : 'text'}
100-
onClick={() => toggleHidden(fe_id, !isHidden)}
101-
/>
102-
<Button
103-
size="small"
104-
shape="circle"
105-
className={clockButtonClassName}
106-
icon={<LockOutlined />}
107-
type={isLocked ? 'primary' : 'text'}
108-
onClick={() => toggleLocked(fe_id)}
109-
/>
110-
</Space>
87+
<SortableItem key={fe_id} id={fe_id}>
88+
<div className="flex border-b border-b-green-200 border-b-solid py-2">
89+
<div
90+
className={titleClassName}
91+
onClick={() => handleTitleClick(fe_id)}
92+
>
93+
{fe_id === changingTitleId && (
94+
<Input
95+
value={title}
96+
onChange={changeTitle}
97+
onPressEnter={() => setChangingTitleId('')}
98+
onBlur={() => setChangingTitleId('')}
99+
/>
100+
)}
101+
{fe_id !== changingTitleId && title}
102+
</div>
103+
<div className="w-12 text-end">
104+
<Space>
105+
<Button
106+
size="small"
107+
shape="circle"
108+
className={hiddenButtonClassName}
109+
icon={<EyeInvisibleOutlined />}
110+
type={isHidden ? 'primary' : 'text'}
111+
onClick={() => toggleHidden(fe_id, !isHidden)}
112+
/>
113+
<Button
114+
size="small"
115+
shape="circle"
116+
className={clockButtonClassName}
117+
icon={<LockOutlined />}
118+
type={isLocked ? 'primary' : 'text'}
119+
onClick={() => toggleLocked(fe_id)}
120+
/>
121+
</Space>
122+
</div>
111123
</div>
112-
</div>
124+
</SortableItem>
113125
)
114126
})}
115-
</>
127+
</SortableContainer>
116128
)
117129
}
118130

src/store/modules/componentsReducer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'
33
import produce from 'immer'
44
import { nanoid } from 'nanoid'
55
import { cloneDeep } from 'lodash-es'
6+
import { arrayMove } from '@dnd-kit/sortable'
67

78
/** 单个组件信息 */
89
export interface ComponentInfoType {
@@ -259,7 +260,7 @@ export const componentsSlice = createSlice({
259260
const { componentList: curComponentList } = draft
260261
const { oldIndex, newIndex } = action.payload
261262

262-
// draft.componentList = arrayMove(curComponentList, oldIndex, newIndex)
263+
draft.componentList = arrayMove(curComponentList, oldIndex, newIndex)
263264
},
264265
),
265266
},

0 commit comments

Comments
 (0)