( items: T[], folders: ConfigFolder[], afterItemId?: string )
| 163 | // ==================== 拖拽排序辅助 ==================== |
| 164 | |
| 165 | export function calculateInsertPosition<T extends TreeNode>( |
| 166 | items: T[], |
| 167 | folders: ConfigFolder[], |
| 168 | afterItemId?: string |
| 169 | ): { parentFolderId?: string; order: number } { |
| 170 | if (!afterItemId) { |
| 171 | return { order: getMaxOrderAtLevel(items) + 1 } |
| 172 | } |
| 173 | |
| 174 | const afterItem = items.find((i) => i.id === afterItemId) |
| 175 | const afterFolder = folders.find((f) => f.id === afterItemId) |
| 176 | const target = afterItem || afterFolder |
| 177 | |
| 178 | if (!target) { |
| 179 | return { order: getMaxOrderAtLevel(items) + 1 } |
| 180 | } |
| 181 | |
| 182 | const parentFolderId = target.parentFolderId |
| 183 | const siblingItems = items.filter( |
| 184 | (i) => i.parentFolderId === parentFolderId && i.id !== afterItemId |
| 185 | ) |
| 186 | const siblingFolders = folders.filter( |
| 187 | (f) => f.parentFolderId === parentFolderId && f.id !== afterItemId |
| 188 | ) |
| 189 | |
| 190 | const allSiblings = [...siblingItems, ...siblingFolders].sort( |
| 191 | (a, b) => (a.order ?? 0) - (b.order ?? 0) |
| 192 | ) |
| 193 | |
| 194 | const targetOrder = target.order ?? 0 |
| 195 | const nextItem = allSiblings.find((item) => (item.order ?? 0) > targetOrder) |
| 196 | |
| 197 | const order = nextItem ? (targetOrder + (nextItem.order ?? 0)) / 2 : targetOrder + 1 |
| 198 | |
| 199 | return { parentFolderId, order } |
| 200 | } |
| 201 | |
| 202 | export function reorderItems<T extends TreeNode>( |
| 203 | items: T[], |
nothing calls this directly
no test coverage detected