diff --git a/components/canvas/CanvasChatPanel.tsx b/components/canvas/CanvasChatPanel.tsx index c69f22945..5fd78fe5c 100644 --- a/components/canvas/CanvasChatPanel.tsx +++ b/components/canvas/CanvasChatPanel.tsx @@ -8037,7 +8037,7 @@ export function CanvasChatPanel({ { @@ -8059,7 +8059,7 @@ export function CanvasChatPanel({ ) : ( @@ -10799,21 +10799,17 @@ export function CanvasChatPanel({ > - {getToolbarItem("chatModelSelector").iconUrl ? ( - - ) : selectDisplayModel?.avatarUrl ? ( + {selectDisplayModel?.avatarUrl ? ( {selectDisplayModel.displayName { @@ -10822,10 +10818,16 @@ export function CanvasChatPanel({ } }} /> + ) : getToolbarItem("chatModelSelector").iconUrl ? ( + ) : ( diff --git a/components/canvas/canvas-logo-loading.tsx b/components/canvas/canvas-logo-loading.tsx index fb6f8c022..73f273231 100644 --- a/components/canvas/canvas-logo-loading.tsx +++ b/components/canvas/canvas-logo-loading.tsx @@ -21,18 +21,18 @@ export function CanvasLogoLoadingView({ return (
-
-
+
+
-
-
-
+
+
+
{lightLogo ? ( <> {resolvedSiteName} ) : null} ) : ( - + )}
-
+
{label}
diff --git a/components/home/lovart-home.tsx b/components/home/lovart-home.tsx index 3b953b3bc..b98e02491 100644 --- a/components/home/lovart-home.tsx +++ b/components/home/lovart-home.tsx @@ -428,7 +428,6 @@ export function LovartHome({ const [files, setFiles] = useState([]); const [isSubmitting, setIsSubmitting] = useState(false); const [activeCategory, setActiveCategory] = useState("全部"); - const [showAllProjects, setShowAllProjects] = useState(false); const [isProjectsOnlyView, setIsProjectsOnlyView] = useState(false); const [upgradeDialogOpen, setUpgradeDialogOpen] = useState(false); const [accountCenterOpen, setAccountCenterOpen] = useState(false); @@ -463,9 +462,6 @@ export function LovartHome({ const [deletingProjectId, setDeletingProjectId] = useState(null); const [typedPreviewText, setTypedPreviewText] = useState(""); const [previewCursorVisible, setPreviewCursorVisible] = useState(true); - const [routeTransitionLabel, setRouteTransitionLabel] = useState( - null - ); const [isSecondaryDataReady, setIsSecondaryDataReady] = useState(false); const [isFeaturedDataReady, setIsFeaturedDataReady] = useState(false); const projectSectionRef = useRef(null); @@ -716,18 +712,15 @@ export function LovartHome({ .map((item) => String(item || "").trim()) .filter(Boolean) // legacy typo compatibility: treat "惊喜" as "精选" - .map((item) => (item === "惊喜" ? "精选" : item)); + .map((item) => (item === "惊喜" ? "精选" : item)) + .filter((item) => item !== "精选"); const uniqueConfigured = Array.from(new Set(configured)); - const hasRealConfig = - uniqueConfigured.length > 0 && - !(uniqueConfigured.length === 1 && uniqueConfigured[0] === "全部"); - - const fallback = ["全部", "精选", ...DISCOVERY_DEFAULT_TABS]; - const base = hasRealConfig ? uniqueConfigured : fallback; - - const withoutAll = base.filter((item) => item !== "全部"); - const merged = ["全部", ...withoutAll]; + const merged = [ + "全部", + ...uniqueConfigured.filter((item) => item !== "全部"), + ...DISCOVERY_DEFAULT_TABS, + ]; return Array.from(new Set(merged)).slice(0, 12); }, [surpriseCategories]); @@ -825,12 +818,10 @@ export function LovartHome({ ); }, [loadedFeaturedImages, activeCategory]); - const shouldShowAllProjects = isProjectsOnlyView || showAllProjects; - const recentProjects = useMemo(() => { const projects = canvasData?.data || []; - return shouldShowAllProjects ? projects : projects.slice(0, 4); - }, [canvasData?.data, shouldShowAllProjects]); + return isProjectsOnlyView ? projects : projects.slice(0, 4); + }, [canvasData?.data, isProjectsOnlyView]); const hasMoreProjects = useMemo(() => { return (canvasData?.data || []).length > 4; @@ -1446,7 +1437,6 @@ export function LovartHome({ return; } setIsProjectsOnlyView(true); - setShowAllProjects(true); projectSectionRef.current?.scrollIntoView({ behavior: "smooth", block: "start" }); }; @@ -1460,11 +1450,6 @@ export function LovartHome({ } if (value.startsWith("/")) { - setRouteTransitionLabel( - value.startsWith("/canvas?mode=agent") - ? "正在进入风格化工作台..." - : "正在打开页面..." - ); router.push(value); return; } @@ -1548,20 +1533,12 @@ export function LovartHome({ return (
- {routeTransitionLabel ? ( -
-
- -
- {routeTransitionLabel} -
-
-
- ) : null} window.scrollTo({ top: 0, behavior: "smooth" })} shouldInvertLogo={shouldInvertLogo} + showBrand={false} siteName={siteName || "Lovart"} > @@ -1810,6 +1787,9 @@ export function LovartHome({ ? "/settings/agent-workflow" : null } + shouldInvertLogo={shouldInvertLogo} + siteLogo={displayLogo} + siteName={siteName || "Lovart"} toolbox1Enabled={siteSettingsData?.toolbox1Enabled !== false} toolbox1Links={toolbox1Links} toolbox2Enabled={siteSettingsData?.toolbox2Enabled === true} @@ -1820,7 +1800,7 @@ export function LovartHome({ tone={resolvedTheme === "dark" ? "dark" : "light"} /> -
+
{!isProjectsOnlyView && ( router.push(`/canvas/${projectId}`)} + onViewAllProjects={openAllProjectsInPage} projects={recentProjects} projectSectionRef={projectSectionRef} - setShowAllProjects={setShowAllProjects} - showAllProjects={showAllProjects} /> {!isProjectsOnlyView && ( diff --git a/components/home/lovart/lovart-featured-gallery.tsx b/components/home/lovart/lovart-featured-gallery.tsx index 4b3bcf373..5d0e93d58 100644 --- a/components/home/lovart/lovart-featured-gallery.tsx +++ b/components/home/lovart/lovart-featured-gallery.tsx @@ -1,7 +1,6 @@ -import { Heart, Loader2, Sparkles } from "lucide-react"; +import { Gem, Heart, Loader2, PlayCircle } from "lucide-react"; import type { Ref } from "react"; import type { FeaturedImage } from "./types"; -import { MASONRY_HEIGHTS } from "./utils"; type LovartFeaturedGalleryProps = { activeCategory: string; @@ -25,19 +24,21 @@ export function LovartFeaturedGallery({ setActiveCategory, }: LovartFeaturedGalleryProps) { return ( -
-

灵感发现

+
+

+ 灵感发现 +

-
+
{categories.map((category) => (
{featuredItems.length === 0 ? ( -
+
{isLoadingFeatured ? "灵感内容加载中..." : "当前没有可展示的灵感数据。"}
) : ( -
+
{featuredItems.map((item, index) => ( diff --git a/components/home/lovart/lovart-projects-section.tsx b/components/home/lovart/lovart-projects-section.tsx index 58ca6d796..561fe9a9c 100644 --- a/components/home/lovart/lovart-projects-section.tsx +++ b/components/home/lovart/lovart-projects-section.tsx @@ -1,4 +1,4 @@ -import { ArrowRight, Loader2, Trash2 } from "lucide-react"; +import { ChevronRight, Loader2, Trash2 } from "lucide-react"; import type { Ref } from "react"; import type { CanvasProject } from "./types"; import { formatRelativeTime } from "./utils"; @@ -10,10 +10,9 @@ type LovartProjectsSectionProps = { onCreateProject: () => void; onDeleteProject: (projectId: string, projectTitle?: string) => void; onOpenProject: (projectId: string) => void; + onViewAllProjects: () => void; projects: CanvasProject[]; projectSectionRef: Ref; - setShowAllProjects: (updater: (value: boolean) => boolean) => void; - showAllProjects: boolean; }; export function LovartProjectsSection({ @@ -23,75 +22,70 @@ export function LovartProjectsSection({ onCreateProject, onDeleteProject, onOpenProject, + onViewAllProjects, projects, projectSectionRef, - setShowAllProjects, - showAllProjects, }: LovartProjectsSectionProps) { return (
-
-

+
+

{isProjectsOnlyView ? "所有项目" : "最近项目"}

{!isProjectsOnlyView && hasMoreProjects ? ( ) : null}
-
+
{projects.map((item) => (
@@ -99,7 +93,7 @@ export function LovartProjectsSection({ type="button" onClick={() => onDeleteProject(item.id, item.title)} disabled={deletingProjectId === item.id} - className="absolute right-5 top-5 z-20 inline-flex h-7 w-7 items-center justify-center rounded-full border border-black/10 bg-white/90 text-black/45 shadow-sm transition hover:border-[#ffb4b4] hover:text-[#ef4444] disabled:cursor-not-allowed disabled:opacity-80 dark:border-white/10 dark:bg-[#18181c]/90 dark:text-white/45" + className="absolute right-3 top-3 z-20 inline-flex h-8 w-8 items-center justify-center rounded-full border border-black/10 bg-white/90 text-black/45 opacity-0 shadow-sm transition hover:border-[#ffb4b4] hover:text-[#ef4444] group-hover:opacity-100 disabled:cursor-not-allowed disabled:opacity-80 dark:border-white/10 dark:bg-[#18181c]/90 dark:text-white/45" aria-label={`删除${item.title || "未命名画布"}`} > {deletingProjectId === item.id ? ( @@ -110,12 +104,6 @@ export function LovartProjectsSection({
))} - - {projects.length === 0 && ( -
- 还没有项目,点击“新建项目”开始。 -
- )}

); diff --git a/components/home/lovart/lovart-sidebar.tsx b/components/home/lovart/lovart-sidebar.tsx index 502f46294..33b10e7c3 100644 --- a/components/home/lovart/lovart-sidebar.tsx +++ b/components/home/lovart/lovart-sidebar.tsx @@ -1,6 +1,5 @@ import { ArrowRight, PlayCircle } from "lucide-react"; import type { ReactNode } from "react"; -import { FloatingSidebarRail } from "@/components/home/floating-sidebar-shell"; import { HoverCard, HoverCardContent, @@ -43,6 +42,9 @@ type LovartSidebarProps = { } ) => ReactNode; settingsHref: string | null; + shouldInvertLogo?: boolean; + siteLogo?: string | null; + siteName: string; toolbox1Enabled: boolean; toolbox1Links: NavLink[]; toolbox2Enabled: boolean; @@ -69,6 +71,9 @@ export function LovartSidebar({ productPlanningEnabled, renderIcon, settingsHref, + shouldInvertLogo = false, + siteLogo, + siteName, toolbox1Enabled, toolbox1Links, toolbox2Enabled, @@ -78,13 +83,14 @@ export function LovartSidebar({ videoCanvasEnabled, tone = "light", }: LovartSidebarProps) { + const isDark = tone === "dark"; const sidebarPopupBaseClass = "rounded-[24px] border border-black/8 bg-white/96 p-2.5 text-[#111827] shadow-[0_24px_64px_rgba(15,23,42,0.12)] backdrop-blur-xl dark:border-white/10 dark:bg-[#141416]/96 dark:text-white dark:shadow-[0_24px_64px_rgba(0,0,0,0.42)]"; const sidebarButtonClass = (active = false) => [ - "group flex h-[34px] w-[34px] shrink-0 items-center justify-center rounded-[10px] text-[#6b7280] transition-all duration-200 hover:bg-black/[0.04] hover:text-[#111827] dark:text-white/62 dark:hover:bg-white/8 dark:hover:text-white", + "group flex h-11 w-11 shrink-0 items-center justify-center rounded-[11px] text-gray-800 transition-colors hover:bg-black/5 dark:text-white dark:hover:bg-white/10", active - ? "bg-[#f1f2f4] text-[#111827] shadow-[inset_0_0_0_1px_rgba(15,23,42,0.04)] dark:bg-white/12 dark:text-white" + ? "bg-black/5 text-gray-950 dark:bg-white/10 dark:text-white" : "", ] .filter(Boolean) @@ -106,7 +112,7 @@ export function LovartSidebar({ > {renderIcon(key, { active: options?.active, - sizeClassName: "h-[15px] w-[15px]", + sizeClassName: "h-[18px] w-[18px]", })} @@ -127,7 +133,7 @@ export function LovartSidebar({ className={sidebarButtonClass()} title={getItem(key).label} > - {renderIcon(key, { sizeClassName: "h-[15px] w-[15px]" })} + {renderIcon(key, { sizeClassName: "h-[18px] w-[18px]" })} + ); diff --git a/components/home/lovart/utils.ts b/components/home/lovart/utils.ts index 6f723c417..27bd8cfe1 100644 --- a/components/home/lovart/utils.ts +++ b/components/home/lovart/utils.ts @@ -127,16 +127,15 @@ export function getUserInitials(user: HomeUser | null) { } export function formatRelativeTime(value?: string) { - if (!value) return "更新于今天"; + if (!value) return "更新于 Jun 11, 2026"; const date = new Date(value); - 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 (Number.isNaN(date.getTime())) return "更新于 Jun 11, 2026"; + const formatted = date.toLocaleDateString("en-US", { + month: "short", + day: "numeric", + year: "numeric", + }); + return `更新于 ${formatted}`; } export function formatPrice(currency: string, value: number) { diff --git a/components/layout/brand-top-bar.tsx b/components/layout/brand-top-bar.tsx index e1f8d31bb..30aa3da41 100644 --- a/components/layout/brand-top-bar.tsx +++ b/components/layout/brand-top-bar.tsx @@ -13,6 +13,7 @@ type BrandTopBarProps = { onLogoClick?: () => void; position?: "fixed" | "sticky" | "static"; shouldInvertLogo?: boolean; + showBrand?: boolean; siteName: string; }; @@ -25,6 +26,7 @@ export function BrandTopBar({ onLogoClick, position = "fixed", shouldInvertLogo = false, + showBrand = true, siteName, }: BrandTopBarProps) { const resolvedSiteName = String(siteName || "").trim() || "由壹点AI"; @@ -45,33 +47,36 @@ export function BrandTopBar({ >
- + {showBrand ? ( + + ) : null}
{actions || children}