From b367a01353b80b28c937ceea4f7c1a4adb912d6a Mon Sep 17 00:00:00 2001 From: zjr Date: Sun, 30 Aug 2026 22:17:00 +0800 Subject: [PATCH 1/4] =?UTF-8?q?[frontend]=20fix:=20=E4=BA=91=E7=9B=98=20PD?= =?UTF-8?q?F=20=E6=94=B9=E4=B8=BA=E5=90=8C=E6=BA=90=E4=BB=A3=E7=90=86+?= =?UTF-8?q?=E6=96=B0=E6=A0=87=E7=AD=BE=E9=A1=B5=E5=8E=9F=E7=94=9F=E9=A2=84?= =?UTF-8?q?=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - next.config: /minio-proxy/* beforeFiles rewrite(Next 服务端转发 nginx→MinIO), 生产模式(NEXT_PUBLIC_API_URL 设值)也保留;MINIO_PROXY_DEST 走 build arg (rewrites 在构建时固化进 routes-manifest,运行时 env 无效) - file-viewer: presigned URL 归一化为同源相对路径,PDF 用 window.open 新标签页 交给浏览器原生查看器(原 iframe 会被 nginx X-Frame-Options SAMEORIGIN 跨源拒绝) - Dockerfile: npm registry 切 npmmirror(musl 平台 swc 二进制不在 Windows 锁文件 里,next build 现场下载直连 npmjs 必断);healthcheck wget 改 127.0.0.1(busybox localhost 解析 IPv6,Next 只绑 IPv4,容器永远 unhealthy) --- frontendv2/Dockerfile | 15 +++- .../components/cloud-drive/file-viewer.tsx | 72 ++++++++++++++++--- frontendv2/next.config.ts | 19 ++++- 3 files changed, 91 insertions(+), 15 deletions(-) diff --git a/frontendv2/Dockerfile b/frontendv2/Dockerfile index 98949af..9945e49 100644 --- a/frontendv2/Dockerfile +++ b/frontendv2/Dockerfile @@ -17,10 +17,20 @@ WORKDIR /app # Override via: docker build --build-arg NEXT_PUBLIC_API_URL=... ARG NEXT_PUBLIC_API_URL="" ARG NEXT_PUBLIC_APISIX_HOST="" +# next build 会把 rewrites() 的 destination 固化进 routes-manifest.json(运行时 +# env 不再参与求值),所以 MinIO 同源代理目标必须作为 build arg 注入。 +# compose 传 http://nginx:80;宿主机本地构建缺省走 http://localhost。 +ARG MINIO_PROXY_DEST="" ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL \ - NEXT_PUBLIC_APISIX_HOST=$NEXT_PUBLIC_APISIX_HOST + NEXT_PUBLIC_APISIX_HOST=$NEXT_PUBLIC_APISIX_HOST \ + MINIO_PROXY_DEST=$MINIO_PROXY_DEST # Install dependencies first to leverage Docker's layer cache. +# registry 切国内镜像:package-lock 在 Windows 生成,Linux/musl 平台的 +# @next/swc 二进制不在锁文件里,`next build` 会现场从 registry 下载约 60MB, +# 直连 npmjs 极易被掐断导致构建崩溃(download-swc 会读取 npm registry 配置, +# 所以这里一处设置同时管住 npm ci 和 swc 下载)。 +RUN npm config set registry https://registry.npmmirror.com COPY package.json package-lock.json ./ RUN npm ci @@ -51,7 +61,8 @@ USER appuser EXPOSE 3000 +# busybox wget 会把 localhost 解析成 IPv6 ::1,而 Next 只绑 IPv4 —— 用 127.0.0.1 HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ - CMD wget -qO- http://localhost:3000/ || exit 1 + CMD wget -qO- http://127.0.0.1:3000/ || exit 1 CMD ["node", "server.js"] diff --git a/frontendv2/components/cloud-drive/file-viewer.tsx b/frontendv2/components/cloud-drive/file-viewer.tsx index d9c377c..c64e24d 100644 --- a/frontendv2/components/cloud-drive/file-viewer.tsx +++ b/frontendv2/components/cloud-drive/file-viewer.tsx @@ -7,21 +7,42 @@ * Next 16 async-params dance, same convention as the shared-note page). * * Fetches a presigned MinIO GET URL (plus inline text for text-like types) - * from /cloud/video/:uuid/raw and renders the file natively: - * - video / audio / image / pdf -> browser element with the presigned URL - * - html / markdown / text -> inline content (no CORS fetch) + * from /cloud/video/:uuid/raw and renders the file: + * - pdf -> auto-open in a NEW browser tab; the + * browser's native PDF viewer takes over + * - video / audio / image -> browser element with the presigned URL + * - html / markdown / text -> inline content (no CORS fetch) * - anything else -> download link * * Layout: sticky frosted header (back + icon + name + size + download) + a * centered reading column. */ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { usePathname, useRouter } from "next/navigation"; import { Markdown } from "@/components/markdown"; import { ArrowLeft, Loader2, AlertCircle, Download, FileText } from "lucide-react"; import { cloudApi, formatBytes, type CloudRawFileResponse } from "@/lib/api/cloud"; import { FileIconTile } from "./file-icon"; +/** + * Normalize the presigned MinIO URL to a same-origin path when it goes + * through the nginx /minio-proxy prefix. Embedding the absolute proxy URL + * (e.g. http://localhost/minio-proxy/...) in an