import React, { useEffect, useState } from 'react'; import { Button, Form, Image, Input, Modal, Popconfirm, Space, Switch, Table, Upload, message } from 'antd'; import { DeleteOutlined, EditOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons'; import { deleteHomeMaterialWatermark, getHomeMaterialWatermarks, updateHomeMaterialWatermark, uploadHomeMaterialWatermark } from '../../api'; import type { HomeMaterialWatermark } from '../../types'; import { apiUrl } from '../../utils/resourceUrl'; interface Props { open?: boolean; onClose?: () => void; embedded?: boolean; onChanged?: () => void; } const WatermarkLibraryModal: React.FC = ({ open = true, onClose, embedded = false, onChanged }) => { const [items, setItems] = useState([]); const [loading, setLoading] = useState(false); const [uploadOpen, setUploadOpen] = useState(false); const [editing, setEditing] = useState(null); const [file, setFile] = useState(null); const [fileList, setFileList] = useState([]); const [previewUrl, setPreviewUrl] = useState(''); const [submitting, setSubmitting] = useState(false); const [form] = Form.useForm(); const load = async () => { setLoading(true); try { const res = await getHomeMaterialWatermarks({ page: 1, pageSize: 200 }); setItems(res.items); } finally { setLoading(false); } }; useEffect(() => { if (open) load(); }, [open]); useEffect(() => { return () => { if (previewUrl.startsWith('blob:')) URL.revokeObjectURL(previewUrl); }; }, [previewUrl]); const resetUploadState = () => { setFile(null); setFileList([]); setPreviewUrl(''); setSubmitting(false); }; const openUpload = () => { setEditing(null); resetUploadState(); form.setFieldsValue({ name: '', is_default: false, is_active: true }); setUploadOpen(true); }; const openEdit = (row: HomeMaterialWatermark) => { setEditing(row); resetUploadState(); setPreviewUrl(apiUrl(row.fileUrl)); form.setFieldsValue({ name: row.name, is_default: row.isDefault, is_active: row.isActive }); setUploadOpen(true); }; const closeUploadModal = () => { if (submitting) return; setUploadOpen(false); resetUploadState(); }; const handleBeforeUpload = (selectedFile: File) => { if (!selectedFile.type.startsWith('image/')) { message.warning('请选择图片文件'); return Upload.LIST_IGNORE; } if (previewUrl.startsWith('blob:')) URL.revokeObjectURL(previewUrl); const nextPreviewUrl = URL.createObjectURL(selectedFile); setFile(selectedFile); setPreviewUrl(nextPreviewUrl); setFileList([{ uid: selectedFile.name, name: selectedFile.name, status: 'done', originFileObj: selectedFile }]); return false; }; const handleRemoveFile = () => { setFile(null); setFileList([]); if (previewUrl.startsWith('blob:')) URL.revokeObjectURL(previewUrl); setPreviewUrl(''); }; const submit = async () => { if (submitting) return; const values = await form.validateFields(); if (!editing && !file) { message.warning('请选择水印图片'); return; } setSubmitting(true); try { if (editing) { await updateHomeMaterialWatermark(editing.id, { name: values.name, is_default: values.is_default, is_active: values.is_active }); } else if (file) { await uploadHomeMaterialWatermark(file, values.name, values.is_default); } message.success('保存成功'); setUploadOpen(false); resetUploadState(); await load(); onChanged?.(); } finally { setSubmitting(false); } }; const table = ( <>
}, { title: '名称', dataIndex: 'name' }, { title: '尺寸', render: (_: unknown, r: HomeMaterialWatermark) => r.width && r.height ? `${r.width}×${r.height}` : '-' }, { title: '默认', dataIndex: 'isDefault', render: (v: boolean) => v ? '是' : '否' }, { title: '启用', dataIndex: 'isActive', render: (v: boolean) => v ? '启用' : '禁用' }, { title: '操作', render: (_: unknown, row: HomeMaterialWatermark) => ( { await deleteHomeMaterialWatermark(row.id); message.success('删除成功'); await load(); onChanged?.(); }}> ), }, ]} />
{!editing && ( handleBeforeUpload(f as File)} onRemove={handleRemoveFile} fileList={fileList} maxCount={1} accept="image/png,image/jpeg,image/webp" disabled={submitting} > {previewUrl && (
)}
)} {editing && previewUrl && ( )}
); if (embedded) return table; return {table}; }; export default WatermarkLibraryModal;