diff --git a/components/canvas/CanvasChatPanel.tsx b/components/canvas/CanvasChatPanel.tsx index 71d3d8b5e..a475ab9bb 100644 --- a/components/canvas/CanvasChatPanel.tsx +++ b/components/canvas/CanvasChatPanel.tsx @@ -1437,6 +1437,34 @@ function buildPreviewImageUrl(url: string, width: number): string { }); } +function ModelAvatarImage({ + src, + alt, + className, + fallback, +}: { + src: string; + alt: string; + className: string; + fallback: JSX.Element; +}) { + const [loadFailed, setLoadFailed] = useState(false); + if (!src || loadFailed) { + return fallback; + } + + return ( + {alt} setLoadFailed(true)} + /> + ); +} + const CANVAS_IMAGE_ANALYSIS_TITLE = "图片分析"; const CANVAS_IMAGE_DONE_SUMMARY = "已完成本次生成,如需微调可继续告诉我。"; const CANVAS_AGENT_SECTION_TITLES = new Set([ @@ -15115,17 +15143,22 @@ export function CanvasChatPanel({ )} > {model.avatarUrl ? ( - {model.displayName} { - if (event.currentTarget.src !== model.avatarUrl) { - event.currentTarget.src = model.avatarUrl || ""; - } - }} + fallback={ + + {model.id === "auto" ? "A" : model.displayName.slice(0, 1)} + + } /> ) : ( {selectDisplayModel?.avatarUrl ? ( - {selectDisplayModel.displayName { - if (event.currentTarget.src !== selectDisplayModel.avatarUrl) { - event.currentTarget.src = selectDisplayModel.avatarUrl || ""; - } - }} + fallback={ + + {(selectDisplayModel?.displayName || "A").slice(0, 1)} + + } /> ) : getToolbarItem("chatModelSelector").iconUrl ? ( (false); + + if (!src || loadFailed) { + return fallback; + } + + return ( + {alt} setLoadFailed(true)} + /> + ); +} + import { Trigger } from "@radix-ui/react-select"; import type { UIMessage } from "ai"; import equal from "fast-deep-equal"; @@ -2132,10 +2162,11 @@ function PureModelSelectorCompact({ title={readOnlyName} > {readOnlyAvatarUrl ? ( - {readOnlyName}} /> ) : ( @@ -2189,10 +2220,11 @@ function PureModelSelectorCompact({ variant="ghost" > {selectedModel?.avatarUrl ? ( - {selectedModel.name}} /> ) : ( @@ -2227,10 +2259,26 @@ function PureModelSelectorCompact({ {model.avatarUrl ? ( - {model.displayName} + {(() => { + if (isVideoProviderType(model)) { + return + } /> ) : ( diff --git a/proxy.ts b/proxy.ts index ab17ebb98..777dcba96 100644 --- a/proxy.ts +++ b/proxy.ts @@ -778,6 +778,11 @@ export async function proxy(request: NextRequest, event: NextFetchEvent) { return NextResponse.next(); } + // 图片代理用于站内图片优化/转码,需支持未登录用户下的公开图片链接渲染。 + if (pathname === "/api/image-proxy" && request.method === "GET") { + return NextResponse.next(); + } + // 允许匿名访问新版首页灵感数据 if (pathname === "/api/featured" || pathname.startsWith("/api/featured/")) { return NextResponse.next();