import React, { useState, useRef, useEffect } from 'react' // Input 组件(复用 Add.jsx 的定义) const Input = ({ form, handleChange, label, field, type = 'text', options = null }) => { const onChange = (e) => { const value = e.target.value if (type === 'number' && value !== '') { const num = parseFloat(value) handleChange(field, isNaN(num) ? '' : num) } else handleChange(field, value) } return (
{label}
{options ? ( ) : ( )}
) } // 选项定义 const statusOptions = [ { value: 'in_collection', label: '收藏中' }, { value: 'selling', label: '出售中' }, { value: 'sold', label: '已售' }, { value: 'grading', label: '送评中' }, { value: 'repairing', label: '修复中' }, { value: 'transit', label: '在途中' }, { value: 'seeking', label: '寻号中' }, { value: 'other', label: '其他' } ] const categoryOptions = [ { value: '自持', label: '自持' }, { value: '寄存', label: '寄存' }, { value: '寄售', label: '寄售' }, { value: '共有', label: '共有' }, { value: '其他', label: '其他' } ] const rarityOptions = [ { value: '通货', label: '通货' }, { value: '特色', label: '特色' }, { value: '少见', label: '少见' }, { value: '稀有', label: '稀有' }, { value: '珍品', label: '珍品' }, { value: '孤品', label: '孤品' } ] const packagingOptions = [ { value: '标十', label: '标十' }, { value: '标百', label: '标百' }, { value: '单张', label: '单张' }, { value: '裸钞', label: '裸钞' } ] export default function Edit() { // 从 URL 获取藏品 ID const params = new URLSearchParams(window.location.hash.split('?')[1] || '') const editId = params.get('id') const [form, setForm] = useState({ name: '', code: '', category: '自持', rarity: '通货', prefixSerial: '', version: '2024 龙', denomination: '', status: 'in_collection', packaging: '单张', material: '塑料钞', issueQuantity: '1 亿', purpose: '收藏', isGraded: false, gradingCompany: '', gradingScore: '', threeStar: false, specialMark: '', serialFeature: '', issuer: '中国人民银行', issueYear: '2024', costPrice: '', targetPrice: '', goalPrice: '', repairFee: '', gradingFee: '', remark: '' }) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [error, setError] = useState('') const [uploadImages, setUploadImages] = useState([]) const fileInputRef = useRef(null) // 加载现有藏品数据 useEffect(() => { if (editId) { const token = localStorage.getItem('token') fetch(`/api/collections/${editId}`, { headers: { 'Authorization': 'Bearer ' + token } }) .then(res => res.json()) .then(data => { // 填充表单 setForm({ name: data.name || '', code: data.code || '', category: data.category || '自持', rarity: data.rarity || '通货', prefixSerial: data.prefixSerial || '', version: data.version || '2024 龙', denomination: data.denomination || '', status: data.status || 'in_collection', packaging: data.packaging || '单张', isGraded: data.isGraded || false, gradingCompany: data.gradingCompany || '', gradingScore: data.gradingScore || '', threeStar: data.threeStar || false, specialMark: data.specialMark || '', serialFeature: data.serialFeature || '', issuer: data.issuer || '中国人民银行', issueYear: data.issueYear || '2024', material: data.material || '塑料钞', issueQuantity: data.issueQuantity || '1 亿', costPrice: data.costPrice || '', targetPrice: data.targetPrice || '', goalPrice: data.goalPrice || '', repairFee: data.repairFee || '', gradingFee: data.gradingFee || '', purpose: data.purpose || '收藏', remark: data.remark || '' }) // 加载图片 if (data.images && Array.isArray(data.images)) { const images = data.images.map(img => ({ file: null, preview: `http://120.26.133.10:3000/${img.path || `uploads/collections/${img.filename}`}`, name: img.original_name || img.filename, size: 0, id: img.id })) setUploadImages(images) } setLoading(false) }) .catch(err => { console.error('加载藏品失败:', err) setError('加载失败:' + err.message) setLoading(false) }) } else { setError('未指定藏品 ID') setLoading(false) } }, [editId]) const handleChange = (key, value) => { setForm({ ...form, [key]: value }) if (key === 'targetPrice' && value) setForm(prev => ({ ...prev, status: 'sold' })) // 版别变化时同步发行年份 if (key === 'version') { const yearMatch = value.match(/(20\d{2})/) if (yearMatch) { setForm(prev => ({ ...prev, issueYear: yearMatch[1] })) } } } // 图片上传处理 const handleImageUpload = async (e) => { const files = Array.from(e.target.files) if (files.length === 0 || !editId) return const token = localStorage.getItem('token') const file = files[0] // 只允许上传 1 张 const imgFormData = new FormData() imgFormData.append('file', file) try { const res = await fetch(`/api/collections/upload-image?collection_id=${editId}`, { method: 'POST', headers: { 'Authorization': 'Bearer ' + token }, body: imgFormData }) if (res.ok) { // 重新加载藏品数据 const dataRes = await fetch(`/api/collections/${editId}`, { headers: { 'Authorization': 'Bearer ' + token } }) const data = await dataRes.json() if (data.images && Array.isArray(data.images)) { const images = data.images.map(img => ({ file: null, preview: `http://120.26.133.10:3000/${img.path || `uploads/collections/${img.filename}`}`, name: img.original_name || img.filename, size: 0, id: img.id })) setUploadImages(images) } alert('图片上传成功!') } else { alert('图片上传失败') } } catch (err) { console.error('图片上传失败:', err) alert('图片上传失败:' + err.message) } } const handleSave = async () => { if (!form.name || !form.version) { setError('名称和版别为必填项'); return } setSaving(true) setError('') const token = localStorage.getItem('token') const formData = convertField(form) try { // 1. 更新藏品信息 const res = await fetch(`/api/collections/${editId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify(formData) }) if (!res.ok) { const data = await res.json() throw new Error(data.error?.message || data.detail || '更新失败') } alert('更新成功!') window.location.hash = '#/list' window.refreshList?.() } catch (e) { console.error('更新失败:', e) alert('更新失败:' + e.message) } finally { setSaving(false) } } // 字段转换函数 const convertField = (obj) => { const map = { id: 'f99_90_id', userId: 'f99_91_user_id', name: 'f01_01_name', code: 'f01_02_code', category: 'f01_03_category', status: 'f01_04_status', remark: 'f01_05_remark', prefixSerial: 'f02_10_prefix_serial', version: 'f02_11_version', packaging: 'f02_12_packaging', rarity: 'f02_13_rarity', isGraded: 'f03_20_is_graded', gradingCompany: 'f03_21_grading_company', gradingScore: 'f03_22_grading_score', threeStar: 'f03_23_three_star', specialMark: 'f04_30_special_mark', serialFeature: 'f04_31_serial_feature', issuer: 'f04_32_issuer', issueYear: 'f04_33_issue_year', material: 'f04_34_material', denomination: 'f04_35_denomination', issueQuantity: 'f04_36_issue_quantity', costPrice: 'f05_40_cost_price', targetPrice: 'f05_41_target_price', goalPrice: 'f05_42_goal_price', repairFee: 'f05_43_repair_fee', gradingFee: 'f05_44_grading_fee', purpose: 'f06_50_purpose' } const result = {} const numberFields = ['costPrice', 'targetPrice', 'goalPrice', 'repairFee', 'gradingFee'] for (const key in obj) { let value = obj[key] if (value === '' || value === null) value = null else if (numberFields.includes(key)) { value = parseFloat(value) if (isNaN(value)) value = null } result[map[key] || key] = value } return result } if (loading) { return (
加载中...
) } return (
{/* 顶部标题 */}
编辑藏品
修改藏品信息
{error && (
⚠️ {error}
)}
{/* 藏品图片 */}
藏品图片 ({uploadImages.length}/1)
{uploadImages.length === 0 && ( )}
{/* 隐藏的文件输入框 */} {uploadImages.length > 0 ? (
{uploadImages.map((img, index) => (
{img.name
{index + 1}/{uploadImages.length}
))}
) : (
📷 暂无图片
)}
{/* 基本信息 */}
基本信息
{/* 评级信息 */}
评级信息
handleChange('isGraded', e.target.checked)} style={{ width: '18px', height: '18px', cursor: 'pointer', accentColor: '#22c55e' }} />
handleChange('threeStar', e.target.checked)} style={{ width: '18px', height: '18px', cursor: 'pointer', accentColor: '#22c55e' }} />
{/* 特殊信息 */}
特殊信息
{/* 价格信息 */}
价格信息
{/* 备注 */}
备注