153 lines
3.9 KiB
TypeScript

import {
Box,
BarChart3,
Briefcase,
Clapperboard,
Edit,
Folder,
Home,
ImageIcon,
Monitor,
Moon,
Palette,
PlayCircle,
Plus,
Settings,
Sparkles,
Star,
Sun,
User,
Wand2,
Workflow,
type LucideIcon,
} from "lucide-react";
import type { LovartHomeSidebarItemKey } from "@/lib/home/lovart-sidebar-config";
import type { HomeUser } from "./types";
export type ThemeMode = "system" | "light" | "dark";
export const THEME_MODE_OPTIONS: Array<{
value: ThemeMode;
label: string;
description: string;
icon: LucideIcon;
}> = [
{
value: "system",
label: "跟随系统",
description: "随浏览器/系统深浅色自动切换",
icon: Monitor,
},
{
value: "light",
label: "浅色模式",
description: "始终使用明亮界面",
icon: Sun,
},
{
value: "dark",
label: "深色模式",
description: "始终使用暗色界面",
icon: Moon,
},
];
export const DISCOVERY_DEFAULT_TABS = [
"品牌设计",
"海报与广告",
"插画",
"UI设计",
"角色设计",
"影片与分镜",
"产品设计",
"建筑设计",
];
export const PROMPT_TAGS = [
{ key: "nanoBananaPro", label: "Nano Banana Pro", icon: Sparkles, highlighted: true },
{ key: "design", label: "Design", icon: ImageIcon, highlighted: false },
{ key: "branding", label: "Branding", icon: Star, highlighted: false },
{ key: "illustration", label: "Illustration", icon: Palette, highlighted: false },
{ key: "ecommerce", label: "E-Commerce", icon: Monitor, highlighted: false },
{ key: "video", label: "Video", icon: Clapperboard, highlighted: false },
] as const;
export const LOVART_HOME_SIDEBAR_FALLBACK_ICONS: Record<
LovartHomeSidebarItemKey,
LucideIcon
> = {
newProject: Plus,
home: Home,
projects: Folder,
profile: User,
gallery: ImageIcon,
tutorial: PlayCircle,
imageEditor: Edit,
aiCad: Box,
agent: Wand2,
videoCanvas: Clapperboard,
flowBoard: Workflow,
productPlanning: BarChart3,
toolbox1: Briefcase,
toolbox2: Briefcase,
settings: Settings,
};
export type LovartPromptTagKey = (typeof PROMPT_TAGS)[number]["key"];
export type LovartPromptTagVisibility = Record<LovartPromptTagKey, boolean>;
export const MASONRY_HEIGHTS = [420, 290, 340, 470, 300, 360, 430, 320];
export const FEATURED_PAGE_SIZE = 24;
export const COMPOSER_PREFIX_DEFAULT = "让Buyi-ai";
export function normalizeComposerPreviewTail(text: string, fixedPrefix: string) {
const trimmed = text.trim();
if (!trimmed) return "";
const sanitizedPrefix = fixedPrefix.trim();
if (sanitizedPrefix && trimmed.startsWith(sanitizedPrefix)) {
return trimmed.slice(sanitizedPrefix.length).trimStart();
}
const legacyPrefixRemoved = trimmed
.replace(/^让\s*buyi[-_ ]?ai\s*/i, "")
.replace(/^让\s*lovart\s*/i, "")
.trimStart();
if (legacyPrefixRemoved !== trimmed) {
return legacyPrefixRemoved;
}
return trimmed;
}
export function getUserInitials(user: HomeUser | null) {
const source = (user?.name || user?.email || "mu").trim();
if (!source) return "mu";
return source.slice(0, 2).toLowerCase();
}
export function formatRelativeTime(value?: string) {
if (!value) return "更新于今天";
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)} 天前`;
}
export function formatPrice(currency: string, value: number) {
if (value <= 0) return "免费";
return `${currency}${value}`;
}
export function formatDateTime(value?: string) {
if (!value) return "-";
const date = new Date(value);
if (Number.isNaN(date.getTime())) return "-";
return date.toLocaleString("zh-CN", { hour12: false });
}