feat: 完善知识库、策略预览与OnlyOffice集成
## 配置与环境 - .env.example: 更新环境变量配置 - docker-compose.yml: 完善Docker编排配置 - docker/README.md: 更新Docker文档 ## 后端知识库模块 - endpoints/knowledge.py: 增强知识库API端点 - schemas/knowledge.py: 扩展知识库数据模型 - services/knowledge.py: 完善知识库业务逻辑 - config.py: 优化配置管理 - storage/knowledge/.index.json: 更新知识库索引 ## 前端功能 - api.js: 完善API服务层 - knowledge.js: 优化知识库服务 - onlyoffice.js: 新增OnlyOffice文档服务集成 - TopBar.vue: 优化顶部导航栏 - PoliciesView.vue: 完善策略视图 - AppShellRouteView.vue: 新增应用外壳路由视图 - views/scripts/PoliciesView.js: 优化策略脚本 - policiesPreviewFormatters.js: 新增策略预览格式化工具 ## 样式 - policies-view.css: 完善策略页样式 ## 测试 - api-request.test.mjs: API请求测试 - onlyoffice-service.test.mjs: OnlyOffice服务测试 - policies-preview-formatters.test.mjs: 策略预览格式化测试
This commit is contained in:
@@ -1,249 +1,281 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import { watch } from 'vue'
|
||||
import { useSystemState } from '../../composables/useSystemState.js'
|
||||
import { useToast } from '../../composables/useToast.js'
|
||||
import {
|
||||
deleteKnowledgeDocument,
|
||||
fetchKnowledgeDocument,
|
||||
fetchKnowledgeDocumentBlob,
|
||||
fetchKnowledgeLibrary,
|
||||
fetchKnowledgeOnlyOfficeConfig,
|
||||
uploadKnowledgeDocument
|
||||
} from '../../services/knowledge.js'
|
||||
import { loadOnlyOfficeApi } from '../../services/onlyoffice.js'
|
||||
import { isManagerUser } from '../../utils/accessControl.js'
|
||||
import {
|
||||
buildExcelPreviewTable,
|
||||
buildPreviewMetaLine,
|
||||
buildPreviewSecondaryMetaLine
|
||||
} from './policiesPreviewFormatters.js'
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
const ONLYOFFICE_EXTENSIONS = new Set(['docx', 'xlsx', 'pptx'])
|
||||
|
||||
function supportsOnlyOfficePreview(document) {
|
||||
return ONLYOFFICE_EXTENSIONS.has(String(document?.extension || '').toLowerCase())
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'PoliciesView' ,
|
||||
setup(props, { emit }) {
|
||||
const folderSearch = ref('')
|
||||
name: 'PoliciesView',
|
||||
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 folders = [
|
||||
{ name: '财务知识库', count: 36, icon: 'mdi mdi-folder' },
|
||||
{ name: '制度政策', count: 8, icon: 'mdi mdi-folder' },
|
||||
{ name: '报销制度', count: 12, icon: 'mdi mdi-folder-open' },
|
||||
{ name: '差旅规范', count: 18, icon: 'mdi mdi-folder' },
|
||||
{ name: '发票管理', count: 14, icon: 'mdi mdi-folder' },
|
||||
{ name: '税务合规', count: 16, icon: 'mdi mdi-folder' },
|
||||
{ name: '预算管理', count: 9, icon: 'mdi mdi-folder' },
|
||||
{ name: '财务共享', count: 7, icon: 'mdi mdi-folder' },
|
||||
{ name: '培训资料', count: 6, icon: 'mdi mdi-folder' },
|
||||
{ name: '常见问答', count: 11, icon: 'mdi mdi-folder' }
|
||||
]
|
||||
|
||||
const documents = [
|
||||
{
|
||||
name: '差旅报销管理办法(2024版)',
|
||||
folder: '差旅规范',
|
||||
tag: '差旅 / 制度',
|
||||
time: '2024-05-12 14:35',
|
||||
version: 'v3.2',
|
||||
state: '已生效',
|
||||
stateTone: 'success',
|
||||
owner: '张明',
|
||||
icon: 'mdi mdi-file-document-outline-pdf pdf',
|
||||
fileType: 'pdf',
|
||||
fileTypeLabel: 'PDF 预览',
|
||||
summary: '面向员工与财务共享团队的差旅费用标准、审批边界和附件要求。',
|
||||
previewPages: [
|
||||
{
|
||||
title: '差旅报销管理办法(2024版)',
|
||||
subtitle: '住宿、交通、审批与附件要求',
|
||||
stats: [
|
||||
{ label: '适用范围', value: '全员' },
|
||||
{ label: '生效日期', value: '2024-05-12' },
|
||||
{ label: '更新重点', value: '住宿标准' }
|
||||
],
|
||||
blocks: [
|
||||
{
|
||||
heading: '一、适用范围',
|
||||
lines: ['适用于国内差旅申请、预订、报销与借款冲销。', '共享中心审核以出差申请、票据与预算中心为准。']
|
||||
},
|
||||
{
|
||||
heading: '二、住宿标准',
|
||||
lines: ['一线城市单晚标准 650 元,超标需附业务说明。', '连续住宿超过 3 晚需补充行程与客户拜访记录。']
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '审批与附件要求',
|
||||
subtitle: '流程节点与必要凭证',
|
||||
stats: [
|
||||
{ label: '附件校验', value: '7 项' },
|
||||
{ label: '审批节点', value: '4 级' },
|
||||
{ label: '自动拦截', value: '超标 / 重复' }
|
||||
],
|
||||
blocks: [
|
||||
{
|
||||
heading: '三、审批规则',
|
||||
lines: ['直属主管审批通过后进入财务复核。', '超预算或超标申请需追加部门负责人审批。']
|
||||
},
|
||||
{
|
||||
heading: '四、附件清单',
|
||||
lines: ['机票行程单、酒店发票、住宿水单、出租车发票。', '如存在改签、退票或异常情况,需补充说明材料。']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '发票查验规范及操作指引',
|
||||
folder: '发票管理',
|
||||
tag: '发票 / 操作',
|
||||
time: '2024-05-10 10:22',
|
||||
version: 'v1.5',
|
||||
state: '已生效',
|
||||
stateTone: 'success',
|
||||
owner: '李娜',
|
||||
icon: 'mdi mdi-file-document-outline-word word',
|
||||
fileType: 'word',
|
||||
fileTypeLabel: 'Word 预览',
|
||||
summary: '说明发票验真路径、异常票据处理方式以及入账留痕要求。',
|
||||
previewPages: [
|
||||
{
|
||||
title: '发票查验规范及操作指引',
|
||||
subtitle: '验真流程与异常识别',
|
||||
stats: [
|
||||
{ label: '查验入口', value: '3 个' },
|
||||
{ label: '异常类型', value: '6 类' },
|
||||
{ label: '责任角色', value: '财务专员' }
|
||||
],
|
||||
blocks: [
|
||||
{
|
||||
heading: '一、查验入口',
|
||||
lines: ['优先通过税务查验接口进行自动验真。', '无法自动识别时转人工核验并保留截图。']
|
||||
},
|
||||
{
|
||||
heading: '二、异常票据',
|
||||
lines: ['票面抬头不一致、号码重复、跨月补录需重点标注。', '出现红冲票据时需关联原单据并补充说明。']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '费用报销标准细则(2024)',
|
||||
folder: '报销制度',
|
||||
tag: '报销 / 标准',
|
||||
time: '2024-05-08 09:16',
|
||||
version: 'v2.1',
|
||||
state: '已生效',
|
||||
stateTone: 'success',
|
||||
owner: '王磊',
|
||||
icon: 'mdi mdi-file-document-outline-pdf pdf',
|
||||
fileType: 'pdf',
|
||||
fileTypeLabel: 'PDF 预览',
|
||||
summary: '定义招待、差旅、办公采购与培训等费用类型的标准与限制。',
|
||||
previewPages: [
|
||||
{
|
||||
title: '费用报销标准细则(2024)',
|
||||
subtitle: '费用口径与报销边界',
|
||||
stats: [
|
||||
{ label: '费用大类', value: '8 类' },
|
||||
{ label: '更新日期', value: '2024-05-08' },
|
||||
{ label: '重点事项', value: '招待 / 交通' }
|
||||
],
|
||||
blocks: [
|
||||
{
|
||||
heading: '一、业务招待',
|
||||
lines: ['需填写客户单位、参与人数及招待事由。', '单次超过 2000 元需上传审批邮件或会议纪要。']
|
||||
},
|
||||
{
|
||||
heading: '二、交通与差旅',
|
||||
lines: ['市内交通按真实票据报销,超标部分需说明。', '夜间出行或跨城交通需关联出差申请。']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '差旅费用标准对照表(国内)',
|
||||
folder: '差旅规范',
|
||||
tag: '差旅 / 标准',
|
||||
time: '2024-05-05 08:20',
|
||||
version: 'v1.3',
|
||||
state: '审批中',
|
||||
stateTone: 'warning',
|
||||
owner: '陈杰',
|
||||
icon: 'mdi mdi-file-document-outline-excel excel',
|
||||
fileType: 'excel',
|
||||
fileTypeLabel: 'Excel 预览',
|
||||
summary: '各城市住宿、餐补与交通等级对照表,供申请与审核环节快速查询。',
|
||||
previewPages: [
|
||||
{
|
||||
title: '差旅费用标准对照表(国内)',
|
||||
subtitle: '城市维度对照',
|
||||
stats: [
|
||||
{ label: '覆盖城市', value: '48 个' },
|
||||
{ label: '住宿档位', value: '4 级' },
|
||||
{ label: '餐补标准', value: '日维度' }
|
||||
],
|
||||
blocks: [
|
||||
{
|
||||
heading: '一、住宿标准',
|
||||
lines: ['北京 / 上海 / 深圳:650 元 / 晚。', '新一线城市:500 元 / 晚,其余城市按 380 元 / 晚执行。']
|
||||
},
|
||||
{
|
||||
heading: '二、交通等级',
|
||||
lines: ['总监及以上可乘坐高铁商务座或机票公务舱。', '其他员工默认经济舱、高铁二等座。']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '借款管理办法及流程',
|
||||
folder: '财务共享',
|
||||
tag: '借款 / 流程',
|
||||
time: '2024-05-03 11:05',
|
||||
version: 'v1.0',
|
||||
state: '已生效',
|
||||
stateTone: 'success',
|
||||
owner: '刘洋',
|
||||
icon: 'mdi mdi-file-document-outline-pdf pdf',
|
||||
fileType: 'pdf',
|
||||
fileTypeLabel: 'PDF 预览',
|
||||
summary: '覆盖差旅借款、项目借款和借款冲销的全流程要求。',
|
||||
previewPages: [
|
||||
{
|
||||
title: '借款管理办法及流程',
|
||||
subtitle: '借款申请与冲销闭环',
|
||||
stats: [
|
||||
{ label: '适用场景', value: '差旅 / 项目' },
|
||||
{ label: '冲销时限', value: '30 天' },
|
||||
{ label: '审批路径', value: '3 级' }
|
||||
],
|
||||
blocks: [
|
||||
{
|
||||
heading: '一、借款申请',
|
||||
lines: ['借款申请需绑定预算中心与费用类型。', '超过 5000 元需部门负责人额外审批。']
|
||||
},
|
||||
{
|
||||
heading: '二、冲销要求',
|
||||
lines: ['借款发生后 30 日内完成报销与冲销。', '逾期未冲销将纳入月度风险提醒。']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const filteredFolders = computed(() => {
|
||||
const key = folderSearch.value.trim()
|
||||
if (!key) return folders
|
||||
return folders.filter((folder) => folder.name.includes(key))
|
||||
})
|
||||
|
||||
const filteredDocuments = computed(() =>
|
||||
documents.filter((doc) => {
|
||||
const inFolder = activeFolder.value ? doc.folder === activeFolder.value : true
|
||||
return inFolder
|
||||
})
|
||||
)
|
||||
|
||||
const pageSizeOpen = ref(false)
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const pageSizes = [10, 20, 50]
|
||||
const pageSizeOpen = ref(false)
|
||||
const loading = ref(false)
|
||||
const uploadInput = ref(null)
|
||||
const uploading = ref(false)
|
||||
const deletingId = ref('')
|
||||
const previewLoading = ref(false)
|
||||
const previewBlobUrl = ref('')
|
||||
const previewError = ref('')
|
||||
const onlyOfficeLoading = ref(false)
|
||||
const onlyOfficeError = ref('')
|
||||
const onlyOfficeEditor = ref(null)
|
||||
const onlyOfficeHostId = ref('knowledge-onlyoffice-preview')
|
||||
const currentPreviewPageIndex = ref(0)
|
||||
|
||||
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 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 shouldUseOnlyOffice = computed(() => supportsOnlyOfficePreview(selectedDocument.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 (onlyOfficeEditor.value?.destroyEditor) {
|
||||
onlyOfficeEditor.value.destroyEditor()
|
||||
}
|
||||
onlyOfficeEditor.value = null
|
||||
}
|
||||
|
||||
async function mountOnlyOfficeEditor(documentId) {
|
||||
onlyOfficeLoading.value = true
|
||||
onlyOfficeError.value = ''
|
||||
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()
|
||||
onlyOfficeEditor.value = new window.DocsAPI.DocEditor(onlyOfficeHostId.value, payload.config)
|
||||
} catch (error) {
|
||||
onlyOfficeError.value = error.message || 'ONLYOFFICE 预览加载失败。'
|
||||
} finally {
|
||||
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 })
|
||||
|
||||
const activeExists = folders.value.some((folder) => folder.name === activeFolder.value)
|
||||
if (!activeExists) {
|
||||
activeFolder.value = folders.value[0]?.name || ''
|
||||
}
|
||||
|
||||
if (options.preserveSelection && selectedDocument.value?.id) {
|
||||
const exists = documents.value.some((doc) => doc.id === selectedDocument.value.id)
|
||||
if (!exists) {
|
||||
selectedDocument.value = null
|
||||
revokePreviewBlob()
|
||||
}
|
||||
}
|
||||
} 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 = ''
|
||||
revokePreviewBlob()
|
||||
destroyOnlyOfficeEditor()
|
||||
|
||||
try {
|
||||
const payload = await fetchKnowledgeDocument(documentId)
|
||||
selectedDocument.value = payload
|
||||
currentPreviewPageIndex.value = 0
|
||||
|
||||
if (supportsOnlyOfficePreview(payload)) {
|
||||
await mountOnlyOfficeEditor(documentId)
|
||||
} else 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 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
|
||||
}
|
||||
|
||||
const confirmed = window.confirm(`确认删除文件“${document.name}”吗?`)
|
||||
if (!confirmed) {
|
||||
return
|
||||
}
|
||||
|
||||
deletingId.value = document.id
|
||||
try {
|
||||
await deleteKnowledgeDocument(document.id)
|
||||
if (selectedDocument.value?.id === document.id) {
|
||||
selectedDocument.value = null
|
||||
revokePreviewBlob()
|
||||
}
|
||||
await loadLibrary()
|
||||
toast('知识库文件已删除。')
|
||||
} catch (error) {
|
||||
toast(error.message || '删除失败。')
|
||||
} finally {
|
||||
deletingId.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
function changePageSize(size) {
|
||||
pageSize.value = size
|
||||
@@ -251,28 +283,79 @@ export default {
|
||||
currentPage.value = 1
|
||||
}
|
||||
|
||||
function closePreview() {
|
||||
selectedDocument.value = null
|
||||
previewError.value = ''
|
||||
currentPreviewPageIndex.value = 0
|
||||
revokePreviewBlob()
|
||||
destroyOnlyOfficeEditor()
|
||||
onlyOfficeError.value = ''
|
||||
}
|
||||
|
||||
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()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
loadLibrary()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
revokePreviewBlob()
|
||||
})
|
||||
|
||||
return {
|
||||
folderSearch,
|
||||
activeFolder,
|
||||
selectedDocument,
|
||||
folders,
|
||||
documents,
|
||||
filteredFolders,
|
||||
filteredDocuments,
|
||||
activePreviewPage,
|
||||
changePageSize,
|
||||
closePreview,
|
||||
excelPreviewTable,
|
||||
currentPage,
|
||||
currentPreviewPageIndex,
|
||||
deletingId,
|
||||
documentSearch,
|
||||
filteredFolders,
|
||||
handleDelete,
|
||||
handleDownload,
|
||||
handleDrop,
|
||||
handleFileInput,
|
||||
isAdmin,
|
||||
loading,
|
||||
pageSize,
|
||||
pageSizes,
|
||||
pageSizeOpen,
|
||||
pageSizes,
|
||||
onlyOfficeError,
|
||||
onlyOfficeHostId,
|
||||
onlyOfficeLoading,
|
||||
previewMetaLine,
|
||||
previewSecondaryMetaLine,
|
||||
previewBlobUrl,
|
||||
previewError,
|
||||
previewLoading,
|
||||
shouldUseOnlyOffice,
|
||||
selectDocument,
|
||||
selectPreviewPage,
|
||||
selectedDocument,
|
||||
totalCount,
|
||||
totalPages,
|
||||
visibleDocuments,
|
||||
changePageSize
|
||||
triggerUpload,
|
||||
uploadHint,
|
||||
uploadInput,
|
||||
uploading,
|
||||
visibleDocuments
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user