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 = {}) {