172 lines
6.6 KiB
TypeScript
172 lines
6.6 KiB
TypeScript
import { CloudUploadOutlined, CloseOutlined, FileImageOutlined, SettingOutlined } from "@ant-design/icons";
|
||
import type { ChangeEvent, DragEvent, RefObject } from "react";
|
||
|
||
type ProductSetOutputKey = "set" | "detail" | "model" | "video";
|
||
|
||
interface EcommerceSetPanelProps {
|
||
setInputRef: RefObject<HTMLInputElement>;
|
||
setImages: Array<{ id: string; src: string; name: string }>;
|
||
isSetUploadDragging: boolean;
|
||
productSetOutputOptions: Array<{ key: ProductSetOutputKey; label: string }>;
|
||
productSetOutput: ProductSetOutputKey;
|
||
platformOptions: string[];
|
||
marketOptions: string[];
|
||
productSetLanguageOptions: string[];
|
||
productSetRatioOptions: string[];
|
||
productSetPlatform: string;
|
||
productSetMarket: string;
|
||
productSetLanguage: string;
|
||
productSetRatio: string;
|
||
setIsSetUploadDragging: (value: boolean) => void;
|
||
handleSetDrop: (event: DragEvent<HTMLButtonElement>) => void;
|
||
handleSetUpload: (event: ChangeEvent<HTMLInputElement>) => void;
|
||
removeSetImage: (id: string) => void;
|
||
handleProductSetOutputChange: (value: ProductSetOutputKey) => void;
|
||
handleProductSetPlatformChange: (value: string) => void;
|
||
handleProductSetMarketChange: (value: string) => void;
|
||
setProductSetLanguage: (value: string) => void;
|
||
setProductSetRatio: (value: string) => void;
|
||
formatRatioDisplayValue: (value: string) => string;
|
||
}
|
||
|
||
export default function EcommerceSetPanel({
|
||
setInputRef,
|
||
setImages,
|
||
isSetUploadDragging,
|
||
productSetOutputOptions,
|
||
productSetOutput,
|
||
platformOptions,
|
||
marketOptions,
|
||
productSetLanguageOptions,
|
||
productSetRatioOptions,
|
||
productSetPlatform,
|
||
productSetMarket,
|
||
productSetLanguage,
|
||
productSetRatio,
|
||
setIsSetUploadDragging,
|
||
handleSetDrop,
|
||
handleSetUpload,
|
||
removeSetImage,
|
||
handleProductSetOutputChange,
|
||
handleProductSetPlatformChange,
|
||
handleProductSetMarketChange,
|
||
setProductSetLanguage,
|
||
setProductSetRatio,
|
||
formatRatioDisplayValue,
|
||
}: EcommerceSetPanelProps) {
|
||
return (
|
||
<>
|
||
<div className="product-clone-panel__scroll">
|
||
<section className="product-clone-field product-set-upload-section">
|
||
<h2>
|
||
上传商品原图
|
||
<CloudUploadOutlined />
|
||
</h2>
|
||
<button
|
||
type="button"
|
||
className={`product-clone-upload-zone product-set-upload${isSetUploadDragging ? " is-dragging" : ""}`}
|
||
onClick={() => setInputRef.current?.click()}
|
||
onDragEnter={(event) => {
|
||
event.preventDefault();
|
||
setIsSetUploadDragging(true);
|
||
}}
|
||
onDragOver={(event) => event.preventDefault()}
|
||
onDragLeave={() => setIsSetUploadDragging(false)}
|
||
onDrop={handleSetDrop}
|
||
>
|
||
<span className="product-set-upload-icon">
|
||
<FileImageOutlined />
|
||
</span>
|
||
<span className="product-set-upload-title">拖拽或点击上传</span>
|
||
<strong>
|
||
<span aria-hidden="true">+</span>
|
||
上传图片
|
||
</strong>
|
||
<span className="product-set-upload-note">同一产品,最多 3 张</span>
|
||
</button>
|
||
<input ref={setInputRef} type="file" accept="image/jpeg,image/png,image/webp" multiple onChange={handleSetUpload} />
|
||
{setImages.length ? (
|
||
<div className="product-clone-thumb-row product-set-thumb-row" aria-label="已上传商品原图">
|
||
{setImages.map((item) => (
|
||
<figure key={item.id} className="product-set-thumb">
|
||
<img src={item.src} alt={item.name} />
|
||
<span className="uploaded-image-zoom" aria-hidden="true">
|
||
<img src={item.src} alt="" />
|
||
</span>
|
||
<button type="button" onClick={() => removeSetImage(item.id)} aria-label={`删除${item.name}`}>
|
||
<CloseOutlined />
|
||
</button>
|
||
</figure>
|
||
))}
|
||
</div>
|
||
) : null}
|
||
</section>
|
||
|
||
<section className="product-clone-field product-set-settings-section">
|
||
<h2>
|
||
生成设置
|
||
<SettingOutlined />
|
||
</h2>
|
||
<div className="product-set-setting-block">
|
||
<span className="product-set-setting-title">生成内容</span>
|
||
<div className="product-set-output-grid" role="radiogroup" aria-label="生成内容">
|
||
{productSetOutputOptions.map((option) => (
|
||
<button
|
||
key={option.key}
|
||
type="button"
|
||
className={productSetOutput === option.key ? "is-active" : ""}
|
||
aria-pressed={productSetOutput === option.key}
|
||
onClick={() => handleProductSetOutputChange(option.key)}
|
||
>
|
||
{option.label}
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div className="product-set-setting-block">
|
||
<span className="product-set-setting-title">基础设置</span>
|
||
<div className="product-set-field-grid">
|
||
<label>
|
||
<span>平台</span>
|
||
<select value={productSetPlatform} onChange={(event) => handleProductSetPlatformChange(event.target.value)}>
|
||
{platformOptions.map((item) => (
|
||
<option key={item}>{item}</option>
|
||
))}
|
||
</select>
|
||
</label>
|
||
<label>
|
||
<span>国家</span>
|
||
<select value={productSetMarket} onChange={(event) => handleProductSetMarketChange(event.target.value)}>
|
||
{marketOptions.map((item) => (
|
||
<option key={item}>{item}</option>
|
||
))}
|
||
</select>
|
||
</label>
|
||
<label>
|
||
<span>语言</span>
|
||
<select value={productSetLanguage} onChange={(event) => setProductSetLanguage(event.target.value)}>
|
||
{productSetLanguageOptions.map((item) => (
|
||
<option key={item}>{item}</option>
|
||
))}
|
||
</select>
|
||
</label>
|
||
<label>
|
||
<span>尺寸/比例</span>
|
||
<select
|
||
value={productSetRatio}
|
||
onChange={(event) => setProductSetRatio(event.target.value)}
|
||
disabled={productSetRatioOptions.length <= 1}
|
||
>
|
||
{productSetRatioOptions.map((item) => (
|
||
<option key={item} value={item}>{formatRatioDisplayValue(item)}</option>
|
||
))}
|
||
</select>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</>
|
||
);
|
||
}
|