chore: commit all local pending updates
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-03-03 23:19:54 +08:00
parent 6967fd6683
commit 47ecb1470b
6 changed files with 58 additions and 16 deletions

View File

@ -3,6 +3,7 @@ import NextAuth, { type DefaultSession } from "next-auth";
import type { DefaultJWT } from "next-auth/jwt"; import type { DefaultJWT } from "next-auth/jwt";
import Credentials from "next-auth/providers/credentials"; import Credentials from "next-auth/providers/credentials";
import Google from "next-auth/providers/google"; import Google from "next-auth/providers/google";
import { headers } from "next/headers";
import { DUMMY_PASSWORD } from "@/lib/constants"; import { DUMMY_PASSWORD } from "@/lib/constants";
import { createGuestUser, getAuthSettings, getUser } from "@/lib/db/queries"; import { createGuestUser, getAuthSettings, getUser } from "@/lib/db/queries";
import { buildAuthConfig } from "./auth.config"; import { buildAuthConfig } from "./auth.config";
@ -159,6 +160,37 @@ function createBaseProviders(googleClientId?: string, googleClientSecret?: strin
return providers; return providers;
} }
function normalizeBaseUrl(input?: string | null) {
if (!input) return "";
try {
const parsed = new URL(input);
return `${parsed.protocol}//${parsed.host}`;
} catch {
return "";
}
}
async function resolveRuntimeAuthUrl(settingsAuthUrl?: string | null) {
const fromEnv =
normalizeBaseUrl(process.env.AUTH_URL) ||
normalizeBaseUrl(process.env.NEXTAUTH_URL);
if (fromEnv) return fromEnv;
const fromSettings = normalizeBaseUrl(settingsAuthUrl);
if (fromSettings) return fromSettings;
const requestHeaders = await headers();
const forwardedHost = requestHeaders.get("x-forwarded-host");
const host = requestHeaders.get("host");
const resolvedHost = forwardedHost || host || "";
if (!resolvedHost) return "";
const forwardedProto = requestHeaders.get("x-forwarded-proto");
const protocol = forwardedProto || "https";
return `${protocol}://${resolvedHost}`;
}
export const { export const {
handlers: { GET, POST }, handlers: { GET, POST },
auth, auth,
@ -167,7 +199,7 @@ export const {
} = NextAuth(async () => { } = NextAuth(async () => {
const runtimeAuthSettings = await getAuthSettings().catch(() => null as any); const runtimeAuthSettings = await getAuthSettings().catch(() => null as any);
const resolvedAuthUrl = const resolvedAuthUrl =
runtimeAuthSettings?.authUrl || process.env.AUTH_URL || undefined; (await resolveRuntimeAuthUrl(runtimeAuthSettings?.authUrl)) || undefined;
const googleClientId = const googleClientId =
runtimeAuthSettings?.googleClientId || process.env.GOOGLE_CLIENT_ID || ""; runtimeAuthSettings?.googleClientId || process.env.GOOGLE_CLIENT_ID || "";
const googleClientSecret = const googleClientSecret =

View File

@ -1930,6 +1930,9 @@ export async function POST(request: Request) {
const explicitFollowLatestResult = /(上一张|上一轮|刚生成|最新生成|这个结果|该结果|按这个结果|继续在这张|基于这张结果|延续上一次结果)/i.test( const explicitFollowLatestResult = /(上一张|上一轮|刚生成|最新生成|这个结果|该结果|按这个结果|继续在这张|基于这张结果|延续上一次结果)/i.test(
textContent textContent
); );
const explicitUseOriginalUpload = /(原图|上传图|参考图|最初那张|第一张图|素材图)/i.test(
textContent
);
const latestAssistantImages: string[] = []; const latestAssistantImages: string[] = [];
const latestUserImages: string[] = []; const latestUserImages: string[] = [];
@ -1982,22 +1985,24 @@ export async function POST(request: Request) {
} }
} }
if (explicitFollowLatestResult && latestAssistantImages.length > 0) { if (explicitUseOriginalUpload && latestUserImages.length > 0) {
smartAutoHistoryImages = latestAssistantImages.slice(0, 4);
console.log(
"[Smart Auto Mode] 🖼️ Using latest generated image(s) by explicit instruction:",
smartAutoHistoryImages.length
);
} else if (latestUserImages.length > 0) {
smartAutoHistoryImages = latestUserImages.slice(0, 4); smartAutoHistoryImages = latestUserImages.slice(0, 4);
console.log( console.log(
"[Smart Auto Mode] 🖼️ Using latest user-uploaded image(s) to avoid iterative blur:", "[Smart Auto Mode] 🖼️ Using latest user-uploaded image(s) by explicit instruction:",
smartAutoHistoryImages.length smartAutoHistoryImages.length
); );
} else if (latestAssistantImages.length > 0) { } else if (latestAssistantImages.length > 0) {
smartAutoHistoryImages = latestAssistantImages.slice(0, 4); smartAutoHistoryImages = latestAssistantImages.slice(0, 4);
console.log( console.log(
"[Smart Auto Mode] 🖼️ Fallback to latest generated image(s):", explicitFollowLatestResult
? "[Smart Auto Mode] 🖼️ Using latest generated image(s) by explicit instruction:"
: "[Smart Auto Mode] 🖼️ Using latest generated image(s) for continuous edit:",
smartAutoHistoryImages.length
);
} else if (latestUserImages.length > 0) {
smartAutoHistoryImages = latestUserImages.slice(0, 4);
console.log(
"[Smart Auto Mode] 🖼️ Fallback to latest user-uploaded image(s):",
smartAutoHistoryImages.length smartAutoHistoryImages.length
); );
} }

View File

@ -12,7 +12,6 @@ import {
Download, Download,
Eye, Eye,
EyeOff, EyeOff,
FileBox,
Grid3X3, Grid3X3,
History, History,
ImagePlus, ImagePlus,
@ -20,12 +19,14 @@ import {
Layers3, Layers3,
Loader2, Loader2,
Maximize, Maximize,
Package,
Palette, Palette,
PenLine, PenLine,
Play, Play,
PlusCircle, PlusCircle,
RefreshCw, RefreshCw,
RotateCw, RotateCw,
Scissors,
Settings2, Settings2,
Sparkles, Sparkles,
Sun, Sun,
@ -414,6 +415,7 @@ export default function CanvasModel3DPage() {
// Effect hooks for data loading and cleanup // Effect hooks for data loading and cleanup
useEffect(() => { useEffect(() => {
console.log("CanvasModel3DPage mounted - v2.0");
const loadBalance = async () => { const loadBalance = async () => {
const result = await model3DGenerationService.getBalance(); const result = await model3DGenerationService.getBalance();
if (!result.success) return; if (!result.success) return;
@ -1301,7 +1303,10 @@ export default function CanvasModel3DPage() {
</Button> </Button>
<div className="flex flex-col"> <div className="flex flex-col">
<span className="font-semibold text-sm leading-none"> <span className="font-semibold text-sm leading-none">
3D 工作台 3D 工作台{" "}
<span className="ml-1 rounded bg-primary/10 px-1 text-[10px] text-primary">
v2.0
</span>
</span> </span>
<span className="mt-0.5 text-[10px] text-muted-foreground"> <span className="mt-0.5 text-[10px] text-muted-foreground">
Tripo3D 驱动 Tripo3D 驱动

View File

@ -561,7 +561,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
{/* 1. Canvas Layer (Full Screen) - 使用 key 强制在 id 变化时重新挂载 */} {/* 1. Canvas Layer (Full Screen) - 使用 key 强制在 id 变化时重新挂载 */}
<div className="absolute inset-0 z-0" key={`workspace-${id}`}> <div className="absolute inset-0 z-0" key={`workspace-${id}`}>
<CanvasWorkspace /> <CanvasWorkspace occlusionRight={isPanelOpen ? 476 : 0} />
</div> </div>
{/* Brand Entry (Top Left) */} {/* Brand Entry (Top Left) */}
@ -663,7 +663,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
"absolute top-4 right-4 bottom-4 z-10 w-[460px] max-w-[calc(100vw-1rem)] transition-all duration-300 ease-in-out", "absolute top-4 right-4 bottom-4 z-10 w-[460px] max-w-[calc(100vw-1rem)] transition-all duration-300 ease-in-out",
isPanelOpen ? "translate-x-0 opacity-100" : "translate-x-[120%] opacity-0 pointer-events-none" isPanelOpen ? "translate-x-0 opacity-100" : "translate-x-[120%] opacity-0 pointer-events-none"
)}> )}>
<div className="h-full w-full rounded-2xl border bg-background/90 backdrop-blur-md shadow-2xl overflow-hidden flex flex-col"> <div className="h-full w-full rounded-2xl border bg-white dark:bg-zinc-950 shadow-2xl overflow-hidden flex flex-col">
{panelMode === 'chat' ? ( {panelMode === 'chat' ? (
// AI 对话内容 - 使用 key 强制在 id 变化时重新挂载 // AI 对话内容 - 使用 key 强制在 id 变化时重新挂载
<div className="flex-1 overflow-hidden" key={`chat-${id}`}> <div className="flex-1 overflow-hidden" key={`chat-${id}`}>

View File

@ -1138,7 +1138,7 @@ export function LovartHome({
}, [accountCenterData?.profile, currentPlan?.monthlyCredits, currentPlan?.name, membershipData?.summary?.currentCredits, membershipData?.summary?.dailyFreeCredits, user?.email, userDisplayName]); }, [accountCenterData?.profile, currentPlan?.monthlyCredits, currentPlan?.name, membershipData?.summary?.currentCredits, membershipData?.summary?.dailyFreeCredits, user?.email, userDisplayName]);
return ( return (
<div className="min-h-svh bg-[#f4f4f4] text-[#171717]"> <div className="min-h-svh bg-[#f4f4f4] text-[#171717] [&_button]:cursor-pointer [&_input]:cursor-pointer [&_textarea]:cursor-pointer [&_img]:cursor-pointer [&_a]:cursor-pointer [&_[role=button]]:cursor-pointer">
<header className="fixed left-0 top-0 z-40 h-[68px] w-full bg-[#f4f4f4]/90 backdrop-blur"> <header className="fixed left-0 top-0 z-40 h-[68px] w-full bg-[#f4f4f4]/90 backdrop-blur">
<div className="flex h-full items-center justify-between px-7"> <div className="flex h-full items-center justify-between px-7">
<button <button

File diff suppressed because one or more lines are too long