feat(doclib): 文档库支持多选文档后批量设置分享。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
dd4fdf1e6e
commit
0baa6880f7
3 files changed
+55
-20
No files matched your search
@@ -11,11 +11,13 @@
|
||||
:close-on-press-escape="!saving"
|
||||
:show-close="!saving"
|
||||
>
|
||||
<p class="doclib-summary">{{ document?.name }}</p>
|
||||
<p class="doclib-summary">{{ summaryText }}</p>
|
||||
<el-form label-position="top">
|
||||
<el-form-item>
|
||||
<template #label
|
||||
>分享给<span class="form-label-tip">可多选,取消选择即收回访问权限</span></template
|
||||
>分享给<span class="form-label-tip"
|
||||
>可多选,取消选择即收回访问权限;保存后对所选文档整份覆盖</span
|
||||
></template
|
||||
>
|
||||
<el-select
|
||||
v-model="userIds"
|
||||
@@ -56,15 +58,15 @@
|
||||
import { Close, Check } from '@element-plus/icons-vue'
|
||||
import {
|
||||
fetchDoclibUsers,
|
||||
saveDoclibShares,
|
||||
saveDoclibBatchShares,
|
||||
type DoclibDocument,
|
||||
type DoclibPerson
|
||||
} from '@/api/doclib'
|
||||
import { createLatestRequest } from './model'
|
||||
const props = defineProps<{ modelValue: boolean; document: DoclibDocument | null }>()
|
||||
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<string[]>([])
|
||||
const people = ref<DoclibPerson[]>([])
|
||||
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<string, DoclibPerson>()
|
||||
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 {
|
||||
/* 请求层统一展示错误 */
|
||||
|
||||
@@ -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: '生产部' }))
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
>
|
||||
<el-button
|
||||
:disabled="!actions.share || loading || busy"
|
||||
@click="openShare(selected[0])"
|
||||
@click="openShare(selected)"
|
||||
><el-icon><Share /></el-icon>设置分享</el-button
|
||||
>
|
||||
<el-button
|
||||
@@ -195,7 +195,7 @@
|
||||
@download="download([$event])"
|
||||
@view="openDetail"
|
||||
/>
|
||||
<ShareDialog v-model="shareVisible" :document="shareDocument" @saved="shareSaved" />
|
||||
<ShareDialog v-model="shareVisible" :documents="shareDocuments" @saved="shareSaved" />
|
||||
<el-dialog
|
||||
v-model="folderVisible"
|
||||
:title="renameMode ? '重命名文件夹' : '新建文件夹'"
|
||||
@@ -489,14 +489,22 @@
|
||||
}
|
||||
}
|
||||
const shareVisible = ref(false)
|
||||
const shareDocument = ref<DoclibDocument | null>(null)
|
||||
function openShare(row: DoclibDocument) {
|
||||
if (!row?.canManage) return
|
||||
shareDocument.value = row
|
||||
const shareDocuments = ref<DoclibDocument[]>([])
|
||||
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)
|
||||
|
||||
Reference in new issue
Block a user