83 lines
3.8 KiB
TypeScript
83 lines
3.8 KiB
TypeScript
import { Checkbox, Empty, Image, Space, Tag, Typography } from 'antd';
|
|
import { ProductAsset, ProductDetail } from '@/services/product';
|
|
|
|
const { Text } = Typography;
|
|
|
|
const GROUP_NAME: Record<string, string> = {
|
|
main: '主图',
|
|
sku: 'SKU 图',
|
|
detail: '详情图',
|
|
video: '视频',
|
|
param: '参数图',
|
|
generated: '生成图',
|
|
};
|
|
|
|
const STATUS_TAG: Record<string, { color: string; text: string }> = {
|
|
pending: { color: 'default', text: '待下载' },
|
|
downloading: { color: 'processing', text: '下载中' },
|
|
uploaded: { color: 'green', text: '已就绪' },
|
|
failed: { color: 'red', text: '失败' },
|
|
};
|
|
|
|
interface Props {
|
|
assets: ProductAsset[];
|
|
product: ProductDetail;
|
|
onSave: (p: Partial<ProductDetail>) => void;
|
|
onRefresh: () => void;
|
|
}
|
|
|
|
export default function ImagePanel({ assets, product, onSave }: Props) {
|
|
const selected = (product.images ?? []) as string[];
|
|
|
|
const toggle = (url: string) => {
|
|
const next = selected.includes(url) ? selected.filter((u) => u !== url) : [...selected, url];
|
|
onSave({ images: next });
|
|
};
|
|
|
|
const groups = [...new Set(assets.map((a) => a.group_key))];
|
|
|
|
return (
|
|
<div>
|
|
<Text type="secondary">勾选图片加入发布主图(images 数组,顺序即 Ozon 展示顺序)。</Text>
|
|
{groups.length === 0 && <Empty description="暂无素材" />}
|
|
{groups.map((g) => (
|
|
<div key={g} style={{ marginTop: 16 }}>
|
|
<Text strong>{GROUP_NAME[g] ?? g}</Text>
|
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 12, marginTop: 8 }}>
|
|
{assets
|
|
.filter((a) => a.group_key === g)
|
|
.map((a) => {
|
|
const url = a.stored_url || a.source_url;
|
|
const tag = STATUS_TAG[a.status] ?? STATUS_TAG.pending;
|
|
const usable = a.status === 'uploaded';
|
|
return (
|
|
<div key={a.id} style={{ width: 140 }}>
|
|
<Image
|
|
src={url}
|
|
width={140}
|
|
height={140}
|
|
style={{ objectFit: 'cover', borderRadius: 6 }}
|
|
fallback="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><rect width='140' height='140' fill='%23eee'/><text x='20' y='70' font-size='12' fill='%23999'>无预览</text></svg>"
|
|
/>
|
|
<Space direction="vertical" size={2} style={{ marginTop: 6, width: '100%' }}>
|
|
<Tag color={tag.color}>{tag.text}</Tag>
|
|
{a.variant_name && <Text ellipsis style={{ fontSize: 12 }}>{a.variant_name}</Text>}
|
|
{usable && a.stored_url && (
|
|
<Checkbox
|
|
checked={selected.includes(a.stored_url)}
|
|
onChange={() => toggle(a.stored_url!)}
|
|
>
|
|
加入主图
|
|
</Checkbox>
|
|
)}
|
|
</Space>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|