新增前端归档中心视图及相关工具函数,扩充知识库文档分类和 提取器支持多种格式,增强编排器报销查询的多维度检索,优 化本体规则和用户代理审核消息,前端完善报销创建和审批详 情交互细节,补充单元测试覆盖。
684 lines
21 KiB
JavaScript
684 lines
21 KiB
JavaScript
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||
|
||
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
|
||
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
|
||
import { useSystemState } from '../../composables/useSystemState.js'
|
||
import { useToast } from '../../composables/useToast.js'
|
||
import {
|
||
deleteKnowledgeDocument,
|
||
fetchKnowledgeDocument,
|
||
fetchKnowledgeDocumentBlob,
|
||
fetchKnowledgeLibrary,
|
||
fetchKnowledgeOnlyOfficeConfig,
|
||
syncKnowledgeLibrary,
|
||
uploadKnowledgeDocument
|
||
} from '../../services/knowledge.js'
|
||
import { loadOnlyOfficeApi } from '../../services/onlyoffice.js'
|
||
import { isManagerUser } from '../../utils/accessControl.js'
|
||
import {
|
||
buildExcelPreviewTable,
|
||
buildPreviewMetaLine,
|
||
buildPreviewSecondaryMetaLine
|
||
} from './policiesPreviewFormatters.js'
|
||
import {
|
||
canUseOnlyOfficePreview,
|
||
resolveKnowledgePreviewMode,
|
||
shouldRenderOnlyOfficeHost,
|
||
shouldRenderOnlyOfficePreview
|
||
} from './knowledgePreviewMode.js'
|
||
import { resolveKnowledgePreviewLayoutState } from './knowledgePreviewLayout.js'
|
||
import {
|
||
resolveInitialKnowledgeFolder,
|
||
resolveKnowledgeFolderIcon
|
||
} from './knowledgeFolderSelection.js'
|
||
import { buildOnlyOfficePreviewConfig } from './onlyOfficePreviewConfig.js'
|
||
|
||
const KNOWLEDGE_POLL_INTERVAL_MS = 5000
|
||
|
||
function triggerFileDownload(blob, filename) {
|
||
const url = URL.createObjectURL(blob)
|
||
const anchor = document.createElement('a')
|
||
anchor.href = url
|
||
anchor.download = filename
|
||
anchor.click()
|
||
URL.revokeObjectURL(url)
|
||
}
|
||
|
||
let bodyOverflowSnapshot = ''
|
||
let bodyOverscrollBehaviorSnapshot = ''
|
||
let libraryPollTimer = 0
|
||
|
||
function setBodyScrollLocked(isLocked) {
|
||
if (typeof document === 'undefined') {
|
||
return
|
||
}
|
||
|
||
const { body } = document
|
||
if (!body) {
|
||
return
|
||
}
|
||
|
||
if (isLocked) {
|
||
if (body.dataset.knowledgePreviewLocked === 'true') {
|
||
return
|
||
}
|
||
|
||
bodyOverflowSnapshot = body.style.overflow
|
||
bodyOverscrollBehaviorSnapshot = body.style.overscrollBehavior
|
||
body.style.overflow = 'hidden'
|
||
body.style.overscrollBehavior = 'contain'
|
||
body.dataset.knowledgePreviewLocked = 'true'
|
||
return
|
||
}
|
||
|
||
if (body.dataset.knowledgePreviewLocked !== 'true') {
|
||
return
|
||
}
|
||
|
||
body.style.overflow = bodyOverflowSnapshot
|
||
body.style.overscrollBehavior = bodyOverscrollBehaviorSnapshot
|
||
delete body.dataset.knowledgePreviewLocked
|
||
bodyOverflowSnapshot = ''
|
||
bodyOverscrollBehaviorSnapshot = ''
|
||
}
|
||
|
||
export default {
|
||
name: 'PoliciesView',
|
||
components: {
|
||
ConfirmDialog,
|
||
TableLoadingState
|
||
},
|
||
emits: ['summary-change'],
|
||
setup(_, { emit }) {
|
||
const { currentUser } = useSystemState()
|
||
const { toast } = useToast()
|
||
|
||
const documentSearch = ref('')
|
||
const activeFolder = ref('')
|
||
const folders = ref([])
|
||
const documents = ref([])
|
||
const selectedDocument = ref(null)
|
||
const pageSizeOpen = ref(false)
|
||
const currentPage = ref(1)
|
||
const pageSize = ref(10)
|
||
const pageSizes = [10, 20, 50]
|
||
const loading = ref(false)
|
||
const uploadInput = ref(null)
|
||
const uploading = ref(false)
|
||
const deletingId = ref('')
|
||
const syncingFolder = ref(false)
|
||
const deleteDialogOpen = ref(false)
|
||
const deleteTargetDocument = ref(null)
|
||
const previewLoading = ref(false)
|
||
const previewBlobUrl = ref('')
|
||
const previewError = ref('')
|
||
const onlyOfficeLoading = ref(false)
|
||
const onlyOfficeError = ref('')
|
||
const onlyOfficeAvailable = ref(false)
|
||
const onlyOfficeEditor = ref(null)
|
||
const onlyOfficeHostId = ref('knowledge-onlyoffice-preview')
|
||
const onlyOfficeReadyTimeoutId = ref(0)
|
||
const currentPreviewPageIndex = ref(0)
|
||
const previewDialogPanel = ref(null)
|
||
|
||
const isAdmin = computed(() => isManagerUser(currentUser.value))
|
||
const uploadHint = computed(() =>
|
||
isAdmin.value
|
||
? '支持 PDF / Word / Excel / PPT / 图片 / 文本文件,重复同名文件将自动覆盖并升级版本'
|
||
: '当前账号只有查阅权限,上传、删除和修改仅管理员可用'
|
||
)
|
||
|
||
const filteredFolders = computed(() => folders.value)
|
||
|
||
const filteredDocuments = computed(() => {
|
||
const key = documentSearch.value.trim()
|
||
|
||
return documents.value.filter((doc) => {
|
||
const inFolder = activeFolder.value ? doc.folder === activeFolder.value : true
|
||
const matchesSearch = key ? doc.name.includes(key) : true
|
||
return inFolder && matchesSearch
|
||
})
|
||
})
|
||
const activeFolderDocuments = computed(() =>
|
||
documents.value.filter((doc) => (activeFolder.value ? doc.folder === activeFolder.value : true))
|
||
)
|
||
const activeFolderIngestStats = computed(() => {
|
||
const stats = {
|
||
total: activeFolderDocuments.value.length,
|
||
pending: 0,
|
||
syncing: 0,
|
||
ingested: 0,
|
||
failed: 0
|
||
}
|
||
|
||
for (const doc of activeFolderDocuments.value) {
|
||
const stateCode = Number(doc?.stateCode || 0)
|
||
if (stateCode === 2) {
|
||
stats.syncing += 1
|
||
} else if (stateCode === 3) {
|
||
stats.ingested += 1
|
||
} else if (stateCode === 4) {
|
||
stats.failed += 1
|
||
} else {
|
||
stats.pending += 1
|
||
}
|
||
}
|
||
return stats
|
||
})
|
||
const knowledgeSyncButtonLabel = computed(() => {
|
||
if (syncingFolder.value || activeFolderIngestStats.value.syncing > 0) {
|
||
return '归纳中...'
|
||
}
|
||
return '知识归纳'
|
||
})
|
||
const knowledgeSyncHint = computed(() => {
|
||
const stats = activeFolderIngestStats.value
|
||
if (!activeFolder.value) {
|
||
return '请选择一个固定知识目录后再触发归纳。'
|
||
}
|
||
if (!stats.total) {
|
||
return '当前目录暂无文档,上传后即可进行知识归纳。'
|
||
}
|
||
if (stats.syncing > 0) {
|
||
return `当前目录有 ${stats.syncing} 份文档正在归纳,完成后会自动刷新状态。`
|
||
}
|
||
if (stats.pending > 0 || stats.failed > 0) {
|
||
return `当前目录待归纳 ${stats.pending} 份,需重试 ${stats.failed} 份。`
|
||
}
|
||
return `当前目录 ${stats.ingested} 份文档已归纳,可手动触发一次增量检查。`
|
||
})
|
||
const canTriggerKnowledgeSync = computed(
|
||
() =>
|
||
isAdmin.value
|
||
&& Boolean(activeFolder.value)
|
||
&& activeFolderIngestStats.value.total > 0
|
||
&& !syncingFolder.value
|
||
&& activeFolderIngestStats.value.syncing === 0
|
||
)
|
||
|
||
const totalCount = computed(() => filteredDocuments.value.length)
|
||
const totalPages = computed(() => Math.max(1, Math.ceil(totalCount.value / pageSize.value)))
|
||
const visibleDocuments = computed(() => {
|
||
const start = (currentPage.value - 1) * pageSize.value
|
||
return filteredDocuments.value.slice(start, start + pageSize.value)
|
||
})
|
||
const activePreviewPage = computed(() => {
|
||
const pages = selectedDocument.value?.previewPages || []
|
||
return pages[currentPreviewPageIndex.value] || pages[0] || null
|
||
})
|
||
const previewMetaLine = computed(() => buildPreviewMetaLine(selectedDocument.value))
|
||
const previewSecondaryMetaLine = computed(() =>
|
||
buildPreviewSecondaryMetaLine(selectedDocument.value, activePreviewPage.value)
|
||
)
|
||
const previewLayoutState = computed(() =>
|
||
resolveKnowledgePreviewLayoutState(selectedDocument.value)
|
||
)
|
||
const previewMode = computed(() =>
|
||
resolveKnowledgePreviewMode(selectedDocument.value, {
|
||
onlyOfficeAvailable: onlyOfficeAvailable.value
|
||
})
|
||
)
|
||
const shouldRenderOnlyOffice = computed(() =>
|
||
shouldRenderOnlyOfficePreview(selectedDocument.value, {
|
||
onlyOfficeLoading: onlyOfficeLoading.value,
|
||
onlyOfficeAvailable: onlyOfficeAvailable.value,
|
||
onlyOfficeError: onlyOfficeError.value
|
||
})
|
||
)
|
||
const shouldRenderOnlyOfficeHostNode = computed(() =>
|
||
shouldRenderOnlyOfficeHost(selectedDocument.value, {
|
||
onlyOfficeLoading: onlyOfficeLoading.value,
|
||
onlyOfficeAvailable: onlyOfficeAvailable.value,
|
||
onlyOfficeError: onlyOfficeError.value
|
||
})
|
||
)
|
||
const excelPreviewTable = computed(() =>
|
||
selectedDocument.value?.previewKind === 'table'
|
||
? buildExcelPreviewTable(activePreviewPage.value)
|
||
: { headers: [], rows: [] }
|
||
)
|
||
|
||
function revokePreviewBlob() {
|
||
if (previewBlobUrl.value) {
|
||
URL.revokeObjectURL(previewBlobUrl.value)
|
||
previewBlobUrl.value = ''
|
||
}
|
||
}
|
||
|
||
function destroyOnlyOfficeEditor() {
|
||
if (onlyOfficeReadyTimeoutId.value) {
|
||
window.clearTimeout(onlyOfficeReadyTimeoutId.value)
|
||
onlyOfficeReadyTimeoutId.value = 0
|
||
}
|
||
if (onlyOfficeEditor.value?.destroyEditor) {
|
||
onlyOfficeEditor.value.destroyEditor()
|
||
}
|
||
onlyOfficeEditor.value = null
|
||
}
|
||
|
||
async function mountOnlyOfficeEditor(documentId) {
|
||
onlyOfficeLoading.value = true
|
||
onlyOfficeError.value = ''
|
||
onlyOfficeAvailable.value = false
|
||
destroyOnlyOfficeEditor()
|
||
|
||
try {
|
||
const payload = await fetchKnowledgeOnlyOfficeConfig(documentId)
|
||
await loadOnlyOfficeApi(payload.documentServerUrl)
|
||
await nextTick()
|
||
|
||
if (!window.DocsAPI?.DocEditor) {
|
||
throw new Error('ONLYOFFICE 编辑器未正确加载。')
|
||
}
|
||
|
||
onlyOfficeHostId.value = `knowledge-onlyoffice-preview-${documentId}`
|
||
await nextTick()
|
||
const config = buildOnlyOfficePreviewConfig(payload.config, {
|
||
viewportHeight: window.innerHeight
|
||
})
|
||
const upstreamEvents = config.events || {}
|
||
config.events = {
|
||
...upstreamEvents,
|
||
onAppReady(event) {
|
||
if (onlyOfficeReadyTimeoutId.value) {
|
||
window.clearTimeout(onlyOfficeReadyTimeoutId.value)
|
||
onlyOfficeReadyTimeoutId.value = 0
|
||
}
|
||
onlyOfficeAvailable.value = true
|
||
onlyOfficeLoading.value = false
|
||
upstreamEvents.onAppReady?.(event)
|
||
},
|
||
onError(event) {
|
||
if (onlyOfficeReadyTimeoutId.value) {
|
||
window.clearTimeout(onlyOfficeReadyTimeoutId.value)
|
||
onlyOfficeReadyTimeoutId.value = 0
|
||
}
|
||
const errorCode = event?.data?.errorCode
|
||
const errorDescription = event?.data?.errorDescription
|
||
const message = errorDescription
|
||
? `ONLYOFFICE 预览失败:${errorDescription}`
|
||
: `ONLYOFFICE 预览失败${errorCode ? `(错误码 ${errorCode})` : '。'}`
|
||
onlyOfficeError.value = message
|
||
onlyOfficeLoading.value = false
|
||
console.error('ONLYOFFICE onError', event)
|
||
toast(message)
|
||
upstreamEvents.onError?.(event)
|
||
}
|
||
}
|
||
onlyOfficeEditor.value = new window.DocsAPI.DocEditor(onlyOfficeHostId.value, config)
|
||
onlyOfficeReadyTimeoutId.value = window.setTimeout(() => {
|
||
if (!onlyOfficeAvailable.value && !onlyOfficeError.value) {
|
||
onlyOfficeError.value = 'ONLYOFFICE 预览初始化超时。请检查浏览器是否拦截了 iframe 或混合内容。'
|
||
onlyOfficeLoading.value = false
|
||
toast(onlyOfficeError.value)
|
||
}
|
||
}, 10000)
|
||
return true
|
||
} catch (error) {
|
||
onlyOfficeError.value = error.message || 'ONLYOFFICE 预览加载失败。'
|
||
toast(onlyOfficeError.value)
|
||
return false
|
||
} finally {
|
||
if (onlyOfficeError.value) {
|
||
onlyOfficeLoading.value = false
|
||
}
|
||
}
|
||
}
|
||
|
||
async function loadLibrary(options = {}) {
|
||
loading.value = true
|
||
try {
|
||
const payload = await fetchKnowledgeLibrary()
|
||
folders.value = payload.folders || []
|
||
documents.value = payload.documents || []
|
||
emit('summary-change', { totalDocuments: documents.value.length })
|
||
|
||
activeFolder.value = resolveInitialKnowledgeFolder(folders.value, activeFolder.value)
|
||
|
||
if (options.preserveSelection && selectedDocument.value?.id) {
|
||
const nextDocument = documents.value.find((doc) => doc.id === selectedDocument.value.id)
|
||
const exists = Boolean(nextDocument)
|
||
if (!exists) {
|
||
closePreview()
|
||
} else {
|
||
selectedDocument.value = {
|
||
...selectedDocument.value,
|
||
...nextDocument
|
||
}
|
||
}
|
||
}
|
||
syncLibraryPolling()
|
||
} catch (error) {
|
||
emit('summary-change', { totalDocuments: 0 })
|
||
toast(error.message || '知识库加载失败。')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
async function selectDocument(documentId) {
|
||
previewLoading.value = true
|
||
previewError.value = ''
|
||
onlyOfficeError.value = ''
|
||
onlyOfficeAvailable.value = false
|
||
revokePreviewBlob()
|
||
destroyOnlyOfficeEditor()
|
||
|
||
try {
|
||
const payload = await fetchKnowledgeDocument(documentId)
|
||
selectedDocument.value = payload
|
||
currentPreviewPageIndex.value = 0
|
||
|
||
if (canUseOnlyOfficePreview(payload)) {
|
||
previewLoading.value = false
|
||
await mountOnlyOfficeEditor(documentId)
|
||
return
|
||
}
|
||
|
||
if (payload.previewKind === 'pdf' || payload.previewKind === 'image') {
|
||
const blob = await fetchKnowledgeDocumentBlob(documentId, 'inline')
|
||
previewBlobUrl.value = URL.createObjectURL(blob)
|
||
}
|
||
} catch (error) {
|
||
previewError.value = error.message || '预览加载失败。'
|
||
toast(previewError.value)
|
||
} finally {
|
||
previewLoading.value = false
|
||
}
|
||
}
|
||
|
||
async function handleDownload(document) {
|
||
try {
|
||
const blob = await fetchKnowledgeDocumentBlob(document.id, 'attachment')
|
||
triggerFileDownload(blob, document.name)
|
||
} catch (error) {
|
||
toast(error.message || '下载失败。')
|
||
}
|
||
}
|
||
|
||
function patchDocumentState(documentId, patch) {
|
||
documents.value = documents.value.map((doc) =>
|
||
doc.id === documentId ? { ...doc, ...patch } : doc
|
||
)
|
||
|
||
if (selectedDocument.value?.id === documentId) {
|
||
selectedDocument.value = {
|
||
...selectedDocument.value,
|
||
...patch
|
||
}
|
||
}
|
||
syncLibraryPolling()
|
||
}
|
||
|
||
function hasSyncingDocuments() {
|
||
return documents.value.some((doc) => Number(doc?.stateCode || 0) === 2)
|
||
}
|
||
|
||
function stopLibraryPolling() {
|
||
if (libraryPollTimer) {
|
||
window.clearInterval(libraryPollTimer)
|
||
libraryPollTimer = 0
|
||
}
|
||
}
|
||
|
||
function startLibraryPolling() {
|
||
stopLibraryPolling()
|
||
libraryPollTimer = window.setInterval(() => {
|
||
loadLibrary({ preserveSelection: true })
|
||
}, KNOWLEDGE_POLL_INTERVAL_MS)
|
||
}
|
||
|
||
function syncLibraryPolling() {
|
||
if (hasSyncingDocuments()) {
|
||
startLibraryPolling()
|
||
return
|
||
}
|
||
stopLibraryPolling()
|
||
}
|
||
|
||
async function handleKnowledgeSync() {
|
||
if (!canTriggerKnowledgeSync.value) {
|
||
return
|
||
}
|
||
|
||
syncingFolder.value = true
|
||
try {
|
||
const payload = await syncKnowledgeLibrary({
|
||
folder: activeFolder.value,
|
||
documentIds: [],
|
||
force: false
|
||
})
|
||
|
||
const queuedIds = Array.isArray(payload?.document_ids) ? payload.document_ids : []
|
||
for (const documentId of queuedIds) {
|
||
patchDocumentState(documentId, {
|
||
stateCode: 2,
|
||
state: '\u5f52\u7eb3\u4e2d',
|
||
stateTone: 'warning',
|
||
ingestTime: ''
|
||
})
|
||
}
|
||
|
||
await loadLibrary({ preserveSelection: true })
|
||
toast(payload?.summary || '\u77e5\u8bc6\u5f52\u7eb3\u4efb\u52a1\u5df2\u63d0\u4ea4\u3002')
|
||
} catch (error) {
|
||
await loadLibrary({ preserveSelection: true })
|
||
toast(error.message || '\u77e5\u8bc6\u5f52\u7eb3\u89e6\u53d1\u5931\u8d25\u3002')
|
||
} finally {
|
||
syncingFolder.value = false
|
||
}
|
||
}
|
||
|
||
function triggerUpload() {
|
||
if (!isAdmin.value || uploading.value) {
|
||
return
|
||
}
|
||
uploadInput.value?.click()
|
||
}
|
||
|
||
async function uploadFiles(fileList) {
|
||
const files = Array.from(fileList || []).filter(Boolean)
|
||
if (!files.length || !activeFolder.value || !isAdmin.value) {
|
||
return
|
||
}
|
||
|
||
uploading.value = true
|
||
try {
|
||
let latestDocumentId = ''
|
||
for (const file of files) {
|
||
const payload = await uploadKnowledgeDocument({ folder: activeFolder.value, file })
|
||
latestDocumentId = payload.id
|
||
}
|
||
|
||
await loadLibrary({ preserveSelection: true })
|
||
toast(files.length > 1 ? `已上传 ${files.length} 个知识库文件。` : '知识库文件已上传。')
|
||
|
||
if (latestDocumentId) {
|
||
await selectDocument(latestDocumentId)
|
||
}
|
||
} catch (error) {
|
||
toast(error.message || '上传失败。')
|
||
} finally {
|
||
uploading.value = false
|
||
if (uploadInput.value) {
|
||
uploadInput.value.value = ''
|
||
}
|
||
}
|
||
}
|
||
|
||
async function handleFileInput(event) {
|
||
await uploadFiles(event.target.files)
|
||
}
|
||
|
||
async function handleDrop(event) {
|
||
if (!isAdmin.value) {
|
||
return
|
||
}
|
||
await uploadFiles(event.dataTransfer?.files)
|
||
}
|
||
|
||
async function handleDelete(document) {
|
||
if (!isAdmin.value || deletingId.value) {
|
||
return
|
||
}
|
||
|
||
deleteTargetDocument.value = document
|
||
deleteDialogOpen.value = true
|
||
}
|
||
|
||
function closeDeleteDialog() {
|
||
if (deletingId.value) {
|
||
return
|
||
}
|
||
|
||
deleteDialogOpen.value = false
|
||
deleteTargetDocument.value = null
|
||
}
|
||
|
||
async function confirmDeleteDocument() {
|
||
const document = deleteTargetDocument.value
|
||
if (!document || !isAdmin.value || deletingId.value) {
|
||
return
|
||
}
|
||
|
||
deletingId.value = document.id
|
||
try {
|
||
await deleteKnowledgeDocument(document.id)
|
||
deleteDialogOpen.value = false
|
||
deleteTargetDocument.value = null
|
||
if (selectedDocument.value?.id === document.id) {
|
||
closePreview()
|
||
}
|
||
await loadLibrary()
|
||
toast('知识库文件已删除。')
|
||
} catch (error) {
|
||
toast(error.message || '删除失败。')
|
||
} finally {
|
||
deletingId.value = ''
|
||
}
|
||
}
|
||
|
||
function changePageSize(size) {
|
||
pageSize.value = size
|
||
pageSizeOpen.value = false
|
||
currentPage.value = 1
|
||
}
|
||
|
||
function closePreview() {
|
||
selectedDocument.value = null
|
||
previewLoading.value = false
|
||
previewError.value = ''
|
||
currentPreviewPageIndex.value = 0
|
||
revokePreviewBlob()
|
||
destroyOnlyOfficeEditor()
|
||
onlyOfficeLoading.value = false
|
||
onlyOfficeError.value = ''
|
||
onlyOfficeAvailable.value = false
|
||
}
|
||
|
||
function handleWindowKeydown(event) {
|
||
if (event.key === 'Escape' && selectedDocument.value) {
|
||
closePreview()
|
||
}
|
||
}
|
||
|
||
function selectPreviewPage(index) {
|
||
currentPreviewPageIndex.value = index
|
||
}
|
||
|
||
watch(filteredDocuments, () => {
|
||
currentPage.value = 1
|
||
pageSizeOpen.value = false
|
||
|
||
if (selectedDocument.value && !filteredDocuments.value.some((doc) => doc.id === selectedDocument.value.id)) {
|
||
closePreview()
|
||
}
|
||
})
|
||
|
||
watch(activeFolder, () => {
|
||
closePreview()
|
||
})
|
||
|
||
watch(
|
||
() => previewLayoutState.value.isPreviewModalOpen,
|
||
async (isAnyOverlayOpen) => {
|
||
setBodyScrollLocked(isAnyOverlayOpen)
|
||
|
||
if (previewLayoutState.value.isPreviewModalOpen) {
|
||
await nextTick()
|
||
previewDialogPanel.value?.focus?.()
|
||
}
|
||
}
|
||
)
|
||
|
||
onMounted(() => {
|
||
loadLibrary()
|
||
window.addEventListener('keydown', handleWindowKeydown)
|
||
})
|
||
|
||
onBeforeUnmount(() => {
|
||
revokePreviewBlob()
|
||
destroyOnlyOfficeEditor()
|
||
setBodyScrollLocked(false)
|
||
stopLibraryPolling()
|
||
window.removeEventListener('keydown', handleWindowKeydown)
|
||
})
|
||
|
||
return {
|
||
activeFolder,
|
||
activeFolderIngestStats,
|
||
activePreviewPage,
|
||
canTriggerKnowledgeSync,
|
||
changePageSize,
|
||
closePreview,
|
||
closeDeleteDialog,
|
||
confirmDeleteDocument,
|
||
excelPreviewTable,
|
||
currentPage,
|
||
currentPreviewPageIndex,
|
||
deleteDialogOpen,
|
||
deleteTargetDocument,
|
||
deletingId,
|
||
documentSearch,
|
||
filteredFolders,
|
||
handleDelete,
|
||
handleDownload,
|
||
handleDrop,
|
||
handleFileInput,
|
||
handleKnowledgeSync,
|
||
isAdmin,
|
||
knowledgeSyncButtonLabel,
|
||
knowledgeSyncHint,
|
||
loading,
|
||
pageSize,
|
||
pageSizeOpen,
|
||
pageSizes,
|
||
onlyOfficeError,
|
||
onlyOfficeHostId,
|
||
onlyOfficeLoading,
|
||
previewDialogPanel,
|
||
previewLayoutState,
|
||
previewMode,
|
||
previewMetaLine,
|
||
previewSecondaryMetaLine,
|
||
previewBlobUrl,
|
||
previewError,
|
||
previewLoading,
|
||
shouldRenderOnlyOffice,
|
||
shouldRenderOnlyOfficeHostNode,
|
||
selectDocument,
|
||
selectPreviewPage,
|
||
selectedDocument,
|
||
resolveKnowledgeFolderIcon,
|
||
syncingFolder,
|
||
totalCount,
|
||
totalPages,
|
||
triggerUpload,
|
||
uploadHint,
|
||
uploadInput,
|
||
uploading,
|
||
visibleDocuments
|
||
}
|
||
}
|
||
}
|