feat: add ONLYOFFICE document preview for contract attachments

DocumentPreviewController provides preview config and file streaming endpoints. ContractDetailView adds 'preview' button to attachment list and opens ONLYOFFICE iframe dialog.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-05-27 08:37:09 +08:00
parent 8c788ea388
commit 8ee9aa51d8
2 changed files with 104 additions and 2 deletions
@@ -86,9 +86,18 @@
<template #default="{ row }">{{ (row.fileSize / 1024).toFixed(1) }} KB</template>
</el-table-column>
<el-table-column prop="createdAt" label="上传时间" width="170" />
<el-table-column label="操作" width="80" fixed="right">
<template #default="{ row }">
<el-button type="primary" link @click="previewAttachment(row)">预览</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog v-model="previewDialogVisible" :title="previewTitle" width="90%" top="5vh" destroy-on-close>
<iframe :src="previewUrl" style="width:100%;height:75vh;border:none;border-radius:4px" />
</el-dialog>
<h3 class="section-title">最近审计</h3>
<el-table v-loading="auditLoading" :data="auditRows" border stripe size="small" style="width: 100%">
<el-table-column label="时间" width="180">
@@ -169,6 +178,15 @@ const auditRows = ref([]);
const attachments = ref([]);
const uploading = ref(false);
const previewDialogVisible = ref(false);
const previewUrl = ref("");
const previewTitle = ref("");
function previewAttachment(row) {
previewTitle.value = row.fileName || "预览";
previewUrl.value = `${window.location.origin}/api/v1/preview/${row.id}`;
previewDialogVisible.value = true;
}
const lineDialogVisible = ref(false);
const lineEditingId = ref(null);
@@ -307,8 +325,8 @@ function formatAuditTime(row) {
async function loadNameMaps() {
try {
const [cRes, pRes] = await Promise.all([
listCustomers({ page: 0, size: 500 }),
listProjects({ page: 0, size: 500 }),
listCustomers({ page: 0, size: 200 }),
listProjects({ page: 0, size: 200 }),
]);
const cBody = cRes.data && typeof cRes.data === "object" ? cRes.data : {};
const pBody = pRes.data && typeof pRes.data === "object" ? pRes.data : {};