From 3c3f407f4b98fb63d147ed788b2e0ebd9d7419e1 Mon Sep 17 00:00:00 2001 From: liaibo Date: Sat, 24 Jan 2026 12:32:51 +0800 Subject: [PATCH] =?UTF-8?q?0.3.5=20=E5=85=B1=E4=BA=AB=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/app/api/onlyoffice/callback/route.ts | 153 ++++++ .../app/onlyoffice/OnlyOfficeClientPage.tsx | 14 +- pw_auth_login_failed.png | Bin 0 -> 5417 bytes pw_onlyoffice_loaded_run1.png | Bin 0 -> 188927 bytes pw_onlyoffice_loaded_run2.png | Bin 0 -> 188927 bytes wolai-frontend/convex/_generated/api.d.ts | 4 + .../convex/_utils/attachmentExtract.ts | 250 +++++++++ wolai-frontend/convex/_utils/ingestJobs.ts | 19 + wolai-frontend/convex/documentGroupShares.ts | 20 + wolai-frontend/convex/documentShares.ts | 144 ++++++ wolai-frontend/convex/documentStars.ts | 7 +- wolai-frontend/convex/documents.ts | 264 +++++++++- wolai-frontend/convex/groupInvitations.ts | 241 +++++++++ wolai-frontend/convex/groupMembers.ts | 42 +- wolai-frontend/convex/groups.ts | 45 +- wolai-frontend/convex/jobs.ts | 100 ++++ wolai-frontend/convex/mediaAssets.ts | 140 ++++- wolai-frontend/convex/schema.ts | 20 + wolai-frontend/convex/tables.ts | 79 +++ wolai-frontend/package.json | 4 +- wolai-frontend/pnpm-lock.yaml | 129 +++++ wolai-frontend/scripts/prod-server.js | 330 ++++++++++++ .../src/app/(app)/documents/[id]/page.tsx | 4 + wolai-frontend/src/app/(auth)/auth/page.tsx | 69 ++- .../src/app/api/media/sign/route.ts | 2 + .../src/app/api/onlyoffice/callback/route.ts | 13 + .../src/app/api/onlyoffice/forcesave/route.ts | 143 ++++++ .../src/app/api/search/documents/route.ts | 478 ++++++++++++++---- .../src/app/cache/[...path]/route.ts | 27 +- .../app/onlyoffice-server/[...path]/route.ts | 78 ++- .../app/onlyoffice/OnlyOfficeClientPage.tsx | 336 +++++++++++- wolai-frontend/src/components/breadcrumb.tsx | 10 +- .../components/editor/blocks/MediaBlock.tsx | 48 +- .../components/editor/document-content.tsx | 91 +++- .../groups/group-manager-dialog.tsx | 277 ++++++++-- .../components/providers/convex-provider.tsx | 8 +- .../src/components/search/search-palette.tsx | 15 +- .../sharing/document-share-dialog.tsx | 122 ++++- .../src/components/sidebar/private-tree.tsx | 12 +- .../src/components/sidebar/sidebar.tsx | 356 +++++++------ .../src/hooks/use-convex-sidebar-data.ts | 2 +- wolai-frontend/src/lib/auth/errors.test.ts | 28 + wolai-frontend/src/lib/auth/errors.ts | 23 + wolai-frontend/src/store/current-document.ts | 27 + 44 files changed, 3754 insertions(+), 420 deletions(-) create mode 100644 desktop-electron/desktop-next/src/app/api/onlyoffice/callback/route.ts create mode 100644 pw_auth_login_failed.png create mode 100644 pw_onlyoffice_loaded_run1.png create mode 100644 pw_onlyoffice_loaded_run2.png create mode 100644 wolai-frontend/convex/_utils/attachmentExtract.ts create mode 100644 wolai-frontend/convex/groupInvitations.ts create mode 100644 wolai-frontend/scripts/prod-server.js create mode 100644 wolai-frontend/src/app/api/onlyoffice/forcesave/route.ts create mode 100644 wolai-frontend/src/lib/auth/errors.test.ts create mode 100644 wolai-frontend/src/lib/auth/errors.ts create mode 100644 wolai-frontend/src/store/current-document.ts diff --git a/desktop-electron/desktop-next/src/app/api/onlyoffice/callback/route.ts b/desktop-electron/desktop-next/src/app/api/onlyoffice/callback/route.ts new file mode 100644 index 00000000..7b180fd6 --- /dev/null +++ b/desktop-electron/desktop-next/src/app/api/onlyoffice/callback/route.ts @@ -0,0 +1,153 @@ +import { NextResponse } from "next/server"; +import supabaseAdmin from "@/lib/supabase/admin"; + +export const dynamic = "force-dynamic"; + +const ONLYOFFICE_CALLBACK_SECRET = String(process.env.ONLYOFFICE_CALLBACK_SECRET || "").trim(); + +type OnlyOfficeCallbackBody = { + status?: number; + url?: string; + key?: string; +}; + +const normalizeSecret = (raw: string) => { + const trimmed = String(raw || "").trim(); + if (!trimmed) return ""; + // 兼容用户把 .env 的值写成 "xxx" / 'xxx' + if ( + (trimmed.startsWith("\"") && trimmed.endsWith("\"") && trimmed.length >= 2) || + (trimmed.startsWith("'") && trimmed.endsWith("'") && trimmed.length >= 2) + ) { + return trimmed.slice(1, -1).trim(); + } + return trimmed; +}; + +const isUuid = (value: string) => + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value); + +const resolveAssetObjectLocation = async (params: { + bucket?: string | null; + storagePath?: string | null; + workspaceId?: string | null; + fileName?: string | null; +}) => { + const { bucket, storagePath, workspaceId, fileName } = params; + const ws = (workspaceId ?? "").trim(); + const fn = (fileName ?? "").trim(); + + if (!ws || !isUuid(ws) || !fn) return null; + + try { + const storage = supabaseAdmin.schema("storage"); + + const b = (bucket ?? "").trim(); + const p = (storagePath ?? "").trim(); + if (b && p) { + const { data: exact, error: exactError } = await storage + .from("objects") + .select("bucket_id,name") + .eq("bucket_id", b) + .eq("name", p) + .limit(1); + if (!exactError && exact && exact.length > 0) { + return { bucket: b, path: p }; + } + } + + const pattern = `${ws}/%/${fn}`; + const { data: candidates, error: candError } = await storage + .from("objects") + .select("bucket_id,name,created_at") + .like("name", pattern) + .order("created_at", { ascending: false }) + .limit(20); + + if (candError || !candidates || candidates.length === 0) return null; + + const exactCandidate = + candidates.find((o) => String(o?.name || "").endsWith(`/${fn}`)) ?? candidates[0]; + if (!exactCandidate?.bucket_id || !exactCandidate?.name) return null; + return { bucket: String(exactCandidate.bucket_id), path: String(exactCandidate.name) }; + } catch { + return null; + } +}; + +export async function POST(request: Request) { + const { searchParams } = new URL(request.url); + const assetId = searchParams.get("assetId") || ""; + + // 说明:ONLYOFFICE 回调由文档服务器触发,不一定携带用户态;这里提供一个可选的共享密钥校验。 + // 若未配置 ONLYOFFICE_CALLBACK_SECRET,则保持兼容不校验。 + if (ONLYOFFICE_CALLBACK_SECRET) { + const got = normalizeSecret(searchParams.get("token") || ""); + const expected = normalizeSecret(ONLYOFFICE_CALLBACK_SECRET); + if (!got || got !== expected) { + return NextResponse.json({ error: 1 }); + } + } + + const body = (await request.json().catch(() => null)) as OnlyOfficeCallbackBody | null; + if (!body) { + return NextResponse.json({ error: 0 }); + } + + const status = Number(body.status ?? -1); + // 说明:仅在文档需要保存时处理(2=ready for saving;6=force save)。 + if (status !== 2 && status !== 6) { + return NextResponse.json({ error: 0 }); + } + + if (!assetId) { + return NextResponse.json({ error: 1 }); + } + if (!body.url) { + return NextResponse.json({ error: 1 }); + } + + try { + const { data: asset, error: assetError } = await supabaseAdmin + .from("media_assets") + .select("*") + .eq("id", assetId) + .single(); + if (assetError || !asset) { + return NextResponse.json({ error: 1 }); + } + + const loc = await resolveAssetObjectLocation({ + bucket: (asset.bucket as string | null) ?? null, + storagePath: (asset.storage_path as string | null) ?? null, + workspaceId: (asset.workspace_id as string | null) ?? null, + fileName: (asset.file_name as string | null) ?? null, + }); + if (!loc) { + return NextResponse.json({ error: 1 }); + } + + const upstream = await fetch(body.url, { method: "GET", redirect: "follow" }); + if (!upstream.ok) { + return NextResponse.json({ error: 1 }); + } + const buf = Buffer.from(await upstream.arrayBuffer()); + + const contentType = String(asset.mime_type || "application/octet-stream"); + const { error: uploadError } = await supabaseAdmin.storage.from(loc.bucket).upload(loc.path, buf, { + contentType, + upsert: true, + }); + if (uploadError) { + return NextResponse.json({ error: 1 }); + } + + // 说明:桌面端(Supabase)模式下,文件 URL 通常是短期 signedUrl; + // 覆盖同一 storage_path 的对象即可让后续刷新/下载拿到最新文件。 + return NextResponse.json({ error: 0 }); + } catch (error) { + console.error("[onlyoffice/callback] supabase writeback failed:", error); + return NextResponse.json({ error: 1 }); + } +} + diff --git a/desktop-electron/desktop-next/src/app/onlyoffice/OnlyOfficeClientPage.tsx b/desktop-electron/desktop-next/src/app/onlyoffice/OnlyOfficeClientPage.tsx index 93d096ec..5f65e5a0 100644 --- a/desktop-electron/desktop-next/src/app/onlyoffice/OnlyOfficeClientPage.tsx +++ b/desktop-electron/desktop-next/src/app/onlyoffice/OnlyOfficeClientPage.tsx @@ -110,7 +110,7 @@ export default function OnlyOfficePage() { } catch { return base; } - }, [fileUrl, storageHostOverride]); + }, [fileUrl, proxyOrigin, runtimeConfig.supabaseUrl, storageHostOverride]); useEffect(() => { if (!baseUrl) { @@ -144,6 +144,16 @@ export default function OnlyOfficePage() { editorConfig: { mode: mode === "view" ? "view" : "edit", lang: "zh-CN", + // 说明:ONLYOFFICE 文档服务器会通过 callbackUrl 回传保存事件; + // 桌面端(standalone)这里必须配置,否则“看似已保存”但不会写回原文件。 + callbackUrl: assetId + ? (() => { + const base = proxyOrigin || window.location.origin; + const cb = new URL("/api/onlyoffice/callback", base); + cb.searchParams.set("assetId", assetId); + return cb.toString(); + })() + : undefined, customization: { feedback: { visible: false }, }, @@ -192,7 +202,7 @@ export default function OnlyOfficePage() { .catch((err: Error) => { setError(err.message); }); - }, [baseUrl, fileName, fileType, mode, resolvedFileUrl, targetDocType]); + }, [assetId, baseUrl, fileName, fileType, mode, proxyOrigin, resolvedFileUrl, targetDocType]); if (error) { return ( diff --git a/pw_auth_login_failed.png b/pw_auth_login_failed.png new file mode 100644 index 0000000000000000000000000000000000000000..c10c9d42f9b296297a565a3287a5ccd0a1ad299e GIT binary patch literal 5417 zcmeH~{a4aw6u`f}Ql_$UW*Lee>v)z;oor&hp=MF*Xsue>1htvE4*5b9VF;*gnW3eX zGt*>q&ek~z+KzxIBAKF@lDed!hVS2*!Pl1*5QVY-V4dTS{BrL-&$-Xbx#!-`b8o@% zXsn%$vkd?Mc1I3Jo&W$VqiOzXletlaA-^^=Dl^gvYy`mWL(Brer;|q_!%tBvl_SF! ztL5fl{e6$u4Wi1W;=Rl}OeXUXN<#VPUG3JNbH+~H;Xn|?Fz%n1twTJR(EvDZImQDI zf6`{OcW+8G%59duM!DI12LR+)n%Nrf%mb_ez%3lG0D$8E;r@)_fuhl9>pC^0(@_JH zSEWVR(UAF$naRrA@BF9JSLNo|lwsWmEEkmf9gChy5zzE+xX!_C@k!L-KB@ntLAM)r zdev*P9$pwEw9yZN;(X2! zFyD`p1C$0BFU*Htu)0*1&)W`vKtI?-?oo~6A4^VuIO8NQd#%yjRFNg4&sm@G9tMn7 zFddwbt^Dc|k8^_Rj>|=uUY5i)v_+BTW!IXB9-`~d+rPaRpkMA84_ZU_xx>+mY)7RF z*sa{ZIIrC5t@=fLfS6rQz~nyF!GaHhM&}}H+fiU_Z*FQUAvid&KC|c z_-HhFWKX_YqdY}8N-|)=#HWE{s6?eXHvnWaC26@!>Ubu!*IWB+Wu2h`lQ9s z{A2`rVycxgz|Q6=9A<8~5HETavBdG@S1Ol*HLph0)VTx(?w^>4bG(t#9IjWL6)N^?pfDhrB51t3K8&*e#I*! zTbyotz9!82wqW+k)k&~e`7J!XSex`H;YQu)r9eO8+Emt}RZxOXzB1Aru1cX(d=c?8 za#WzG)IYjzY3GVct+ac(aH;Qt0FNCVo1-ltC^Or%nNt$)X-_z00Twr!?bAEth{oGh zFtP=zO~IW*7cDrGEdfTSCw_oT(*kYz7r6|F|5l`)R{voNLGJYt8^M@^_S|reeI)iw z?i=)fm;z}E!#MH-M-E0uvLh1n{sjgoVGjTR literal 0 HcmV?d00001 diff --git a/pw_onlyoffice_loaded_run1.png b/pw_onlyoffice_loaded_run1.png new file mode 100644 index 0000000000000000000000000000000000000000..34aa2fbd8668df31e9bed88d5b68c0041837c9a7 GIT binary patch literal 188927 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