diff --git a/src/app/(main)/cps/page.tsx b/src/app/(main)/cps/page.tsx index fa3901e..87e18e0 100644 --- a/src/app/(main)/cps/page.tsx +++ b/src/app/(main)/cps/page.tsx @@ -19,6 +19,7 @@ import { Tabs, Tag, Typography, + Upload, message, } from 'antd'; import { api, errMsg } from '@/lib/api'; @@ -556,6 +557,17 @@ function ActivitiesTab() { ellipsis: true, render: (v: string | null) => v || '-', }, + { + title: '落地页图', + dataIndex: 'image_url', + width: 80, + render: (v: string | null) => + v ? ( + + ) : ( + '-' + ), + }, { title: '状态', dataIndex: 'status', @@ -587,13 +599,86 @@ function ActivitiesTab() { showTotal: (t) => `共 ${t} 个活动`, onChange, }} - scroll={{ x: 1000 }} + scroll={{ x: 1080 }} /> setCreateOpen(false)} onDone={reload} /> ); } +// 淘宝活动落地页图选择器:上传新图 或 点选已有图。受控组件(value = image_url 绝对 URL)。 +function ImagePicker({ value, onChange }: { value?: string | null; onChange?: (v: string) => void }) { + const [existing, setExisting] = useState([]); + const [uploading, setUploading] = useState(false); + + useEffect(() => { + api + .get<{ images: string[] }>('/admin/api/cps/activity-images') + .then((r) => setExisting(r.data.images || [])) + .catch(() => {}); + }, []); + + const upload = async (file: File) => { + setUploading(true); + try { + const fd = new FormData(); + fd.append('file', file); + const r = await api.post<{ url: string }>('/admin/api/cps/upload-image', fd); + onChange?.(r.data.url); + setExisting((prev) => (prev.includes(r.data.url) ? prev : [r.data.url, ...prev])); + message.success('图片已上传'); + } catch (e) { + message.error(errMsg(e, '上传失败')); + } finally { + setUploading(false); + } + }; + + const thumb = (u: string, w: number, selected: boolean) => ( + 落地页图 onChange?.(u)} + style={{ + width: w, + height: Math.round(w * 1.27), + objectFit: 'cover', + borderRadius: 6, + cursor: 'pointer', + border: selected ? '2px solid #ff4d4f' : '2px solid #f0f0f0', + }} + /> + ); + + return ( +
+ { + upload(file); + return false; // 阻止 antd 默认上传,走我们自己的端点 + }} + > + + + {value && ( +
+ 当前: + {thumb(value, 90, true)} +
+ )} + {existing.length > 0 && ( +
+
或选择已有图:
+ {existing.map((u) => thumb(u, 56, u === value))} +
+ )} +
+ ); +} + function ActivityFormModal({ open, onClose, @@ -655,13 +740,22 @@ function ActivityFormModal({ )} {platform === 'taobao' && ( - - - + <> + + + + + + + )} {platform === 'jd' && (