feat: 回收站、批量编辑、合并导入与标签治理
- 数据:Task 增加 deletedAt,schema v2→v3;删除改为软删除,保留 30 天后自动清理 - 回收站:支持恢复、永久删除、二次确认清空;导航栏入口带数量角标 - 批量编辑:多选后统一移动列、改优先级、标签增删、设置截止日、归档 - 合并导入:按 id 匹配、updatedAt 新者胜;覆盖/合并二选一,执行前自动快照 - 标签治理:全局重命名、合并、删除;回收站任务不参与改写 - 看板语义读取统一改用 activeTasks,避免已删除任务泄漏到统计、今日与标签下拉 - UI:回收站图标与备份统一尺寸;批量编辑条统一控件高度并分组 - 测试:705 个单测通过,补充迁移、回收站、批量编辑、合并与标签用例
This commit is contained in:
@@ -12,7 +12,12 @@ import TagFilter from './TagFilter.vue'
|
||||
|
||||
defineProps<{ hiddenNote?: string; selecting?: boolean }>()
|
||||
|
||||
const emit = defineEmits<{ archive: []; 'batch-add': []; 'toggle-select': [] }>()
|
||||
const emit = defineEmits<{
|
||||
archive: []
|
||||
'batch-add': []
|
||||
'toggle-select': []
|
||||
'manage-tags': []
|
||||
}>()
|
||||
|
||||
const store = useTaskStore()
|
||||
const filters = useFilterStore()
|
||||
@@ -24,15 +29,15 @@ const searchRef = ref<HTMLInputElement | null>(null)
|
||||
const PRIORITY_ORDER: readonly Priority[] = [3, 2, 1]
|
||||
|
||||
const dueTodayCount = computed(
|
||||
() => store.tasks.filter((task) => isDueToday(task.dueDate, task.status)).length,
|
||||
() => store.activeTasks.filter((task) => isDueToday(task.dueDate, task.status)).length,
|
||||
)
|
||||
|
||||
const overdueCount = computed(
|
||||
() => store.tasks.filter((task) => isOverdue(task.dueDate, task.status)).length,
|
||||
() => store.activeTasks.filter((task) => isOverdue(task.dueDate, task.status)).length,
|
||||
)
|
||||
|
||||
/** 当前可归档(已完成且超过保留天数)的任务数量 */
|
||||
const archivableCount = computed(() => findArchivableTasks(store.tasks).length)
|
||||
const archivableCount = computed(() => findArchivableTasks(store.activeTasks).length)
|
||||
|
||||
function focusSearch(): void {
|
||||
searchRef.value?.focus()
|
||||
@@ -91,6 +96,7 @@ defineExpose({ focusSearch })
|
||||
:selected="tags"
|
||||
@toggle="filters.toggleTag($event)"
|
||||
@clear="filters.clearTags()"
|
||||
@manage="emit('manage-tags')"
|
||||
/>
|
||||
|
||||
<div class="ml-auto flex items-center gap-1.5">
|
||||
@@ -129,7 +135,7 @@ defineExpose({ focusSearch })
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-x-2 gap-y-1.5 text-xs text-slate-500 dark:text-zinc-400">
|
||||
<span>共 {{ store.tasks.length }} 个任务</span>
|
||||
<span>共 {{ store.activeTasks.length }} 个任务</span>
|
||||
<span v-if="hiddenNote" class="text-slate-400 dark:text-zinc-500">{{ hiddenNote }}</span>
|
||||
|
||||
<div class="ml-auto flex items-center gap-1.5">
|
||||
|
||||
Reference in New Issue
Block a user