import React, { useState, useEffect } from 'react'
export default function Detail() {
const params = new URLSearchParams(window.location.hash.split('?')[1] || '')
const id = params.get('id')
const [collection, setCollection] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState('')
const [showDelete, setShowDelete] = useState(false)
const [showImage, setShowImage] = useState(false)
const [currentImageIndex, setCurrentImageIndex] = useState(0)
useEffect(() => {
if (id) {
fetchDetail()
}
}, [id])
const fetchDetail = async () => {
setLoading(true)
const token = localStorage.getItem('token')
try {
const res = await fetch(`/api/collections/${id}`, {
headers: token ? { 'Authorization': 'Bearer ' + token } : {}
})
if (!res.ok) {
const errorData = await res.json()
const errorCode = errorData.error?.code || 'E00000'
const errorMessage = errorData.error?.message || '加载失败'
// 标准错误码处理
if (res.status === 404) {
setError('E00033: 藏品不存在')
} else if (res.status === 401) {
setError('E00010: 未登录或登录已过期')
} else if (res.status === 403) {
setError('E00014: 无权访问此藏品')
} else {
setError(`${errorCode}: ${errorMessage}`)
}
setLoading(false)
return
}
const data = await res.json()
// 后端已返回 camelCase 格式,直接使用
const collectionData = data.data || data
if (collectionData && collectionData.id) {
setCollection(collectionData)
} else {
setError('E00000: 数据格式错误')
}
} catch (e) {
console.error(e)
setError('E00001: 网络连接失败')
}
setLoading(false)
}
const handleEdit = () => {
window.location.hash = '#/edit?id=' + id
}
const goBack = () => {
// 尝试返回到上次筛选的列表页面
const lastUrl = sessionStorage.getItem('lastListUrl')
if (lastUrl) {
sessionStorage.removeItem('lastListUrl')
window.location.hash = '#' + lastUrl
} else {
window.location.hash = '#/list'
}
}
const doDelete = async () => {
const token = localStorage.getItem('token')
try {
const res = await fetch(`/api/collections/${id}`, {
method: 'DELETE',
headers: { 'Authorization': 'Bearer ' + token }
})
if (res.ok) {
alert('删除成功!')
if (window.refreshList) window.refreshList()
window.location.hash = '#/list'
} else {
alert('删除失败')
}
} catch (e) {
alert('删除失败')
}
setShowDelete(false)
}
const getStatusText = (status) => {
const map = { 'in_collection': '收藏中', 'selling': '出售中', 'sold': '已售', 'grading': '送评中', 'repairing': '修复中', 'transit': '在途中', 'other': '其他' }
return map[status] || status || '-'
}
const getCategoryText = (category) => {
const map = { '自持': '自持', '寄存': '寄存', '寄售': '寄售', '共有': '共有', '寻号': '寻号', '其他': '其他' }
return map[category] || category || '-'
}
const Field = ({ label, value, green }) => (
{label}
{value || '-'}
)
const Section = ({ title, children }) => (
)
if (loading) {
return 加载中...
}
if (error) {
return (
)
}
if (!collection) {
return (
)
}
return (
{/* 顶部 */}
藏品详情
{/* 主信息 */}
{/* 图片显示 */}
{collection.images && collection.images.length > 0 && (
{collection.images.map((img, index) => (
)
{ setCurrentImageIndex(index); setShowImage(true); }}
style={{
width: '100%',
aspectRatio: '1.5',
objectFit: 'contain',
borderRadius: '12px',
border: '2px solid #10b981',
cursor: 'pointer',
boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
background: '#0f172a'
}}
onError={(e) => {
// 图片加载失败时显示灰色占位符,不显示 logo
e.target.style.display = 'none';
e.target.parentElement.innerHTML = '
无图片
';
}}
/>
{collection.images.length > 1 && (
{index + 1}/{collection.images.length}
)}
))}
)}
{collection.name}
{collection.prefixSerial || '-'}
{/* 信息区块 */}
{collection.remark && (
)}
{/* 删除确认弹窗 */}
{showDelete && (
确定删除此藏品?
)}
{/* 图片查看器 */}
{showImage && collection.images && collection.images.length > 0 && (
setShowImage(false)}
>
{/* 左侧切换按钮 */}
{collection.images.length > 1 && (
)}
{/* 图片 */}
![{collection.images[currentImageIndex].originalName]({collection.images[currentImageIndex].path?.startsWith('http'))
e.stopPropagation()}
style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }}
/>
{/* 右侧切换按钮 */}
{collection.images.length > 1 && (
)}
{/* 图片指示器 */}
{collection.images.length > 1 && (
e.stopPropagation()}
>
{collection.images.map((_, index) => (
setCurrentImageIndex(index)}
style={{
width: '12px',
height: '12px',
borderRadius: '50%',
background: index === currentImageIndex ? '#fbbf24' : 'rgba(255,255,255,0.3)',
cursor: 'pointer',
border: '2px solid #fff'
}}
/>
))}
)}
{/* 关闭提示 */}
setShowImage(false)}
>
×
)}
)
}
// v2.7.1