feat(board): 已完成列按完成时间倒序排列
- 已完成列的展示顺序改由 completedAt 倒序决定(新增 sortCompletedDesc 纯函数), 最近完成的永远在最上面;缺 completedAt 的旧数据排在有完成时间的任务之后, 彼此退回 sortOrder 倒序 - 该列停用列内排序:拖拽与 ↑↓ 只能跨列,列头标注「按完成时间倒序」说明口径 - 数据层不动:不迁移 sortOrder,导入导出、快照结构与 schemaVersion 均不变, 倒序只在 BoardView.visibleColumns 单点发生 - 新增 ADR-009,并在 ADR-008 的否决项里标注被部分推翻 - 单测 705 → 738(sortOrder +5、BoardView +5、BoardColumn +1),README 同步
This commit is contained in:
+18
-3
@@ -15,7 +15,7 @@ import { useUiStore } from '@/stores/ui'
|
||||
import { COLUMNS, PRIORITY_LABELS, type ColumnId, type MoveDirection, type Priority } from '@/types/task'
|
||||
import { findArchivableTasks } from '@/utils/archive'
|
||||
import { filterTasks } from '@/utils/filter'
|
||||
import { groupByColumn } from '@/utils/sortOrder'
|
||||
import { groupByColumn, sortCompletedDesc } from '@/utils/sortOrder'
|
||||
|
||||
const store = useTaskStore()
|
||||
const filters = useFilterStore()
|
||||
@@ -45,7 +45,11 @@ function setColumnRef(element: unknown, index: number): void {
|
||||
}
|
||||
|
||||
/** 实际渲染的看板:先按条件筛选,再按列分组,列计数随之反映结果 */
|
||||
const visibleColumns = computed(() => groupByColumn(filterTasks(store.activeTasks, filter.value)))
|
||||
const visibleColumns = computed(() => {
|
||||
const grouped = groupByColumn(filterTasks(store.activeTasks, filter.value))
|
||||
// 已完成列按完成时间倒序展示,与 sortOrder 无关(见 sortCompletedDesc)
|
||||
return { ...grouped, done: sortCompletedDesc(grouped.done) }
|
||||
})
|
||||
|
||||
/**
|
||||
* 每列被隐藏的数量(被筛选掉 + 已归档)。
|
||||
@@ -64,6 +68,15 @@ const hiddenTotal = computed(() =>
|
||||
COLUMNS.reduce((total, column) => total + hiddenCounts.value[column.id], 0),
|
||||
)
|
||||
|
||||
/**
|
||||
* 列内排序是否停用:
|
||||
* - 该列渲染的是子集(被筛选 / 归档隐藏)时,Sortable 给的是子集下标,写回会坏全量顺序
|
||||
* - 已完成列的顺序由完成时间决定(倒序),手动排序没有意义,一律停用
|
||||
*/
|
||||
function isSortDisabled(columnId: ColumnId): boolean {
|
||||
return columnId === 'done' || hiddenCounts.value[columnId] > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 被「隐藏归档」挡掉、且本来能通过当前筛选的任务数。
|
||||
*
|
||||
@@ -163,6 +176,8 @@ function handleKeyMove(payload: { id: string; direction: MoveDirection }): void
|
||||
if (!target) return
|
||||
store.moveTask(task.id, target.id, store.byColumn[target.id].length)
|
||||
} else {
|
||||
// 已完成列按完成时间倒序,列内调序没有意义,也不写 sortOrder
|
||||
if (task.status === 'done') return
|
||||
if (hiddenCounts.value[task.status] > 0) return
|
||||
const column = store.byColumn[task.status]
|
||||
const currentIndex = column.findIndex((item) => item.id === task.id)
|
||||
@@ -336,7 +351,7 @@ watch(filter, () => {
|
||||
:ref="(element) => setColumnRef(element, index)"
|
||||
:column="column"
|
||||
:tasks="visibleColumns[column.id]"
|
||||
:sort-disabled="hiddenCounts[column.id] > 0"
|
||||
:sort-disabled="isSortDisabled(column.id)"
|
||||
:selectable="selecting"
|
||||
:selected-ids="selectedIds"
|
||||
@toggle="toggleTask"
|
||||
|
||||
Reference in New Issue
Block a user