From aec6ef7c79befac42ae4be995f39b681a454bf9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B2=E8=BE=B0=E7=94=9F=E4=BA=A7?= Date: Tue, 14 Apr 2026 23:47:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A1=A8=E6=8B=86=E5=88=86seek=5Finfo?= =?UTF-8?q?=E5=92=8Cdeal=5Finfo=EF=BC=8C=E4=BC=98=E5=8C=96=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=92=8C=E5=88=86=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/main.py | 7 + backend/app/models/deal_info.py | 54 +++++++ backend/app/models/seek_info.py | 39 +++++ backend/app/routers/deal.py | 243 +++++++++++++++++++++++++++++ backend/app/routers/information.py | 2 +- backend/app/routers/seek.py | 184 ++++++++++++++++++++++ frontend/src/pages/List.jsx | 6 +- frontend/src/pages/News.jsx | 91 +++++------ 8 files changed, 574 insertions(+), 52 deletions(-) create mode 100644 backend/app/models/deal_info.py create mode 100644 backend/app/models/seek_info.py create mode 100644 backend/app/routers/deal.py create mode 100644 backend/app/routers/seek.py diff --git a/backend/app/main.py b/backend/app/main.py index 73ade76..0587121 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -17,6 +17,8 @@ from app.routers import ocr as ocr_router from app.routers import users as users_router from app.routers import information as information_router from app.routers import yichens as yichens_router +from app.routers import seek as seek_router +from app.routers import deal as deal_router # 版本信息 - 从 config/VERSION 文件读取 def get_version(): @@ -84,6 +86,8 @@ app.include_router(users_router.router) # 当前用户接口 app.include_router(users_router.admin_router) # 管理员用户管理 app.include_router(information_router.router) app.include_router(yichens_router.router) # 一尘看板 +app.include_router(seek_router.router) # 寻配号 +app.include_router(deal_router.router) # 成交行情 @app.get("/") @@ -106,3 +110,6 @@ if __name__ == "__main__": import uvicorn port = int(os.getenv("PORT", "3000")) uvicorn.run(app, host="0.0.0.0", port=port) + +from app.routers import seek as seek_router +from app.routers import deal as deal_router diff --git a/backend/app/models/deal_info.py b/backend/app/models/deal_info.py new file mode 100644 index 0000000..82e3206 --- /dev/null +++ b/backend/app/models/deal_info.py @@ -0,0 +1,54 @@ +from sqlalchemy import Column, String, Text, Float, Date, Boolean, Integer, DateTime +from sqlalchemy.sql import func +from app.core.database import Base +import uuid + +def generate_uuid(): + return str(uuid.uuid4()) + +class DealInfo(Base): + __tablename__ = "deal_info" + + id = Column(String(36), primary_key=True, default=generate_uuid) + user_id = Column(String(36), nullable=True, index=True) + + # 标题和内容 + title = Column(String(255), nullable=False) + content = Column(Text, nullable=True) + + # 成交信息 + deal_price = Column(Float, nullable=True) # 成交价格 + deal_date = Column(Date, nullable=True) # 成交日期 + deal_no = Column(String(20), nullable=True, index=True) # 行情编号(从A000001开始递增) + + # 包装和分类 + packaging = Column(String(50), nullable=True) # 包装(标百/标十/单张) + category = Column(String(100), nullable=True) # 分类 + + # 评级相关 + is_graded = Column(Boolean, default=False) # 是否评级 + grading_company = Column(String(100), nullable=True) # 评级机构 + grading_score = Column(String(50), nullable=True) # 评级分数 + + # 号码特征 + tail_number = Column(String(10), nullable=True) # 尾号 + size_type = Column(String(20), nullable=True) # 大小号 + + # 版别 + version = Column(String(50), nullable=True) # 版别 + + # 交易信息 + platform = Column(String(50), nullable=True) # 成交平台 + seller = Column(String(100), nullable=True) # 出售者 + buyer = Column(String(100), nullable=True) # 购买者 + + # 状态 + status = Column(String(20), default="active") + + # 统计 + view_count = Column(Integer, default=0) + contact_count = Column(Integer, default=0) + + # 时间 + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), onupdate=func.now()) \ No newline at end of file diff --git a/backend/app/models/seek_info.py b/backend/app/models/seek_info.py new file mode 100644 index 0000000..eb3fd6c --- /dev/null +++ b/backend/app/models/seek_info.py @@ -0,0 +1,39 @@ +from sqlalchemy import Column, String, Text, Float, Date, Boolean, Integer, DateTime +from sqlalchemy.sql import func +from app.core.database import Base +import uuid + +def generate_uuid(): + return str(uuid.uuid4()) + +class SeekInfo(Base): + __tablename__ = "seek_info" + + id = Column(String(36), primary_key=True, default=generate_uuid) + user_id = Column(String(36), nullable=False, index=True) + + # 标题和内容 + title = Column(String(255), nullable=False) + content = Column(Text, nullable=True) + + # 期望条件(求购条件) + expect_category = Column(String(100), nullable=True) # 期望类别 + expect_version = Column(String(100), nullable=True) # 期望版别 + expect_packaging = Column(String(100), nullable=True) # 期望包装 + expect_number = Column(String(50), nullable=True) # 期望号码 + expect_price_min = Column(Float, nullable=True) # 期望最低价 + expect_price_max = Column(Float, nullable=True) # 期望最高价 + + # 匹配状态 + status = Column(String(20), default="active") # active/closed/expired + is_matched = Column(String(10), default="false") # 是否已匹配 + matched_user_id = Column(String(36), nullable=True) # 匹配的用户ID + matched_contact = Column(String(100), nullable=True) # 匹配的联系方式 + + # 统计 + view_count = Column(Integer, default=0) + contact_count = Column(Integer, default=0) + + # 时间 + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), onupdate=func.now()) \ No newline at end of file diff --git a/backend/app/routers/deal.py b/backend/app/routers/deal.py new file mode 100644 index 0000000..29bcb3d --- /dev/null +++ b/backend/app/routers/deal.py @@ -0,0 +1,243 @@ +from fastapi import APIRouter, Depends, Query, HTTPException +from sqlalchemy.orm import Session +from pydantic import BaseModel +from typing import Optional +from datetime import datetime, date +from app.core.database import get_db +from app.core.auth import get_current_user +from app.models.deal_info import DealInfo + +router = APIRouter(prefix="/api/deal", tags=["成交行情"]) + +# ============ Schema ============ +class DealInfoCreate(BaseModel): + title: str + content: Optional[str] = None + deal_price: Optional[float] = None + deal_date: Optional[str] = None # YYYY-MM-DD + packaging: Optional[str] = None + category: Optional[str] = None + is_graded: Optional[bool] = False + grading_company: Optional[str] = None + grading_score: Optional[str] = None + tail_number: Optional[str] = None + size_type: Optional[str] = None + version: Optional[str] = None + platform: Optional[str] = None + seller: Optional[str] = None + buyer: Optional[str] = None + +class DealInfoUpdate(BaseModel): + title: Optional[str] = None + content: Optional[str] = None + deal_price: Optional[float] = None + deal_date: Optional[str] = None + packaging: Optional[str] = None + category: Optional[str] = None + is_graded: Optional[bool] = None + grading_company: Optional[str] = None + grading_score: Optional[str] = None + tail_number: Optional[str] = None + size_type: Optional[str] = None + version: Optional[str] = None + platform: Optional[str] = None + seller: Optional[str] = None + buyer: Optional[str] = None + status: Optional[str] = None + +class DealInfoResponse(BaseModel): + id: str + user_id: Optional[str] + title: str + content: Optional[str] + deal_price: Optional[float] + deal_date: Optional[date] + deal_no: Optional[str] + packaging: Optional[str] + category: Optional[str] + is_graded: Optional[bool] + grading_company: Optional[str] + grading_score: Optional[str] + tail_number: Optional[str] + size_type: Optional[str] + version: Optional[str] + platform: Optional[str] + seller: Optional[str] + buyer: Optional[str] + status: str + view_count: int + contact_count: int + created_at: Optional[datetime] + updated_at: Optional[datetime] + + class Config: + from_attributes = True + +# 生成行情编号 +def generate_deal_no(db: Session): + """生成行情编号,从A000001开始递增""" + last = db.query(DealInfo).order_by(DealInfo.deal_no.desc()).first() + if last and last.deal_no: + # 例如 A000001 -> 2 -> A000002 + num = int(last.deal_no[1:]) + 1 + return f"A{num:06d}" + return "A000001" + +# ============ API ============ +@router.get("/list", response_model=list[DealInfoResponse]) +def get_deal_list( + status: str = Query("active"), + deal_date: Optional[str] = Query(None), + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=500), + current_user: Optional = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取成交行情列表""" + query = db.query(DealInfo).filter(DealInfo.status == status) + + # 成交日期过滤 + if deal_date: + query = query.filter(DealInfo.deal_date == deal_date) + + # 排序:优先成交日期倒序,同日按编号倒序 + query = query.order_by(DealInfo.deal_date.desc().nullslast(), DealInfo.deal_no.desc().nullslast()) + + # 分页 + offset = (page - 1) * page_size + items = query.offset(offset).limit(page_size).all() + + return items + +@router.get("/stats") +def get_deal_stats( + db: Session = Depends(get_db) +): + """获取成交行情统计""" + total = db.query(DealInfo).filter(DealInfo.status == "active").count() + + # 按日期统计 + from sqlalchemy import func + date_stats = db.query( + DealInfo.deal_date, + func.count(DealInfo.id).label('count') + ).filter( + DealInfo.status == "active", + DealInfo.deal_date.isnot(None) + ).group_by(DealInfo.deal_date).order_by(DealInfo.deal_date.desc()).limit(10).all() + + return { + "total": total, + "by_date": [{"date": str(d.deal_date), "count": d.count} for d in date_stats] + } + +@router.post("", response_model=DealInfoResponse) +def create_deal( + data: DealInfoCreate, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """创建成交行情""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + # 生成行情编号 + deal_no = generate_deal_no(db) + + # 解析日期 + deal_date = None + if data.deal_date: + try: + deal_date = datetime.strptime(data.deal_date, "%Y-%m-%d").date() + except: + pass + + deal = DealInfo( + user_id=current_user.f99_90_id if current_user else None, + title=data.title, + content=data.content, + deal_price=data.deal_price, + deal_date=deal_date, + deal_no=deal_no, + packaging=data.packaging, + category=data.category, + is_graded=data.is_graded or False, + grading_company=data.grading_company, + grading_score=data.grading_score, + tail_number=data.tail_number, + size_type=data.size_type, + version=data.version, + platform=data.platform, + seller=data.seller, + buyer=data.buyer, + status="active" + ) + db.add(deal) + db.commit() + db.refresh(deal) + return deal + +@router.get("/{deal_id}", response_model=DealInfoResponse) +def get_deal( + deal_id: str, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取成交行情详情""" + deal = db.query(DealInfo).filter(DealInfo.id == deal_id).first() + if not deal: + raise HTTPException(status_code=404, detail="成交行情不存在") + + # 增加浏览数 + deal.view_count += 1 + db.commit() + + return deal + +@router.put("/{deal_id}", response_model=DealInfoResponse) +def update_deal( + deal_id: str, + data: DealInfoUpdate, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """更新成交行情""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + deal = db.query(DealInfo).filter(DealInfo.id == deal_id).first() + if not deal: + raise HTTPException(status_code=404, detail="成交行情不存在") + + # 处理日期 + if data.deal_date: + try: + data.deal_date = datetime.strptime(data.deal_date, "%Y-%m-%d").date() + except: + data.deal_date = None + + for key, value in data.model_dump(exclude_unset=True).items(): + setattr(deal, key, value) + + db.commit() + db.refresh(deal) + return deal + +@router.delete("/{deal_id}") +def delete_deal( + deal_id: str, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """删除成交行情""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + deal = db.query(DealInfo).filter(DealInfo.id == deal_id).first() + if not deal: + raise HTTPException(status_code=404, detail="成交行情不存在") + + deal.status = "deleted" + db.commit() + + return {"message": "删除成功"} \ No newline at end of file diff --git a/backend/app/routers/information.py b/backend/app/routers/information.py index 5aa7503..e572a95 100644 --- a/backend/app/routers/information.py +++ b/backend/app/routers/information.py @@ -134,7 +134,7 @@ def get_information_list( query = query.filter(Information.deal_date == deal_date_obj) # 按创建时间倒序 - query = query.order_by(Information.created_at.desc()) + query = query.order_by(Information.deal_date.desc().nullslast(), Information.deal_no.desc().nullslast()) # 分页 offset = (page - 1) * page_size diff --git a/backend/app/routers/seek.py b/backend/app/routers/seek.py new file mode 100644 index 0000000..77c5236 --- /dev/null +++ b/backend/app/routers/seek.py @@ -0,0 +1,184 @@ +from fastapi import APIRouter, Depends, Query, HTTPException +from sqlalchemy.orm import Session +from pydantic import BaseModel +from typing import Optional +from datetime import datetime +from app.core.database import get_db +from app.core.auth import get_current_user +from app.models.seek_info import SeekInfo + +router = APIRouter(prefix="/api/seek", tags=["寻配号"]) + +# ============ Schema ============ +class SeekInfoCreate(BaseModel): + title: str + content: Optional[str] = None + expect_category: Optional[str] = None + expect_version: Optional[str] = None + expect_packaging: Optional[str] = None + expect_number: Optional[str] = None + expect_price_min: Optional[float] = None + expect_price_max: Optional[float] = None + +class SeekInfoUpdate(BaseModel): + title: Optional[str] = None + content: Optional[str] = None + expect_category: Optional[str] = None + expect_version: Optional[str] = None + expect_packaging: Optional[str] = None + expect_number: Optional[str] = None + expect_price_min: Optional[float] = None + expect_price_max: Optional[float] = None + status: Optional[str] = None + +class SeekInfoResponse(BaseModel): + id: str + user_id: str + title: str + content: Optional[str] + expect_category: Optional[str] + expect_version: Optional[str] + expect_packaging: Optional[str] + expect_number: Optional[str] + expect_price_min: Optional[float] + expect_price_max: Optional[float] + status: str + is_matched: Optional[str] + matched_user_id: Optional[str] + matched_contact: Optional[str] + view_count: int + contact_count: int + created_at: Optional[datetime] + updated_at: Optional[datetime] + + class Config: + from_attributes = True + +# ============ API ============ +@router.get("/list", response_model=list[SeekInfoResponse]) +def get_seek_list( + status: str = Query("active"), + page: int = Query(1, ge=1), + page_size: int = Query(20, ge=1, le=100), + current_user: Optional = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取寻配号列表""" + query = db.query(SeekInfo).filter(SeekInfo.status == status) + + # 排序 + query = query.order_by(SeekInfo.created_at.desc()) + + # 分页 + offset = (page - 1) * page_size + items = query.offset(offset).limit(page_size).all() + + return items + +@router.get("/stats") +def get_seek_stats( + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取寻配号统计""" + total = db.query(SeekInfo).filter(SeekInfo.status == "active").count() + matched = db.query(SeekInfo).filter(SeekInfo.is_matched == "true").count() + + return { + "total": total, + "matched": matched, + "unmatched": total - matched + } + +@router.post("", response_model=SeekInfoResponse) +def create_seek( + data: SeekInfoCreate, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """创建寻配号""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + seek = SeekInfo( + user_id=current_user.f99_90_id, + title=data.title, + content=data.content, + expect_category=data.expect_category, + expect_version=data.expect_version, + expect_packaging=data.expect_packaging, + expect_number=data.expect_number, + expect_price_min=data.expect_price_min, + expect_price_max=data.expect_price_max, + status="active" + ) + db.add(seek) + db.commit() + db.refresh(seek) + return seek + +@router.get("/{seek_id}", response_model=SeekInfoResponse) +def get_seek( + seek_id: str, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取寻配号详情""" + seek = db.query(SeekInfo).filter(SeekInfo.id == seek_id).first() + if not seek: + raise HTTPException(status_code=404, detail="寻配号不存在") + + # 增加浏览数 + seek.view_count += 1 + db.commit() + + return seek + +@router.put("/{seek_id}", response_model=SeekInfoResponse) +def update_seek( + seek_id: str, + data: SeekInfoUpdate, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """更新寻配号""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + seek = db.query(SeekInfo).filter( + SeekInfo.id == seek_id, + SeekInfo.user_id == current_user.f99_90_id + ).first() + + if not seek: + raise HTTPException(status_code=404, detail="寻配号不存在") + + for key, value in data.model_dump(exclude_unset=True).items(): + setattr(seek, key, value) + + db.commit() + db.refresh(seek) + return seek + +@router.delete("/{seek_id}") +def delete_seek( + seek_id: str, + current_user = Depends(get_current_user), + db: Session = Depends(get_db) +): + """删除寻配号""" + if not current_user: + raise HTTPException(status_code=401, detail="请先登录") + + seek = db.query(SeekInfo).filter( + SeekInfo.id == seek_id, + SeekInfo.user_id == current_user.f99_90_id + ).first() + + if not seek: + raise HTTPException(status_code=404, detail="寻配号不存在") + + seek.status = "deleted" + db.commit() + + return {"message": "删除成功"} \ No newline at end of file diff --git a/frontend/src/pages/List.jsx b/frontend/src/pages/List.jsx index d8f0030..a7deae7 100644 --- a/frontend/src/pages/List.jsx +++ b/frontend/src/pages/List.jsx @@ -79,7 +79,7 @@ export default function List() { } try { const user = JSON.parse(userStr) - const res = await fetch(`${API_BASE}/api/information/list?info_type=deal&page_size=500`, { + const res = await fetch(`${API_BASE}/api/deal/list?page_size=500`, { headers: { 'Authorization': 'Bearer ' + token } }) const data = await res.json() @@ -758,7 +758,7 @@ function DealListItem({ deal, onRefresh }) { const saveEdit = async () => { const token = localStorage.getItem('token') try { - await fetch(`${API_BASE}/api/information/${deal.id}`, { + await fetch(`${API_BASE}/api/deal/${deal.id}`, { method: 'PUT', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(editForm) @@ -772,7 +772,7 @@ function DealListItem({ deal, onRefresh }) { if (!confirm('确定删除这条行情?')) return const token = localStorage.getItem('token') try { - await fetch(`${API_BASE}/api/information/${deal.id}`, { + await fetch(`${API_BASE}/api/deal/${deal.id}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } }) diff --git a/frontend/src/pages/News.jsx b/frontend/src/pages/News.jsx index 6fc2f88..c77c20f 100644 --- a/frontend/src/pages/News.jsx +++ b/frontend/src/pages/News.jsx @@ -79,16 +79,21 @@ export default function News() { const headers = token ? { Authorization: `Bearer ${token}` } : {} // 构建URL参数 - let url = `${API_BASE}/api/information/list?info_type=${type}` + // 使用新的独立API(seek和deal已拆分) + let url = activeTab === 'yichen' + ? `${API_BASE}/api/information/list?info_type=${activeTab}` + : activeTab === 'seek' + ? `${API_BASE}/api/seek/list` + : `${API_BASE}/api/deal/list` - // 成交行情tab,获取500条数据 + // 成交行情和寻配号每页500条 if (activeTab === 'deal') { - url += `&page_size=500` + url += (url.includes('?') ? '&' : '?') + 'page_size=500' if (dealDate) { - url += `&deal_date=${dealDate}` + url += '&deal_date=' + dealDate } - } else { - url += `&page=${currentPage}&page_size=50` + } else if (activeTab === 'seek') { + url += (url.includes("?") ? "&" : "?") + "page=" + currentPage + "&page_size=500" } const res = await fetch(url, { headers }) @@ -107,25 +112,17 @@ export default function News() { // 成交行情按分类排序 let sortedData = data || [] - if (activeTab === 'deal') { - const categoryOrder = ['带4号', '带7号', '永恒号', '天马号', '天马王', '金山号', '金山王', '钻石号', '朦胧号', '朦胧王', '金马号', '金马王', '倒置号', '圆圆号'] - // 标准化分类名称(通货->带4号,无4->带7号) - const normalizeCat = (c) => { - if (c === '通货') return '带4号' - if (c === '无4') return '带7号' - return c - } + if (activeTab === 'deal' || activeTab === 'seek') { + // 优先按日期倒序,同日按编号倒序 sortedData = [...(data || [])].sort((a, b) => { - const contentA = a.content || '' - const contentB = b.content || '' - const catA = normalizeCat(contentA.match(/分类:\s*(.+?)(?:\n|$)/)?.[1]?.trim() || a.category || '') - const catB = normalizeCat(contentB.match(/分类:\s*(.+?)(?:\n|$)/)?.[1]?.trim() || b.category || '') - const idxA = categoryOrder.indexOf(catA) - const idxB = categoryOrder.indexOf(catB) - return (idxA === -1 ? 999 : idxA) - (idxB === -1 ? 999 : idxB) + const dateA = a.deal_date || a.created_at?.split('T')[0] || "" + const dateB = b.deal_date || b.created_at?.split('T')[0] || "" + if (dateA !== dateB) return dateB.localeCompare(dateA) + const noA = a.deal_no || "" + const noB = b.deal_no || "" + return noB.localeCompare(noA) }) } - setInfoList(sortedData) } catch (e) { console.error(e) @@ -293,12 +290,12 @@ export default function News() { const token = localStorage.getItem('token') if (!token) { alert('请先登录'); return } try { - const res = await fetch(`${API_BASE}/api/information/my/list`, { + const res = await fetch(`${API_BASE}/api/seek/list`, { headers: { Authorization: `Bearer ${token}` } }) const data = await res.json() - // 过滤出寻号类型的并筛选当前用户 - const seeks = Array.isArray(data) ? data.filter(item => item.info_type === 'seek' && item.user_id === currentUserId) : [] + // 筛选当前用户 + const seeks = Array.isArray(data) ? data.filter(item => item.user_id === currentUserId) : [] setMySeekList(seeks) setInfoList(seeks) // 在主列表显示 } catch (e) { console.error(e) } @@ -309,7 +306,7 @@ export default function News() { const token = localStorage.getItem('token') if (!token) { alert('请先登录'); return } try { - const res = await fetch(`${API_BASE}/api/information/list?info_type=seek`, { + const res = await fetch(`${API_BASE}/api/seek/list`, { headers: { Authorization: `Bearer ${token}` } }) const data = await res.json() @@ -707,28 +704,26 @@ export default function News() { else if (serial.startsWith('J3')) version = '蛇钞' return ( -
- {/* 第一行:成交日期 | 版别 | 包装 | 分类 | 价格 */} -
-
- {dealDate} - | - {version} - | - {packaging} - | - {category} -
-
¥{item.deal_price?.toLocaleString()}
+
+ {/* 标题行:冠字号 + 价格 */} +
+ {serial} + ¥{item.deal_price?.toLocaleString()} + {item.deal_no}
- {/* 第二行:冠字号 | 评级机构 | 分数 | 平台 */} -
- {serial} - | - {gradingCompany && <>{gradingCompany}|} - {grade} - | - {platform} + {/* 信息行:版别 | 包装 | 分类 | 评级 | 分数 | 平台 */} +
+ {version} + | + {packaging} + | + {category} + {gradingCompany && <>|{gradingCompany}} + {grade && <>|{grade}} + | + {platform} + | + {dealDate}
) @@ -1085,7 +1080,7 @@ export default function News() { )} {/* 分页组件 */} - {totalPages > 1 && ( + {infoList.length > 0 && (