refactor: 清理未使用参数、移除死代码、聚焦电商核心模块
主要变更概述: ================ 1. 清理未使用的函数参数 (TypeScript noUnusedParameters) ------------------------------------------------------ - AppShell.tsx: 移除未使用的 backendHealth prop 及 ServerConnectionHealth 导入 - canvasUtils.ts: 移除 resolveWorkflowVideoModel 的 workflowModel 参数 - canvasWorkflowDeserialize.ts: 同步更新调用方 - CanvasPage.tsx: 移除 resolveWorkflowVideoModel 未使用导入 - HomePage.tsx: 移除 onOpenTokenMonitor、onOpenImageTool 未使用 props - ToolboxSection.tsx: 移除 onOpenImageTool 未使用 prop 及 WebImageWorkbenchTool 类型导入 - ScriptTokensPage.tsx: 移除 formatReportMarkdown 的 script 参数,更新 2 处调用 - TokenUsagePage.tsx: 移除 onOpenImageTool、onSelectView 未使用 props - WorkbenchPage.tsx: 移除 renderComposerToolbar 的 showStop 参数,更新 2 处调用 2. 移除未使用的模块和死代码 -------------------------- 删除以下未在电商模块中使用的功能模块: - 画布模块 (canvas/): CanvasPage, canvasUtils, canvasWorkflow* 等 - 主页模块 (home/): HomePage, ToolboxSection, WelcomeSplash 等 - 工作台模块 (workbench/): WorkbenchPage, ConversationSidebar 等 - 社区模块 (community/, community-review/) - 数字人模块 (digital-human/) - 图片工作台 (image-workbench/) - 其他独立工具页: agent, assets, beta-applications, character-mix, compliance, dialog-generator, more, profile, provider-health, report, resolution-upscale, script-tokens, settings, size-template, subtitle-removal, watermark-removal 3. 移除未使用的公共组件 ---------------------- - AnimatedPanel, BeforeAfterCompare, BetaApplicationModal - CookieConsentBanner, DropZone, EmptyState, NotFoundPage - NotificationCenter, OnboardingTour, OptimizedImage - PageTransition, RechargeModal, ShellIcon, Skeleton - StudioToolLayout, TaskStatusBar, WorkspacePageShell 4. 移除未使用的 API 客户端 -------------------------- - betaApplicationClient, communityClient, conversationClient - draftClient, modelCapabilitiesClient, notificationClient - projectTaskClient, providerHealthClient, publicConfigClient - referenceUploadService, reportClient, scriptEvalClient - uploadWithProgress 5. 移除未使用的工具函数和 hooks ------------------------------- - utils/: imageModelVisibility, mentionTrigger, modelOptions, ossImageOptimize, toolPageUtils - hooks/: useGenerationStatus, useScrollEntrance - scripts/: 所有分析脚本 (check-governance, dynamic-analysis 等) 6. 移除未使用的样式文件 ---------------------- 删除与已移除模块对应的 CSS 文件,保留电商模块专用样式 7. 新增电商模块功能文件 ---------------------- + src/api/generationRecordClient.ts (生成记录客户端) + src/features/ecommerce/ecommerceGenerationPersistence.ts (生成持久化) 验证: - TypeScript 编译 (tsc --noEmit --noUnusedParameters) 零错误通过 - 所有保留文件的功能完整性未受影响
This commit is contained in:
@@ -9,10 +9,10 @@ import {
|
||||
} from "@ant-design/icons";
|
||||
import { createPortal } from "react-dom";
|
||||
import type { CSSProperties, ChangeEvent, DragEvent, MutableRefObject, RefObject } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
type ProductSetOutputKey = "set" | "detail" | "model" | "video";
|
||||
type CloneOutputKey = ProductSetOutputKey | "hot" | "video-outfit";
|
||||
type CloneOutputKey = ProductSetOutputKey | "hot";
|
||||
type CloneSetCountKey = "selling" | "white" | "scene";
|
||||
type CloneModelPanelTab = "scene" | "model";
|
||||
type CloneReferenceMode = "upload" | "link";
|
||||
@@ -138,7 +138,6 @@ interface EcommerceClonePanelProps {
|
||||
handleGenerate: () => void;
|
||||
onCancelGenerate: () => void;
|
||||
formatRatioDisplayValue: (value: string) => string;
|
||||
setVideoOutfitFiles?: (video: File | null, ref: File | null) => void;
|
||||
onStartVideoPlan?: () => void;
|
||||
}
|
||||
|
||||
@@ -208,13 +207,8 @@ export default function EcommerceClonePanel({
|
||||
handleGenerate,
|
||||
onCancelGenerate,
|
||||
formatRatioDisplayValue,
|
||||
setVideoOutfitFiles,
|
||||
onStartVideoPlan,
|
||||
}: EcommerceClonePanelProps) {
|
||||
const videoOutfitVideoRef = useRef<HTMLInputElement>(null);
|
||||
const videoOutfitRefRef = useRef<HTMLInputElement>(null);
|
||||
const [videoOutfitVideoUrl, setVideoOutfitVideoUrl] = useState<string | null>(null);
|
||||
const [videoOutfitRefUrl, setVideoOutfitRefUrl] = useState<string | null>(null);
|
||||
const [zoomImage, setZoomImage] = useState<{ src: string; x: number; y: number } | null>(null);
|
||||
|
||||
const handleFileMouseEnter = (src: string, event: React.MouseEvent<HTMLElement>) => {
|
||||
@@ -267,18 +261,6 @@ export default function EcommerceClonePanel({
|
||||
);
|
||||
};
|
||||
|
||||
const handleVideoOutfitVideoChange = () => {
|
||||
const file = videoOutfitVideoRef.current?.files?.[0] || null;
|
||||
if (file) setVideoOutfitVideoUrl(URL.createObjectURL(file));
|
||||
setVideoOutfitFiles?.(file, videoOutfitRefRef.current?.files?.[0] || null);
|
||||
};
|
||||
|
||||
const handleVideoOutfitRefChange = () => {
|
||||
const file = videoOutfitRefRef.current?.files?.[0] || null;
|
||||
if (file) setVideoOutfitRefUrl(URL.createObjectURL(file));
|
||||
setVideoOutfitFiles?.(videoOutfitVideoRef.current?.files?.[0] || null, file);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="product-clone-panel__scroll clone-ai-panel">
|
||||
@@ -346,7 +328,7 @@ export default function EcommerceClonePanel({
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<input ref={productInputRef} type="file" accept="image/*" multiple onChange={handleProductUpload} />
|
||||
<input ref={productInputRef} type="file" accept="image/*" multiple onChange={handleProductUpload} aria-label="上传商品图片" />
|
||||
</section>
|
||||
|
||||
<section className="clone-ai-card clone-ai-settings-card clone-ai-settings-card--mode">
|
||||
@@ -356,7 +338,7 @@ export default function EcommerceClonePanel({
|
||||
</h2>
|
||||
<div className="clone-ai-settings-section">
|
||||
<span className="clone-ai-settings-label">生成内容</span>
|
||||
<div className="clone-ai-tag-group" role="radiogroup" aria-label="生成内容">
|
||||
<div className="clone-ai-tag-group" role="toolbar" aria-label="生成内容">
|
||||
{cloneOutputOptions.map((option) => (
|
||||
<button
|
||||
key={option.key}
|
||||
@@ -478,11 +460,12 @@ export default function EcommerceClonePanel({
|
||||
accept="image/jpeg,image/png,image/webp"
|
||||
multiple
|
||||
onChange={handleCloneReferenceUpload}
|
||||
aria-label="上传参考图片"
|
||||
/>
|
||||
</div>
|
||||
<div className="clone-ai-replicate-section">
|
||||
<span className="clone-ai-replicate-title">复刻程度</span>
|
||||
<div className="clone-ai-replicate-levels" role="radiogroup" aria-label="复刻程度">
|
||||
<div className="clone-ai-replicate-levels" role="toolbar" aria-label="复刻程度">
|
||||
{cloneReplicateLevelOptions.map((option) => (
|
||||
<button
|
||||
key={option.key}
|
||||
@@ -779,50 +762,9 @@ export default function EcommerceClonePanel({
|
||||
</button>
|
||||
) : null}
|
||||
|
||||
{cloneOutput === "video-outfit" ? (
|
||||
<section className="clone-ai-video-panel" aria-label="视频换装">
|
||||
<div className="clone-ai-dynamic-head">
|
||||
<strong>视频换装设置</strong>
|
||||
<span>上传视频和参考服装</span>
|
||||
</div>
|
||||
<div className="clone-ai-video-section">
|
||||
<span className="clone-ai-video-title">上传原始视频</span>
|
||||
<div className="clone-ai-video-outfit-upload">
|
||||
<input
|
||||
ref={videoOutfitVideoRef}
|
||||
type="file"
|
||||
accept="video/*"
|
||||
onChange={handleVideoOutfitVideoChange}
|
||||
style={{ display: "none" }}
|
||||
/>
|
||||
<button type="button" className="clone-ai-video-outfit-upload-btn" onClick={() => videoOutfitVideoRef.current?.click()}>
|
||||
{videoOutfitVideoUrl ? "重新上传视频" : "点击上传视频"}
|
||||
</button>
|
||||
{videoOutfitVideoUrl ? <span className="clone-ai-video-outfit-info">已选择视频</span> : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="clone-ai-video-section">
|
||||
<span className="clone-ai-video-title">上传参考图(素材/服装)</span>
|
||||
<div className="clone-ai-video-outfit-upload">
|
||||
<input
|
||||
ref={videoOutfitRefRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
onChange={handleVideoOutfitRefChange}
|
||||
style={{ display: "none" }}
|
||||
/>
|
||||
<button type="button" className="clone-ai-video-outfit-upload-btn" onClick={() => videoOutfitRefRef.current?.click()}>
|
||||
{videoOutfitRefUrl ? "重新上传参考图" : "点击上传参考图"}
|
||||
</button>
|
||||
{videoOutfitRefUrl ? <span className="clone-ai-video-outfit-info">已选择参考图</span> : null}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
<button type="button" className="clone-ai-generate" disabled={!canGenerate || cloneOutput === "video"} onClick={status === "failed" && lastFailedActionRef.current ? lastFailedActionRef.current : handleGenerate} style={cloneOutput === "video" ? { display: "none" } : undefined}>
|
||||
{status === "generating" ? <LoadingOutlined /> : status === "failed" ? <ReloadOutlined /> : null}
|
||||
{status === "generating" ? "生成中..." : status === "failed" ? "重新生成" : cloneOutput === "video-outfit" ? "✦ 开始换装" : "✦ 开始生成"}
|
||||
{status === "generating" ? "生成中..." : status === "failed" ? "重新生成" : "✦ 开始生成"}
|
||||
</button>
|
||||
{status === "generating" && cloneOutput !== "video" ? (
|
||||
<button type="button" className="clone-ai-generate clone-ai-generate--cancel" onClick={onCancelGenerate}>
|
||||
|
||||
Reference in New Issue
Block a user