From 2a2ab701e31d76a3ab6fa8025a04dd41edc04f16 Mon Sep 17 00:00:00 2001 From: ludan <251918489@qq.com> Date: Thu, 18 Jun 2026 13:23:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B7=A5=E5=85=B7=E5=AD=90=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E9=9A=90=E8=97=8FTopbar=E3=80=81=E9=99=90=E5=88=B6?= =?UTF-8?q?=E7=B4=A0=E6=9D=90=E4=B8=8A=E4=BC=A0=E6=95=B0=E9=87=8F=E3=80=81?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A7=BB=E5=8A=A8=E7=AB=AF=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本次修改主要包含以下变更: 一、工具子页面隐藏Topbar(App.tsx / EcommercePage.tsx): - 新增 onWorkspaceChromeChange 回调,EcommercePage 向 App 层通知当前是否为工具子页面 - 工具子页面(智能抠图/快速详情/水印移除/翻译/图片编辑/一键套图/文案/一键视频等)自动隐藏顶部导航栏 - 组件卸载时重置 isToolPage 状态,避免切换页面时残留 二、素材上传数量限制(EcommercePage.tsx): - maxCloneProductImages 从 20 张调整为 10 张 - 上传超限时 toast 提示用户「最多上传 10 张素材」 - 新增 AppstoreAddOutlined、HighlightOutlined、TranslationOutlined、PlayCircleOutlined 等图标导入 三、移动端布局修复(ecommerce.css + ecommerce-standalone.css): - 指令栏容器宽度限制为 calc(100vw - 24px),防止溢出 - 素材缩略图区域改为横向滚动,隐藏滚动条 - 缩略图固定 flex-shrink: 0 防止被压缩(58px / 54px) - 工具栏宽度 100%,box-sizing 修复 - 新增工具页面相关样式规则 变更文件: - src/App.tsx (+26) - src/features/ecommerce/EcommercePage.tsx (+66) - src/styles/ecommerce-standalone.css (+209) - src/styles/pages/ecommerce.css (+198) --- src/App.tsx | 26 +-- src/features/ecommerce/EcommercePage.tsx | 66 +++++-- src/styles/ecommerce-standalone.css | 209 +++++++++++++++++++++++ src/styles/pages/ecommerce.css | 198 ++++++++++++++++++--- 4 files changed, 450 insertions(+), 49 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index c79923d..82369d2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -347,6 +347,8 @@ function App() { toast.info("Bug 反馈入口已保留,后续可接入反馈页面。"); }; + const shouldShowEcommerceTopbar = currentPage === "workspace" && !workspaceChrome.isToolPage; + return (
- + {shouldShowEcommerceTopbar ? ( + + ) : null}
{session ? ( diff --git a/src/features/ecommerce/EcommercePage.tsx b/src/features/ecommerce/EcommercePage.tsx index 9390eec..b2378a9 100644 --- a/src/features/ecommerce/EcommercePage.tsx +++ b/src/features/ecommerce/EcommercePage.tsx @@ -1,5 +1,7 @@ import { AppstoreOutlined, + AppstoreAddOutlined, + BorderOuterOutlined, ClearOutlined, CloudUploadOutlined, CloseOutlined, @@ -7,14 +9,17 @@ import { EditOutlined, FireOutlined, FileImageOutlined, + FileTextOutlined, FolderOpenOutlined, FrownOutlined, GlobalOutlined, + HighlightOutlined, LayoutOutlined, LoadingOutlined, MenuFoldOutlined, MenuUnfoldOutlined, PaperClipOutlined, + PlayCircleOutlined, PlusOutlined, QuestionCircleOutlined, ReloadOutlined, @@ -22,6 +27,7 @@ import { SettingOutlined, SkinOutlined, TableOutlined, + TranslationOutlined, VideoCameraOutlined, } from "@ant-design/icons"; import { @@ -256,6 +262,7 @@ import { interface ProductClonePageProps { + onWorkspaceChromeChange?: (state: { isToolPage: boolean }) => void; [key: string]: unknown; } @@ -811,7 +818,7 @@ const cloneSetCountOptions: Array<{ const cloneSetCountKeys = cloneSetCountOptions.map((option) => option.key); const minCloneSetTotal = 1; const maxCloneSetTotal = 16; -const maxCloneProductImages = 20; +const maxCloneProductImages = 10; const maxCloneReferenceImages = 20; const cloneVideoDurationMin = 5; const cloneVideoDurationMax = 45; @@ -1084,6 +1091,7 @@ function mergeEcommerceHistoryRecords(...recordGroups: EcommerceHistoryRecord[][ } function ProductClonePage(_props: ProductClonePageProps = {}) { + const { onWorkspaceChromeChange } = _props; const setInputRef = useRef(null); const productInputRef = useRef(null); const cloneReferenceInputRef = useRef(null); @@ -2939,7 +2947,13 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { const imageFiles = notifyRejectedImages(files); if (!imageFiles.length) return; const remainingSlots = maxCloneProductImages - productImages.length; - if (remainingSlots <= 0) return; + if (remainingSlots <= 0) { + toast.info(`最多上传 ${maxCloneProductImages} 张素材`); + return; + } + if (imageFiles.length > remainingSlots) { + toast.info(`最多上传 ${maxCloneProductImages} 张素材,已自动保留前 ${remainingSlots} 张`); + } const localItems = createLocalImageItems(imageFiles, remainingSlots, "product"); setProductImages((current) => [...current, ...localItems].slice(0, maxCloneProductImages)); @@ -4668,6 +4682,29 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { const isQuickSetTool = isCloneTool && activeQuickTool === "quick-set"; const isCopywritingTool = isCloneTool && activeQuickTool === "copywriting"; const isOneClickVideoTool = isCloneTool && activeQuickTool === "oneClickVideo"; + const isWorkspaceToolPage = + !isCloneTool || + isSmartCutoutTool || + isQuickDetailTool || + isWatermarkTool || + isTranslateTool || + isImageEditTool || + isHotCloneTool || + isQuickSetTool || + isCopywritingTool || + isOneClickVideoTool || + isVideoWorkspaceVisible || + Boolean(activeHistoryRecordId); + + useEffect(() => { + onWorkspaceChromeChange?.({ isToolPage: isWorkspaceToolPage }); + }, [isWorkspaceToolPage, onWorkspaceChromeChange]); + + useEffect(() => { + return () => { + onWorkspaceChromeChange?.({ isToolPage: false }); + }; + }, [onWorkspaceChromeChange]); const pageLabel = isSetTool ? "商品套图" : isDetail ? "A+/详情页" : isTryOn ? "AI服饰穿戴" : activeToolMeta?.label || "商品工具"; const setPrimaryLabel = setImages.length === 0 @@ -6328,7 +6365,13 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {