From bbea5d1e58a21117d68b318a419d6e390e919c58 Mon Sep 17 00:00:00 2001 From: ludan <251918489@qq.com> Date: Thu, 11 Jun 2026 11:31:39 +0800 Subject: [PATCH] feat: enhance ecommerce UI with typewriter animation, icon buttons, responsive layout, and refined design tokens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - EcommercePage.tsx: Add typewriter animation (useTypewriter hook) for slogan text with blinking cursor; replace text-based add/delete buttons with Ant Design icons (CloudUploadOutlined, DeleteOutlined); make command history panel responsive to window width (auto-collapse ≤1180px); update button labels from generic "添加" to context-specific "上传商品图" / "上传素材" - New useTypewriter.ts hook: Character-by-character typewriter animation with configurable speed and pause-before-loop, auto-resets on text change - reset.css: Add comprehensive HTML/body typography baseline (font-size, text-rendering, font-smoothing, line-height); extend reset coverage to select/canvas/svg elements; add overflow-wrap:anywhere for text-bearing elements; add min-width:0 to prevent form element overflow - primitives.css: Add reusable typography utility classes (ui-page-title, ui-section-title, ui-body-copy) with design token references - tokens.css: Expand design token set for typography scales, font weights, and leading values - ecommerce-standalone.css: Add 689 lines of standalone ecommerce page styles - Page CSS (ecommerce, image-workbench, more-tools, more, script-tokens, script-tokens-v5, studio-layout): Enhanced visual styles and layout refinements across all pages - app-shell.css: Shell-level layout and styling improvements --- src/features/ecommerce/EcommercePage.tsx | 36 +- src/hooks/useTypewriter.ts | 48 ++ src/styles/base/reset.css | 56 +- src/styles/components/primitives.css | 113 +++- src/styles/ecommerce-standalone.css | 689 +++++++++++++++++++++++ src/styles/pages/ecommerce.css | 494 ++++++++++++++++ src/styles/pages/image-workbench.css | 78 +++ src/styles/pages/more-tools.css | 61 ++ src/styles/pages/more.css | 37 ++ src/styles/pages/script-tokens-v5.css | 86 +++ src/styles/pages/script-tokens.css | 83 +++ src/styles/pages/studio-layout.css | 78 +++ src/styles/shell/app-shell.css | 61 ++ src/styles/tokens.css | 58 +- 14 files changed, 1963 insertions(+), 15 deletions(-) create mode 100644 src/hooks/useTypewriter.ts diff --git a/src/features/ecommerce/EcommercePage.tsx b/src/features/ecommerce/EcommercePage.tsx index 2d72959..a5db2c8 100644 --- a/src/features/ecommerce/EcommercePage.tsx +++ b/src/features/ecommerce/EcommercePage.tsx @@ -2,6 +2,7 @@ AppstoreOutlined, CloudUploadOutlined, CloseOutlined, + DeleteOutlined, FileImageOutlined, FolderOpenOutlined, FrownOutlined, @@ -16,6 +17,7 @@ TableOutlined, } from "@ant-design/icons"; import { useEffect, useMemo, useRef, useState, type CSSProperties, type ChangeEvent, type DragEvent, type MouseEvent as ReactMouseEvent, type PointerEvent as ReactPointerEvent, type ReactNode } from "react"; +import { useTypewriter } from "../../hooks/useTypewriter"; import "../../styles/pages/ecommerce.css"; import "../../styles/pages/local-theme-parity.css"; import { ossAssets } from "../../data/ossAssets"; @@ -1187,7 +1189,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { const [visibleComposerMenu, setVisibleComposerMenu] = useState(null); const [isComposerMenuClosing, setIsComposerMenuClosing] = useState(false); const [composerPopoverLeft, setComposerPopoverLeft] = useState(0); - const [isCommandHistoryCollapsed, setIsCommandHistoryCollapsed] = useState(false); + const [isCommandHistoryCollapsed, setIsCommandHistoryCollapsed] = useState(() => (typeof window !== "undefined" ? window.innerWidth <= 1180 : false)); const [openCloneModelSelect, setOpenCloneModelSelect] = useState(null); const [cloneModelSelectDropUp, setCloneModelSelectDropUp] = useState(false); const [cloneReferenceMode, setCloneReferenceMode] = useState("upload"); @@ -1223,6 +1225,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { offsetY: 0, }); const [isCommandComposerCompact, setIsCommandComposerCompact] = useState(false); + const typewriterText = useTypewriter("万物皆可AI,广告素材一键生成"); useEffect(() => { return () => { @@ -1238,6 +1241,16 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { previewOffsetRef.current = previewOffset; }, [previewOffset]); + useEffect(() => { + if (typeof window === "undefined") return undefined; + const syncHistoryPanel = () => { + setIsCommandHistoryCollapsed(window.innerWidth <= 1180); + }; + syncHistoryPanel(); + window.addEventListener("resize", syncHistoryPanel); + return () => window.removeEventListener("resize", syncHistoryPanel); + }, []); + const previewTransformStyle = useMemo( () => ({ transform: `translate3d(${previewOffset.x}px, ${previewOffset.y}px, 0) scale(${previewZoom})`, @@ -3729,7 +3742,10 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { if (isCommandComposerCompact) setIsCommandComposerCompact(false); }} > -

万物皆可AI,广告素材一键生成

+

+ {typewriterText} + +

- - 添加 + + 上传商品图 {productImages.length || videoOutfitVideoFile ? (
@@ -3783,7 +3799,9 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { - + ))} {videoOutfitVideoFile && videoOutfitPreviewUrl ? ( @@ -3792,7 +3810,9 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { - + ) : null} @@ -3836,8 +3856,8 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { if (files.length) addComposerAssets(files); }} > - - 添加 + + 上传素材