Skip to content

Commit fd65991

Browse files
committed
fix: review suggestion
1 parent 7a5941c commit fd65991

3 files changed

Lines changed: 53 additions & 79 deletions

File tree

packages/canvas/container/src/components/CanvasMenu.vue

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,6 @@ export default {
123123
const multiSelectMenus = ref([
124124
{ name: '删除', code: 'multiDel' },
125125
{ name: '复制', code: 'multiCopy' },
126-
{
127-
name: '插入',
128-
items: [
129-
{ name: '向前', code: 'insert', value: 'top' },
130-
{ name: '向后', code: 'insert', value: 'bottom' }
131-
]
132-
},
133126
{
134127
name: '添加父级',
135128
items: [
@@ -219,6 +212,8 @@ export default {
219212
multiCopy() {
220213
const ids = multiSelectedStates.value.map((state) => state.id)
221214
ids.forEach((id) => copyNode(id))
215+
216+
useCanvas().canvasApi.value.updateRect?.()
222217
},
223218
config() {
224219
activeSetting(PLUGIN_NAME.Props)

packages/canvas/container/src/composables/useMultiSelect.ts

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,19 @@
11
import { ref } from 'vue'
2-
import { useCanvas } from '@opentiny/tiny-engine-meta-register'
2+
import { useCanvas, useMessage, useHistory } from '@opentiny/tiny-engine-meta-register'
33
import { utils } from '@opentiny/tiny-engine-utils'
4-
import { getDocument, getRect, querySelectById, POSITION, insertNode } from '../container'
5-
6-
interface Schema {
7-
id: string | null
8-
componentName: string
9-
props?: Record<string, any>
10-
children?: Schema[]
11-
parent?: {
12-
id: string
13-
children: Schema[]
14-
}
15-
}
4+
import { getDocument, getRect, querySelectById, POSITION, insertNode, selectNode } from '../container'
5+
import type { Node } from '../../../types'
166

177
interface SelectionState {
188
id: string
199
top?: number
2010
left?: number
2111
width?: number
2212
height?: number
23-
schema?: Schema
13+
schema?: any
2414
parent?: {
2515
id: string
26-
children: Schema[]
16+
children: Node[]
2717
}
2818
}
2919

@@ -82,6 +72,19 @@ export const useMultiSelect = () => {
8272
multiSelectedStates.value = []
8373
}
8474

75+
/**
76+
* 获取选中节点在父节点children中的索引位置
77+
* @param {children} children 父节点的children
78+
* @param {string[]} selectedIds 选中的节点ID列表
79+
* @returns {number[]} 排序后的索引数组
80+
*/
81+
const getSelectedNodeIndices = (children: Node[], selectedIds: string[]): number[] => {
82+
return selectedIds
83+
.map((id) => children.findIndex((child: Node) => child.id === id))
84+
.filter((index) => index !== -1)
85+
.sort((a, b) => a - b)
86+
}
87+
8588
/**
8689
* 判断选中的节点是否都是兄弟节点且是连续的
8790
* @returns {boolean} 如果所有选中节点都有相同的父节点且在父节点的children中是连续的,返回true;否则返回false
@@ -102,18 +105,12 @@ export const useMultiSelect = () => {
102105

103106
if (nodesWithParent.some((node) => node.parent.id !== parentId)) return false
104107

105-
const nodeIndices = multiSelectedStates.value
106-
.map((node) => firstParent.children.findIndex((child: Schema) => child.id === node.id))
107-
.sort((a, b) => a - b)
108+
// 获取并检查索引
109+
const selectedIds = multiSelectedStates.value.map((state) => state.id)
110+
const nodeIndices = getSelectedNodeIndices(firstParent.children, selectedIds)
108111

109112
// 检查索引是否连续
110-
for (let i = 1; i < nodeIndices.length; i++) {
111-
if (nodeIndices[i] !== nodeIndices[i - 1] + 1) {
112-
return false
113-
}
114-
}
115-
116-
return true
113+
return nodeIndices.every((value, index) => value === nodeIndices[0] + index)
117114
}
118115

119116
/**
@@ -138,36 +135,25 @@ export const useMultiSelect = () => {
138135
const selectedIds = multiSelectedStates.value.map((state) => state.id)
139136

140137
// 找出所有选中节点在父节点children中的索引位置
141-
const indices = selectedIds
142-
.map((id) => parent.children.findIndex((child: Schema) => child.id === id))
143-
.sort((a, b) => a - b)
138+
const indices = getSelectedNodeIndices(parent.children, selectedIds)
144139

145-
// 检查索引是否连续
146-
for (let i = 1; i < indices.length; i++) {
147-
if (indices[i] !== indices[i - 1] + 1) {
148-
return false
149-
}
150-
}
140+
if (indices.length === 0) return false
151141

152-
// 记录最后一个节点和它的位置
153-
const lastIndex = indices[indices.length - 1]
154-
const lastNode = parent.children[lastIndex]
142+
// 获取第一个和最后一个选中节点的索引
143+
const firstIndex = indices[0]
155144

156-
// 从父节点中移除这些节点
157-
const selectedNodes: Schema[] = []
158-
indices.reverse().forEach((index) => {
159-
selectedNodes.unshift(parent.children.splice(index, 1)[0])
160-
})
145+
// 复制选中的节点(不从原来的位置移除)
146+
const selectedNodes = indices.map((index) => parent.children[index])
161147

162148
// 创建新的包装组件
163-
const wrapSchema: Schema = {
149+
const wrapSchema: Node = {
164150
componentName,
165151
id: utils.guid(),
166152
props: { ...props },
167153
children: selectedNodes
168154
}
169155

170-
// 特殊处理popover等组件
156+
// 特殊处理 TinyPopover 等组件
171157
if (componentName === 'TinyPopover') {
172158
wrapSchema.props = {
173159
width: 200,
@@ -203,16 +189,23 @@ export const useMultiSelect = () => {
203189
]
204190
}
205191

206-
// 将包装组件插入到页面底部
207-
insertNode(
208-
{
209-
node: lastNode,
210-
parent,
211-
data: wrapSchema
212-
},
213-
POSITION.RIGHT
214-
)
192+
// 从后向前删除原来的节点,避免索引变化
193+
for (let i = indices.length - 1; i >= 0; i--) {
194+
parent.children.splice(indices[i], 1)
195+
}
196+
197+
// 将新容器插入到第一个选中节点的位置
198+
parent.children.splice(firstIndex, 0, wrapSchema)
199+
200+
// 触发更新,重新选中节点
201+
useMessage().publish({ topic: 'schemaChange', data: {} })
202+
203+
setTimeout(() => {
204+
useCanvas().setNode(wrapSchema, parent)
205+
selectNode(wrapSchema.id)
206+
}, 0)
215207

208+
useHistory().addHistory()
216209
return true
217210
}
218211

@@ -223,8 +216,8 @@ export const useMultiSelect = () => {
223216
* @param {Schema} childSchema 子组件架构
224217
* @returns {Schema} 包装组件架构
225218
*/
226-
const createWrapperSchema = (componentName: string, props: Record<string, any> = {}, childSchema: Schema): Schema => {
227-
let wrapSchema: Schema = {
219+
const createWrapperSchema = (componentName: string, props: Record<string, any> = {}, childSchema: Node): Node => {
220+
let wrapSchema: Node = {
228221
componentName,
229222
id: null,
230223
props: {

packages/canvas/container/src/container.ts

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,7 @@ const insertReplace = ({ parent, node, data }: InsertOptions) => {
323323
parentId: parent.id || '',
324324
newNodeData: data,
325325
position: 'replace',
326-
referTargetNodeId: node.id,
327-
nodeIndex
326+
referTargetNodeId: node.id
328327
})
329328
}
330329
}
@@ -906,22 +905,9 @@ export const insertNode = (
906905
}
907906

908907
export const addComponent = (data: Node, position: string) => {
909-
if (multiSelectedStates.value.length === 1) {
910-
const { schema, parent } = getCurrent()
911-
912-
insertNode({ node: schema, parent, data }, position)
913-
} else {
914-
// 多选时,根据位置判断向上还是向下添加节点
915-
const targetNode =
916-
position === 'top'
917-
? multiSelectedStates.value[0]
918-
: multiSelectedStates.value[multiSelectedStates.value.length - 1]
908+
const { schema, parent } = getCurrent()
919909

920-
const node = targetNode.schema
921-
const parent = useCanvas().getNodeWithParentById(targetNode.id)
922-
923-
insertNode({ node, parent, data }, position)
924-
}
910+
insertNode({ node: schema, parent, data }, position)
925911
}
926912

927913
export const copyNode = (id: string) => {

0 commit comments

Comments
 (0)