import React, { useState, useEffect } from 'react' // 资讯页面 - 展示寻配号和行情信息(所有人可见) export default function News() { const [activeTab, setActiveTab] = useState('deal') const [showSeekPublish, setShowSeekPublish] = useState(false) const [showMySeeks, setShowMySeeks] = useState(false) // 我的寻号 const [showMatchList, setShowMatchList] = useState(false) const [matchCollections, setMatchCollections] = useState([]) const [seekForm, setSeekForm] = useState({ edition: '龙钞', type: '', category: '寻号', price: '', matchType: '模糊', features: '', content: '', title: '', contact: '' }) const [infoList, setInfoList] = useState([]) const [loading, setLoading] = useState(false) const API_BASE = localStorage.getItem('API_BASE') || '' // 获取资讯列表 useEffect(() => { fetchInfoList() }, [activeTab]) // 自动生成寻号标题 useEffect(() => { const title = `「寻号 ${seekForm.edition || '龙钞,马钞,蛇钞'} ${seekForm.type || '不限'} J0${seekForm.features || 'XXXXXXXX'} ${seekForm.matchType}」` setSeekForm(prev => ({...prev, title})) }, [seekForm.edition, seekForm.type, seekForm.features, seekForm.matchType]) const fetchInfoList = async () => { setLoading(true) try { // 寻配号对所有人公开,无需登录即可查看 const token = localStorage.getItem('token') // 根据tab获取不同类型的数据 const type = activeTab === 'seek' ? 'seek' : 'deal' // 始终传递token,以便获取准确的matched_count const headers = token ? { Authorization: `Bearer ${token}` } : {} const res = await fetch(`${API_BASE}/api/information/list?info_type=${type}`, { headers }) const data = await res.json() console.log('资讯列表:', data) setInfoList(data || []) } catch (e) { console.error(e) } setLoading(false) } // 获取匹配藏品列表 const fetchMatchCollections = async (infoId) => { const token = localStorage.getItem('token') if (!token) { alert('请先登录'); return } try { const res = await fetch(`${API_BASE}/api/information/seek/match?info_id=${infoId}`, { headers: { Authorization: `Bearer ${token}` } }) const data = await res.json() console.log('匹配结果:', data) console.log('匹配数量:', data.matched_count) console.log('藏品列表:', data.collections) setMatchCollections(data.collections || []) setShowMatchList(true) } catch (e) { console.error('获取匹配藏品失败:', e) alert('获取匹配藏品失败: ' + e.message) } } // 获取我的寻号列表 const [mySeekList, setMySeekList] = useState([]) const [editingSeek, setEditingSeek] = useState(null) const fetchMySeeks = async () => { const token = localStorage.getItem('token') if (!token) { alert('请先登录'); return } try { const res = await fetch(`${API_BASE}/api/information/my/list`, { headers: { Authorization: `Bearer ${token}` } }) const data = await res.json() // 过滤出寻号类型的 const seeks = Array.isArray(data) ? data.filter(item => item.info_type === 'seek') : [] setMySeekList(seeks) } catch (e) { console.error(e) } } // 更新寻号 const handleUpdateSeek = async () => { if (!editingSeek) return const token = localStorage.getItem('token') try { // 解析正文中的号码特征和联系方式 const content = (editingSeek.content || '') + '\n联系方式: ' + editingSeek.contact await fetch(`${API_BASE}/api/information/${editingSeek.id}`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ title: editingSeek.title, content, expect_category: editingSeek.edition, expect_number: editingSeek.features ? 'J0' + editingSeek.features : null }) }) setEditingSeek(null) fetchMySeeks() } catch (e) { alert('更新失败') } } const handleSeekPublish = async () => { if (!seekForm.contact) { alert('请填写联系方式'); return } // 类型改为非必选 try { const token = localStorage.getItem('token') const content = (seekForm.content ? seekForm.content + '\n' : '') + (seekForm.price ? `价格: ${seekForm.price}` : '') + (seekForm.features ? '\n号码特征: J0' + seekForm.features : '') + '\n联系方式: ' + seekForm.contact // 从edition映射到category const categoryMap = { '龙钞': '龙钞', '马钞': '马钞', '蛇钞': '蛇钞' } const res = await fetch(`${API_BASE}/api/information/`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ title: seekForm.title, content, info_type: 'seek', expect_category: seekForm.edition, expect_number: seekForm.features ? 'J0' + seekForm.features : None }) }) const data = await res.json() if (data.id || data.code === 0) { alert('发布成功!') setShowSeekPublish(false) setSeekForm({ edition: '龙钞', type: '', category: '寻号', price: '', matchType: '模糊', features: '', content: '', title: '', contact: '' }) fetchInfoList() } else { alert(data.message || '发布失败') } } catch (e) { alert('发布失败: ' + e.message) } } // Tab切换 const tabs = [ { key: 'seek', label: '🔍 寻配号' }, { key: 'deal', label: '💰 成交行情' } ] const formatDate = (dateStr) => { if (!dateStr) return '-' const date = new Date(dateStr) return `${date.getMonth() + 1}/${date.getDate()}` } return (
{/* Tab导航 */}
{tabs.map(tab => (
setActiveTab(tab.key)} style={{ padding: '10px 20px', borderRadius: '8px', background: activeTab === tab.key ? '#3b82f6' : 'transparent', color: '#fff', cursor: 'pointer', whiteSpace: 'nowrap', fontSize: '14px' }} > {tab.label}
))}
{/* 资讯列表 */}
{showSeekPublish && activeTab === 'seek' && (
{['龙钞','马钞','蛇钞'].map(item => { const isSelected = seekForm.edition ? seekForm.edition.split(',').includes(item) : false return ( ) })}
{['标百','标十','单张'].map(e => ( ))}
{['求购','出售','寻号'].map(e => ( ))}
setSeekForm({...seekForm, price: e.target.value})} placeholder="请输入价格" style={{ width: '100%', padding: '8px', marginTop: '6px', background: '#0f172a', border: '1px solid #334155', borderRadius: '6px', color: '#fff', fontSize: '13px', boxSizing: 'border-box' }} />
{['精准','模糊'].map(e => ( ))}
{[0,1,2,3,4,5,6,7,8,9].map(i => { const isFixed = i < 2 const char = i === 0 ? 'J' : (i === 1 ? '0' : (seekForm.features[i - 2] || '')) const isDigit = /[0-9]/.test(char) const letterColor = isFixed ? '#10b981' : (isDigit ? '#fff' : ({ X: '#94a3b8', A: '#f472b6', B: '#60a5fa', C: '#34d399', D: '#fbbf24', E: '#a78bfa', F: '#fb923c', G: '#22d3ee' }[char] || '#fff')) return { if (el) el.dataset.index = i }} type="text" maxLength={1} value={char} readOnly={isFixed} onChange={(e) => { if (i < 2) return const val = e.target.value.toUpperCase().replace(/[^0-9XABCFG]/g, '') const newFeatures = (seekForm.features || '').split('') while (newFeatures.length < 8) newFeatures.push('') newFeatures[i - 2] = val setSeekForm({...seekForm, features: newFeatures.join('')}) // 自动跳转下一个 if (val && i < 9) { setTimeout(() => { const nextInput = document.querySelector(`input[data-index="${i+1}"]`) if (nextInput) nextInput.focus() }, 50) } }} onKeyDown={(e) => { // 按Delete或Backspace且当前为空时,跳回前一个 if ((e.key === 'Backspace' || e.key === 'Delete') && !char && i > 2) { setTimeout(() => { const prevInput = document.querySelector(`input[data-index="${i-1}"]`) if (prevInput) prevInput.focus() }, 50) } }} style={{ width: '32px', height: '36px', textAlign: 'center', padding: '6px', background: '#0f172a', border: '1px solid #334155', borderRadius: '4px', color: letterColor, fontSize: '14px', boxSizing: 'border-box' }} /> })}
备注说明:X=任意数字 A=非4 B=非47 C=非347 D=非247 E=非2347 F=非23457 G=非123457