From 707b6494daf8286647ef23eecccb1664e689e130 Mon Sep 17 00:00:00 2001 From: ddCat <2695092045@qq.com> Date: Thu, 17 Sep 2026 23:32:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(create):=20=E5=AF=B9=E8=AF=9D=E9=A1=B5?= =?UTF-8?q?=E5=B8=83=E5=B1=80=20-=20=E5=8A=A0=E5=AE=BD=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E5=8C=BA=E5=B9=B6=E4=BF=AE=E6=AD=A3=E5=8F=82=E6=95=B0=E5=BC=B9?= =?UTF-8?q?=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 开始对话后工具条进顶栏、模式切换横排到录音左侧,输入区加宽并去掉黑底;参数弹窗改用工作台表面色,去掉细线描边。 Co-authored-by: Cursor --- web/src/pages/create/creation-product.css | 152 +++++ web/src/pages/create/creation-types.ts | 1 + web/src/pages/create/creation-workspace.tsx | 12 +- web/src/pages/create/index.tsx | 6 +- web/src/styles/globals.css | 612 +++++++++++++------- web/src/styles/workspace-product.css | 38 +- web/test/create-library-button.test.ts | 40 +- 7 files changed, 627 insertions(+), 234 deletions(-) diff --git a/web/src/pages/create/creation-product.css b/web/src/pages/create/creation-product.css index 6b9df9301..5795d5ecd 100644 --- a/web/src/pages/create/creation-product.css +++ b/web/src/pages/create/creation-product.css @@ -54,6 +54,7 @@ .app-product-workspace .creation-home .creation-submit.ant-btn:not(:disabled):hover .creation-submit-action::after { animation: creation-submit-sheen 640ms cubic-bezier(.16, 1, .3, 1); } .app-product-workspace .creation-home .creation-submit.ant-btn:not(:disabled):hover .creation-submit-action svg { transform: translateY(-1px); } .app-product-workspace .creation-home .creation-submit.ant-btn:not(:disabled):active .creation-submit-action { transform: scale(.97); } + .app-product-workspace .creation-home .creation-chat-composer.is-thread .creation-submit.ant-btn .creation-submit-action { height: 34px; padding: 0 14px; } } .creation-inspiration-filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px; } .creation-inspiration-filters button { display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; min-height: 36px; border: 0; border-radius: 999px; color: var(--user-ink-muted); background: transparent; font-size: 13px; transition: background var(--user-motion), color var(--user-motion); } @@ -120,3 +121,154 @@ .app-user-workspace .creation-submit-action { transition: none !important; transform: none !important; } .app-product-workspace .creation-home .creation-submit.ant-btn:not(:disabled):hover .creation-submit-action::after { animation: none; } } + +/* 参数弹窗挂在 body overlays,必须直接用用户表面 token;描边由 Ant inner 的 1px border 造成。 */ +.app-user-overlays .creation-control-popover, +.app-product-overlays .creation-control-popover { + --popover: var(--user-surface-raised); + --border: transparent; + --creation-text: var(--user-ink); + --creation-muted: var(--user-ink-muted); + --creation-faint: var(--user-ink-soft); + --control-selected-bg: var(--user-control-pressed); + --control-selected-fg: var(--user-ink); +} + +.app-user-overlays .creation-control-popover .ant-popover-arrow, +.app-product-overlays .creation-control-popover .ant-popover-arrow { display: none; } + +.app-user-overlays .creation-control-popover.ant-popover, +.app-user-overlays .creation-control-popover .ant-popover-container, +.app-user-overlays .creation-control-popover .ant-popover-inner, +.app-user-overlays .creation-control-popover-surface, +.app-product-overlays .creation-control-popover.ant-popover, +.app-product-overlays .creation-control-popover .ant-popover-container, +.app-product-overlays .creation-control-popover .ant-popover-inner, +.app-product-overlays .creation-control-popover-surface { + border: 0 !important; + outline: 0 !important; + background: var(--user-surface-raised) !important; + background-image: none !important; + box-shadow: 0 18px 40px rgba(0, 0, 0, .36) !important; + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; + border-radius: 16px !important; +} + +.app-user-overlays .creation-control-popover .ant-popover-inner, +.app-product-overlays .creation-control-popover .ant-popover-inner { + overflow: hidden; + padding: 0 !important; +} + +.app-user-overlays .creation-parameter-menu, +.app-product-overlays .creation-parameter-menu { padding: 12px !important; } + +.app-user-overlays .creation-parameter-section h3, +.app-user-overlays .creation-duration-heading > span, +.app-product-overlays .creation-parameter-section h3, +.app-product-overlays .creation-duration-heading > span { color: var(--user-ink-muted) !important; } + +.app-user-overlays .creation-parameter-section > header > span, +.app-user-overlays .creation-duration-heading strong, +.app-product-overlays .creation-parameter-section > header > span, +.app-product-overlays .creation-duration-heading strong { color: var(--user-ink) !important; } + +.app-user-overlays .creation-choice-grid, +.app-product-overlays .creation-choice-grid { gap: 6px !important; } + +.app-user-overlays .creation-choice-grid button, +.app-user-overlays .creation-duration-choices button, +.app-product-overlays .creation-choice-grid button, +.app-product-overlays .creation-duration-choices button { + min-height: 40px !important; + border: 0 !important; + border-radius: 10px !important; + background: transparent !important; + box-shadow: none !important; + color: var(--user-ink-muted) !important; +} + +.app-user-overlays .creation-choice-grid.is-resolution button, +.app-user-overlays .creation-choice-grid.is-quality button, +.app-user-overlays .creation-choice-grid.is-count button, +.app-user-overlays .creation-duration-choices button, +.app-product-overlays .creation-choice-grid.is-resolution button, +.app-product-overlays .creation-choice-grid.is-quality button, +.app-product-overlays .creation-choice-grid.is-count button, +.app-product-overlays .creation-duration-choices button { min-height: 34px !important; } + +.app-user-overlays .creation-choice-grid button:hover, +.app-user-overlays .creation-duration-choices button:hover, +.app-product-overlays .creation-choice-grid button:hover, +.app-product-overlays .creation-duration-choices button:hover { + background: var(--user-surface-hover) !important; + color: var(--user-ink) !important; +} + +.app-user-overlays .creation-choice-grid button.is-selected, +.app-user-overlays .creation-duration-choices button.is-selected, +.app-product-overlays .creation-choice-grid button.is-selected, +.app-product-overlays .creation-duration-choices button.is-selected { + background: var(--user-control-pressed) !important; + color: var(--user-ink) !important; +} + +.app-user-overlays .creation-choice-grid .creation-ratio-preview > span, +.app-product-overlays .creation-choice-grid .creation-ratio-preview > span { + border: 0 !important; + border-radius: 3px !important; + background: currentColor; + opacity: .55; +} + +.app-user-overlays .creation-choice-grid button.is-selected .creation-ratio-preview > span, +.app-product-overlays .creation-choice-grid button.is-selected .creation-ratio-preview > span { opacity: .92; } + +.app-user-overlays .creation-custom-value, +.app-product-overlays .creation-custom-value { + border: 0 !important; + background: var(--user-surface-muted) !important; + color: var(--user-ink-muted) !important; +} + +.app-user-overlays .creation-parameter-menu .image-size-tiers button, +.app-user-overlays .creation-parameter-menu .image-size-ratios button, +.app-user-overlays .creation-parameter-menu .image-size-auto, +.app-product-overlays .creation-parameter-menu .image-size-tiers button, +.app-product-overlays .creation-parameter-menu .image-size-ratios button, +.app-product-overlays .creation-parameter-menu .image-size-auto { + border: 0 !important; + background: var(--user-surface-muted) !important; + box-shadow: none !important; + color: var(--user-ink-muted) !important; +} + +.app-user-overlays .creation-parameter-menu .image-size-tiers button[aria-pressed="true"], +.app-user-overlays .creation-parameter-menu .image-size-ratios button[aria-pressed="true"], +.app-user-overlays .creation-parameter-menu .image-size-auto[aria-pressed="true"], +.app-product-overlays .creation-parameter-menu .image-size-tiers button[aria-pressed="true"], +.app-product-overlays .creation-parameter-menu .image-size-ratios button[aria-pressed="true"], +.app-product-overlays .creation-parameter-menu .image-size-auto[aria-pressed="true"] { + background: var(--user-control-pressed) !important; + box-shadow: none !important; + color: var(--user-ink) !important; +} + +.app-user-overlays .creation-parameter-menu .image-size-ratio-icon, +.app-product-overlays .creation-parameter-menu .image-size-ratio-icon { + border: 0 !important; + background: currentColor; + opacity: .55; +} + +html:not(.dark) .app-user-overlays .creation-control-popover.ant-popover, +html:not(.dark) .app-user-overlays .creation-control-popover .ant-popover-container, +html:not(.dark) .app-user-overlays .creation-control-popover .ant-popover-inner, +html:not(.dark) .app-user-overlays .creation-control-popover-surface, +html:not(.dark) .app-product-overlays .creation-control-popover.ant-popover, +html:not(.dark) .app-product-overlays .creation-control-popover .ant-popover-container, +html:not(.dark) .app-product-overlays .creation-control-popover .ant-popover-inner, +html:not(.dark) .app-product-overlays .creation-control-popover-surface { + box-shadow: 0 16px 40px rgba(25, 25, 30, .12) !important; +} diff --git a/web/src/pages/create/creation-types.ts b/web/src/pages/create/creation-types.ts index a87ad2c6e..b791ed6a4 100644 --- a/web/src/pages/create/creation-types.ts +++ b/web/src/pages/create/creation-types.ts @@ -35,6 +35,7 @@ export type CreationMessage = { export type CreationConversation = { id: string; title: string; updatedAt: string; canvasId?: string; messages: CreationMessage[] }; export const modeLabels: Record = { text: "文本", image: "图片", video: "视频" }; +export const defaultCreationMode: CreationMode = "image"; export const shotScriptLabels: Record = { text: "创作思路", image: "画面指令", video: "镜头脚本" }; export const ratioOptions = [ { value: "1:1", label: "方形" }, diff --git a/web/src/pages/create/creation-workspace.tsx b/web/src/pages/create/creation-workspace.tsx index de4e260ec..01c624530 100644 --- a/web/src/pages/create/creation-workspace.tsx +++ b/web/src/pages/create/creation-workspace.tsx @@ -1,9 +1,11 @@ import { ImageSizePicker } from "@/components/image-size-picker"; import { imageResolutionUsesQuality } from "@/lib/image-size-presets"; +import { createPortal } from "react-dom"; import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState, type CSSProperties, type PointerEvent, type ReactNode, type RefObject } from "react"; import { App, Button, Dropdown, Popover } from "antd"; import { AppDrawer } from "@/components/ui/product/app-drawer"; import { AppModal } from "@/components/ui/product/app-modal"; +import { useWorkspaceTopBarMount } from "@/components/layout/workspace-top-bar-extension"; import { Tooltip } from "@/components/ui/base/tooltip"; import { Reorder, LayoutGroup, motion, useReducedMotion } from "motion/react"; import { ArrowDown, ArrowUp, Brain, ChevronDown, ChevronLeft, ChevronRight, Clapperboard, Clock3, Copy, Download, FileText, Film, History, Image as ImageIcon, LoaderCircle, Maximize2, MessageSquareText, Minimize2, MoreHorizontal, Music2, Pencil, Plus, RefreshCw, Search, SlidersHorizontal, Sparkles, Trash2, UserRound, WandSparkles, Waves, X } from "lucide-react"; @@ -174,7 +176,8 @@ export function CreationWorkspaceToolbar({ shots, onJumpToShot, onNewConversatio window.addEventListener("mousedown", onPointerDown); return () => window.removeEventListener("mousedown", onPointerDown); }, [railOpen]); - return
+ const mount = useWorkspaceTopBarMount(); + const toolbar =
{railOpen ?
@@ -196,6 +199,9 @@ export function CreationWorkspaceToolbar({ shots, onJumpToShot, onNewConversatio
; + if (mount) return createPortal(toolbar, mount); + if (mount === null) return null; + return toolbar; } export function CreationMessageView({ item, shotNumber, onRetryFailure, onCreateVariant, onEditUserMessage, onContinueCanvas, openingCanvas }: { item: CreationMessage; shotNumber: number; onRetryFailure: () => void; onCreateVariant: () => void; onEditUserMessage: (text: string) => void; onContinueCanvas: (ids?: string[]) => void; openingCanvas: boolean }) { @@ -492,7 +498,6 @@ export function CreationComposer(props: ComposerProps) { spotlightColor="color-mix(in srgb, var(--user-ink) 12%, transparent)" spotlightRadius={280} > - {props.variant === "thread" ?
: null}
{ const target = props.references.find((item) => item.id === reference.id); if (target?.attachmentId) props.onReplaceReferenceFiles(target.attachmentId, files); }} /> @@ -564,6 +569,7 @@ export function CreationComposer(props: ComposerProps) {