Files
ozon-seller-kit/studio/src/pages/product/ImagePanel.tsx
T

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>
);
}