feat(board): 支持批量添加与批量删除任务

- 批量添加面板:一行一条,整批共用目标列、优先级、标签与截止日期
- 快速新增支持粘贴多行文本,直接拆成多条任务
- 多选模式支持全选可见任务、整批删除,撤销时连原顺序一起还原
- 批量创建与删除走 store 的批量方法,一次落盘、一次广播
- 补充单元测试与 E2E 用例
This commit is contained in:
chenshoulin
2026-10-19 17:21:42 +08:00
parent 4aba003a9e
commit 2d6e24dc91
21 changed files with 1518 additions and 37 deletions
+44
View File
@@ -214,3 +214,47 @@ describe('BoardColumn 拖拽事件接线', () => {
expect(options.filter).toBe('button')
})
})
describe('BoardColumn 多选模式', () => {
function mountSelectable(tasks: Task[], selectedIds: Set<string>) {
const pinia = createPinia()
setActivePinia(pinia)
const store = useTaskStore()
store.init({ repository: createMemoryTaskRepository(tasks), crossTab: false })
const wrapper = mount(BoardColumn, {
props: { column: TODO_COLUMN, tasks: store.byColumn.todo, selectable: true, selectedIds },
global: { plugins: [pinia] },
})
return { store, wrapper }
}
it('卡片变为可勾选,selectedIds 决定勾选态', () => {
const { wrapper } = mountSelectable(
[makeTask({ id: 'task-1' }), makeTask({ id: 'task-2' })],
new Set(['task-2']),
)
expect(wrapper.find('[data-task-id="task-1"]').attributes('aria-checked')).toBe('false')
expect(wrapper.find('[data-task-id="task-2"]').attributes('aria-checked')).toBe('true')
})
it('点击卡片 emit select 并带上 id', async () => {
const { wrapper } = mountSelectable([makeTask({ id: 'task-1' })], new Set())
await wrapper.find('article').trigger('click')
expect(wrapper.emitted('select')).toEqual([['task-1']])
expect(wrapper.emitted('open')).toBeUndefined()
})
it('多选时禁止拖拽(同列与跨列都不允许)', () => {
const { wrapper } = mountSelectable([makeTask()], new Set())
const same = wrapper.find('[data-column-id="todo"]').element
const other = document.createElement('div')
const onMove = lastDragOptions().onMove
expect(onMove?.({ from: same, to: same }, new Event('move'))).toBe(false)
expect(onMove?.({ from: same, to: other }, new Event('move'))).toBe(false)
})
})