diff --git a/web-admin/src/views/doclib/enter/ShareDialog.vue b/web-admin/src/views/doclib/enter/ShareDialog.vue index a92ccde68..c61ba47b7 100644 --- a/web-admin/src/views/doclib/enter/ShareDialog.vue +++ b/web-admin/src/views/doclib/enter/ShareDialog.vue @@ -11,11 +11,13 @@ :close-on-press-escape="!saving" :show-close="!saving" > -

{{ document?.name }}

+

{{ summaryText }}

分享给可多选,取消选择即收回访问权限;保存后对所选文档整份覆盖 () + import { createLatestRequest, shareUserIntersection } from './model' + const props = defineProps<{ modelValue: boolean; documents: DoclibDocument[] }>() const emit = defineEmits<{ 'update:modelValue': [value: boolean] - saved: [document: DoclibDocument] + saved: [documents: DoclibDocument[]] }>() const visible = computed({ get: () => props.modelValue, @@ -77,17 +79,31 @@ const userIds = ref([]) const people = ref([]) const requests = createLatestRequest() + const ownerIds = computed( + () => new Set(props.documents.map((doc) => doc.ownerId).filter(Boolean)) + ) + const summaryText = computed(() => { + const names = props.documents.map((doc) => doc.name).filter(Boolean) + if (!names.length) return '未选择文档' + if (names.length === 1) return names[0] + const shown = names.slice(0, 5) + const more = names.length > 5 ? `等 ${names.length} 个` : '' + return `已选 ${names.length} 个文档:${shown.join('、')}${more ? ` ${more}` : ''}` + }) const options = computed(() => { - const candidates = new Map((props.document?.shares || []).map((person) => [person.id, person])) + const candidates = new Map() + for (const doc of props.documents) { + for (const person of doc.shares || []) candidates.set(person.id, person) + } people.value.forEach((person) => candidates.set(person.id, person)) - return [...candidates.values()].filter((person) => person.id !== props.document?.ownerId) + return [...candidates.values()].filter((person) => !ownerIds.value.has(person.id)) }) watch( () => props.modelValue, (value) => { requests.invalidate() if (!value) return - userIds.value = (props.document?.shares || []).map((person) => person.id) + userIds.value = shareUserIntersection(props.documents) people.value = [] void searchUsers('') } @@ -109,12 +125,17 @@ } } async function save() { - if (!props.document?.canManage || saving.value) return + if (!props.documents.length || props.documents.some((doc) => !doc.canManage) || saving.value) { + return + } saving.value = true try { - const updated = await saveDoclibShares(props.document.id, userIds.value) + const updated = await saveDoclibBatchShares( + props.documents.map((doc) => doc.id), + userIds.value + ) ElMessage.success('分享设置已保存') - emit('saved', updated) + emit('saved', updated || []) emit('update:modelValue', false) } catch { /* 请求层统一展示错误 */ diff --git a/web-admin/src/views/doclib/enter/browser.test.mjs b/web-admin/src/views/doclib/enter/browser.test.mjs index 5d5f17934..334f3b313 100644 --- a/web-admin/src/views/doclib/enter/browser.test.mjs +++ b/web-admin/src/views/doclib/enter/browser.test.mjs @@ -95,6 +95,12 @@ await context.route('**/api/**', async (route) => { return ok({ list, total: list.length }) } if (path === '/web/doclib/users') return ok([{ id: 'other', name: '同事', deptName: '生产部' }]) + if (path === '/web/doclib/files/batch-shares' && req.method() === 'POST') { + const body = req.postDataJSON() + sharedUsers = body.userIds + file.shares = sharedUsers.map((id) => ({ id, name: '同事', deptName: '生产部' })) + return ok([file]) + } if (path.endsWith('/shares')) { sharedUsers = req.postDataJSON().userIds file.shares = sharedUsers.map((id) => ({ id, name: '同事', deptName: '生产部' })) diff --git a/web-admin/src/views/doclib/enter/index.vue b/web-admin/src/views/doclib/enter/index.vue index b76f38c31..302a7f1ff 100644 --- a/web-admin/src/views/doclib/enter/index.vue +++ b/web-admin/src/views/doclib/enter/index.vue @@ -78,7 +78,7 @@ > 设置分享 - + (null) - function openShare(row: DoclibDocument) { - if (!row?.canManage) return - shareDocument.value = row + const shareDocuments = ref([]) + function openShare(rows: DoclibDocument | DoclibDocument[] | null | undefined) { + const list = (Array.isArray(rows) ? rows : rows ? [rows] : []).filter( + (row): row is DoclibDocument => !!row?.id && row.canManage + ) + if (!list.length) return + shareDocuments.value = list shareVisible.value = true } - function shareSaved(row: DoclibDocument) { - if (detail.value?.id === row.id) detail.value = row + function shareSaved(rows: DoclibDocument[]) { + const updated = Array.isArray(rows) ? rows : [] + const current = detail.value + if (current) { + const match = updated.find((row) => row.id === current.id) + if (match) detail.value = match + } void refresh() } const detailVisible = ref(false)