Skip to content

Commit fff1549

Browse files
committed
fix: enhancing typescript
1 parent da6e86b commit fff1549

2 files changed

Lines changed: 112 additions & 41 deletions

File tree

packages/canvas/container/src/composables/useMultiDrag.js renamed to packages/canvas/container/src/composables/useMultiDrag.ts

Lines changed: 101 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { reactive, computed, toRaw } from 'vue'
2+
import type { ComputedRef } from 'vue'
3+
import type { PositionType } from '../container'
24
import { useMultiSelect } from './useMultiSelect'
35
import { useCanvas } from '@opentiny/tiny-engine-meta-register'
46
import { NODE_TAG, NODE_UID } from '../../../common'
@@ -19,13 +21,66 @@ import {
1921
getDocument
2022
} from '../container'
2123

22-
const initialMultiDragState = {
24+
interface Position {
25+
x: number
26+
y: number
27+
}
28+
29+
interface Offset {
30+
offsetX: number
31+
offsetY: number
32+
initialX: number
33+
initialY: number
34+
}
35+
36+
interface NodeSchema {
37+
id: string
38+
componentName: string
39+
children?: NodeSchema[]
40+
[key: string]: any
41+
}
42+
43+
interface MultiDragState {
44+
keydown: boolean
45+
draging: boolean
46+
dragStarted: boolean
47+
initialMousePos: Position | null
48+
nodes: NodeSchema[]
49+
offsets: Map<string, Offset>
50+
mouse: Position | null
51+
position: PositionType | null
52+
targetNodeId: string | null
53+
}
54+
55+
interface SelectState {
56+
id: string
57+
componentName: string
58+
schema: NodeSchema
59+
top?: number
60+
left?: number
61+
width?: number
62+
height?: number
63+
doc?: Document
64+
[key: string]: any
65+
}
66+
67+
interface InsertOperation {
68+
sourceId: string
69+
targetNodeData: {
70+
parent: NodeSchema | null
71+
node: NodeSchema
72+
data: NodeSchema
73+
}
74+
position: PositionType
75+
}
76+
77+
const initialMultiDragState: MultiDragState = {
2378
keydown: false,
2479
draging: false,
2580
dragStarted: false, // 标记是否已经开始拖拽
2681
initialMousePos: null, // 初始鼠标位置
2782
nodes: [], // 存储被拖拽的多个节点信息
28-
offsets: new Map(), // 存储每个节点的偏移量
83+
offsets: new Map<string, Offset>(), // 存储每个节点的偏移量
2984
mouse: null, // 鼠标位置
3085
position: null, // 放置位置
3186
targetNodeId: null // 当前点击的节点ID
@@ -35,16 +90,17 @@ const initialMultiDragState = {
3590
const DRAG_THRESHOLD = 5
3691

3792
export const useMultiDrag = () => {
38-
const multiDragState = reactive({ ...initialMultiDragState })
39-
const { multiSelectedStates, multiStateLength } = useMultiSelect()
93+
const multiDragState = reactive<MultiDragState>({ ...initialMultiDragState })
94+
const { multiSelectedStates } = useMultiSelect()
95+
const multiStateLength = computed<number>(() => (multiSelectedStates.value as SelectState[]).length)
4096

4197
// 准备拖拽 - 仅记录初始状态,不立即开始拖拽
42-
const startMultiDrag = (event, element) => {
98+
const startMultiDrag = (event: MouseEvent, element: HTMLElement): boolean => {
4399
if (multiStateLength.value <= 1) return false
44100

45101
// 检查点击的元素是否是已选中的节点之一
46102
const clickedNodeId = element?.getAttribute(NODE_UID)
47-
if (!clickedNodeId || !multiSelectedStates.value.some((state) => state.id === clickedNodeId)) {
103+
if (!clickedNodeId || !(multiSelectedStates.value as SelectState[]).some((state) => state.id === clickedNodeId)) {
48104
return false
49105
}
50106

@@ -54,10 +110,10 @@ export const useMultiDrag = () => {
54110
multiDragState.draging = false
55111
multiDragState.initialMousePos = { x: clientX, y: clientY }
56112
multiDragState.targetNodeId = clickedNodeId
57-
multiDragState.nodes = toRaw(multiSelectedStates.value).map((state) => state.schema)
113+
multiDragState.nodes = toRaw(multiSelectedStates.value as SelectState[]).map((state) => state.schema)
58114

59115
// 计算每个节点相对于鼠标的偏移量
60-
multiSelectedStates.value.forEach((state) => {
116+
;(multiSelectedStates.value as SelectState[]).forEach((state) => {
61117
const elem = querySelectById(state.id)
62118
if (elem) {
63119
const { x, y } = elem.getBoundingClientRect()
@@ -74,7 +130,11 @@ export const useMultiDrag = () => {
74130
}
75131

76132
// 计算放置位置
77-
const calculateDropPosition = (event, rect, configure) => {
133+
const calculateDropPosition = (
134+
event: MouseEvent,
135+
rect: DOMRect,
136+
configure: { isContainer?: boolean } | null
137+
): PositionType => {
78138
const { clientX: mouseX, clientY: mouseY } = event
79139
// 参考单选节点的实现,使用更精确的计算方式
80140
const yAbs = Math.min(20, rect.height / 3)
@@ -99,15 +159,20 @@ export const useMultiDrag = () => {
99159
}
100160

101161
// 计算鼠标移动距离
102-
const calculateDistance = (pos1, pos2) => {
162+
const calculateDistance = (pos1: Position | null, pos2: Position | null): number => {
103163
if (!pos1 || !pos2) return 0
104164
const dx = pos1.x - pos2.x
105165
const dy = pos1.y - pos2.y
106166
return Math.sqrt(dx * dx + dy * dy)
107167
}
108168

109169
// 检查是否允许放置
110-
const checkAllowInsert = (configure, nodes, targetId, position) => {
170+
const checkAllowInsert = (
171+
configure: { isContainer?: boolean } | null,
172+
nodes: NodeSchema[],
173+
targetId: string,
174+
position: PositionType
175+
): boolean => {
111176
// 如果没有配置,不允许放置
112177
if (!configure) return false
113178

@@ -183,11 +248,11 @@ export const useMultiDrag = () => {
183248
}
184249

185250
// 拖拽移动
186-
const moveMultiDrag = (event) => {
251+
const moveMultiDrag = (event: MouseEvent): boolean => {
187252
if (!multiDragState.keydown || multiStateLength.value <= 1) return false
188253

189254
const { clientX, clientY } = event
190-
const currentMousePos = { x: clientX, y: clientY }
255+
const currentMousePos: Position = { x: clientX, y: clientY }
191256

192257
// 如果拖拽还未开始,检查是否超过阈值
193258
if (!multiDragState.dragStarted) {
@@ -217,7 +282,7 @@ export const useMultiDrag = () => {
217282
return false
218283
}
219284

220-
const targetElement = getElement(event.target)
285+
const targetElement = getElement(event.target as HTMLElement)
221286

222287
// 特殊处理:如果没有找到目标元素,检查是否是body元素或其直接子元素
223288
if (!targetElement) {
@@ -226,7 +291,11 @@ export const useMultiDrag = () => {
226291
const body = doc.body
227292

228293
// 如果鼠标在body区域内,则视为拖拽到body
229-
if (event.target === body || event.target.parentElement === body || event.target === doc.documentElement) {
294+
if (
295+
event.target === body ||
296+
(event.target as HTMLElement).parentElement === body ||
297+
event.target === doc.documentElement
298+
) {
230299
// 获取body中的所有顶级节点
231300
const { getSchema } = useCanvas()
232301
const bodySchema = getSchema()
@@ -252,9 +321,9 @@ export const useMultiDrag = () => {
252321
const { clientY } = event
253322

254323
// 遍历body的直接子节点,找到最接近鼠标位置的节点
255-
let closestNode = null
324+
let closestNode: HTMLElement | null = null
256325
let closestDistance = Infinity
257-
let position = POSITION.IN // 默认放置到body内部
326+
let position: PositionType = POSITION.IN // 默认放置到body内部
258327

259328
for (const childSchema of bodyChildren) {
260329
const childElement = querySelectById(childSchema.id)
@@ -283,7 +352,7 @@ export const useMultiDrag = () => {
283352
const rect = closestNode.getBoundingClientRect()
284353

285354
// 检查是否允许放置
286-
const isForbidden = !checkAllowInsert(configure, multiDragState.nodes, nodeId, position)
355+
const isForbidden = !checkAllowInsert(configure, multiDragState.nodes, nodeId!, position)
287356

288357
// 更新lineState
289358
Object.assign(lineState, {
@@ -341,7 +410,7 @@ export const useMultiDrag = () => {
341410
if (parent) {
342411
// 根据放置位置调整目标节点
343412
const children = parent.children || []
344-
const targetIndex = children.findIndex((child) => child.id === targetId)
413+
const targetIndex = children.findIndex((child: NodeSchema) => child.id === targetId)
345414

346415
// 如果是放置到节点下方,使用下一个兄弟节点作为目标
347416
if ((position === POSITION.BOTTOM || position === POSITION.RIGHT) && targetIndex < children.length - 1) {
@@ -454,7 +523,7 @@ export const useMultiDrag = () => {
454523
}
455524

456525
// 结束拖拽
457-
const endMultiDrag = () => {
526+
const endMultiDrag = (): boolean => {
458527
// 只有真正开始拖拽后才处理放置逻辑
459528
if (!multiDragState.draging || !multiDragState.dragStarted || multiStateLength.value <= 1) {
460529
// 重置状态
@@ -475,7 +544,7 @@ export const useMultiDrag = () => {
475544

476545
if (finalTargetNode) {
477546
// 创建一个操作批次,以便能够一次性添加历史记录
478-
const operations = []
547+
const operations: InsertOperation[] = []
479548

480549
// 收集要移动的节点ID,用于后续检查
481550
const movingNodeIds = multiDragState.nodes.map((node) => node.id)
@@ -512,7 +581,7 @@ export const useMultiDrag = () => {
512581
operations.push({
513582
sourceId,
514583
targetNodeData,
515-
position
584+
position: position as PositionType
516585
})
517586
})
518587

@@ -560,7 +629,7 @@ export const useMultiDrag = () => {
560629
// 延迟执行,确保DOM已更新
561630
setTimeout(() => {
562631
// 重建多选状态
563-
const newMultiSelection = []
632+
const newMultiSelection: SelectState[] = []
564633

565634
// 收集所有操作后的节点ID
566635
const newNodeIds = operations.map((op) => op.targetNodeData.data.id)
@@ -572,9 +641,9 @@ export const useMultiDrag = () => {
572641
const { node } = useCanvas().getNodeWithParentById(nodeId) || {}
573642
if (!node) return
574643

575-
const state = {
644+
const state: SelectState = {
576645
id: nodeId,
577-
componentName: element.getAttribute(NODE_TAG),
646+
componentName: element.getAttribute(NODE_TAG) || '',
578647
schema: node
579648
}
580649

@@ -614,12 +683,12 @@ export const useMultiDrag = () => {
614683
}
615684

616685
// 判断是否处于多选拖拽状态
617-
const isMultiDragging = () => {
686+
const isMultiDragging = (): boolean => {
618687
return multiDragState.draging && multiDragState.dragStarted && multiStateLength.value > 1
619688
}
620689

621690
// 获取多选拖拽的位置描述
622-
const getMultiDragPositionText = computed(() => {
691+
const getMultiDragPositionText: ComputedRef<string> = computed(() => {
623692
if (!isMultiDragging()) return ''
624693

625694
const { position, forbidden, id } = lineState
@@ -640,15 +709,15 @@ export const useMultiDrag = () => {
640709
}
641710

642711
switch (position) {
643-
case 'top':
712+
case POSITION.TOP:
644713
return `放置到 ${targetComponentName || '目标节点'} 上方`
645-
case 'bottom':
714+
case POSITION.BOTTOM:
646715
return `放置到 ${targetComponentName || '目标节点'} 下方`
647-
case 'left':
716+
case POSITION.LEFT:
648717
return `放置到 ${targetComponentName || '目标节点'} 左侧`
649-
case 'right':
718+
case POSITION.RIGHT:
650719
return `放置到 ${targetComponentName || '目标节点'} 右侧`
651-
case 'in':
720+
case POSITION.IN:
652721
return `放置到 ${targetComponentName || '容器'} 内部`
653722
default:
654723
return ''

packages/canvas/container/src/container.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,16 @@ export interface DragOffset {
3838
y: number
3939
}
4040

41+
export type PositionType = 'top' | 'bottom' | 'left' | 'right' | 'in' | 'out'
42+
4143
export const POSITION = Object.freeze({
42-
TOP: 'top',
43-
BOTTOM: 'bottom',
44-
LEFT: 'left',
45-
RIGHT: 'right',
46-
IN: 'in',
47-
OUT: 'out'
48-
})
44+
TOP: 'top' as PositionType,
45+
BOTTOM: 'bottom' as PositionType,
46+
LEFT: 'left' as PositionType,
47+
RIGHT: 'right' as PositionType,
48+
IN: 'in' as PositionType,
49+
OUT: 'out' as PositionType
50+
} as const)
4951

5052
export const initialDragState = {
5153
keydown: false,
@@ -506,7 +508,7 @@ export const allowInsert = (configure: any = hoverState.configure || {}, data: N
506508
return flag
507509
}
508510

509-
const isAncestor = (ancestor: string | Node, descendant: string | Node) => {
511+
export const isAncestor = (ancestor: string | Node, descendant: string | Node) => {
510512
const ancestorId = typeof ancestor === 'string' ? ancestor : ancestor.id
511513
let descendantId = typeof descendant === 'string' ? descendant : descendant.id
512514

@@ -848,7 +850,7 @@ export const hoverNode = (id: string, data: Node) => {
848850

849851
export const insertNode = (
850852
node: { node: Node; parent: Node; data: Node },
851-
position: string = POSITION.IN,
853+
position: PositionType = POSITION.IN,
852854
select = true
853855
) => {
854856
if (!node.parent) {

0 commit comments

Comments
 (0)