Compare commits
4 Commits
ae87b10fe0
...
0b56cd7891
| Author | SHA1 | Date |
|---|---|---|
|
|
0b56cd7891 | |
|
|
7100f2d40e | |
|
|
41b3353613 | |
|
|
e6a0b4fb34 |
|
|
@ -636,183 +636,183 @@ def delete_information(
|
|||
|
||||
|
||||
# 寻配号 - 自动匹配推荐藏品
|
||||
@router.get("/seek/match")
|
||||
def get_seek_match(
|
||||
info_id: str,
|
||||
current_user: Optional[User] = Depends(get_current_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取符合条件的我的藏品推荐"""
|
||||
if not current_user:
|
||||
raise HTTPException(status_code=401, detail="请先登录")
|
||||
|
||||
# DEPRECATED (use /api/seek/*): @router.get("/seek/match")
|
||||
# DEPRECATED: def get_seek_match(
|
||||
# DEPRECATED: info_id: str,
|
||||
# DEPRECATED: current_user: Optional[User] = Depends(get_current_user),
|
||||
# DEPRECATED: db: Session = Depends(get_db)
|
||||
# DEPRECATED: ):
|
||||
# DEPRECATED: """获取符合条件的我的藏品推荐"""
|
||||
# DEPRECATED: if not current_user:
|
||||
# DEPRECATED: raise HTTPException(status_code=401, detail="请先登录")
|
||||
# DEPRECATED:
|
||||
# 先查 information 表
|
||||
info = db.query(Information).filter(
|
||||
Information.id == info_id,
|
||||
Information.info_type == "seek"
|
||||
).first()
|
||||
|
||||
# DEPRECATED: info = db.query(Information).filter(
|
||||
# DEPRECATED: Information.id == info_id,
|
||||
# DEPRECATED: Information.info_type == "seek"
|
||||
# DEPRECATED: ).first()
|
||||
# DEPRECATED:
|
||||
# 如果 information 表没有,尝试 seek_info 表
|
||||
if not info:
|
||||
from app.models.seek_info import SeekInfo
|
||||
info = db.query(SeekInfo).filter(SeekInfo.id == info_id).first()
|
||||
|
||||
if not info:
|
||||
raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
|
||||
# DEPRECATED: if not info:
|
||||
# DEPRECATED: from app.models.seek_info import SeekInfo
|
||||
# DEPRECATED: info = db.query(SeekInfo).filter(SeekInfo.id == info_id).first()
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: if not info:
|
||||
# DEPRECATED: raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
# DEPRECATED:
|
||||
# 更新用户配号(寻号)次数
|
||||
current_user.f99_96_search_count = (current_user.f99_96_search_count or 0) + 1
|
||||
db.commit()
|
||||
|
||||
# DEPRECATED: current_user.f99_96_search_count = (current_user.f99_96_search_count or 0) + 1
|
||||
# DEPRECATED: db.commit()
|
||||
# DEPRECATED:
|
||||
# 获取用户所有藏品
|
||||
collections = db.query(Collection).filter(
|
||||
Collection.f99_91_user_id == current_user.f99_90_id,
|
||||
Collection.f01_04_status == "in_collection"
|
||||
).all()
|
||||
|
||||
# DEPRECATED: collections = db.query(Collection).filter(
|
||||
# DEPRECATED: Collection.f99_91_user_id == current_user.f99_90_id,
|
||||
# DEPRECATED: Collection.f01_04_status == "in_collection"
|
||||
# DEPRECATED: ).all()
|
||||
# DEPRECATED:
|
||||
# 去掉版别筛选,因为藏品分类和发布需求的版别不同
|
||||
# if info.expect_category:
|
||||
# collections = [c for c in collections if c.f01_03_category == info.expect_category]
|
||||
|
||||
# DEPRECATED:
|
||||
# 按号码特征模式匹配
|
||||
matched = []
|
||||
if info.expect_number and len(info.expect_number) == 10:
|
||||
pattern = info.expect_number[2:] # 后8位
|
||||
for c in collections:
|
||||
number = c.f02_10_prefix_serial or ''
|
||||
# DEPRECATED: matched = []
|
||||
# DEPRECATED: if info.expect_number and len(info.expect_number) == 10:
|
||||
# DEPRECATED: pattern = info.expect_number[2:] # 后8位
|
||||
# DEPRECATED: for c in collections:
|
||||
# DEPRECATED: number = c.f02_10_prefix_serial or ''
|
||||
# 去掉J0前缀后取前8位
|
||||
if len(number) >= 10 and number.startswith('J0'):
|
||||
col_pattern = number[2:10] # 取J0后面的8位
|
||||
if match_pattern(col_pattern, pattern):
|
||||
matched.append(c)
|
||||
elif len(number) >= 8:
|
||||
col_pattern = number[:8] # 取前8位
|
||||
if match_pattern(col_pattern, pattern):
|
||||
matched.append(c)
|
||||
else:
|
||||
matched = collections
|
||||
|
||||
return {
|
||||
"info_id": info_id,
|
||||
"matched_count": len(matched),
|
||||
"collections": [
|
||||
{
|
||||
"id": c.f99_90_id,
|
||||
"code": c.f01_02_code or '',
|
||||
"name": c.f01_01_name,
|
||||
"number": c.f02_10_prefix_serial,
|
||||
"status": c.f01_04_status,
|
||||
"category": c.f01_03_category,
|
||||
"version": c.f02_11_version,
|
||||
"packaging": c.f02_12_packaging,
|
||||
"cost_price": c.f05_40_cost_price,
|
||||
}
|
||||
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 []
|
||||
}
|
||||
|
||||
|
||||
# DEPRECATED: if len(number) >= 10 and number.startswith('J0'):
|
||||
# DEPRECATED: col_pattern = number[2:10] # 取J0后面的8位
|
||||
# DEPRECATED: if match_pattern(col_pattern, pattern):
|
||||
# DEPRECATED: matched.append(c)
|
||||
# DEPRECATED: elif len(number) >= 8:
|
||||
# DEPRECATED: col_pattern = number[:8] # 取前8位
|
||||
# DEPRECATED: if match_pattern(col_pattern, pattern):
|
||||
# DEPRECATED: matched.append(c)
|
||||
# DEPRECATED: else:
|
||||
# DEPRECATED: matched = collections
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: return {
|
||||
# DEPRECATED: "info_id": info_id,
|
||||
# DEPRECATED: "matched_count": len(matched),
|
||||
# DEPRECATED: "collections": [
|
||||
# DEPRECATED: {
|
||||
# DEPRECATED: "id": c.f99_90_id,
|
||||
# DEPRECATED: "code": c.f01_02_code or '',
|
||||
# DEPRECATED: "name": c.f01_01_name,
|
||||
# DEPRECATED: "number": c.f02_10_prefix_serial,
|
||||
# DEPRECATED: "status": c.f01_04_status,
|
||||
# DEPRECATED: "category": c.f01_03_category,
|
||||
# DEPRECATED: "version": c.f02_11_version,
|
||||
# DEPRECATED: "packaging": c.f02_12_packaging,
|
||||
# DEPRECATED: "cost_price": c.f05_40_cost_price,
|
||||
# DEPRECATED: }
|
||||
# DEPRECATED: for c in matched
|
||||
# DEPRECATED: ],
|
||||
# DEPRECATED: "network_matched_count": match_collections_count_from_coolbot(info.expect_number) if info.expect_number else 0,
|
||||
# DEPRECATED: "network_collections": match_collections_list_from_coolbot(info.expect_number, limit=20) if info.expect_number else []
|
||||
# DEPRECATED: }
|
||||
# DEPRECATED:
|
||||
# DEPRECATED:
|
||||
# 获取网络数据匹配列表
|
||||
@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
|
||||
}
|
||||
|
||||
|
||||
# DEPRECATED (use /api/seek/*): @router.get("/seek/network-match/{info_id}")
|
||||
# DEPRECATED: def get_network_match(
|
||||
# DEPRECATED: info_id: str,
|
||||
# DEPRECATED: limit: int = Query(20, ge=1, le=100),
|
||||
# DEPRECATED: db: Session = Depends(get_db)
|
||||
# DEPRECATED: ):
|
||||
# DEPRECATED: """获取一尘数据库中匹配的藏品列表"""
|
||||
# DEPRECATED: info = db.query(Information).filter(
|
||||
# DEPRECATED: Information.id == info_id,
|
||||
# DEPRECATED: Information.info_type == "seek"
|
||||
# DEPRECATED: ).first()
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: if not info:
|
||||
# DEPRECATED: raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: if not info.expect_number:
|
||||
# DEPRECATED: return {"matched_count": 0, "collections": []}
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: matched = match_collections_list_from_coolbot(info.expect_number, limit=limit)
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: return {
|
||||
# DEPRECATED: "matched_count": len(matched),
|
||||
# DEPRECATED: "collections": matched
|
||||
# DEPRECATED: }
|
||||
# DEPRECATED:
|
||||
# DEPRECATED:
|
||||
# 我的寻号列表
|
||||
@router.get("/my-seeks")
|
||||
def get_my_seeks(
|
||||
current_user: Optional[User] = Depends(get_current_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取当前用户发布的所有寻号信息"""
|
||||
if not current_user:
|
||||
raise HTTPException(status_code=401, detail="请先登录")
|
||||
|
||||
items = db.query(Information).filter(
|
||||
Information.user_id == current_user.f99_90_id,
|
||||
Information.info_type == "seek",
|
||||
Information.status == "active"
|
||||
).order_by(Information.created_at.desc()).all()
|
||||
|
||||
result = []
|
||||
for item in items:
|
||||
# DEPRECATED (use /api/seek/*): @router.get("/my-seeks")
|
||||
# DEPRECATED: def get_my_seeks(
|
||||
# DEPRECATED: current_user: Optional[User] = Depends(get_current_user),
|
||||
# DEPRECATED: db: Session = Depends(get_db)
|
||||
# DEPRECATED: ):
|
||||
# DEPRECATED: """获取当前用户发布的所有寻号信息"""
|
||||
# DEPRECATED: if not current_user:
|
||||
# DEPRECATED: raise HTTPException(status_code=401, detail="请先登录")
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: items = db.query(Information).filter(
|
||||
# DEPRECATED: Information.user_id == current_user.f99_90_id,
|
||||
# DEPRECATED: Information.info_type == "seek",
|
||||
# DEPRECATED: Information.status == "active"
|
||||
# DEPRECATED: ).order_by(Information.created_at.desc()).all()
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: result = []
|
||||
# DEPRECATED: for item in items:
|
||||
# 计算匹配数量
|
||||
matched_count = 0
|
||||
if item.expect_number:
|
||||
matched_count = match_collections_count(db, current_user.f99_90_id, item.expect_number)
|
||||
|
||||
result.append(InformationResponse(
|
||||
id=item.id,
|
||||
user_id=item.user_id,
|
||||
info_type=item.info_type,
|
||||
title=item.title,
|
||||
content=item.content,
|
||||
collection_id=item.collection_id,
|
||||
expect_category=item.expect_category,
|
||||
expect_version=item.expect_version,
|
||||
expect_packaging=item.expect_packaging,
|
||||
expect_number=item.expect_number,
|
||||
expect_price_min=item.expect_price_min,
|
||||
expect_price_max=item.expect_price_max,
|
||||
deal_price=item.deal_price,
|
||||
deal_date=item.deal_date,
|
||||
status=item.status,
|
||||
is_matched=item.is_matched,
|
||||
matched_user_id=item.matched_user_id,
|
||||
matched_contact=item.matched_contact,
|
||||
view_count=item.view_count,
|
||||
contact_count=item.contact_count,
|
||||
created_at=item.created_at,
|
||||
user_name=item.user.f01_01_name if item.user else None,
|
||||
user_avatar=item.user.avatar if item.user else None,
|
||||
collection_name=item.collection.f01_01_name if item.collection else None,
|
||||
collection_category=item.collection.f01_03_category 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,
|
||||
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,
|
||||
))
|
||||
|
||||
# DEPRECATED: matched_count = 0
|
||||
# DEPRECATED: if item.expect_number:
|
||||
# DEPRECATED: matched_count = match_collections_count(db, current_user.f99_90_id, item.expect_number)
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: result.append(InformationResponse(
|
||||
# DEPRECATED: id=item.id,
|
||||
# DEPRECATED: user_id=item.user_id,
|
||||
# DEPRECATED: info_type=item.info_type,
|
||||
# DEPRECATED: title=item.title,
|
||||
# DEPRECATED: content=item.content,
|
||||
# DEPRECATED: collection_id=item.collection_id,
|
||||
# DEPRECATED: expect_category=item.expect_category,
|
||||
# DEPRECATED: expect_version=item.expect_version,
|
||||
# DEPRECATED: expect_packaging=item.expect_packaging,
|
||||
# DEPRECATED: expect_number=item.expect_number,
|
||||
# DEPRECATED: expect_price_min=item.expect_price_min,
|
||||
# DEPRECATED: expect_price_max=item.expect_price_max,
|
||||
# DEPRECATED: deal_price=item.deal_price,
|
||||
# DEPRECATED: deal_date=item.deal_date,
|
||||
# DEPRECATED: status=item.status,
|
||||
# DEPRECATED: is_matched=item.is_matched,
|
||||
# DEPRECATED: matched_user_id=item.matched_user_id,
|
||||
# DEPRECATED: matched_contact=item.matched_contact,
|
||||
# DEPRECATED: view_count=item.view_count,
|
||||
# DEPRECATED: contact_count=item.contact_count,
|
||||
# DEPRECATED: created_at=item.created_at,
|
||||
# DEPRECATED: user_name=item.user.f01_01_name if item.user else None,
|
||||
# DEPRECATED: user_avatar=item.user.avatar if item.user else None,
|
||||
# DEPRECATED: collection_name=item.collection.f01_01_name if item.collection else None,
|
||||
# DEPRECATED: collection_category=item.collection.f01_03_category if item.collection else None,
|
||||
# DEPRECATED: collection_version=item.collection.f02_11_version if item.collection else None,
|
||||
# DEPRECATED: collection_number=item.collection.f02_10_prefix_serial if item.collection else None,
|
||||
# DEPRECATED: matched_count=matched_count,
|
||||
# DEPRECATED: network_matched_count=match_collections_count_from_coolbot(item.expect_number) if item.info_type == 'seek' and item.expect_number else 0,
|
||||
# DEPRECATED: ))
|
||||
# DEPRECATED:
|
||||
# 获取总数并设置响应头
|
||||
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
|
||||
|
||||
# DEPRECATED: from fastapi import Response
|
||||
# DEPRECATED: total_query = db.query(Information).filter(Information.status == status)
|
||||
# DEPRECATED: if info_type:
|
||||
# DEPRECATED: total_query = total_query.filter(Information.info_type == info_type)
|
||||
# DEPRECATED: total_count = total_query.count()
|
||||
# DEPRECATED: total_pages = (total_count + page_size - 1) // page_size
|
||||
# DEPRECATED:
|
||||
# 设置响应头
|
||||
response.headers['X-Total-Pages'] = str(total_pages)
|
||||
response.headers['X-Total-Count'] = str(total_count)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# DEPRECATED: response.headers['X-Total-Pages'] = str(total_pages)
|
||||
# DEPRECATED: response.headers['X-Total-Count'] = str(total_count)
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: return result
|
||||
# DEPRECATED:
|
||||
# DEPRECATED:
|
||||
# 成交数据统计
|
||||
@router.get("/deal/stats")
|
||||
# DEPRECATED (use /api/deal/stats): @router.get("/deal/stats")
|
||||
def get_deal_stats(
|
||||
days: int = Query(7, ge=1, le=90, description="统计天数"),
|
||||
db: Session = Depends(get_db)
|
||||
|
|
@ -959,49 +959,49 @@ class MatchSeekRequest(BaseModel):
|
|||
contact: Optional[str] = None
|
||||
|
||||
|
||||
@router.post("/seek/match-confirm")
|
||||
def match_seek(
|
||||
request: MatchSeekRequest,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""确认匹配寻号 - 用户愿意交换联系方式给发布者"""
|
||||
info = db.query(Information).filter(
|
||||
Information.id == request.info_id,
|
||||
Information.info_type == "seek",
|
||||
Information.status == "active"
|
||||
).first()
|
||||
|
||||
if not info:
|
||||
raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
|
||||
# DEPRECATED (use /api/seek/*): @router.post("/seek/match-confirm")
|
||||
# DEPRECATED: def match_seek(
|
||||
# DEPRECATED: request: MatchSeekRequest,
|
||||
# DEPRECATED: current_user: User = Depends(get_current_user),
|
||||
# DEPRECATED: db: Session = Depends(get_db)
|
||||
# DEPRECATED: ):
|
||||
# DEPRECATED: """确认匹配寻号 - 用户愿意交换联系方式给发布者"""
|
||||
# DEPRECATED: info = db.query(Information).filter(
|
||||
# DEPRECATED: Information.id == request.info_id,
|
||||
# DEPRECATED: Information.info_type == "seek",
|
||||
# DEPRECATED: Information.status == "active"
|
||||
# DEPRECATED: ).first()
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: if not info:
|
||||
# DEPRECATED: raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
# DEPRECATED:
|
||||
# 检查是否已被匹配(一个寻号只能被一个用户匹配)
|
||||
if info.is_matched == "matched":
|
||||
raise HTTPException(status_code=400, detail="该寻号已被其他用户匹配")
|
||||
|
||||
# DEPRECATED: if info.is_matched == "matched":
|
||||
# DEPRECATED: raise HTTPException(status_code=400, detail="该寻号已被其他用户匹配")
|
||||
# DEPRECATED:
|
||||
# 更新匹配状态
|
||||
info.is_matched = "matched"
|
||||
info.matched_user_id = current_user.f99_90_id
|
||||
# DEPRECATED: info.is_matched = "matched"
|
||||
# DEPRECATED: info.matched_user_id = current_user.f99_90_id
|
||||
# 保存匹配者的联系方式
|
||||
info.matched_contact = request.contact or ''
|
||||
|
||||
# DEPRECATED: info.matched_contact = request.contact or ''
|
||||
# DEPRECATED:
|
||||
# 更新发布寻号者的内容,显示有藏品被匹配
|
||||
original_content = info.content or ""
|
||||
# DEPRECATED: original_content = info.content or ""
|
||||
# 添加匹配信息:藏品被XX藏友匹配,联系方式为:xxx
|
||||
match_info = f"\n藏品被{current_user.f01_01_name}匹配成功!联系方式:{request.collection_id or '已交换'}"
|
||||
info.content = original_content + match_info
|
||||
|
||||
db.commit()
|
||||
|
||||
return {"message": "匹配成功,已通知发布者", "is_matched": "matched"}
|
||||
|
||||
|
||||
# DEPRECATED: match_info = f"\n藏品被{current_user.f01_01_name}匹配成功!联系方式:{request.collection_id or '已交换'}"
|
||||
# DEPRECATED: info.content = original_content + match_info
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: db.commit()
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: return {"message": "匹配成功,已通知发布者", "is_matched": "matched"}
|
||||
# DEPRECATED:
|
||||
# DEPRECATED:
|
||||
# ============ 添加留言 ============
|
||||
class CommentRequest(BaseModel):
|
||||
information_id: str
|
||||
content: str
|
||||
|
||||
|
||||
# DEPRECATED: class CommentRequest(BaseModel):
|
||||
# DEPRECATED: information_id: str
|
||||
# DEPRECATED: content: str
|
||||
# DEPRECATED:
|
||||
# DEPRECATED:
|
||||
@router.post("/comment")
|
||||
def add_comment(
|
||||
request: CommentRequest,
|
||||
|
|
@ -1063,84 +1063,84 @@ def get_comments(
|
|||
|
||||
|
||||
# ============ 获取匹配者信息 ============
|
||||
@router.get("/seek/matched-user/{info_id}")
|
||||
def get_matched_user(
|
||||
info_id: str,
|
||||
current_user: User = Depends(get_current_user),
|
||||
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="寻配号信息不存在")
|
||||
|
||||
# DEPRECATED (use /api/seek/*): @router.get("/seek/matched-user/{info_id}")
|
||||
# DEPRECATED: def get_matched_user(
|
||||
# DEPRECATED: info_id: str,
|
||||
# DEPRECATED: current_user: User = Depends(get_current_user),
|
||||
# DEPRECATED: db: Session = Depends(get_db)
|
||||
# DEPRECATED: ):
|
||||
# DEPRECATED: """获取寻号的匹配者信息(仅发布者可见)"""
|
||||
# DEPRECATED: info = db.query(Information).filter(
|
||||
# DEPRECATED: Information.id == info_id,
|
||||
# DEPRECATED: Information.info_type == "seek"
|
||||
# DEPRECATED: ).first()
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: if not info:
|
||||
# DEPRECATED: raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
# DEPRECATED:
|
||||
# 只有发布者可以看到匹配者信息
|
||||
if info.user_id != current_user.f99_90_id:
|
||||
raise HTTPException(status_code=403, detail="无权访问")
|
||||
|
||||
if not info.matched_user_id:
|
||||
return {"message": "暂无匹配者"}
|
||||
|
||||
# DEPRECATED: if info.user_id != current_user.f99_90_id:
|
||||
# DEPRECATED: raise HTTPException(status_code=403, detail="无权访问")
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: if not info.matched_user_id:
|
||||
# DEPRECATED: return {"message": "暂无匹配者"}
|
||||
# DEPRECATED:
|
||||
# 获取匹配者信息
|
||||
matched_user = db.query(User).filter(User.f99_90_id == info.matched_user_id).first()
|
||||
if not matched_user:
|
||||
return {"message": "匹配者不存在"}
|
||||
|
||||
return {
|
||||
"matched_user_id": info.matched_user_id,
|
||||
"user_name": matched_user.f01_01_name,
|
||||
"phone": matched_user.phone,
|
||||
"matched_contact": info.matched_contact,
|
||||
"matched_at": info.updated_at.isoformat() if info.updated_at else None
|
||||
}
|
||||
|
||||
|
||||
# DEPRECATED: matched_user = db.query(User).filter(User.f99_90_id == info.matched_user_id).first()
|
||||
# DEPRECATED: if not matched_user:
|
||||
# DEPRECATED: return {"message": "匹配者不存在"}
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: return {
|
||||
# DEPRECATED: "matched_user_id": info.matched_user_id,
|
||||
# DEPRECATED: "user_name": matched_user.f01_01_name,
|
||||
# DEPRECATED: "phone": matched_user.phone,
|
||||
# DEPRECATED: "matched_contact": info.matched_contact,
|
||||
# DEPRECATED: "matched_at": info.updated_at.isoformat() if info.updated_at else None
|
||||
# DEPRECATED: }
|
||||
# DEPRECATED:
|
||||
# DEPRECATED:
|
||||
# ============ 获取发布者信息 ============
|
||||
@router.get("/seek/publisher/{info_id}")
|
||||
def get_publisher_info(
|
||||
info_id: str,
|
||||
current_user: User = Depends(get_current_user),
|
||||
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="寻配号信息不存在")
|
||||
|
||||
# DEPRECATED (use /api/seek/*): @router.get("/seek/publisher/{info_id}")
|
||||
# DEPRECATED: def get_publisher_info(
|
||||
# DEPRECATED: info_id: str,
|
||||
# DEPRECATED: current_user: User = Depends(get_current_user),
|
||||
# DEPRECATED: db: Session = Depends(get_db)
|
||||
# DEPRECATED: ):
|
||||
# DEPRECATED: """获取寻号的发布者信息(仅匹配者可见)"""
|
||||
# DEPRECATED: info = db.query(Information).filter(
|
||||
# DEPRECATED: Information.id == info_id,
|
||||
# DEPRECATED: Information.info_type == "seek"
|
||||
# DEPRECATED: ).first()
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: if not info:
|
||||
# DEPRECATED: raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
# DEPRECATED:
|
||||
# 只有匹配者可以看到发布者信息
|
||||
if not info.matched_user_id or info.matched_user_id != current_user.f99_90_id:
|
||||
raise HTTPException(status_code=403, detail="无权访问")
|
||||
|
||||
# DEPRECATED: if not info.matched_user_id or info.matched_user_id != current_user.f99_90_id:
|
||||
# DEPRECATED: raise HTTPException(status_code=403, detail="无权访问")
|
||||
# DEPRECATED:
|
||||
# 获取发布者信息
|
||||
publisher = db.query(User).filter(User.f99_90_id == info.user_id).first()
|
||||
if not publisher:
|
||||
return {"message": "发布者不存在"}
|
||||
|
||||
# DEPRECATED: publisher = db.query(User).filter(User.f99_90_id == info.user_id).first()
|
||||
# DEPRECATED: if not publisher:
|
||||
# DEPRECATED: return {"message": "发布者不存在"}
|
||||
# DEPRECATED:
|
||||
# 从content中解析联系方式
|
||||
contact = ''
|
||||
if info.content:
|
||||
import re
|
||||
match = re.search(r'联系方式[:\s]*(.+?)(?:\n|$)', info.content)
|
||||
if match:
|
||||
contact = match.group(1).strip()
|
||||
|
||||
return {
|
||||
"user_id": info.user_id,
|
||||
"user_name": publisher.f01_01_name,
|
||||
"phone": publisher.phone,
|
||||
"contact": contact,
|
||||
"created_at": info.created_at.isoformat() if info.created_at else None
|
||||
}
|
||||
|
||||
|
||||
# DEPRECATED: contact = ''
|
||||
# DEPRECATED: if info.content:
|
||||
# DEPRECATED: import re
|
||||
# DEPRECATED: match = re.search(r'联系方式[:\s]*(.+?)(?:\n|$)', info.content)
|
||||
# DEPRECATED: if match:
|
||||
# DEPRECATED: contact = match.group(1).strip()
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: return {
|
||||
# DEPRECATED: "user_id": info.user_id,
|
||||
# DEPRECATED: "user_name": publisher.f01_01_name,
|
||||
# DEPRECATED: "phone": publisher.phone,
|
||||
# DEPRECATED: "contact": contact,
|
||||
# DEPRECATED: "created_at": info.created_at.isoformat() if info.created_at else None
|
||||
# DEPRECATED: }
|
||||
# DEPRECATED:
|
||||
# DEPRECATED:
|
||||
@router.get("/yichen-posts")
|
||||
def get_yichen_posts(category: str = None, search: str = None, page: int = 1, page_size: int = 20):
|
||||
from app.models.models import Information
|
||||
|
|
@ -1156,59 +1156,59 @@ def get_yichen_posts(category: str = None, search: str = None, page: int = 1, pa
|
|||
return {"data": items, "pagination": {"page": page, "limit": page_size, "total": total}}
|
||||
|
||||
|
||||
@router.get("/seek/stats")
|
||||
def get_seek_stats(
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取寻配号统计数据"""
|
||||
# DEPRECATED (use /api/seek/*): @router.get("/seek/stats")
|
||||
# DEPRECATED: def get_seek_stats(
|
||||
# DEPRECATED: current_user: User = Depends(get_current_user),
|
||||
# DEPRECATED: db: Session = Depends(get_db)
|
||||
# DEPRECATED: ):
|
||||
# DEPRECATED: """获取寻配号统计数据"""
|
||||
# 寻号需求数(seek类型且expect_number不为空的总数)
|
||||
seek_count = db.query(Information).filter(
|
||||
Information.info_type == 'seek',
|
||||
Information.expect_number.isnot(None),
|
||||
Information.expect_number != ''
|
||||
).count()
|
||||
|
||||
# DEPRECATED: seek_count = db.query(Information).filter(
|
||||
# DEPRECATED: Information.info_type == 'seek',
|
||||
# DEPRECATED: Information.expect_number.isnot(None),
|
||||
# DEPRECATED: Information.expect_number != ''
|
||||
# DEPRECATED: ).count()
|
||||
# DEPRECATED:
|
||||
# 我的匹配:自有藏品匹配成功的寻号帖子数量
|
||||
# 即 is_matched = 'confirmed' 的记录,用户ID等于当前用户
|
||||
user_matched_count = 0
|
||||
if current_user:
|
||||
user_matched_count = db.query(Information).filter(
|
||||
Information.info_type == 'seek',
|
||||
Information.expect_number.isnot(None),
|
||||
Information.expect_number != '',
|
||||
Information.matched_user_id == current_user.f99_90_id,
|
||||
Information.is_matched == 'confirmed'
|
||||
).count()
|
||||
|
||||
# DEPRECATED: user_matched_count = 0
|
||||
# DEPRECATED: if current_user:
|
||||
# DEPRECATED: user_matched_count = db.query(Information).filter(
|
||||
# DEPRECATED: Information.info_type == 'seek',
|
||||
# DEPRECATED: Information.expect_number.isnot(None),
|
||||
# DEPRECATED: Information.expect_number != '',
|
||||
# DEPRECATED: Information.matched_user_id == current_user.f99_90_id,
|
||||
# DEPRECATED: Information.is_matched == 'confirmed'
|
||||
# DEPRECATED: ).count()
|
||||
# DEPRECATED:
|
||||
# 总共匹配:自有匹配成功 + 网络数据匹配成功
|
||||
# 自有匹配成功:is_matched = 'confirmed'
|
||||
# 网络数据匹配成功:查询每个帖子的network_matched_count并求和
|
||||
seeks = db.query(Information).filter(
|
||||
Information.info_type == 'seek',
|
||||
Information.expect_number.isnot(None),
|
||||
Information.expect_number != ''
|
||||
).all()
|
||||
|
||||
total_self_matched = 0
|
||||
total_network_matched = 0
|
||||
for seek in seeks:
|
||||
# DEPRECATED: seeks = db.query(Information).filter(
|
||||
# DEPRECATED: Information.info_type == 'seek',
|
||||
# DEPRECATED: Information.expect_number.isnot(None),
|
||||
# DEPRECATED: Information.expect_number != ''
|
||||
# DEPRECATED: ).all()
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: total_self_matched = 0
|
||||
# DEPRECATED: total_network_matched = 0
|
||||
# DEPRECATED: for seek in seeks:
|
||||
# 自身匹配成功
|
||||
if seek.is_matched == 'confirmed':
|
||||
total_self_matched += 1
|
||||
# DEPRECATED: if seek.is_matched == 'confirmed':
|
||||
# DEPRECATED: total_self_matched += 1
|
||||
# 网络数据匹配成功(通过coolbot数据库查询)
|
||||
if seek.expect_number:
|
||||
network_count = match_collections_count_from_coolbot(seek.expect_number)
|
||||
total_network_matched += network_count
|
||||
|
||||
total_matched_count = total_self_matched + total_network_matched
|
||||
|
||||
return {
|
||||
"seekCount": seek_count,
|
||||
"userMatchedCount": user_matched_count,
|
||||
"totalMatchedCount": total_matched_count
|
||||
}
|
||||
|
||||
# DEPRECATED: if seek.expect_number:
|
||||
# DEPRECATED: network_count = match_collections_count_from_coolbot(seek.expect_number)
|
||||
# DEPRECATED: total_network_matched += network_count
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: total_matched_count = total_self_matched + total_network_matched
|
||||
# DEPRECATED:
|
||||
# DEPRECATED: return {
|
||||
# DEPRECATED: "seekCount": seek_count,
|
||||
# DEPRECATED: "userMatchedCount": user_matched_count,
|
||||
# DEPRECATED: "totalMatchedCount": total_matched_count
|
||||
# DEPRECATED: }
|
||||
# DEPRECATED:
|
||||
# 批量解析行情数据API
|
||||
@router.post("/batch-parse")
|
||||
async def batch_parse_deals(text: str = Body(..., embed=True)):
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
# seek - 寻配号路由
|
||||
# Version: 0.0.3 (2026-04-24)
|
||||
# 更新:添加缺失端点,清理废弃依赖
|
||||
|
||||
from fastapi import APIRouter, Depends, Query, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from pydantic import BaseModel
|
||||
|
|
@ -6,8 +10,13 @@ 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
|
||||
from app.models.models import User, Collection, Information
|
||||
from sqlalchemy import text
|
||||
from app.models.models import User, Collection
|
||||
from app.utils.coolbot_matcher import (
|
||||
match_pattern,
|
||||
match_self_collections_count,
|
||||
match_collections_count_from_coolbot,
|
||||
match_collections_list_from_coolbot
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/api/seek", tags=["寻配号"])
|
||||
|
||||
|
|
@ -59,6 +68,11 @@ class SeekInfoResponse(BaseModel):
|
|||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
class MatchConfirmRequest(BaseModel):
|
||||
info_id: str
|
||||
contact: Optional[str] = None
|
||||
collection_id: Optional[str] = None
|
||||
|
||||
# ============ API ============
|
||||
@router.get("/list", response_model=list[SeekInfoResponse])
|
||||
def get_seek_list(
|
||||
|
|
@ -83,22 +97,12 @@ def get_seek_list(
|
|||
offset = (page - 1) * page_size
|
||||
items = query.offset(offset).limit(page_size).all()
|
||||
|
||||
# 添加用户名和匹配数量
|
||||
from app.routers.information import match_collections_count, match_collections_count_from_coolbot
|
||||
result = []
|
||||
for item in items:
|
||||
user = db.query(User).filter(User.f99_90_id == item.user_id).first()
|
||||
user_name = user.f01_01_name if user else '匿名用户'
|
||||
|
||||
# 计算匹配数量
|
||||
matched_count = 0
|
||||
network_matched_count = 0
|
||||
if item.expect_number and len(item.expect_number) == 10:
|
||||
if current_user and current_user.f99_90_id:
|
||||
matched_count = match_collections_count(db, current_user.f99_90_id, item.expect_number)
|
||||
network_matched_count = match_collections_count_from_coolbot(item.expect_number)
|
||||
|
||||
# 构建响应
|
||||
# 构建响应(不实时计算网络匹配,网络匹配在点击时再查)
|
||||
result.append(SeekInfoResponse(
|
||||
id=item.id,
|
||||
user_id=item.user_id,
|
||||
|
|
@ -119,8 +123,8 @@ def get_seek_list(
|
|||
created_at=item.created_at,
|
||||
updated_at=item.updated_at,
|
||||
user_name=user_name,
|
||||
matched_count=matched_count,
|
||||
network_matched_count=network_matched_count
|
||||
matched_count=0,
|
||||
network_matched_count=0
|
||||
))
|
||||
|
||||
return result
|
||||
|
|
@ -232,7 +236,9 @@ def delete_seek(
|
|||
db.commit()
|
||||
|
||||
return {"message": "删除成功"}
|
||||
# 获取自有藏品匹配列表
|
||||
|
||||
# ============ 匹配相关API ============
|
||||
|
||||
@router.get("/my-match")
|
||||
def get_seek_match(
|
||||
info_id: str,
|
||||
|
|
@ -254,7 +260,6 @@ def get_seek_match(
|
|||
).all()
|
||||
|
||||
# 按号码特征模式匹配
|
||||
from app.routers.information import match_pattern
|
||||
matched = []
|
||||
if info.expect_number and len(info.expect_number) == 10:
|
||||
pattern = info.expect_number[2:]
|
||||
|
|
@ -280,7 +285,6 @@ def get_seek_match(
|
|||
]
|
||||
}
|
||||
|
||||
# 获取网络数据匹配列表
|
||||
@router.get("/network-match/{info_id}")
|
||||
def get_network_match(
|
||||
info_id: str,
|
||||
|
|
@ -288,8 +292,6 @@ def get_network_match(
|
|||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取一尘数据库中匹配的藏品列表"""
|
||||
from app.routers.information import match_collections_list_from_coolbot
|
||||
|
||||
info = db.query(SeekInfo).filter(SeekInfo.id == info_id).first()
|
||||
if not info:
|
||||
raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
|
|
@ -299,3 +301,107 @@ def get_network_match(
|
|||
|
||||
matched = match_collections_list_from_coolbot(info.expect_number, limit=limit)
|
||||
return {"matched_count": len(matched), "collections": matched}
|
||||
|
||||
@router.post("/match-confirm")
|
||||
def match_seek_confirm(
|
||||
request: MatchConfirmRequest,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""确认匹配寻号 - 用户愿意交换联系方式给发布者"""
|
||||
info = db.query(SeekInfo).filter(
|
||||
SeekInfo.id == request.info_id,
|
||||
SeekInfo.status == "active"
|
||||
).first()
|
||||
|
||||
if not info:
|
||||
raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
|
||||
# 检查是否已被匹配(一个寻号只能被一个用户匹配)
|
||||
if info.is_matched == "matched":
|
||||
raise HTTPException(status_code=400, detail="该寻号已被其他用户匹配")
|
||||
|
||||
# 检查是否是自己发布的
|
||||
if info.user_id == current_user.f99_90_id:
|
||||
raise HTTPException(status_code=400, detail="不能匹配自己发布的寻号")
|
||||
|
||||
# 更新匹配状态
|
||||
info.is_matched = "matched"
|
||||
info.matched_user_id = current_user.f99_90_id
|
||||
info.matched_contact = request.contact or ''
|
||||
|
||||
# 更新发布寻号者的内容,显示有藏品被匹配
|
||||
original_content = info.content or ""
|
||||
match_info = f"\n藏品被{current_user.f01_01_name}匹配成功!联系方式:{request.collection_id or '已交换'}"
|
||||
info.content = original_content + match_info
|
||||
|
||||
db.commit()
|
||||
|
||||
return {"message": "匹配成功,已通知发布者", "is_matched": "matched"}
|
||||
|
||||
@router.get("/matched-user/{info_id}")
|
||||
def get_matched_user(
|
||||
info_id: str,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取寻号的匹配者信息(仅发布者可见)"""
|
||||
info = db.query(SeekInfo).filter(SeekInfo.id == info_id).first()
|
||||
|
||||
if not info:
|
||||
raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
|
||||
# 只有发布者可以看到匹配者信息
|
||||
if info.user_id != current_user.f99_90_id:
|
||||
raise HTTPException(status_code=403, detail="无权访问")
|
||||
|
||||
if not info.matched_user_id:
|
||||
return {"message": "暂无匹配者"}
|
||||
|
||||
# 获取匹配者信息
|
||||
matched_user = db.query(User).filter(User.f99_90_id == info.matched_user_id).first()
|
||||
if not matched_user:
|
||||
return {"message": "匹配者不存在"}
|
||||
|
||||
return {
|
||||
"matched_user_id": info.matched_user_id,
|
||||
"user_name": matched_user.f01_01_name,
|
||||
"phone": matched_user.phone,
|
||||
"matched_contact": info.matched_contact,
|
||||
}
|
||||
|
||||
@router.get("/publisher/{info_id}")
|
||||
def get_publisher_info(
|
||||
info_id: str,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""获取寻号的发布者信息(仅匹配者可见)"""
|
||||
info = db.query(SeekInfo).filter(SeekInfo.id == info_id).first()
|
||||
|
||||
if not info:
|
||||
raise HTTPException(status_code=404, detail="寻配号信息不存在")
|
||||
|
||||
# 只有匹配者可以看到发布者信息
|
||||
if not info.matched_user_id or info.matched_user_id != current_user.f99_90_id:
|
||||
raise HTTPException(status_code=403, detail="无权访问")
|
||||
|
||||
# 获取发布者信息
|
||||
publisher = db.query(User).filter(User.f99_90_id == info.user_id).first()
|
||||
if not publisher:
|
||||
return {"message": "发布者不存在"}
|
||||
|
||||
# 从content中解析联系方式
|
||||
contact = ''
|
||||
if info.content:
|
||||
import re
|
||||
match = re.search(r'联系方式[:\s]*(.+?)(?:\n|$)', info.content)
|
||||
if match:
|
||||
contact = match.group(1).strip()
|
||||
|
||||
return {
|
||||
"user_id": info.user_id,
|
||||
"user_name": publisher.f01_01_name,
|
||||
"phone": publisher.phone,
|
||||
"contact": contact,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,208 @@
|
|||
# coolbot_matcher - 一尘数据库号码匹配工具
|
||||
# Version: 0.0.1 (2026-04-24)
|
||||
# 描述:从一尘数据库(coolbot_data)查询匹配的藏品号码
|
||||
|
||||
from typing import List
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.orm import Session
|
||||
from app.core.coolbot_db import coolbot_engine
|
||||
|
||||
|
||||
def match_pattern(col_number: str, pattern: str) -> bool:
|
||||
"""匹配号码特征模式
|
||||
|
||||
通配符规则:
|
||||
- X = 任意数字
|
||||
- A = 非4
|
||||
- B = 非47
|
||||
- C = 非347
|
||||
- D = 非247
|
||||
- E = 非2347
|
||||
"""
|
||||
if not col_number or not pattern:
|
||||
return False
|
||||
|
||||
if len(col_number) != len(pattern):
|
||||
return False
|
||||
|
||||
for i, p in enumerate(pattern):
|
||||
c = col_number[i]
|
||||
if p == 'X':
|
||||
continue # 任意数字
|
||||
elif p == 'A':
|
||||
if c == '4':
|
||||
return False
|
||||
elif p == 'B':
|
||||
if c == '4':
|
||||
return False
|
||||
if i < len(col_number) - 1 and col_number[i+1] == '7' and pattern[i+1] == 'X':
|
||||
return False
|
||||
elif p == 'C':
|
||||
if c in '347':
|
||||
return False
|
||||
elif p == 'D':
|
||||
if c in '247':
|
||||
return False
|
||||
elif p == 'E':
|
||||
if c in '2347':
|
||||
return False
|
||||
elif p == 'L':
|
||||
# L = 带4
|
||||
if c != '4':
|
||||
return False
|
||||
elif p == 'N':
|
||||
# N = 无4
|
||||
if c == '4':
|
||||
return False
|
||||
else:
|
||||
if c != p:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def match_self_collections_count(db: Session, user_id: str, expect_number: str) -> int:
|
||||
"""根据号码特征计算匹配藏品数量(从用户自有藏品)
|
||||
|
||||
Args:
|
||||
db: 数据库会话
|
||||
user_id: 用户ID
|
||||
expect_number: 期望号码,如 "J012345678" (固定J0前缀+8位特征)
|
||||
|
||||
Returns:
|
||||
匹配的藏品数量
|
||||
"""
|
||||
from app.models.models import Collection
|
||||
|
||||
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
|
||||
|
||||
# 获取用户所有藏品
|
||||
collections = db.query(Collection).filter(
|
||||
Collection.f99_91_user_id == user_id,
|
||||
Collection.f01_04_status == "in_collection"
|
||||
).all()
|
||||
|
||||
count = 0
|
||||
for c in collections:
|
||||
number = c.f02_10_prefix_serial or ''
|
||||
if len(number) >= 10 and number.startswith('J0'):
|
||||
col_pattern = number[2:10]
|
||||
if match_pattern(col_pattern, pattern):
|
||||
count += 1
|
||||
elif len(number) >= 8:
|
||||
col_pattern = number[:8]
|
||||
if match_pattern(col_pattern, pattern):
|
||||
count += 1
|
||||
|
||||
return count
|
||||
|
||||
|
||||
def match_collections_count_from_coolbot(expect_number: str) -> int:
|
||||
"""根据号码特征计算匹配藏品数量(从coolbot_data数据库)
|
||||
|
||||
Args:
|
||||
expect_number: 期望号码,如 "J012345678" (固定J0前缀+8位特征)
|
||||
|
||||
Returns:
|
||||
匹配的藏品数量
|
||||
"""
|
||||
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
|
||||
|
||||
query = 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%'
|
||||
""")
|
||||
|
||||
try:
|
||||
with coolbot_engine.connect() as conn:
|
||||
result = conn.execute(query)
|
||||
|
||||
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数据库)
|
||||
|
||||
Args:
|
||||
expect_number: 期望号码,如 "J012345678"
|
||||
limit: 返回的最大数量
|
||||
|
||||
Returns:
|
||||
匹配的藏品列表
|
||||
"""
|
||||
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 []
|
||||
|
||||
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 []
|
||||
|
|
@ -1,5 +1,25 @@
|
|||
# 版本更新记录
|
||||
|
||||
## v0.0.7 (2026-04-24)
|
||||
|
||||
### 代码清理
|
||||
- **coolbot_matcher.py** (新建)
|
||||
- 功能:创建一尘数据库号码匹配工具模块
|
||||
- 包含:match_pattern, match_self_collections_count, match_collections_count_from_coolbot, match_collections_list_from_coolbot
|
||||
|
||||
- **seek.py**
|
||||
- 功能:更新导入,添加缺失端点
|
||||
- 新增端点:/match-confirm, /matched-user/{id}, /publisher/{id}
|
||||
- 优化:移除列表接口网络匹配实时计算,提升加载速度
|
||||
|
||||
- **information.py**
|
||||
- 清理:注释废弃的seek/deal重复端点,统一使用/api/seek/*和/api/deal/*
|
||||
|
||||
- **News.jsx**
|
||||
- 迁移:seek相关API从/api/information/*迁移到/api/seek/*
|
||||
|
||||
---
|
||||
|
||||
## v1.2.98 (2026-04-19)
|
||||
|
||||
### 前端更新
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"version": "0.0.6",
|
||||
"updated": "2026-04-19",
|
||||
"version": "0.0.7",
|
||||
"updated": "2026-04-24",
|
||||
"modules": {
|
||||
"frontend": {
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"pages": {
|
||||
"Add": "0.0.1",
|
||||
"Admin": "0.0.1",
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
"Home": "0.0.1",
|
||||
"List": "0.0.1",
|
||||
"Login": "0.0.1",
|
||||
"News": "0.0.1",
|
||||
"News": "0.0.2",
|
||||
"News_YichensBoard": "0.0.1",
|
||||
"Settings": "0.0.1",
|
||||
"Stats": "0.0.1",
|
||||
|
|
@ -23,16 +23,16 @@
|
|||
}
|
||||
},
|
||||
"backend": {
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"routers": {
|
||||
"auth": "0.0.1",
|
||||
"collections": "0.0.1",
|
||||
"deal": "0.0.1",
|
||||
"information": "0.0.1",
|
||||
"information": "0.0.2",
|
||||
"news": "0.0.1",
|
||||
"ocr": "0.0.1",
|
||||
"operations": "0.0.1",
|
||||
"seek": "0.0.1",
|
||||
"seek": "0.0.2",
|
||||
"users": "0.0.1",
|
||||
"yichens": "0.0.1"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* News - 资讯列表页面
|
||||
* Version: 0.0.1
|
||||
* 更新:
|
||||
* Version: 0.0.2 (2026-04-24)
|
||||
* 更新:迁移seek相关API到/api/seek/*
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect } from 'react'
|
||||
|
|
@ -195,7 +195,7 @@ export default function News() {
|
|||
if (!token) { alert('请先登录'); return }
|
||||
try {
|
||||
const phone = getUserPhone()
|
||||
const res = await fetch(`${API_BASE}/api/information/seek/match-confirm`, {
|
||||
const res = await fetch(`${API_BASE}/api/seek/match-confirm`, {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ info_id: infoId, contact: phone || '用户已同意' })
|
||||
|
|
@ -232,7 +232,7 @@ export default function News() {
|
|||
if (!token) { alert('请先登录'); return }
|
||||
}
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}/api/information/seek/matched-user/${infoId}`, { headers: { Authorization: `Bearer ${token}` } })
|
||||
const res = await fetch(`${API_BASE}/api/seek/matched-user/${infoId}`, { headers: { Authorization: `Bearer ${token}` } })
|
||||
console.log('Matched user response:', res.status)
|
||||
const data = await res.json()
|
||||
console.log('Matched user data:', data)
|
||||
|
|
@ -245,7 +245,7 @@ export default function News() {
|
|||
const token = localStorage.getItem('token')
|
||||
if (!token) { alert('请先登录'); return }
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}/api/information/seek/publisher/${infoId}`, { headers: { Authorization: `Bearer ${token}` } })
|
||||
const res = await fetch(`${API_BASE}/api/seek/publisher/${infoId}`, { headers: { Authorization: `Bearer ${token}` } })
|
||||
console.log('Publisher response:', res.status)
|
||||
const data = await res.json()
|
||||
console.log('Publisher data:', data)
|
||||
|
|
@ -257,7 +257,7 @@ export default function News() {
|
|||
const token = localStorage.getItem('token')
|
||||
if (!token) { alert('请先登录'); return }
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}/api/information/seek/match?info_id=${infoId}`, {
|
||||
const res = await fetch(`${API_BASE}/api/seek/my-match?info_id=${infoId}`, {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
})
|
||||
const data = await res.json()
|
||||
|
|
@ -331,7 +331,7 @@ export default function News() {
|
|||
try {
|
||||
// 解析正文中的号码特征和联系方式
|
||||
const content = (editingSeek.content || '') + '\n联系方式: ' + editingSeek.contact
|
||||
await fetch(`${API_BASE}/api/information/${editingSeek.id}`, {
|
||||
await fetch(`${API_BASE}/api/seek/${editingSeek.id}`, {
|
||||
method: 'PUT',
|
||||
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
|
|
@ -355,14 +355,13 @@ export default function News() {
|
|||
const token = localStorage.getItem('token')
|
||||
// 从edition映射到category
|
||||
const categoryMap = { '龙钞': '龙钞', '马钞': '马钞', '蛇钞': '蛇钞' }
|
||||
const res = await fetch(`${API_BASE}/api/information/`, {
|
||||
const res = await fetch(`${API_BASE}/api/seek/`, {
|
||||
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
|
||||
expect_number: seekForm.features ? 'J0' + seekForm.features : null
|
||||
})
|
||||
})
|
||||
const data = await res.json()
|
||||
|
|
|
|||
Loading…
Reference in New Issue