0fc180637c
通过 display:none 模式实现轻量 KeepAlive,电商页面首次访问后保持挂载, 切换到其他页面再切回时所有右侧面板状态(上传图片、生成进度、结果)完整保留。 同时清理项目中的临时文件和本地冗余图片。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
169 lines
6.0 KiB
TypeScript
169 lines
6.0 KiB
TypeScript
import { CloudUploadOutlined, LoadingOutlined, QuestionCircleOutlined } from "@ant-design/icons";
|
||
import type { ChangeEvent, RefObject } from "react";
|
||
import { EcommerceProgressBar } from "../EcommerceProgressBar";
|
||
|
||
interface EcommerceDetailPanelProps {
|
||
detailInputRef: RefObject<HTMLInputElement>;
|
||
detailProductImages: Array<{ id: string; src: string; name: string }>;
|
||
detailPlatform: string;
|
||
detailMarket: string;
|
||
detailLanguage: string;
|
||
detailType: string;
|
||
detailRequirement: string;
|
||
selectedDetailModules: string[];
|
||
detailStatus: string;
|
||
canGenerateDetail: boolean;
|
||
detailPrimaryLabel: string;
|
||
platformOptions: string[];
|
||
marketOptions: string[];
|
||
detailLanguageOptions: string[];
|
||
detailTypeOptions: string[];
|
||
detailModules: Array<{ id: string; title: string; desc: string }>;
|
||
handleDetailUpload: (event: ChangeEvent<HTMLInputElement>) => void;
|
||
handleDetailPlatformChange: (value: string) => void;
|
||
handleDetailMarketChange: (value: string) => void;
|
||
setDetailLanguage: (value: string) => void;
|
||
setDetailType: (value: string) => void;
|
||
setDetailRequirement: (value: string) => void;
|
||
handleDetailAiWrite: () => void;
|
||
toggleDetailModule: (id: string) => void;
|
||
handleDetailGenerate: () => void;
|
||
}
|
||
|
||
export default function EcommerceDetailPanel({
|
||
detailInputRef,
|
||
detailProductImages,
|
||
detailPlatform,
|
||
detailMarket,
|
||
detailLanguage,
|
||
detailType,
|
||
detailRequirement,
|
||
selectedDetailModules,
|
||
detailStatus,
|
||
canGenerateDetail,
|
||
detailPrimaryLabel,
|
||
platformOptions,
|
||
marketOptions,
|
||
detailLanguageOptions,
|
||
detailTypeOptions,
|
||
detailModules,
|
||
handleDetailUpload,
|
||
handleDetailPlatformChange,
|
||
handleDetailMarketChange,
|
||
setDetailLanguage,
|
||
setDetailType,
|
||
setDetailRequirement,
|
||
handleDetailAiWrite,
|
||
toggleDetailModule,
|
||
handleDetailGenerate,
|
||
}: EcommerceDetailPanelProps) {
|
||
return (
|
||
<>
|
||
<div className="product-clone-panel__scroll">
|
||
<section className="product-clone-field">
|
||
<h2>
|
||
商品原图
|
||
<QuestionCircleOutlined />
|
||
</h2>
|
||
<button type="button" className="product-clone-upload-zone product-detail-upload" onClick={() => detailInputRef.current?.click()}>
|
||
<strong>
|
||
<CloudUploadOutlined />
|
||
上传图片
|
||
</strong>
|
||
<span>同一产品,最多3张。</span>
|
||
</button>
|
||
<input ref={detailInputRef} type="file" accept="image/*" multiple onChange={handleDetailUpload} />
|
||
{detailProductImages.length ? (
|
||
<div className="product-clone-thumb-row" aria-label="已上传商品原图">
|
||
{detailProductImages.map((item) => (
|
||
<figure key={item.id} className="product-clone-uploaded-thumb">
|
||
<img src={item.src} alt={item.name} />
|
||
<span className="uploaded-image-zoom" aria-hidden="true">
|
||
<img src={item.src} alt="" />
|
||
</span>
|
||
</figure>
|
||
))}
|
||
</div>
|
||
) : null}
|
||
</section>
|
||
|
||
<section className="product-clone-field">
|
||
<h2>生成设置</h2>
|
||
<div className="product-detail-settings-grid">
|
||
<select value={detailPlatform} onChange={(event) => handleDetailPlatformChange(event.target.value)}>
|
||
{platformOptions.map((item) => (
|
||
<option key={item}>{item}</option>
|
||
))}
|
||
</select>
|
||
<select value={detailMarket} onChange={(event) => handleDetailMarketChange(event.target.value)}>
|
||
{marketOptions.map((item) => (
|
||
<option key={item}>{item}</option>
|
||
))}
|
||
</select>
|
||
<select value={detailLanguage} onChange={(event) => setDetailLanguage(event.target.value)}>
|
||
{detailLanguageOptions.map((item) => (
|
||
<option key={item}>{item}</option>
|
||
))}
|
||
</select>
|
||
<select value={detailType} onChange={(event) => setDetailType(event.target.value)}>
|
||
{detailTypeOptions.map((item) => (
|
||
<option key={item}>{item}</option>
|
||
))}
|
||
</select>
|
||
</div>
|
||
</section>
|
||
|
||
<section className="product-clone-field product-detail-requirement">
|
||
<h2>
|
||
商品卖点&要求
|
||
<QuestionCircleOutlined />
|
||
<button
|
||
type="button"
|
||
onClick={(event) => {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
handleDetailAiWrite();
|
||
}}
|
||
>
|
||
AI 帮写
|
||
</button>
|
||
</h2>
|
||
<textarea
|
||
value={detailRequirement}
|
||
onChange={(event) => setDetailRequirement(event.target.value)}
|
||
placeholder={"建议包含以下信息生成更精准:\n1.产品名称\n2.核心卖点\n3.适用人群\n4.期望场景\n5.具体参数"}
|
||
/>
|
||
</section>
|
||
|
||
<section className="product-clone-field">
|
||
<h2>
|
||
包含模块(多选)
|
||
<QuestionCircleOutlined />
|
||
</h2>
|
||
<div className="product-detail-module-grid">
|
||
{detailModules.map((module) => (
|
||
<button
|
||
key={module.id}
|
||
type="button"
|
||
className={selectedDetailModules.includes(module.id) ? "is-active" : ""}
|
||
onClick={() => toggleDetailModule(module.id)}
|
||
>
|
||
<strong>{module.title}</strong>
|
||
<span>{module.desc}</span>
|
||
</button>
|
||
))}
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<footer className="product-clone-panel__footer">
|
||
{detailStatus === "generating" ? <EcommerceProgressBar status="generating" label="A+详情页" /> : null}
|
||
<button type="button" className="product-clone-primary" disabled={!canGenerateDetail} onClick={handleDetailGenerate}>
|
||
{detailStatus === "generating" ? <LoadingOutlined /> : null}
|
||
{detailPrimaryLabel}
|
||
</button>
|
||
</footer>
|
||
</>
|
||
);
|
||
}
|