import { useState } from 'react'; import { Button, Descriptions, Divider, Drawer, Form, Input, InputNumber, Modal, Select, Space, Table, Tabs, Tag, Typography, message, } from 'antd'; import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; import type { ColumnsType } from 'antd/es/table'; import { request } from '../lib/api'; import { AROMA_TYPE_LABELS, PRODUCT_STATUS_LABELS, fmtTime } from '../lib/constants'; import { useAdminList } from '../lib/useAdminList'; import OssUpload from '../components/OssUpload'; import DetailImageUrlList from '../components/DetailImageUrlList'; import ProductDetailTemplatePicker from '../components/ProductDetailTemplatePicker'; import type { FormInstance } from 'antd/es/form'; type ProductDetailContentDto = { storyTitle?: string; storyText?: string; features?: Array<{ icon: string; title: string; desc: string }>; }; type Row = { id: string; skuCode: string; barcode69: string; name: string; subtitle?: string; aromaType: string; spec: string; price: number; benefitAmount: number; status: string; sortOrder: number; mainImageUrl?: string | null; carouselUrls?: string[]; detailImageUrls?: string[]; detailContent?: ProductDetailContentDto | null; createdAt: string; }; type ProductFormValues = { skuCode?: string; barcode69?: string; name: string; subtitle?: string; aromaType?: string; spec: string; price: number; benefitAmount?: number; status?: string; sortOrder?: number; coverUrl?: string; carouselUrls?: string[]; detailImageUrls?: string[]; storyTitle?: string; storyText?: string; features?: Array<{ icon?: string; title?: string; desc?: string }>; }; function mapDetailToForm(d: Record) { const detail = (d.detailContent ?? {}) as ProductDetailContentDto; return { ...d, coverUrl: (d as { mainImageUrl?: string }).mainImageUrl, carouselUrls: ((d as Row).carouselUrls?.length ? (d as Row).carouselUrls : ['']) as string[], detailImageUrls: ((d as Row).detailImageUrls?.length ? (d as Row).detailImageUrls : ['']) as string[], storyTitle: detail.storyTitle ?? '', storyText: detail.storyText ?? '', features: detail.features?.length ? detail.features : [{ icon: 'water_drop', title: '', desc: '' }], }; } function buildProductPayload(v: ProductFormValues) { const carouselUrls = (v.carouselUrls ?? []).map((u) => u?.trim()).filter(Boolean); const detailImageUrls = (v.detailImageUrls ?? []).map((u) => u?.trim()).filter(Boolean); const features = (v.features ?? []) .filter((f) => f?.title?.trim() || f?.desc?.trim()) .map((f) => ({ icon: f.icon?.trim() || 'star', title: f.title?.trim() || '', desc: f.desc?.trim() || '', })); const detailContent: ProductDetailContentDto = { storyTitle: v.storyTitle?.trim() || undefined, storyText: v.storyText?.trim() || undefined, features: features.length ? features : undefined, }; return { skuCode: v.skuCode, barcode69: v.barcode69, name: v.name, subtitle: v.subtitle, aromaType: v.aromaType, spec: v.spec, price: v.price, benefitAmount: v.benefitAmount, status: v.status, sortOrder: v.sortOrder, coverUrl: v.coverUrl, carouselUrls, detailImageUrls, detailContent, }; } function ImageUrlList({ name, label, bizType }: { name: string; label: string; bizType: string }) { return ( {(fields, { add, remove }) => ( <> {fields.map((field) => ( {fields.length > 1 && ( remove(field.name)} style={{ marginTop: 8 }} /> )} ))} )} ); } function ProductDetailFields({ form, aromaType }: { form: FormInstance; aromaType?: string }) { return ( <> 详情页轮播(CAROUSEL) 详情长图(DETAIL,可逐张修改) 卖点特色 {(fields, { add, remove }) => ( <> {fields.map((field) => ( {fields.length > 1 && ( remove(field.name)} style={{ marginTop: 30 }} /> )} ))} )} ); } function BaseInfoFields({ mode }: { mode: 'create' | 'edit' }) { return ( <> {mode === 'create' && ( <> ({ value, label }))} /> { setPage(p); setPageSize(ps); } }} /> setDrawerOpen(false)} extra={detail && ( )}> {detail && ( <> {String(detail.skuCode)} {String(detail.barcode69)} {AROMA_TYPE_LABELS[String(detail.aromaType)] || String(detail.aromaType)}
}, { key: 'detail', label: '详情页', children: ( ), }, ]} /> )}
setCreateOpen(false)} onOk={async () => { const v = await createForm.validateFields(); const payload = buildProductPayload(v); await request('/admin/products', { method: 'POST', body: JSON.stringify(payload) }); message.success('已创建'); setCreateOpen(false); createForm.resetFields(); void reload(); }} width={720}>
}, { key: 'detail', label: '详情页', children: ( prev.aromaType !== cur.aromaType}> {() => ( )} ), }, ]} />
); }