From 459dc5ccbb509e504dd46485d9b86cc364ea72c0 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 13 Feb 2026 19:52:09 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E5=81=9A=E6=96=B0=E7=89=88=E9=A6=96?= =?UTF-8?q?=E9=A1=B5=E5=B8=83=E5=B1=80=E5=B9=B6=E5=AE=8C=E5=96=84=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E9=A6=96=E9=A1=B5=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/home/lovart-home.tsx | 866 +++++++++++++++++++------------- 1 file changed, 523 insertions(+), 343 deletions(-) diff --git a/components/home/lovart-home.tsx b/components/home/lovart-home.tsx index 8e26e486f..f662d51c5 100644 --- a/components/home/lovart-home.tsx +++ b/components/home/lovart-home.tsx @@ -1,13 +1,18 @@ "use client"; -import { Fragment, useMemo, useRef, useState } from "react"; -import useSWR from "swr"; +import { Fragment, useEffect, useMemo, useRef, useState } from "react"; import { useRouter } from "next/navigation"; +import useSWR from "swr"; import { Bell, ChevronDown, Folder, + Globe, + Heart, + Hexagon, Home, + Info, + MapPin, Plus, Send, Sparkles, @@ -47,6 +52,10 @@ type FeaturedImage = { thumbnailUrl: string; originalUrl: string; prompt?: string | null; + user?: { + name?: string; + department?: string; + }; }; type MembershipSummaryResponse = { @@ -86,17 +95,39 @@ type UploadFileItem = { previewUrl: string; }; +const DISCOVERY_DEFAULT_TABS = [ + "品牌设计", + "海报与广告", + "插画", + "UI设计", + "角色设计", + "影片与分镜", + "产品设计", + "建筑设计", +]; + +const PROMPT_TAGS = [ + "Nano Banana Pro", + "Design", + "Branding", + "Illustration", + "E-Commerce", + "Video", +]; + +const MASONRY_HEIGHTS = [420, 290, 340, 470, 300, 360, 430, 320]; + function formatRelativeTime(value?: string) { - if (!value) return "刚刚更新"; + if (!value) return "更新于今天"; const date = new Date(value); - if (Number.isNaN(date.getTime())) return "刚刚更新"; + if (Number.isNaN(date.getTime())) return "更新于今天"; const diffMs = Date.now() - date.getTime(); const minute = 60 * 1000; const hour = 60 * minute; const day = 24 * hour; - if (diffMs < hour) return `${Math.max(1, Math.round(diffMs / minute))} 分钟前`; - if (diffMs < day) return `${Math.round(diffMs / hour)} 小时前`; - return `${Math.round(diffMs / day)} 天前`; + if (diffMs < hour) return `更新于 ${Math.max(1, Math.round(diffMs / minute))} 分钟前`; + if (diffMs < day) return `更新于 ${Math.round(diffMs / hour)} 小时前`; + return `更新于 ${Math.round(diffMs / day)} 天前`; } function formatPrice(currency: string, value: number) { @@ -117,7 +148,8 @@ export function LovartHome({ const [activeCategory, setActiveCategory] = useState("全部"); const [upgradeDialogOpen, setUpgradeDialogOpen] = useState(false); const [billingCycle, setBillingCycle] = useState<"monthly" | "annual">("monthly"); - const moduleBRef = useRef(null); + const projectSectionRef = useRef(null); + const filesRef = useRef([]); const { data: canvasData, mutate: mutateCanvas } = useSWR<{ success: boolean; @@ -126,7 +158,7 @@ export function LovartHome({ const { data: featuredData } = useSWR<{ images: FeaturedImage[]; - }>("/api/featured?page=1&pageSize=18", fetcher); + }>("/api/featured?page=1&pageSize=40", fetcher); const { data: membershipData } = useSWR( "/api/user/membership-summary", @@ -137,23 +169,6 @@ export function LovartHome({ const membershipPlans = membershipConfig?.plans || []; const currentPlan = membershipData?.currentPlan; - const categoryTabs = useMemo(() => { - const base = surpriseCategories.length > 0 ? surpriseCategories : ["全部", "惊喜"]; - if (!base.includes("全部")) { - return ["全部", ...base]; - } - return base; - }, [surpriseCategories]); - - const filteredFeatured = useMemo(() => { - const images = featuredData?.images || []; - if (activeCategory === "全部") return images; - const keyword = activeCategory.toLowerCase(); - return images.filter((item) => - String(item.prompt || "").toLowerCase().includes(keyword) - ); - }, [featuredData?.images, activeCategory]); - const groupedModelRows = useMemo(() => { const rows = membershipConfig?.modelRows || []; return rows.reduce>((acc, row) => { @@ -165,6 +180,40 @@ export function LovartHome({ }, {}); }, [membershipConfig?.modelRows]); + const discoveryTabs = useMemo(() => { + const merged = [ + "全部", + ...surpriseCategories.filter((item) => item && item !== "全部"), + ...DISCOVERY_DEFAULT_TABS, + ]; + return Array.from(new Set(merged)).slice(0, 12); + }, [surpriseCategories]); + + const featuredItems = useMemo(() => { + const images = featuredData?.images || []; + if (activeCategory === "全部") { + return images; + } + const keyword = activeCategory.toLowerCase(); + return images.filter((item) => + String(item.prompt || "").toLowerCase().includes(keyword) + ); + }, [featuredData?.images, activeCategory]); + + const recentProjects = useMemo(() => { + return (canvasData?.data || []).slice(0, 7); + }, [canvasData?.data]); + + useEffect(() => { + filesRef.current = files; + }, [files]); + + useEffect(() => { + return () => { + filesRef.current.forEach((item) => URL.revokeObjectURL(item.previewUrl)); + }; + }, []); + const handleAddFiles = (targetFiles: FileList | null) => { if (!targetFiles || targetFiles.length === 0) return; @@ -279,93 +328,85 @@ export function LovartHome({ }; return ( -
- - -
-
-
+
+
+
+ + +
+ + + + + - -
-
-
- {currentPlan?.name || "Free"} + +
+
+
+
+ {currentPlan?.name || "Free"} +
-
+
- + 积分 - {membershipData?.summary?.currentCredits ?? 0} + {membershipData?.summary?.currentCredits ?? 0}
- + 每日免费积分 - {membershipData?.summary?.dailyFreeCredits ?? 0} + {membershipData?.summary?.dailyFreeCredits ?? 0}
-
- {(user.name || user.email || "U").slice(0, 1).toUpperCase()} + + +
+
+
+ + + +
+
+ + +
+ {siteLogo ? ( + {siteName} + ) : ( +
+ +
+ )} +

+ {siteName || "Lovart"} 让设计更简单 +

+
+

懂你的设计代理,帮你搞定一切

+ +
+