Add tree multiselection, batch actions and Markdown export

This commit is contained in:
eezd committed 2026-10-21 16:10:49 +08:00
1 parent f473ec64b6
commit ffc95d6dbc
14 files changed
+532 -46

No files matched your search

+41
View File
@@ -0,0 +1,41 @@
import { api } from './api'
import { basename, joinPath } from './paths'
import { minimalPaths } from './selection'
import { flush, move, refreshTree, remove, toast, ws } from './workspace'
export async function batchFiles(action: 'move' | 'delete', paths: string[], destination = '') {
const subjects = minimalPaths(paths)
if (action === 'delete' && !confirm(`将选中的 ${subjects.length} 项移入回收站?文件夹内的内容也会一起删除。`)) return
const failures: string[] = []
let succeeded = 0
for (const path of subjects) {
try {
const result = action === 'move' ? await move(path, joinPath(destination, basename(path))) : await remove(path)
if (result.ok) succeeded++
else failures.push(`${path}:${result.error}`)
} catch (cause) { failures.push(`${path}:${cause instanceof Error ? cause.message : String(cause)}`) }
}
await refreshTree().catch((cause) => toast('刷新目录失败:' + String(cause)))
toast(`${action === 'move' ? '移动' : '删除'}完成:成功 ${succeeded} 项,失败 ${failures.length} 项${failures.length ? ';' + failures.join(';') : ''}`)
}
export async function exportFiles(paths: string[]) {
const subjects = minimalPaths(paths)
const tabs = ws.tabs.filter((tab) => subjects.some((path) => tab.path === path || tab.path.startsWith(path + '/')))
try {
await Promise.all(tabs.map((tab) => flush(tab.path)))
if (tabs.some((tab) => tab.dirty || tab.status !== 'ready')) throw new Error('请先保存笔记并解决冲突,再导出')
const response = await api.exportFiles(subjects)
const blob = await response.blob()
const disposition = response.headers.get('Content-Disposition') ?? ''
const encoded = /filename\*=utf-8''([^;]+)/i.exec(disposition)?.[1]
const plain = /filename="([^"]+)"|filename=([^;]+)/i.exec(disposition)
const filename = encoded ? decodeURIComponent(encoded) : plain?.[1] ?? plain?.[2] ?? '导出.zip'
const url = URL.createObjectURL(blob)
const link = Object.assign(document.createElement('a'), { href: url, download: filename })
document.body.append(link)
link.click()
link.remove()
setTimeout(() => URL.revokeObjectURL(url), 1000)
} catch (cause) { toast('导出失败:' + (cause instanceof Error ? cause.message : String(cause))) }
}