功能(文档预览):集成 ONLYOFFICE 安全只读预览与工作台体验
Client Quality Gates / Shared client and Web (push) Has been cancelled
Client Quality Gates / macOS Desktop (push) Has been cancelled

新增 ONLYOFFICE 配置签名、内部内容接口、容器编排与反向代理。

打通网页端和桌面端独立预览工作区,完善文档入口、布局及帮助体验。

补充桌面安全发布门禁、开发脚本、使用文档和前后端测试。
This commit is contained in:
Cheng Zhou
2026-07-14 14:19:17 +08:00
parent 44db5db838
commit c68dddfc01
50 changed files with 2429 additions and 677 deletions
@@ -163,6 +163,7 @@
<script setup lang="ts">
import { computed, defineAsyncComponent, onMounted, reactive, ref, watch } from "vue";
import { useRouter } from "vue-router";
import { ElMessage, ElMessageBox } from "element-plus";
import { Document, UploadFilled } from "@element-plus/icons-vue";
import { fetchAttachments, deleteAttachment, downloadAttachment, uploadAttachment } from "../../api/attachments";
@@ -177,6 +178,7 @@ import { TEXT } from "../../locales";
import { clientRuntime } from "../../runtime";
import { openFileWithFeedback, pickFilesWithFeedback, saveFileWithFeedback } from "../../utils/fileTaskFeedback";
import { finishDesktopActivity, startDesktopActivity, updateDesktopActivity } from "../../session/desktopActivityCenter";
import { detectFilePreviewKind } from "../../utils/officePreview";
type AttachmentEntityGroup = {
entityType: string;
@@ -223,6 +225,7 @@ const progressMap = reactive<Record<string, number>>({});
const pendingMap = reactive<Record<string, PendingUploadItem[]>>({});
const auth = useAuthStore();
const study = useStudyStore();
const router = useRouter();
const previewVisible = ref(false);
const previewUrl = ref("");
const previewObjectUrl = ref("");
@@ -518,17 +521,8 @@ const openExternally = async (row: any) => {
}
};
const getFileName = (row: any) => (row?.filename || "").toLowerCase();
const getMimeType = (row: any) => (row?.mime_type || row?.content_type || "").toLowerCase();
const detectPreviewType = (row: any) => {
const mime = getMimeType(row);
if (mime.startsWith("image/")) return "image";
if (mime === "application/pdf") return "pdf";
const name = getFileName(row);
if ([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp", ".svg"].some((ext) => name.endsWith(ext))) return "image";
if (name.endsWith(".pdf")) return "pdf";
return "other";
return detectFilePreviewKind(row?.filename, row?.mime_type || row?.content_type);
};
const previewImage = async (row: any) => {
@@ -547,7 +541,12 @@ const previewImage = async (row: any) => {
const preview = async (row: any) => {
previewError.value = "";
previewType.value = detectPreviewType(row);
const detectedType = detectPreviewType(row);
if (detectedType === "office") {
await router.push(`/office-preview/attachment/${row.id}`);
return;
}
previewType.value = detectedType;
previewTitle.value = row?.filename || TEXT.common.labels.preview;
if (previewType.value === "image" || previewType.value === "pdf") {
previewUrl.value = "";