162 lines
7.4 KiB
TypeScript
162 lines
7.4 KiB
TypeScript
import { useState } from 'react';
|
||
import { Col, Divider, Input, Row, Tag, Typography } from 'antd';
|
||
import { ProductDetail } from '@/services/product';
|
||
import CopyPanel from './CopyPanel';
|
||
|
||
const { Text } = Typography;
|
||
|
||
interface Props {
|
||
product: ProductDetail;
|
||
onSave: (p: Partial<ProductDetail>) => Promise<void> | void;
|
||
}
|
||
|
||
/** 产品属性:采集参数只读展示 / 条形码 / 品牌 / 简介 / AI 文案 */
|
||
export default function ProductAttributesPanel({ product, onSave }: Props) {
|
||
const raw = (product.raw ?? {}) as Record<string, unknown>;
|
||
const params = raw.params as Array<{ key: string; value: string }> | undefined;
|
||
|
||
const [descExpanded, setDescExpanded] = useState(false);
|
||
|
||
const updateRaw = (patch: Record<string, unknown>) => {
|
||
onSave({ raw: { ...raw, ...patch } });
|
||
};
|
||
|
||
const sellingPoints = typeof raw.sellingPoints === 'string' ? raw.sellingPoints : '';
|
||
const desc = typeof raw.desc === 'string' ? raw.desc : '';
|
||
|
||
return (
|
||
<div>
|
||
{/* 基础字段:品牌 + 条形码 */}
|
||
<Row gutter={16} style={{ marginBottom: 12 }}>
|
||
<Col span={8}>
|
||
<Text style={{ fontSize: 12, color: '#666', display: 'block', marginBottom: 4 }}>
|
||
品牌(Brand)
|
||
</Text>
|
||
<Input
|
||
value={(raw.brand as string) ?? ''}
|
||
onChange={(e) => updateRaw({ brand: e.target.value })}
|
||
placeholder="采集到的品牌名"
|
||
/>
|
||
</Col>
|
||
<Col span={8}>
|
||
<Text style={{ fontSize: 12, color: '#666', display: 'block', marginBottom: 4 }}>
|
||
条形码(Barcode)
|
||
</Text>
|
||
<Input
|
||
value={product.barcode ?? ''}
|
||
onChange={(e) => onSave({ barcode: e.target.value })}
|
||
placeholder="EAN / UPC / 留空"
|
||
/>
|
||
</Col>
|
||
<Col span={8}>
|
||
<Text style={{ fontSize: 12, color: '#666', display: 'block', marginBottom: 4 }}>
|
||
主题标签(内部备注)
|
||
</Text>
|
||
<Input
|
||
value={(raw.tags as string) ?? ''}
|
||
onChange={(e) => updateRaw({ tags: e.target.value })}
|
||
placeholder="逗号分隔,内部用"
|
||
/>
|
||
</Col>
|
||
</Row>
|
||
|
||
{/* 俄文简介(来自 AI 生成或手动) */}
|
||
<div style={{ marginBottom: 12 }}>
|
||
<Text style={{ fontSize: 12, color: '#666', display: 'block', marginBottom: 4 }}>
|
||
俄文简介(description)
|
||
</Text>
|
||
<Input.TextArea
|
||
autoSize={{ minRows: 3, maxRows: 8 }}
|
||
value={product.description ?? ''}
|
||
onChange={(e) => onSave({ description: e.target.value })}
|
||
placeholder="Описание товара на русском — можно сгенерировать через AI ниже"
|
||
/>
|
||
</div>
|
||
|
||
{/* 采集参数展示(只读,参考用) */}
|
||
{Array.isArray(params) && params.length > 0 && (
|
||
<div style={{ marginBottom: 12, padding: '12px 16px', background: '#fafafa', borderRadius: 8 }}>
|
||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 8 }}>
|
||
<Text style={{ fontSize: 12, color: '#666', fontWeight: 500 }}>
|
||
采集参数({params.length} 项,只读参考)
|
||
</Text>
|
||
{params.length > 8 && (
|
||
<a style={{ fontSize: 12 }} onClick={() => setDescExpanded(!descExpanded)}>
|
||
{descExpanded ? '收起' : `展开全部 ${params.length} 项`}
|
||
</a>
|
||
)}
|
||
</div>
|
||
<Row gutter={[8, 4]}>
|
||
{(descExpanded ? params : params.slice(0, 8)).map((p, i) => (
|
||
<Col key={i} span={12}>
|
||
<div style={{ display: 'flex', gap: 6, alignItems: 'baseline' }}>
|
||
<Tag
|
||
style={{
|
||
fontSize: 11,
|
||
maxWidth: 120,
|
||
overflow: 'hidden',
|
||
textOverflow: 'ellipsis',
|
||
whiteSpace: 'nowrap',
|
||
flexShrink: 0,
|
||
}}
|
||
>
|
||
{p.key}
|
||
</Tag>
|
||
<Text style={{ fontSize: 12 }} ellipsis={{ tooltip: p.value }}>
|
||
{p.value}
|
||
</Text>
|
||
</div>
|
||
</Col>
|
||
))}
|
||
</Row>
|
||
{!descExpanded && params.length > 8 && (
|
||
<Text type="secondary" style={{ fontSize: 11, marginTop: 4, display: 'block' }}>
|
||
还有 {params.length - 8} 项未显示
|
||
</Text>
|
||
)}
|
||
</div>
|
||
)}
|
||
|
||
{/* 采集卖点 / 描述(只读参考) */}
|
||
{(sellingPoints || desc) && (
|
||
<div style={{ marginBottom: 12, padding: '12px 16px', background: '#fafafa', borderRadius: 8 }}>
|
||
{sellingPoints && (
|
||
<>
|
||
<Text style={{ fontSize: 12, color: '#666', fontWeight: 500, display: 'block', marginBottom: 4 }}>
|
||
采集卖点(参考)
|
||
</Text>
|
||
<Text style={{ fontSize: 12, whiteSpace: 'pre-wrap' }}>
|
||
{sellingPoints}
|
||
</Text>
|
||
</>
|
||
)}
|
||
{desc && (
|
||
<>
|
||
<Text
|
||
style={{
|
||
fontSize: 12,
|
||
color: '#666',
|
||
fontWeight: 500,
|
||
display: 'block',
|
||
marginTop: sellingPoints ? 8 : 0,
|
||
marginBottom: 4,
|
||
}}
|
||
>
|
||
采集描述(参考)
|
||
</Text>
|
||
<Text style={{ fontSize: 12, whiteSpace: 'pre-wrap' }}>
|
||
{desc.slice(0, 300)}
|
||
{desc.length > 300 && '…'}
|
||
</Text>
|
||
</>
|
||
)}
|
||
</div>
|
||
)}
|
||
|
||
<Divider style={{ margin: '16px 0' }} />
|
||
|
||
<CopyPanel product={product} onSave={onSave} />
|
||
</div>
|
||
);
|
||
}
|