v2.0.0-preview.1 - 重构TaskList部分

This commit is contained in:
LINING-PC\lining
2025-12-16 18:28:19 +08:00
parent 6a73194c21
commit 987abf6e48
16 changed files with 1320 additions and 842 deletions
@@ -0,0 +1,116 @@
import { ref, computed, type Ref } from 'vue'
import type { Task } from '../../../models/classes/Task'
/**
* TaskList 布局计算逻辑
* 包含虚拟滚动、任务扁平化、可见区域计算等
*/
// 常量定义
export const ROW_HEIGHT = 51 // 每行高度(与TaskList Row一致)
export const VERTICAL_BUFFER = 5 // 上下额外渲染的缓冲行数
export interface TaskWithLevel {
task: Task
level: number
}
export interface TaskWithLevelAndIndex extends TaskWithLevel {
rowIndex: number
}
export interface VisibleTaskRange {
startIndex: number
endIndex: number
}
export function useTaskListLayout(tasks: Ref<Task[]>) {
// 纵向虚拟滚动相关状态
const taskListScrollTop = ref(0)
const taskListBodyHeight = ref(0)
/**
* 获取当前折叠状态下的可见任务列表(扁平化)
*/
const getFlattenedVisibleTasks = (
taskList: Task[],
level = 0,
): TaskWithLevel[] => {
const result: TaskWithLevel[] = []
for (const task of taskList) {
result.push({ task, level })
const isMilestoneGroup = task.type === 'milestone-group'
if (!isMilestoneGroup && task.children && task.children.length > 0 && !task.collapsed) {
result.push(...getFlattenedVisibleTasks(task.children, level + 1))
}
}
return result
}
// 扁平化后的可见任务列表
const flattenedTasks = computed(() => getFlattenedVisibleTasks(tasks.value))
/**
* 计算可视区域任务范围
*/
const visibleTaskRange = computed<VisibleTaskRange>(() => {
const scrollTop = taskListScrollTop.value
const containerHeight = taskListBodyHeight.value || 600
const startIndex = Math.floor(scrollTop / ROW_HEIGHT) - VERTICAL_BUFFER
const endIndex = Math.ceil((scrollTop + containerHeight) / ROW_HEIGHT) + VERTICAL_BUFFER
const total = flattenedTasks.value.length
const clampedStart = Math.min(Math.max(0, startIndex), total)
const clampedEnd = Math.min(total, Math.max(clampedStart + 1, endIndex))
return {
startIndex: clampedStart,
endIndex: clampedEnd,
}
})
/**
* 虚拟列表中需要渲染的任务
*/
const visibleTasks = computed<TaskWithLevelAndIndex[]>(() => {
const { startIndex, endIndex } = visibleTaskRange.value
const slicedTasks = flattenedTasks.value.slice(startIndex, endIndex)
// 添加 rowIndex(基于在扁平化列表中的实际索引)
return slicedTasks.map((item, index) => ({
...item,
rowIndex: startIndex + index,
}))
})
/**
* Spacer 高度用于撑起滚动区域
*/
const totalContentHeight = computed(() => flattenedTasks.value.length * ROW_HEIGHT)
const startSpacerHeight = computed(() => visibleTaskRange.value.startIndex * ROW_HEIGHT)
const endSpacerHeight = computed(() => {
const visibleHeight = visibleTasks.value.length * ROW_HEIGHT
return Math.max(0, totalContentHeight.value - startSpacerHeight.value - visibleHeight)
})
return {
// 状态
taskListScrollTop,
taskListBodyHeight,
// 计算属性
flattenedTasks,
visibleTaskRange,
visibleTasks,
totalContentHeight,
startSpacerHeight,
endSpacerHeight,
// 方法
getFlattenedVisibleTasks,
}
}