v1.2.50 阶段性完善版本:寻配号优化、网络数据匹配、分页功能、logo修复
This commit is contained in:
parent
693e13bbab
commit
e8c3069bfd
|
|
@ -1,12 +1,14 @@
|
||||||
# 资讯API路由
|
# 资讯API路由
|
||||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||||
from sqlalchemy.orm import Session, joinedload
|
from sqlalchemy.orm import Session, joinedload
|
||||||
|
from sqlalchemy import text
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
|
|
||||||
from app.core.database import get_db
|
from app.core.database import get_db
|
||||||
from app.core.auth import get_current_user
|
from app.core.auth import get_current_user
|
||||||
|
from app.core.coolbot_db import coolbot_engine
|
||||||
from app.models.models import User, Information, Collection
|
from app.models.models import User, Information, Collection
|
||||||
|
|
||||||
router = APIRouter(prefix="/api/information", tags=["资讯"])
|
router = APIRouter(prefix="/api/information", tags=["资讯"])
|
||||||
|
|
@ -74,6 +76,8 @@ class InformationResponse(BaseModel):
|
||||||
collection_number: Optional[str] = None
|
collection_number: Optional[str] = None
|
||||||
# 匹配数量(我的藏品中满足条件的数量)
|
# 匹配数量(我的藏品中满足条件的数量)
|
||||||
matched_count: Optional[int] = 0
|
matched_count: Optional[int] = 0
|
||||||
|
# 网络数据匹配数量(coolbot_data数据库中满足条件的数量)
|
||||||
|
network_matched_count: Optional[int] = 0
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
|
@ -87,7 +91,8 @@ def get_information_list(
|
||||||
page: int = Query(1, ge=1),
|
page: int = Query(1, ge=1),
|
||||||
page_size: int = Query(20, ge=1, le=100),
|
page_size: int = Query(20, ge=1, le=100),
|
||||||
current_user: Optional[User] = Depends(get_current_user),
|
current_user: Optional[User] = Depends(get_current_user),
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db),
|
||||||
|
response: Response = None
|
||||||
):
|
):
|
||||||
"""获取资讯列表(公开,无需登录)"""
|
"""获取资讯列表(公开,无需登录)"""
|
||||||
query = db.query(Information).options(
|
query = db.query(Information).options(
|
||||||
|
|
@ -142,8 +147,21 @@ def get_information_list(
|
||||||
collection_version=item.collection.f02_11_version if item.collection else None,
|
collection_version=item.collection.f02_11_version if item.collection else None,
|
||||||
collection_number=item.collection.f02_10_prefix_serial if item.collection else None,
|
collection_number=item.collection.f02_10_prefix_serial if item.collection else None,
|
||||||
matched_count=matched_count,
|
matched_count=matched_count,
|
||||||
|
network_matched_count=match_collections_count_from_coolbot(item.expect_number) if item.info_type == 'seek' and item.expect_number else 0,
|
||||||
))
|
))
|
||||||
|
|
||||||
|
# 获取总数并设置响应头
|
||||||
|
from fastapi import Response
|
||||||
|
total_query = db.query(Information).filter(Information.status == status)
|
||||||
|
if info_type:
|
||||||
|
total_query = total_query.filter(Information.info_type == info_type)
|
||||||
|
total_count = total_query.count()
|
||||||
|
total_pages = (total_count + page_size - 1) // page_size
|
||||||
|
|
||||||
|
# 设置响应头
|
||||||
|
response.headers['X-Total-Pages'] = str(total_pages)
|
||||||
|
response.headers['X-Total-Count'] = str(total_count)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -182,6 +200,110 @@ def match_collections_count(db: Session, user_id: str, expect_number: str) -> in
|
||||||
return count
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
def match_collections_count_from_coolbot(expect_number: str) -> int:
|
||||||
|
"""根据号码特征计算匹配藏品数量(从coolbot_data数据库)"""
|
||||||
|
if not expect_number or len(expect_number) != 10:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# 固定前缀
|
||||||
|
if not expect_number.startswith('J0'):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
pattern = expect_number[2:] # 后8位
|
||||||
|
if not pattern:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# 直接查询coolbot_data数据库
|
||||||
|
query = text("""
|
||||||
|
SELECT COUNT(*) FROM collections
|
||||||
|
WHERE crown_code IS NOT NULL
|
||||||
|
AND crown_code != ''
|
||||||
|
AND LENGTH(crown_code) >= 10
|
||||||
|
AND crown_code LIKE 'J0%'
|
||||||
|
""")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with coolbot_engine.connect() as conn:
|
||||||
|
result = conn.execute(query)
|
||||||
|
total_count = result.scalar() or 0
|
||||||
|
|
||||||
|
# 遍历匹配
|
||||||
|
query_all = text("""
|
||||||
|
SELECT id, crown_code FROM collections
|
||||||
|
WHERE crown_code IS NOT NULL
|
||||||
|
AND crown_code != ''
|
||||||
|
AND LENGTH(crown_code) >= 10
|
||||||
|
AND crown_code LIKE 'J0%'
|
||||||
|
""")
|
||||||
|
result = conn.execute(query_all)
|
||||||
|
|
||||||
|
match_count = 0
|
||||||
|
for row in result:
|
||||||
|
crown_code = row[1]
|
||||||
|
if crown_code and len(crown_code) >= 10:
|
||||||
|
col_pattern = crown_code[2:10]
|
||||||
|
if match_pattern(col_pattern, pattern):
|
||||||
|
match_count += 1
|
||||||
|
|
||||||
|
return match_count
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error querying coolbot_data: {e}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def match_collections_list_from_coolbot(expect_number: str, limit: int = 20) -> List[dict]:
|
||||||
|
"""获取匹配的藏品列表(从coolbot_data数据库)"""
|
||||||
|
if not expect_number or len(expect_number) != 10:
|
||||||
|
return []
|
||||||
|
|
||||||
|
# 固定前缀
|
||||||
|
if not expect_number.startswith('J0'):
|
||||||
|
return []
|
||||||
|
|
||||||
|
pattern = expect_number[2:] # 后8位
|
||||||
|
if not pattern:
|
||||||
|
return []
|
||||||
|
|
||||||
|
# 直接查询coolbot_data数据库
|
||||||
|
query = text("""
|
||||||
|
SELECT id, name, category, crown_code, price, post_title, post_url, author, post_crawled_at
|
||||||
|
FROM collections
|
||||||
|
WHERE crown_code IS NOT NULL
|
||||||
|
AND crown_code != ''
|
||||||
|
AND LENGTH(crown_code) >= 10
|
||||||
|
AND crown_code LIKE 'J0%'
|
||||||
|
""")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with coolbot_engine.connect() as conn:
|
||||||
|
result = conn.execute(query)
|
||||||
|
|
||||||
|
matched = []
|
||||||
|
for row in result:
|
||||||
|
crown_code = row[3]
|
||||||
|
if crown_code and len(crown_code) >= 10:
|
||||||
|
col_pattern = crown_code[2:10]
|
||||||
|
if match_pattern(col_pattern, pattern):
|
||||||
|
matched.append({
|
||||||
|
"id": row[0],
|
||||||
|
"name": row[1],
|
||||||
|
"category": row[2],
|
||||||
|
"crown_code": crown_code,
|
||||||
|
"price": float(row[4]) if row[4] else None,
|
||||||
|
"post_title": row[5],
|
||||||
|
"post_url": row[6],
|
||||||
|
"author": row[7],
|
||||||
|
"post_crawled_at": row[8].isoformat() if row[8] else None
|
||||||
|
})
|
||||||
|
if len(matched) >= limit:
|
||||||
|
break
|
||||||
|
|
||||||
|
return matched
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error querying coolbot_data: {e}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def match_pattern(col_number: str, pattern: str) -> bool:
|
def match_pattern(col_number: str, pattern: str) -> bool:
|
||||||
"""匹配号码特征模式"""
|
"""匹配号码特征模式"""
|
||||||
# X = 任意数字
|
# X = 任意数字
|
||||||
|
|
@ -502,7 +624,36 @@ def get_seek_match(
|
||||||
"cost_price": c.f05_40_cost_price,
|
"cost_price": c.f05_40_cost_price,
|
||||||
}
|
}
|
||||||
for c in matched
|
for c in matched
|
||||||
]
|
],
|
||||||
|
"network_matched_count": match_collections_count_from_coolbot(info.expect_number) if info.expect_number else 0,
|
||||||
|
"network_collections": match_collections_list_from_coolbot(info.expect_number, limit=20) if info.expect_number else []
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# 获取网络数据匹配列表
|
||||||
|
@router.get("/seek/network-match/{info_id}")
|
||||||
|
def get_network_match(
|
||||||
|
info_id: str,
|
||||||
|
limit: int = Query(20, ge=1, le=100),
|
||||||
|
db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
"""获取一尘数据库中匹配的藏品列表"""
|
||||||
|
info = db.query(Information).filter(
|
||||||
|
Information.id == info_id,
|
||||||
|
Information.info_type == "seek"
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if not info:
|
||||||
|
raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||||
|
|
||||||
|
if not info.expect_number:
|
||||||
|
return {"matched_count": 0, "collections": []}
|
||||||
|
|
||||||
|
matched = match_collections_list_from_coolbot(info.expect_number, limit=limit)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"matched_count": len(matched),
|
||||||
|
"collections": matched
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -558,8 +709,21 @@ def get_my_seeks(
|
||||||
collection_version=item.collection.f02_11_version if item.collection else None,
|
collection_version=item.collection.f02_11_version if item.collection else None,
|
||||||
collection_number=item.collection.f02_10_prefix_serial if item.collection else None,
|
collection_number=item.collection.f02_10_prefix_serial if item.collection else None,
|
||||||
matched_count=matched_count,
|
matched_count=matched_count,
|
||||||
|
network_matched_count=match_collections_count_from_coolbot(item.expect_number) if item.info_type == 'seek' and item.expect_number else 0,
|
||||||
))
|
))
|
||||||
|
|
||||||
|
# 获取总数并设置响应头
|
||||||
|
from fastapi import Response
|
||||||
|
total_query = db.query(Information).filter(Information.status == status)
|
||||||
|
if info_type:
|
||||||
|
total_query = total_query.filter(Information.info_type == info_type)
|
||||||
|
total_count = total_query.count()
|
||||||
|
total_pages = (total_count + page_size - 1) // page_size
|
||||||
|
|
||||||
|
# 设置响应头
|
||||||
|
response.headers['X-Total-Pages'] = str(total_pages)
|
||||||
|
response.headers['X-Total-Count'] = str(total_count)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
VERSION=1.2.49
|
VERSION=1.2.50
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<title>甲辰收藏 v1.2.49</title>
|
<title>甲辰收藏 v1.2.50</title>
|
||||||
|
|
||||||
<!-- Favicon -->
|
<!-- Favicon -->
|
||||||
<link rel="icon" type="image/png" href="/static/icons/favicon.png" />
|
<link rel="icon" type="image/png" href="/static/icons/favicon.png" />
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ export default function News() {
|
||||||
const [matchedStatus, setMatchedStatus] = useState({}) // 存储各寻号的匹配状态
|
const [matchedStatus, setMatchedStatus] = useState({}) // 存储各寻号的匹配状态
|
||||||
const [showMatchList, setShowMatchList] = useState(false)
|
const [showMatchList, setShowMatchList] = useState(false)
|
||||||
const [matchCollections, setMatchCollections] = useState([])
|
const [matchCollections, setMatchCollections] = useState([])
|
||||||
|
const [networkMatchCollections, setNetworkMatchCollections] = useState([])
|
||||||
|
const [showNetworkMatchList, setShowNetworkMatchList] = useState(false)
|
||||||
const [customModal, setCustomModal] = useState({show: false, title: '', content: ''})
|
const [customModal, setCustomModal] = useState({show: false, title: '', content: ''})
|
||||||
const [seekForm, setSeekForm] = useState({
|
const [seekForm, setSeekForm] = useState({
|
||||||
edition: '龙钞', type: '', category: '寻号', price: '', matchType: '模糊', features: '', content: '', title: '', contact: getUserPhone() || ''
|
edition: '龙钞', type: '', category: '寻号', price: '', matchType: '模糊', features: '', content: '', title: '', contact: getUserPhone() || ''
|
||||||
|
|
@ -41,6 +43,8 @@ export default function News() {
|
||||||
const [viewMode, setViewMode] = useState('all')
|
const [viewMode, setViewMode] = useState('all')
|
||||||
const [expandedItems, setExpandedItems] = useState({}) // 展开状态
|
const [expandedItems, setExpandedItems] = useState({}) // 展开状态
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [currentPage, setCurrentPage] = useState(1)
|
||||||
|
const [totalPages, setTotalPages] = useState(1)
|
||||||
|
|
||||||
const API_BASE = localStorage.getItem('API_BASE') || ''
|
const API_BASE = localStorage.getItem('API_BASE') || ''
|
||||||
const currentUser = localStorage.getItem('token') ? { id: 'logged_in' } : null
|
const currentUser = localStorage.getItem('token') ? { id: 'logged_in' } : null
|
||||||
|
|
@ -73,7 +77,10 @@ export default function News() {
|
||||||
const type = activeTab === 'seek' ? 'seek' : activeTab === 'deal' ? 'deal' : 'yichen'
|
const type = activeTab === 'seek' ? 'seek' : activeTab === 'deal' ? 'deal' : 'yichen'
|
||||||
// 始终传递token,以便获取准确的matched_count
|
// 始终传递token,以便获取准确的matched_count
|
||||||
const headers = token ? { Authorization: `Bearer ${token}` } : {}
|
const headers = token ? { Authorization: `Bearer ${token}` } : {}
|
||||||
const res = await fetch(`${API_BASE}/api/information/list?info_type=${type}`, { headers })
|
const res = await fetch(`${API_BASE}/api/information/list?info_type=${type}&page=${currentPage}&page_size=50`, { headers })
|
||||||
|
// 从响应头获取总页数
|
||||||
|
const total = res.headers.get('X-Total-Pages') || res.headers.get('x-total-pages')
|
||||||
|
if (total) setTotalPages(parseInt(total))
|
||||||
// 检查响应状态
|
// 检查响应状态
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
console.error('获取资讯列表失败:', res.status)
|
console.error('获取资讯列表失败:', res.status)
|
||||||
|
|
@ -147,10 +154,11 @@ export default function News() {
|
||||||
const token = localStorage.getItem('token')
|
const token = localStorage.getItem('token')
|
||||||
if (!token) { alert('请先登录'); return }
|
if (!token) { alert('请先登录'); return }
|
||||||
try {
|
try {
|
||||||
|
const phone = getUserPhone()
|
||||||
const res = await fetch(`${API_BASE}/api/information/seek/match-confirm`, {
|
const res = await fetch(`${API_BASE}/api/information/seek/match-confirm`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
|
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ info_id: infoId })
|
body: JSON.stringify({ info_id: infoId, contact: phone || '用户已同意' })
|
||||||
})
|
})
|
||||||
const data = await res.json()
|
const data = await res.json()
|
||||||
if (data.message === '匹配成功,已通知发布者') {
|
if (data.message === '匹配成功,已通知发布者') {
|
||||||
|
|
@ -188,7 +196,7 @@ export default function News() {
|
||||||
console.log('Matched user response:', res.status)
|
console.log('Matched user response:', res.status)
|
||||||
const data = await res.json()
|
const data = await res.json()
|
||||||
console.log('Matched user data:', data)
|
console.log('Matched user data:', data)
|
||||||
if (data.user_name) setCustomModal({show: true, title: '匹配者信息', content: `用户名: ${data.user_name}\n联系方式: ${data.matched_contact || '未提供'}`})
|
if (data.user_name) setCustomModal({show: true, title: '匹配者信息', content: `用户名: ${data.user_name}\n手机号: ${data.phone || '未提供'}\n\n免责声明及风险提示:所有用户信息仅作参考,交易请走正规平台,如产生经济损失与本站无关,后果自负。`})
|
||||||
else if (data.detail) alert(data.detail)
|
else if (data.detail) alert(data.detail)
|
||||||
} catch (e) { console.error(e) }
|
} catch (e) { console.error(e) }
|
||||||
}
|
}
|
||||||
|
|
@ -201,7 +209,7 @@ export default function News() {
|
||||||
console.log('Publisher response:', res.status)
|
console.log('Publisher response:', res.status)
|
||||||
const data = await res.json()
|
const data = await res.json()
|
||||||
console.log('Publisher data:', data)
|
console.log('Publisher data:', data)
|
||||||
if (data.user_name) setCustomModal({show: true, title: '发布者信息', content: `用户名: ${data.user_name}\n联系方式: ${data.contact || '未提供'}`})
|
if (data.user_name) setCustomModal({show: true, title: '发布者信息', content: `用户名: ${data.user_name}\n手机号: ${data.phone || '未提供'}\n\n免责声明及风险提示:所有用户信息仅作参考,交易请走正规平台,如产生经济损失与本站无关,后果自负。`})
|
||||||
else if (data.detail) alert(data.detail)
|
else if (data.detail) alert(data.detail)
|
||||||
} catch (e) { console.error(e) }
|
} catch (e) { console.error(e) }
|
||||||
}
|
}
|
||||||
|
|
@ -224,6 +232,20 @@ export default function News() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取网络数据匹配列表
|
||||||
|
const fetchNetworkMatchCollections = async (infoId) => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${API_BASE}/api/information/seek/network-match/${infoId}`)
|
||||||
|
const data = await res.json()
|
||||||
|
console.log('网络数据匹配结果:', data)
|
||||||
|
setNetworkMatchCollections(data.collections || [])
|
||||||
|
setShowNetworkMatchList(true)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('获取网络匹配藏品失败:', e)
|
||||||
|
alert('获取网络匹配藏品失败: ' + e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取当前用户ID
|
// 获取当前用户ID
|
||||||
const currentUserId = getStoredUserId()
|
const currentUserId = getStoredUserId()
|
||||||
|
|
||||||
|
|
@ -527,8 +549,16 @@ export default function News() {
|
||||||
style={{ color: '#10b981', fontSize: '13px', fontWeight: 'bold', cursor: 'pointer' }}
|
style={{ color: '#10b981', fontSize: '13px', fontWeight: 'bold', cursor: 'pointer' }}
|
||||||
onClick={() => fetchMatchCollections(item.id)}
|
onClick={() => fetchMatchCollections(item.id)}
|
||||||
>
|
>
|
||||||
配号结果: {item.matched_count || 0}条藏品匹配成功
|
自有{item.matched_count || 0}条藏品匹配成功
|
||||||
</span>
|
</span>
|
||||||
|
{item.network_matched_count !== undefined && (
|
||||||
|
<span
|
||||||
|
style={{ color: '#3b82f6', fontSize: '13px', fontWeight: 'bold', cursor: 'pointer', marginLeft: '12px' }}
|
||||||
|
onClick={() => fetchNetworkMatchCollections(item.id)}
|
||||||
|
>
|
||||||
|
网络数据{item.network_matched_count}条匹配成功
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* 正文 - 默认收起,点击展开 */}
|
{/* 正文 - 默认收起,点击展开 */}
|
||||||
|
|
@ -615,23 +645,24 @@ export default function News() {
|
||||||
<div style={{ display: 'flex', gap: '8px', marginTop: '8px' }}>
|
<div style={{ display: 'flex', gap: '8px', marginTop: '8px' }}>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (item.is_matched === 'matched') return
|
||||||
if (item.matched_count > 0) {
|
if (item.matched_count > 0) {
|
||||||
matchAndContact(item.id)
|
matchAndContact(item.id)
|
||||||
} else {
|
} else {
|
||||||
setCustomModal({show: true, title: '提示', content: '暂无匹配藏品,无法匹配'})
|
setCustomModal({show: true, title: '提示', content: '暂无匹配藏品,无法匹配'})
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled={item.matched_count === 0}
|
disabled={item.matched_count === 0 || item.is_matched === 'matched'}
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
padding: '8px 12px',
|
padding: '8px 12px',
|
||||||
borderRadius: '6px',
|
borderRadius: '6px',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
background: item.matched_count > 0 ? '#3b82f6' : '#4b5563',
|
background: (item.matched_count > 0 && item.is_matched !== 'matched') ? '#3b82f6' : '#4b5563',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
cursor: item.matched_count > 0 ? 'pointer' : 'not-allowed',
|
cursor: (item.matched_count > 0 && item.is_matched !== 'matched') ? 'pointer' : 'not-allowed',
|
||||||
opacity: item.matched_count > 0 ? 1 : 0.5
|
opacity: (item.matched_count > 0 && item.is_matched !== 'matched') ? 1 : 0.5
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
匹配并联系藏友
|
匹配并联系藏友
|
||||||
|
|
@ -753,6 +784,74 @@ export default function News() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* 网络数据匹配藏品列表弹窗 */}
|
||||||
|
{showNetworkMatchList && (
|
||||||
|
<div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.8)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||||
|
<div style={{ background: '#1e293b', borderRadius: '12px', padding: '20px', width: '90%', maxHeight: '80vh', overflow: 'auto' }}>
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '16px' }}>
|
||||||
|
<h3 style={{ color: '#fff', margin: 0 }}>匹配藏品清单(网络数据)</h3>
|
||||||
|
<button onClick={() => setShowNetworkMatchList(false)} style={{ background: 'transparent', border: 'none', color: '#94a3b8', fontSize: '20px', cursor: 'pointer' }}>×</button>
|
||||||
|
</div>
|
||||||
|
{networkMatchCollections.length === 0 ? (
|
||||||
|
<div style={{ color: '#94a3b8', textAlign: 'center', padding: '20px' }}>暂无匹配藏品</div>
|
||||||
|
) : (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
||||||
|
{networkMatchCollections.map(c => (
|
||||||
|
<div
|
||||||
|
key={c.id}
|
||||||
|
style={{ background: '#0f172a', borderRadius: '8px', padding: '12px', cursor: 'pointer' }}
|
||||||
|
onClick={() => {
|
||||||
|
if (c.post_url) {
|
||||||
|
window.open(c.post_url, '_blank')
|
||||||
|
}
|
||||||
|
setShowNetworkMatchList(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ color: '#e2e8f0', fontSize: '13px' }}>
|
||||||
|
<span style={{ color: '#94a3b8' }}>名称: </span>{c.name || '-'}
|
||||||
|
</div>
|
||||||
|
<div style={{ color: '#e2e8f0', fontSize: '13px', marginTop: '4px' }}>
|
||||||
|
<span style={{ color: '#94a3b8' }}>冠字号: </span>{c.crown_code}
|
||||||
|
</div>
|
||||||
|
{c.price && (
|
||||||
|
<div style={{ color: '#e2e8f0', fontSize: '13px', marginTop: '4px' }}>
|
||||||
|
<span style={{ color: '#94a3b8' }}>价格: </span>¥{c.price}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div style={{ color: '#3b82f6', fontSize: '12px', marginTop: '6px' }}>
|
||||||
|
点击查看原帖 →
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 分页组件 */}
|
||||||
|
{totalPages > 1 && (
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '8px', padding: '16px', marginTop: '8px' }}>
|
||||||
|
<button
|
||||||
|
onClick={() => { if (currentPage > 1) { setCurrentPage(currentPage - 1); fetchInfoList() } }}
|
||||||
|
disabled={currentPage === 1}
|
||||||
|
style={{ padding: '8px 16px', borderRadius: '6px', border: 'none', background: currentPage === 1 ? '#374151' : '#3b82f6', color: currentPage === 1 ? '#6b7280' : '#fff', cursor: currentPage === 1 ? 'not-allowed' : 'pointer', fontSize: '13px' }}
|
||||||
|
>
|
||||||
|
上一页
|
||||||
|
</button>
|
||||||
|
<span style={{ color: '#94a3b8', fontSize: '13px' }}>
|
||||||
|
第 {currentPage} / {totalPages} 页
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
onClick={() => { if (currentPage < totalPages) { setCurrentPage(currentPage + 1); fetchInfoList() } }}
|
||||||
|
disabled={currentPage >= totalPages}
|
||||||
|
style={{ padding: '8px 16px', borderRadius: '6px', border: 'none', background: currentPage >= totalPages ? '#374151' : '#3b82f6', color: currentPage >= totalPages ? '#6b7280' : '#fff', cursor: currentPage >= totalPages ? 'not-allowed' : 'pointer', fontSize: '13px' }}
|
||||||
|
>
|
||||||
|
下一页
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 我的寻号弹窗 */}
|
{/* 我的寻号弹窗 */}
|
||||||
{showMySeeks && (
|
{showMySeeks && (
|
||||||
<div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.8)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
<div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.8)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue