From 522ef36e7a5ddf24fb0fd36a5cb35d54f406f9fc Mon Sep 17 00:00:00 2001 From: wuzilong <704541015@qq.com> Date: Thu, 12 Nov 2026 17:41:48 +0800 Subject: [PATCH] =?UTF-8?q?feat(doclib):=20=E5=85=81=E8=AE=B8=E5=A4=9A?= =?UTF-8?q?=E9=80=89=E5=8F=AF=E7=AE=A1=E7=90=86=E6=96=87=E6=A1=A3=E5=88=86?= =?UTF-8?q?=E4=BA=AB=E5=B9=B6=E8=AE=A1=E7=AE=97=E5=88=86=E4=BA=AB=E4=BA=BA?= =?UTF-8?q?=E4=BA=A4=E9=9B=86=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- .../src/views/doclib/enter/model.test.ts | 24 +++++++++++++++++-- web-admin/src/views/doclib/enter/model.ts | 19 ++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/web-admin/src/views/doclib/enter/model.test.ts b/web-admin/src/views/doclib/enter/model.test.ts index 34d038057..68247aabd 100644 --- a/web-admin/src/views/doclib/enter/model.test.ts +++ b/web-admin/src/views/doclib/enter/model.test.ts @@ -14,7 +14,7 @@ const node = (id: string, scope: 'mine' | 'shared', children: any[] = []) => ({ children }) -test('分享接收人只能下载,混合选择不能批量删除', () => { +test('可管理文档可多选分享,混合选择不能分享', () => { assert.deepEqual(actionsFor([{ canManage: false }]), { share: false, download: true, @@ -25,10 +25,30 @@ test('分享接收人只能下载,混合选择不能批量删除', () => { download: true, delete: false }) - assert.deepEqual(actionsFor([{ canManage: true }]), { share: true, download: true, delete: true }) + assert.deepEqual(actionsFor([{ canManage: true }]), { + share: true, + download: true, + delete: true + }) + assert.deepEqual(actionsFor([{ canManage: true }, { canManage: true }]), { + share: true, + download: true, + delete: true + }) assert.deepEqual(actionsFor([]), { share: false, download: false, delete: false }) }) +test('分享人初始勾选取所选文档交集', async () => { + const { shareUserIntersection } = await import('./model') + const docs = [ + { shares: [{ id: 'a' }, { id: 'b' }] }, + { shares: [{ id: 'b' }, { id: 'c' }] } + ] + assert.deepEqual(shareUserIntersection(docs), ['b']) + assert.deepEqual(shareUserIntersection([{ shares: [{ id: 'a' }] }, { shares: [] }]), []) + assert.deepEqual(shareUserIntersection([]), []) +}) + test('同一个目录在不同范围有独立树节点,已删除目录不再命中', () => { const mine = node('root', 'mine', [node('child', 'mine')]) const shared = node('root', 'shared') diff --git a/web-admin/src/views/doclib/enter/model.ts b/web-admin/src/views/doclib/enter/model.ts index 3ac2a58e8..7ce8c2048 100644 --- a/web-admin/src/views/doclib/enter/model.ts +++ b/web-admin/src/views/doclib/enter/model.ts @@ -2,12 +2,29 @@ import type { DoclibFolder } from '@/api/doclib' export function actionsFor(rows: Array<{ canManage: boolean }>) { return { - share: rows.length === 1 && rows[0].canManage, + share: rows.length > 0 && rows.every((row) => row.canManage), download: rows.length > 0, delete: rows.length > 0 && rows.every((row) => row.canManage) } } +/** 多选打开分享弹窗时,初始勾选为各文档现有分享人的交集。 */ +export function shareUserIntersection( + documents: Array<{ shares?: Array<{ id: string }> | null }> +): string[] { + if (!documents.length) return [] + let ids = new Set( + (documents[0].shares || []).map((person) => String(person.id || '').trim()).filter(Boolean) + ) + for (const doc of documents.slice(1)) { + const next = new Set( + (doc.shares || []).map((person) => String(person.id || '').trim()).filter(Boolean) + ) + ids = new Set([...ids].filter((id) => next.has(id))) + } + return [...ids] +} + export function findFolder(nodes: DoclibFolder[], id: string): DoclibFolder | undefined { for (const node of nodes) { if (node.id === id) return node