import React, { useState, useEffect } from 'react' import { APP_VERSION } from '../config/version' export default function Home() { const [user, setUser] = useState(null) const [stats, setStats] = useState({ totalCount: 0, totalCost: 0, totalRevenue: 0, expectedProfit: 0, totalProfit: 0, gradedCount: 0 }) const [recentCollections, setRecentCollections] = useState([]) const [yichensStats, setYichensStats] = useState({ total: 0, deals: 0, wants: 0, dragons: 0, horses: 0, tianma: 0 }) const [seekStats, setSeekStats] = useState({ seekCount: 0, matchedCount: 0 }) const [recentPosts, setRecentPosts] = useState([]) const [dragonStats, setDragonStats] = useState({}) const [dealStats, setDealStats] = useState({ total: 0, items: [] }) const [dealVersion, setDealVersion] = useState('龙钞') const [dealDetailItems, setDealDetailItems] = useState(null) const currentPath = window.location.hash.slice(1) || '/' // 成交行情数据处理 const categoryOrder = ['带4号', '带7号', '永恒号', '天马号', '天马王', '金山号', '金山王', '钻石号', '朦胧号', '朦胧王', '金马号', '金马王', '倒置号', '圆圆号'] const normalizeCat = (c) => { if (c === '通货') return '带4号' if (c === '无4') return '带7号' return c } const calcDealAvg = (pkg, cat) => { const items = dealStats.items.filter(item => { const content = item.content || '' const p = content.includes('包装:') ? content.split('包装:')[1].split('\n')[0].trim() : (item.packaging || '') let c = content.includes('分类:') ? content.split('分类:')[1].split('\n')[0].trim() : (item.category || '') c = normalizeCat(c) return p === pkg && c === cat }) if (items.length === 0) return null const sum = items.reduce((a, b) => a + (b.deal_price || 0), 0) return { avg: Math.round(sum / items.length), count: items.length, items } } // 获取今日成交数据 useEffect(() => { const today = new Date() const dealDate = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}` fetch(`/api/information/list?info_type=deal&deal_date=${dealDate}&page_size=500`) .then(res => res.json()) .then(data => { if (Array.isArray(data)) { setDealStats({ total: data.length, items: data }) } }) .catch(() => {}) }, []) useEffect(() => { const token = localStorage.getItem('token') const userData = localStorage.getItem('user') if (userData) { try { setUser(JSON.parse(userData)) } catch (e) { console.error('Parse user error:', e) } } if (token) { fetch('/api/collections/stats', { headers: { 'Authorization': 'Bearer ' + token } }).then(res => { if (!res.ok) throw new Error('Stats API failed') return res.json() }).then(data => { // stats API直接返回对象,不需要data.data包装 const info = data.totalCount !== undefined ? data : (data.data || data) if (info && info.totalCount !== undefined) { // 从byGrading计算评级数 const gradedCount = info.byGrading ? (info.byGrading.find(x => x.isGraded === true)?.count || 0) : 0 setStats({ totalCount: info.totalCount || 0, totalCost: info.totalCost || 0, totalRevenue: info.totalRevenue || 0, expectedProfit: info.expectedProfit || 0, totalProfit: info.totalProfit || 0, gradedCount: gradedCount }) } }) fetch('/api/collections?limit=5&sort=createdAt&order=desc', { headers: { 'Authorization': 'Bearer ' + token } }).then(res => res.json()).then(data => { // 新格式 {data:[], pagination:{}} 或老格式 {items:[]} const list = data.data || data.items || data if (Array.isArray(list)) { setRecentCollections(list) } }) } }, []) // 获取一尘看板数据 useEffect(() => { fetch('/api/yichens/stats/dragons-today').then(res => res.json()).then(data => { setDragonStats(data || {}) }).catch(() => {}) fetch('/api/yichens/stats/today').then(res => res.json()).then(data => { setYichensStats(data || {}) }).catch(() => {}) // 获取最新一尘帖子 fetch('/api/yichens/stats/dragons-today').then(res => res.json()).then(data => { setDragonStats(data || {}) }).catch(() => {}) fetch('/api/yichens/posts?limit=20&offset=0').then(res => res.json()).then(data => { setRecentPosts(data.posts || data || []) }).catch(() => {}) // 获取寻配号统计数据 fetch('/api/information/seek/stats').then(res => res.json()).then(data => { setSeekStats(data || {}) }).catch(() => {}) }, []) // 检查是否为管理员 const isAdmin = user && user.role === 'admin' const handleLogout = () => { localStorage.removeItem('token') localStorage.removeItem('user') window.location.hash = '#/login' window.location.reload() } const formatMoney = (val) => { if (!val || val === 0) return '0' const v = val / 10000 return v.toFixed(1) } const statCards = [ { label: '藏品数', value: stats.totalCount, color: '#3b82f6' }, { label: '总成本', value: formatMoney(stats.totalCost) + '万', color: '#22c55e' }, { label: '总收入', value: formatMoney(stats.totalRevenue) + '万', color: '#06b6d4' }, { label: '评级数', value: stats.gradedCount, color: '#8b5cf6' }, { label: '预期利润', value: formatMoney(stats.expectedProfit) + '万', color: stats.expectedProfit >= 0 ? '#f59e0b' : '#ef4444' }, { label: '总利润', value: formatMoney(stats.totalProfit) + '万', color: stats.totalProfit >= 0 ? '#10b981' : '#f43f5e' } ] return (
| {['标百', '标十', '单张'].map(p => ( | {p} | ))}
|---|---|
| {cat} | {rowData.map((d, i) => (
{d ? (
setDealDetailItems(d.items)}>
¥{d.avg.toLocaleString()}
({d.count})
) : -}
|
))}