From 624129f3c98c06060dd9649d46a1db1402659f01 Mon Sep 17 00:00:00 2001 From: huangmin <2927933426@qq.com> Date: Wed, 3 Jun 2026 12:46:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E7=89=88=E6=9C=AC=EF=BC=8C=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E4=B8=8B=E6=8B=89=E8=8F=9C=E5=8D=95=E5=92=8C?= =?UTF-8?q?=E5=9B=BE=E6=A0=87=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 8 +- src/app/page.tsx | 412 +++++++++++++++++++++- src/components/ProjectActionsDropdown.tsx | 48 +++ src/components/icons/index.tsx | 169 +++++++++ src/store/execution/nanoBananaExecutor.ts | 7 +- 5 files changed, 637 insertions(+), 7 deletions(-) create mode 100644 src/components/ProjectActionsDropdown.tsx create mode 100644 src/components/icons/index.tsx diff --git a/package-lock.json b/package-lock.json index 297f9fae..a0ec7e2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -254,14 +254,14 @@ } }, "node_modules/@ant-design/icons": { - "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-6.2.3.tgz", - "integrity": "sha512-Pl3aoAtxQeKryYnt6VvDJtOxMOtA8wrRSACe/pTjOAIG3fdHrWm6Ivb4ku9tsFjYroSXBKirvuxG4QkwBXD9gg==", + "version": "6.2.5", + "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-6.2.5.tgz", + "integrity": "sha512-0hKtoKqTjGFOndUyJLJmC9Cg6k4rEO7rLo6xmgbNJH+/ZX1C57RVals2v1j1knHl9n7Q+sBOveTvn931wLOCKw==", "license": "MIT", "dependencies": { "@ant-design/colors": "^8.0.1", "@ant-design/icons-svg": "^4.4.2", - "@rc-component/util": "^1.10.1", + "@rc-component/util": "^1.11.0", "clsx": "^2.1.1" }, "engines": { diff --git a/src/app/page.tsx b/src/app/page.tsx index 7dfec4ca..d2264f47 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,414 @@ +import Link from "next/link"; +import type { ReactNode } from "react"; +import { ProjectActionsDropdown } from "@/components/ProjectActionsDropdown"; +import { + HelpIcon, + GlobeIcon, + CloseIcon, + SearchIcon, + ArrowIcon, + WeChatIcon, + SparklingIcon, + StartCreation +} from "@/components/icons"; + +const assets = { + heroSeedance: + "https://www.figma.com/api/mcp/asset/a7864f0d-0f6b-4509-bca3-26d1016d5d5e", + heroVlog: + "https://www.figma.com/api/mcp/asset/c675f2af-159a-49df-823a-b7d45136a96d", + heroPopi: + "https://www.figma.com/api/mcp/asset/c6cc76f8-ef2e-4236-b991-5e4e126b12f5", + projectAlice: + "https://www.figma.com/api/mcp/asset/9404cb6b-32ce-44ff-81f2-977a3b606915", + projectCoffee: + "https://www.figma.com/api/mcp/asset/5406ee32-dfc1-404f-a892-af494f3d6b27", + projectSakura: + "https://www.figma.com/api/mcp/asset/0033848b-0ca2-4e9e-ab59-b6526a185c5b", + projectUntitled: + "https://www.figma.com/api/mcp/asset/d28a0f40-98d0-4f4f-b3b7-5a507133dad2", + showPopi: + "https://www.figma.com/api/mcp/asset/f6307116-de24-4fb0-b608-f9c62412742e", + showAlice: + "https://www.figma.com/api/mcp/asset/51465958-a0ee-4a87-ba4f-d10a75eb36b0", + showDing: + "https://www.figma.com/api/mcp/asset/dec2b26f-4833-4532-a681-b398a0cb4b41", + showAido: + "https://www.figma.com/api/mcp/asset/09698f2b-ed7c-4356-8a5f-abbaa6b9fba9", + avatarUser: + "https://www.figma.com/api/mcp/asset/14978ca5-92b2-4ade-9687-eef333baa9d0", +}; + +const text = { + closeBanner: "关闭公告", + messages: "消息", + help: "帮助", + language: "语言", + search: "搜索", + moreActions: "更多操作", +}; + +const heroCards = [ + { title: "Seedance 2.0", subtitle: "火热上线", image: assets.heroSeedance }, + { + title: "做一条VLOG分享生活", + subtitle: "精选案例账号", + image: assets.heroVlog, + }, + { + title: "Popi.TV 测试上线", + subtitle: "帮助人类更好的表达", + image: assets.heroPopi, + }, +]; + +const projects = [ + { title: "爱丽丝初稿", date: "2026/06/01", image: assets.projectAlice }, + { title: "喝咖啡Vlog", date: "2026/05/30", image: assets.projectCoffee }, + { title: "赏樱花测试", date: "2026/05/29", image: assets.projectSakura }, + { title: "未命名", date: "2026/05/28", image: assets.projectUntitled }, +]; + +const tabs = [ + "全部", + "精选画布", + "生活Vlog", + "短剧漫剧", + "专业影视", + "商业广告", +]; + +const shows = [ + { + title: "PopiTV", + subtitle: "和爱丽丝一起郊游-Vlog", + image: assets.showPopi, + avatar: "👾", + vip: true, + }, + { + title: "爱丽丝大神", + subtitle: "和爱丽丝一起郊游-Vlog", + image: assets.showAlice, + avatar: "🌸", + vip: true, + }, + { + title: "叮叮频道", + subtitle: "和爱丽丝一起郊游-Vlog", + image: assets.showDing, + avatar: "🌊", + }, + { + title: "Aido", + subtitle: "和爱丽丝一起郊游-Vlog", + image: assets.showAido, + avatar: "🌿", + }, +]; + +function DiamondLogo({ label }: { label: string }) { + return ( + + {label} + + {label} + + + ); +} + +function HeaderIconButton({ + children, + label, +}: { + children: ReactNode; + label: string; +}) { + return ( + + ); +} + +function Header() { + return ( +
+
+
+ + NEW + + + 会员2.0焕新升级 积分特惠 限时福利 + + + Seedance 2.0 火热上线 + + + HOT + + + 会员低至 63 折 + + + 最高可获积分 17600 + +
+ +
+ +
+ + +
+
+ ); +} + +function HeroCard({ + title, + subtitle, + image, +}: { + title: string; + subtitle: string; + image: string; +}) { + return ( +
+ +
+
+

+ {title} +

+

{subtitle}

+
+
+ ); +} + +function ProjectCard({ + title, + date, + image, +}: { + title: string; + date: string; + image: string; +}) { + return ( +
+
+ +
+
+
+

+ {title} +

+

{date}

+
+ +
+
+ ); +} + +function ShowCard({ + title, + subtitle, + image, + avatar, + vip, +}: { + title: string; + subtitle: string; + image: string; + avatar: string; + vip?: boolean; +}) { + return ( +
+
+ +
+
+
+ + {avatar} + +

+ {title} +

+ {vip ? ( + + VIP + + ) : null} +
+

+ {subtitle} +

+
+
+ ); +} export default function Home() { return ( -
11111111111111
+
+
+ +
+
+ {heroCards.map((card) => ( + + ))} +
+ +
+
+

+ 最近项目 +

+ + 全部项目 + +
+
+ + + + 开始创作 + + + {projects.map((project) => ( + + ))} +
+ +
+
+ +
+
+
+

+ TV show +

+
+ {tabs.map((tab, index) => ( + + ))} +
+
+
+ + +
+
+
+ {shows.map((show) => ( + + ))} +
+
+
+
); -} \ No newline at end of file +} diff --git a/src/components/ProjectActionsDropdown.tsx b/src/components/ProjectActionsDropdown.tsx new file mode 100644 index 00000000..1672b41e --- /dev/null +++ b/src/components/ProjectActionsDropdown.tsx @@ -0,0 +1,48 @@ +"use client"; + +import { Dropdown, type MenuProps } from "antd"; +import { useState } from "react"; + +const projectActionItems: MenuProps["items"] = [ + { key: "open", label: "打开" }, + { key: "rename", label: "重命名" }, + { key: "change-cover", label: "修改封面" }, + { key: "duplicate", label: "创建副本" }, + { key: "delete", label: "删除项目" }, +]; + +export function ProjectActionsDropdown({ + title, + label, +}: { + title: string; + label: string; +}) { + const [open, setOpen] = useState(false); + + return ( + ( +
+ {menu} +
+ )} + > + +
+ ); +} diff --git a/src/components/icons/index.tsx b/src/components/icons/index.tsx new file mode 100644 index 00000000..593aea2a --- /dev/null +++ b/src/components/icons/index.tsx @@ -0,0 +1,169 @@ +export function MessageIcon() { + return ( + + ); +} + +export function HelpIcon() { + return ( + + ); +} + +export function GlobeIcon() { + return ( + + ); +} + +export function CloseIcon() { + return ( + + ); +} + +export function SearchIcon() { + return ( + + ); +} + +export function ArrowIcon() { + return ( + + ); +} +export const WeChatIcon = () => ( + +); + +export const SparklingIcon = () => ( + + + + + + + + + + +); +export const StartCreation = () => ( + +); diff --git a/src/store/execution/nanoBananaExecutor.ts b/src/store/execution/nanoBananaExecutor.ts index b2863c1f..83b6bf9c 100644 --- a/src/store/execution/nanoBananaExecutor.ts +++ b/src/store/execution/nanoBananaExecutor.ts @@ -47,6 +47,11 @@ export interface NanoBananaOptions { useStoredFallback?: boolean; } +type GeneratedResultImage = { + url: string; + previewImg?: string; +}; + const GEMINI_RESOLUTIONS: Resolution[] = ["512", "1K", "2K", "4K"]; function normalizeGeminiResolution(value: string): Resolution { @@ -289,7 +294,7 @@ export async function executeNanoBanana( signal, }); } - const resultImages = result.success && Array.isArray(result.images) && result.images.length > 0 + const resultImages: GeneratedResultImage[] = result.success && Array.isArray(result.images) && result.images.length > 0 ? result.images : result.success && result.image ? [result.image]