v0.0.5 - 寻配号功能优化
This commit is contained in:
parent
6667671f46
commit
d47a002495
|
|
@ -0,0 +1,48 @@
|
||||||
|
{
|
||||||
|
"version": "1.2.98",
|
||||||
|
"updated": "2026-04-19",
|
||||||
|
"modules": {
|
||||||
|
"frontend": {
|
||||||
|
"version": "1.2.98",
|
||||||
|
"pages": {
|
||||||
|
"Add": "1.2.90",
|
||||||
|
"Admin": "1.2.98",
|
||||||
|
"Detail": "1.2.90",
|
||||||
|
"Edit": "1.2.90",
|
||||||
|
"Home": "1.2.95",
|
||||||
|
"List": "1.2.93",
|
||||||
|
"Login": "1.2.85",
|
||||||
|
"News": "1.2.80",
|
||||||
|
"News_YichensBoard": "1.2.75",
|
||||||
|
"Settings": "1.2.75",
|
||||||
|
"Stats": "1.2.70",
|
||||||
|
"YichensBoard": "1.2.70"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"version": "1.2.98"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"backend": {
|
||||||
|
"version": "1.2.98",
|
||||||
|
"routers": {
|
||||||
|
"auth": "1.2.90",
|
||||||
|
"collections": "1.2.95",
|
||||||
|
"deal": "1.2.85",
|
||||||
|
"information": "1.2.92",
|
||||||
|
"news": "1.2.80",
|
||||||
|
"ocr": "1.2.75",
|
||||||
|
"operations": "1.2.70",
|
||||||
|
"seek": "1.2.70",
|
||||||
|
"users": "1.2.98",
|
||||||
|
"yichens": "1.2.70"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"core": "1.2.0",
|
||||||
|
"models": "1.2.0",
|
||||||
|
"schemas": "1.2.0",
|
||||||
|
"services": "1.2.0",
|
||||||
|
"utils": "1.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,210 +1,104 @@
|
||||||
# operations - 运营操作路由
|
# 操作路由
|
||||||
# Version: 0.0.1
|
|
||||||
# 更新:
|
|
||||||
|
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
# 更新:
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
||||||
# 更新:
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
# 更新:
|
|
||||||
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.models.models import User, Collection, Operation
|
from app.models.models import User, Collection, Operation
|
||||||
# 更新:
|
|
||||||
from app.schemas.schemas import OperationCreate, OperationResponse
|
from app.schemas.schemas import OperationCreate, OperationResponse
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
router = APIRouter(prefix="/api", tags=["操作"])
|
router = APIRouter(prefix="/api", tags=["操作"])
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.get("/operations", response_model=List[OperationResponse])
|
@router.get("/operations", response_model=List[OperationResponse])
|
||||||
# 更新:
|
|
||||||
def get_operations(
|
def get_operations(
|
||||||
# 更新:
|
|
||||||
collection_id: Optional[str] = None,
|
collection_id: Optional[str] = None,
|
||||||
# 更新:
|
|
||||||
page: int = Query(1, ge=1),
|
page: int = Query(1, ge=1),
|
||||||
# 更新:
|
|
||||||
limit: int = Query(50, ge=1, le=100),
|
limit: int = Query(50, ge=1, le=100),
|
||||||
# 更新:
|
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
# 更新:
|
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
# 更新:
|
|
||||||
):
|
):
|
||||||
# 更新:
|
|
||||||
"""获取操作历史"""
|
"""获取操作历史"""
|
||||||
# 更新:
|
|
||||||
query = db.query(Operation).filter(Operation.user_id == current_user.id)
|
query = db.query(Operation).filter(Operation.user_id == current_user.id)
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
if collection_id:
|
if collection_id:
|
||||||
# 更新:
|
|
||||||
query = query.filter(Operation.collection_id == collection_id)
|
query = query.filter(Operation.collection_id == collection_id)
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
operations = query.order_by(Operation.created_at.desc()) \
|
operations = query.order_by(Operation.created_at.desc()) \
|
||||||
# 更新:
|
|
||||||
.offset((page - 1) * limit) \
|
.offset((page - 1) * limit) \
|
||||||
# 更新:
|
|
||||||
.limit(limit) \
|
.limit(limit) \
|
||||||
# 更新:
|
|
||||||
.all()
|
.all()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
return operations
|
return operations
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.get("/operations/history")
|
@router.get("/operations/history")
|
||||||
# 更新:
|
|
||||||
def get_operation_history(
|
def get_operation_history(
|
||||||
# 更新:
|
|
||||||
collection_id: Optional[str] = None,
|
collection_id: Optional[str] = None,
|
||||||
# 更新:
|
|
||||||
type: Optional[str] = None,
|
type: Optional[str] = None,
|
||||||
# 更新:
|
|
||||||
start_date: Optional[str] = None,
|
start_date: Optional[str] = None,
|
||||||
# 更新:
|
|
||||||
end_date: Optional[str] = None,
|
end_date: Optional[str] = None,
|
||||||
# 更新:
|
|
||||||
page: int = Query(1, ge=1),
|
page: int = Query(1, ge=1),
|
||||||
# 更新:
|
|
||||||
limit: int = Query(50, ge=1, le=100),
|
limit: int = Query(50, ge=1, le=100),
|
||||||
# 更新:
|
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
# 更新:
|
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
# 更新:
|
|
||||||
):
|
):
|
||||||
# 更新:
|
|
||||||
"""获取操作历史(带统计)"""
|
"""获取操作历史(带统计)"""
|
||||||
# 更新:
|
|
||||||
query = db.query(Operation).filter(Operation.user_id == current_user.id)
|
query = db.query(Operation).filter(Operation.user_id == current_user.id)
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
if collection_id:
|
if collection_id:
|
||||||
# 更新:
|
|
||||||
query = query.filter(Operation.collection_id == collection_id)
|
query = query.filter(Operation.collection_id == collection_id)
|
||||||
# 更新:
|
|
||||||
if type:
|
if type:
|
||||||
# 更新:
|
|
||||||
query = query.filter(Operation.type == type)
|
query = query.filter(Operation.type == type)
|
||||||
# 更新:
|
|
||||||
if start_date:
|
if start_date:
|
||||||
# 更新:
|
|
||||||
query = query.filter(Operation.created_at >= start_date)
|
query = query.filter(Operation.created_at >= start_date)
|
||||||
# 更新:
|
|
||||||
if end_date:
|
if end_date:
|
||||||
# 更新:
|
|
||||||
query = query.filter(Operation.created_at <= end_date)
|
query = query.filter(Operation.created_at <= end_date)
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
total = query.count()
|
total = query.count()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
data = query.order_by(Operation.created_at.desc()) \
|
data = query.order_by(Operation.created_at.desc()) \
|
||||||
# 更新:
|
|
||||||
.offset((page - 1) * limit) \
|
.offset((page - 1) * limit) \
|
||||||
# 更新:
|
|
||||||
.limit(limit) \
|
.limit(limit) \
|
||||||
# 更新:
|
|
||||||
.all()
|
.all()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
return {
|
return {
|
||||||
# 更新:
|
|
||||||
"data": data,
|
"data": data,
|
||||||
# 更新:
|
|
||||||
"pagination": {
|
"pagination": {
|
||||||
# 更新:
|
|
||||||
"page": page,
|
"page": page,
|
||||||
# 更新:
|
|
||||||
"limit": limit,
|
"limit": limit,
|
||||||
# 更新:
|
|
||||||
"total": total,
|
"total": total,
|
||||||
# 更新:
|
|
||||||
"pages": (total + limit - 1) // limit
|
"pages": (total + limit - 1) // limit
|
||||||
# 更新:
|
|
||||||
}
|
}
|
||||||
# 更新:
|
|
||||||
}
|
}
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.post("/operations", response_model=OperationResponse)
|
@router.post("/operations", response_model=OperationResponse)
|
||||||
# 更新:
|
|
||||||
def create_operation(
|
def create_operation(
|
||||||
# 更新:
|
|
||||||
operation_data: OperationCreate,
|
operation_data: OperationCreate,
|
||||||
# 更新:
|
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
# 更新:
|
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
# 更新:
|
|
||||||
):
|
):
|
||||||
# 更新:
|
|
||||||
"""创建操作记录"""
|
"""创建操作记录"""
|
||||||
# 更新:
|
|
||||||
# 验证藏品存在
|
# 验证藏品存在
|
||||||
# 更新:
|
|
||||||
collection = db.query(Collection).filter(
|
collection = db.query(Collection).filter(
|
||||||
# 更新:
|
|
||||||
Collection.id == operation_data.collection_id,
|
Collection.id == operation_data.collection_id,
|
||||||
# 更新:
|
|
||||||
Collection.user_id == current_user.id
|
Collection.user_id == current_user.id
|
||||||
# 更新:
|
|
||||||
).first()
|
).first()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
if not collection:
|
if not collection:
|
||||||
# 更新:
|
|
||||||
raise HTTPException(status_code=404, detail="藏品不存在")
|
raise HTTPException(status_code=404, detail="藏品不存在")
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
operation = Operation(
|
operation = Operation(
|
||||||
# 更新:
|
|
||||||
collection_id=operation_data.collection_id,
|
collection_id=operation_data.collection_id,
|
||||||
# 更新:
|
|
||||||
user_id=current_user.id,
|
user_id=current_user.id,
|
||||||
# 更新:
|
|
||||||
type=operation_data.type,
|
type=operation_data.type,
|
||||||
# 更新:
|
|
||||||
price=operation_data.price,
|
price=operation_data.price,
|
||||||
# 更新:
|
|
||||||
note=operation_data.note
|
note=operation_data.note
|
||||||
# 更新:
|
|
||||||
)
|
)
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
db.add(operation)
|
db.add(operation)
|
||||||
# 更新:
|
|
||||||
db.commit()
|
db.commit()
|
||||||
# 更新:
|
|
||||||
db.refresh(operation)
|
db.refresh(operation)
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
return operation
|
return operation
|
||||||
# 更新:
|
|
||||||
|
|
|
||||||
|
|
@ -1,230 +1,384 @@
|
||||||
# seek - 寻号匹配路由
|
# seek - 寻号匹配路由
|
||||||
# Version: 0.0.1
|
# Version: 0.0.1
|
||||||
|
# 更新:
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Query, HTTPException
|
from fastapi import APIRouter, Depends, Query, HTTPException
|
||||||
|
# 更新:
|
||||||
# Version: 1.2.x
|
# Version: 1.2.x
|
||||||
|
# 更新:
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
# 更新:
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from typing import Optional, List
|
# 更新:
|
||||||
|
from typing import Optional
|
||||||
|
# 更新:
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
# 更新:
|
||||||
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.models.seek_info import SeekInfo
|
from app.models.seek_info import SeekInfo
|
||||||
from app.models.models import User
|
# 更新:
|
||||||
from app.routers.information import match_collections_count_from_coolbot
|
|
||||||
|
|
||||||
|
# 更新:
|
||||||
router = APIRouter(prefix="/api/seek", tags=["寻配号"])
|
router = APIRouter(prefix="/api/seek", tags=["寻配号"])
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
# ============ Schema ============
|
# ============ Schema ============
|
||||||
|
# 更新:
|
||||||
class SeekInfoCreate(BaseModel):
|
class SeekInfoCreate(BaseModel):
|
||||||
|
# 更新:
|
||||||
title: str
|
title: str
|
||||||
|
# 更新:
|
||||||
content: Optional[str] = None
|
content: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
expect_category: Optional[str] = None
|
expect_category: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
expect_version: Optional[str] = None
|
expect_version: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
expect_packaging: Optional[str] = None
|
expect_packaging: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
expect_number: Optional[str] = None
|
expect_number: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
expect_price_min: Optional[float] = None
|
expect_price_min: Optional[float] = None
|
||||||
|
# 更新:
|
||||||
expect_price_max: Optional[float] = None
|
expect_price_max: Optional[float] = None
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
class SeekInfoUpdate(BaseModel):
|
class SeekInfoUpdate(BaseModel):
|
||||||
|
# 更新:
|
||||||
title: Optional[str] = None
|
title: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
content: Optional[str] = None
|
content: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
expect_category: Optional[str] = None
|
expect_category: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
expect_version: Optional[str] = None
|
expect_version: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
expect_packaging: Optional[str] = None
|
expect_packaging: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
expect_number: Optional[str] = None
|
expect_number: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
expect_price_min: Optional[float] = None
|
expect_price_min: Optional[float] = None
|
||||||
|
# 更新:
|
||||||
expect_price_max: Optional[float] = None
|
expect_price_max: Optional[float] = None
|
||||||
|
# 更新:
|
||||||
status: Optional[str] = None
|
status: Optional[str] = None
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
class SeekInfoResponse(BaseModel):
|
class SeekInfoResponse(BaseModel):
|
||||||
|
# 更新:
|
||||||
id: str
|
id: str
|
||||||
|
# 更新:
|
||||||
user_id: str
|
user_id: str
|
||||||
user_name: Optional[str] = None
|
# 更新:
|
||||||
network_matched_count: Optional[int] = 0
|
|
||||||
title: str
|
title: str
|
||||||
|
# 更新:
|
||||||
content: Optional[str]
|
content: Optional[str]
|
||||||
|
# 更新:
|
||||||
expect_category: Optional[str]
|
expect_category: Optional[str]
|
||||||
|
# 更新:
|
||||||
expect_version: Optional[str]
|
expect_version: Optional[str]
|
||||||
|
# 更新:
|
||||||
expect_packaging: Optional[str]
|
expect_packaging: Optional[str]
|
||||||
|
# 更新:
|
||||||
expect_number: Optional[str]
|
expect_number: Optional[str]
|
||||||
|
# 更新:
|
||||||
expect_price_min: Optional[float]
|
expect_price_min: Optional[float]
|
||||||
|
# 更新:
|
||||||
expect_price_max: Optional[float]
|
expect_price_max: Optional[float]
|
||||||
|
# 更新:
|
||||||
status: str
|
status: str
|
||||||
|
# 更新:
|
||||||
is_matched: Optional[str]
|
is_matched: Optional[str]
|
||||||
|
# 更新:
|
||||||
matched_user_id: Optional[str]
|
matched_user_id: Optional[str]
|
||||||
|
# 更新:
|
||||||
matched_contact: Optional[str]
|
matched_contact: Optional[str]
|
||||||
|
# 更新:
|
||||||
view_count: int
|
view_count: int
|
||||||
|
# 更新:
|
||||||
contact_count: int
|
contact_count: int
|
||||||
|
# 更新:
|
||||||
created_at: Optional[datetime]
|
created_at: Optional[datetime]
|
||||||
|
# 更新:
|
||||||
updated_at: Optional[datetime]
|
updated_at: Optional[datetime]
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
class Config:
|
class Config:
|
||||||
|
# 更新:
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
# ============ API ============
|
# ============ API ============
|
||||||
|
# 更新:
|
||||||
@router.get("/list", response_model=list[SeekInfoResponse])
|
@router.get("/list", response_model=list[SeekInfoResponse])
|
||||||
|
# 更新:
|
||||||
def get_seek_list(
|
def get_seek_list(
|
||||||
|
# 更新:
|
||||||
status: str = Query("active"),
|
status: str = Query("active"),
|
||||||
|
# 更新:
|
||||||
page: int = Query(1, ge=1),
|
page: int = Query(1, ge=1),
|
||||||
|
# 更新:
|
||||||
page_size: int = Query(20, ge=1, le=1000),
|
page_size: int = Query(20, ge=1, le=1000),
|
||||||
|
# 更新:
|
||||||
user_only: bool = Query(False),
|
user_only: bool = Query(False),
|
||||||
|
# 更新:
|
||||||
current_user: Optional = Depends(get_current_user),
|
current_user: Optional = Depends(get_current_user),
|
||||||
|
# 更新:
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
|
# 更新:
|
||||||
):
|
):
|
||||||
|
# 更新:
|
||||||
"""获取寻配号列表"""
|
"""获取寻配号列表"""
|
||||||
|
# 更新:
|
||||||
query = db.query(SeekInfo).filter(SeekInfo.status == status)
|
query = db.query(SeekInfo).filter(SeekInfo.status == status)
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
# 我的寻配号:只查看自己的
|
# 我的寻配号:只查看自己的
|
||||||
|
# 更新:
|
||||||
if user_only and current_user:
|
if user_only and current_user:
|
||||||
|
# 更新:
|
||||||
query = query.filter(SeekInfo.user_id == current_user.f99_90_id)
|
query = query.filter(SeekInfo.user_id == current_user.f99_90_id)
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
# 排序
|
# 排序
|
||||||
|
# 更新:
|
||||||
query = query.order_by(SeekInfo.created_at.desc())
|
query = query.order_by(SeekInfo.created_at.desc())
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
# 分页
|
# 分页
|
||||||
|
# 更新:
|
||||||
offset = (page - 1) * page_size
|
offset = (page - 1) * page_size
|
||||||
|
# 更新:
|
||||||
items = query.offset(offset).limit(page_size).all()
|
items = query.offset(offset).limit(page_size).all()
|
||||||
|
# 更新:
|
||||||
|
|
||||||
# 关联查询用户名
|
# 更新:
|
||||||
result = []
|
return items
|
||||||
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 None
|
|
||||||
# 计算网络数据匹配数
|
|
||||||
network_matched_count = 0
|
|
||||||
if item.expect_number:
|
|
||||||
network_matched_count = match_collections_count_from_coolbot(item.expect_number)
|
|
||||||
|
|
||||||
result.append({
|
|
||||||
"id": item.id,
|
|
||||||
"user_id": item.user_id,
|
|
||||||
"user_name": user_name,
|
|
||||||
"title": item.title,
|
|
||||||
"content": item.content,
|
|
||||||
"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,
|
|
||||||
"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,
|
|
||||||
"network_matched_count": network_matched_count,
|
|
||||||
"created_at": item.created_at.isoformat() if item.created_at else None,
|
|
||||||
"updated_at": item.updated_at.isoformat() if item.updated_at else None,
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
# 更新:
|
||||||
@router.get("/stats")
|
@router.get("/stats")
|
||||||
|
# 更新:
|
||||||
def get_seek_stats(
|
def get_seek_stats(
|
||||||
|
# 更新:
|
||||||
current_user = Depends(get_current_user),
|
current_user = Depends(get_current_user),
|
||||||
|
# 更新:
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
|
# 更新:
|
||||||
):
|
):
|
||||||
|
# 更新:
|
||||||
"""获取寻配号统计"""
|
"""获取寻配号统计"""
|
||||||
|
# 更新:
|
||||||
total = db.query(SeekInfo).filter(SeekInfo.status == "active").count()
|
total = db.query(SeekInfo).filter(SeekInfo.status == "active").count()
|
||||||
|
# 更新:
|
||||||
matched = db.query(SeekInfo).filter(SeekInfo.is_matched == "true").count()
|
matched = db.query(SeekInfo).filter(SeekInfo.is_matched == "true").count()
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
return {
|
return {
|
||||||
|
# 更新:
|
||||||
"total": total,
|
"total": total,
|
||||||
|
# 更新:
|
||||||
"matched": matched,
|
"matched": matched,
|
||||||
|
# 更新:
|
||||||
"unmatched": total - matched
|
"unmatched": total - matched
|
||||||
|
# 更新:
|
||||||
}
|
}
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
@router.post("", response_model=SeekInfoResponse)
|
@router.post("", response_model=SeekInfoResponse)
|
||||||
|
# 更新:
|
||||||
def create_seek(
|
def create_seek(
|
||||||
|
# 更新:
|
||||||
data: SeekInfoCreate,
|
data: SeekInfoCreate,
|
||||||
|
# 更新:
|
||||||
current_user = Depends(get_current_user),
|
current_user = Depends(get_current_user),
|
||||||
|
# 更新:
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
|
# 更新:
|
||||||
):
|
):
|
||||||
|
# 更新:
|
||||||
"""创建寻配号"""
|
"""创建寻配号"""
|
||||||
|
# 更新:
|
||||||
if not current_user:
|
if not current_user:
|
||||||
|
# 更新:
|
||||||
raise HTTPException(status_code=401, detail="请先登录")
|
raise HTTPException(status_code=401, detail="请先登录")
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
seek = SeekInfo(
|
seek = SeekInfo(
|
||||||
|
# 更新:
|
||||||
user_id=current_user.f99_90_id,
|
user_id=current_user.f99_90_id,
|
||||||
|
# 更新:
|
||||||
title=data.title,
|
title=data.title,
|
||||||
|
# 更新:
|
||||||
content=data.content,
|
content=data.content,
|
||||||
|
# 更新:
|
||||||
expect_category=data.expect_category,
|
expect_category=data.expect_category,
|
||||||
|
# 更新:
|
||||||
expect_version=data.expect_version,
|
expect_version=data.expect_version,
|
||||||
|
# 更新:
|
||||||
expect_packaging=data.expect_packaging,
|
expect_packaging=data.expect_packaging,
|
||||||
|
# 更新:
|
||||||
expect_number=data.expect_number,
|
expect_number=data.expect_number,
|
||||||
|
# 更新:
|
||||||
expect_price_min=data.expect_price_min,
|
expect_price_min=data.expect_price_min,
|
||||||
|
# 更新:
|
||||||
expect_price_max=data.expect_price_max,
|
expect_price_max=data.expect_price_max,
|
||||||
|
# 更新:
|
||||||
status="active"
|
status="active"
|
||||||
|
# 更新:
|
||||||
)
|
)
|
||||||
|
# 更新:
|
||||||
db.add(seek)
|
db.add(seek)
|
||||||
|
# 更新:
|
||||||
db.commit()
|
db.commit()
|
||||||
|
# 更新:
|
||||||
db.refresh(seek)
|
db.refresh(seek)
|
||||||
|
# 更新:
|
||||||
return seek
|
return seek
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
@router.get("/{seek_id}", response_model=SeekInfoResponse)
|
@router.get("/{seek_id}", response_model=SeekInfoResponse)
|
||||||
|
# 更新:
|
||||||
def get_seek(
|
def get_seek(
|
||||||
|
# 更新:
|
||||||
seek_id: str,
|
seek_id: str,
|
||||||
|
# 更新:
|
||||||
current_user = Depends(get_current_user),
|
current_user = Depends(get_current_user),
|
||||||
|
# 更新:
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
|
# 更新:
|
||||||
):
|
):
|
||||||
|
# 更新:
|
||||||
"""获取寻配号详情"""
|
"""获取寻配号详情"""
|
||||||
|
# 更新:
|
||||||
seek = db.query(SeekInfo).filter(SeekInfo.id == seek_id).first()
|
seek = db.query(SeekInfo).filter(SeekInfo.id == seek_id).first()
|
||||||
|
# 更新:
|
||||||
if not seek:
|
if not seek:
|
||||||
|
# 更新:
|
||||||
raise HTTPException(status_code=404, detail="寻配号不存在")
|
raise HTTPException(status_code=404, detail="寻配号不存在")
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
# 增加浏览数
|
# 增加浏览数
|
||||||
|
# 更新:
|
||||||
seek.view_count += 1
|
seek.view_count += 1
|
||||||
|
# 更新:
|
||||||
db.commit()
|
db.commit()
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
return seek
|
return seek
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
@router.put("/{seek_id}", response_model=SeekInfoResponse)
|
@router.put("/{seek_id}", response_model=SeekInfoResponse)
|
||||||
|
# 更新:
|
||||||
def update_seek(
|
def update_seek(
|
||||||
|
# 更新:
|
||||||
seek_id: str,
|
seek_id: str,
|
||||||
|
# 更新:
|
||||||
data: SeekInfoUpdate,
|
data: SeekInfoUpdate,
|
||||||
|
# 更新:
|
||||||
current_user = Depends(get_current_user),
|
current_user = Depends(get_current_user),
|
||||||
|
# 更新:
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
|
# 更新:
|
||||||
):
|
):
|
||||||
|
# 更新:
|
||||||
"""更新寻配号"""
|
"""更新寻配号"""
|
||||||
|
# 更新:
|
||||||
if not current_user:
|
if not current_user:
|
||||||
|
# 更新:
|
||||||
raise HTTPException(status_code=401, detail="请先登录")
|
raise HTTPException(status_code=401, detail="请先登录")
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
seek = db.query(SeekInfo).filter(
|
seek = db.query(SeekInfo).filter(
|
||||||
|
# 更新:
|
||||||
SeekInfo.id == seek_id,
|
SeekInfo.id == seek_id,
|
||||||
|
# 更新:
|
||||||
SeekInfo.user_id == current_user.f99_90_id
|
SeekInfo.user_id == current_user.f99_90_id
|
||||||
|
# 更新:
|
||||||
).first()
|
).first()
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
if not seek:
|
if not seek:
|
||||||
|
# 更新:
|
||||||
raise HTTPException(status_code=404, detail="寻配号不存在")
|
raise HTTPException(status_code=404, detail="寻配号不存在")
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
for key, value in data.model_dump(exclude_unset=True).items():
|
for key, value in data.model_dump(exclude_unset=True).items():
|
||||||
|
# 更新:
|
||||||
setattr(seek, key, value)
|
setattr(seek, key, value)
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
db.commit()
|
db.commit()
|
||||||
|
# 更新:
|
||||||
db.refresh(seek)
|
db.refresh(seek)
|
||||||
|
# 更新:
|
||||||
return seek
|
return seek
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
@router.delete("/{seek_id}")
|
@router.delete("/{seek_id}")
|
||||||
|
# 更新:
|
||||||
def delete_seek(
|
def delete_seek(
|
||||||
|
# 更新:
|
||||||
seek_id: str,
|
seek_id: str,
|
||||||
|
# 更新:
|
||||||
current_user = Depends(get_current_user),
|
current_user = Depends(get_current_user),
|
||||||
|
# 更新:
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
|
# 更新:
|
||||||
):
|
):
|
||||||
|
# 更新:
|
||||||
"""删除寻配号"""
|
"""删除寻配号"""
|
||||||
|
# 更新:
|
||||||
if not current_user:
|
if not current_user:
|
||||||
|
# 更新:
|
||||||
raise HTTPException(status_code=401, detail="请先登录")
|
raise HTTPException(status_code=401, detail="请先登录")
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
seek = db.query(SeekInfo).filter(
|
seek = db.query(SeekInfo).filter(
|
||||||
|
# 更新:
|
||||||
SeekInfo.id == seek_id,
|
SeekInfo.id == seek_id,
|
||||||
|
# 更新:
|
||||||
SeekInfo.user_id == current_user.f99_90_id
|
SeekInfo.user_id == current_user.f99_90_id
|
||||||
|
# 更新:
|
||||||
).first()
|
).first()
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
if not seek:
|
if not seek:
|
||||||
|
# 更新:
|
||||||
raise HTTPException(status_code=404, detail="寻配号不存在")
|
raise HTTPException(status_code=404, detail="寻配号不存在")
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
seek.status = "deleted"
|
seek.status = "deleted"
|
||||||
|
# 更新:
|
||||||
db.commit()
|
db.commit()
|
||||||
|
# 更新:
|
||||||
|
|
||||||
|
# 更新:
|
||||||
return {"message": "删除成功"}
|
return {"message": "删除成功"}
|
||||||
|
# 更新:
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from fastapi import APIRouter, Depends, HTTPException, status, Query, Body
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
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.models.models import User, Collection, Information
|
from app.models.models import User, Collection
|
||||||
from app.schemas.schemas import UserResponse, UserUpdate
|
from app.schemas.schemas import UserResponse, UserUpdate
|
||||||
|
|
||||||
router = APIRouter(prefix="/api", tags=["用户"])
|
router = APIRouter(prefix="/api", tags=["用户"])
|
||||||
|
|
@ -100,7 +100,7 @@ def get_users(
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
):
|
):
|
||||||
"""获取用户列表(仅管理员)"""
|
"""获取用户列表(仅管理员)"""
|
||||||
if not current_user or current_user.role not in ["admin", "editor"]:
|
if current_user.role not in ["admin", "editor"]:
|
||||||
raise HTTPException(status_code=403, detail="无权访问")
|
raise HTTPException(status_code=403, detail="无权访问")
|
||||||
|
|
||||||
total = db.query(User).count()
|
total = db.query(User).count()
|
||||||
|
|
@ -152,7 +152,7 @@ def get_user(
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
):
|
):
|
||||||
"""获取单个用户信息"""
|
"""获取单个用户信息"""
|
||||||
if not current_user or current_user.role not in ["admin", "editor"]:
|
if current_user.role not in ["admin", "editor"]:
|
||||||
raise HTTPException(status_code=403, detail="无权访问")
|
raise HTTPException(status_code=403, detail="无权访问")
|
||||||
|
|
||||||
user = db.query(User).filter(User.id == user_id).first()
|
user = db.query(User).filter(User.id == user_id).first()
|
||||||
|
|
@ -177,7 +177,7 @@ def get_user_collections(
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
):
|
):
|
||||||
"""获取指定用户的藏品列表"""
|
"""获取指定用户的藏品列表"""
|
||||||
if not current_user or current_user.role not in ["admin", "editor"]:
|
if current_user.role not in ["admin", "editor"]:
|
||||||
raise HTTPException(status_code=403, detail="无权访问")
|
raise HTTPException(status_code=403, detail="无权访问")
|
||||||
|
|
||||||
collections = db.query(Collection).filter(
|
collections = db.query(Collection).filter(
|
||||||
|
|
@ -194,7 +194,7 @@ def get_user_collection_count(
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
):
|
):
|
||||||
"""获取指定用户的藏品数量"""
|
"""获取指定用户的藏品数量"""
|
||||||
if not current_user or current_user.role not in ["admin", "editor"]:
|
if current_user.role not in ["admin", "editor"]:
|
||||||
raise HTTPException(status_code=403, detail="E00050: 仅管理员可访问")
|
raise HTTPException(status_code=403, detail="E00050: 仅管理员可访问")
|
||||||
|
|
||||||
count = db.query(Collection).filter(Collection.user_id == user_id).count()
|
count = db.query(Collection).filter(Collection.user_id == user_id).count()
|
||||||
|
|
@ -219,7 +219,7 @@ def update_user(
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
):
|
):
|
||||||
"""更新用户信息(仅管理员)"""
|
"""更新用户信息(仅管理员)"""
|
||||||
if not current_user or current_user.role not in ["admin", "editor"]:
|
if current_user.role not in ["admin", "editor"]:
|
||||||
raise HTTPException(status_code=403, detail="E00050: 仅管理员可访问")
|
raise HTTPException(status_code=403, detail="E00050: 仅管理员可访问")
|
||||||
|
|
||||||
user = db.query(User).filter(User.f99_90_id == user_id).first()
|
user = db.query(User).filter(User.f99_90_id == user_id).first()
|
||||||
|
|
@ -297,7 +297,7 @@ def delete_user(
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
):
|
):
|
||||||
"""删除用户(仅管理员)"""
|
"""删除用户(仅管理员)"""
|
||||||
if not current_user or current_user.role not in ["admin", "editor"]:
|
if current_user.role not in ["admin", "editor"]:
|
||||||
raise HTTPException(status_code=403, detail="E00050: 仅管理员可访问")
|
raise HTTPException(status_code=403, detail="E00050: 仅管理员可访问")
|
||||||
|
|
||||||
# 不能删除自己
|
# 不能删除自己
|
||||||
|
|
|
||||||
|
|
@ -1,760 +1,377 @@
|
||||||
# yichens - 一尘数据路由
|
|
||||||
# Version: 0.0.1
|
|
||||||
# 更新:
|
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Query
|
from fastapi import APIRouter, Depends, Query
|
||||||
# 更新:
|
|
||||||
# Version: 1.2.x
|
|
||||||
# 更新:
|
|
||||||
from sqlalchemy import func, text
|
from sqlalchemy import func, text
|
||||||
# 更新:
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
# 更新:
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
# 更新:
|
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
# 更新:
|
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
# 更新:
|
|
||||||
from app.core.coolbot_db import get_coolbot_db
|
from app.core.coolbot_db import get_coolbot_db
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
router = APIRouter(prefix="/api/yichens", tags=["一尘看板"])
|
router = APIRouter(prefix="/api/yichens", tags=["一尘看板"])
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
# ============ 数据模型 ============
|
# ============ 数据模型 ============
|
||||||
# 更新:
|
|
||||||
class YichensPostStats(BaseModel):
|
class YichensPostStats(BaseModel):
|
||||||
# 更新:
|
|
||||||
total_posts: int
|
total_posts: int
|
||||||
# 更新:
|
|
||||||
total_deals: int # 出售
|
total_deals: int # 出售
|
||||||
# 更新:
|
|
||||||
total_wants: int # 求购
|
total_wants: int # 求购
|
||||||
# 更新:
|
|
||||||
total_replies: int
|
total_replies: int
|
||||||
# 更新:
|
|
||||||
total_views: int
|
total_views: int
|
||||||
# 更新:
|
|
||||||
avg_price: Optional[float]
|
avg_price: Optional[float]
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
class CategoryStat(BaseModel):
|
class CategoryStat(BaseModel):
|
||||||
# 更新:
|
|
||||||
category: str
|
category: str
|
||||||
# 更新:
|
|
||||||
count: int
|
count: int
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
class PostItem(BaseModel):
|
class PostItem(BaseModel):
|
||||||
# 更新:
|
|
||||||
post_id: str
|
post_id: str
|
||||||
# 更新:
|
|
||||||
title: str
|
title: str
|
||||||
# 更新:
|
|
||||||
category: Optional[str]
|
category: Optional[str]
|
||||||
# 更新:
|
|
||||||
post_type: str
|
post_type: str
|
||||||
# 更新:
|
|
||||||
price: Optional[float]
|
price: Optional[float]
|
||||||
# 更新:
|
|
||||||
author_username: str
|
author_username: str
|
||||||
# 更新:
|
|
||||||
post_time: str
|
post_time: str
|
||||||
# 更新:
|
|
||||||
reply_count: int
|
reply_count: int
|
||||||
# 更新:
|
|
||||||
view_count: int
|
view_count: int
|
||||||
# 更新:
|
|
||||||
url: Optional[str]
|
url: Optional[str]
|
||||||
# 更新:
|
|
||||||
content: Optional[str]
|
content: Optional[str]
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
class UserStat(BaseModel):
|
class UserStat(BaseModel):
|
||||||
# 更新:
|
|
||||||
total_users: int
|
total_users: int
|
||||||
# 更新:
|
|
||||||
new_users_today: int
|
new_users_today: int
|
||||||
# 更新:
|
|
||||||
sellers: int
|
sellers: int
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
class UserItem(BaseModel):
|
class UserItem(BaseModel):
|
||||||
# 更新:
|
|
||||||
user_id: str
|
user_id: str
|
||||||
# 更新:
|
|
||||||
username: str
|
username: str
|
||||||
# 更新:
|
|
||||||
avatar_url: Optional[str]
|
avatar_url: Optional[str]
|
||||||
# 更新:
|
|
||||||
content: Optional[str]
|
content: Optional[str]
|
||||||
# 更新:
|
|
||||||
credit_level: Optional[str]
|
credit_level: Optional[str]
|
||||||
# 更新:
|
|
||||||
credit_score: Optional[int]
|
credit_score: Optional[int]
|
||||||
# 更新:
|
|
||||||
post_count: int
|
post_count: int
|
||||||
# 更新:
|
|
||||||
is_seller: bool
|
is_seller: bool
|
||||||
# 更新:
|
|
||||||
registration_date: Optional[str]
|
registration_date: Optional[str]
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
# ============ 统计接口 ============
|
# ============ 统计接口 ============
|
||||||
# 更新:
|
|
||||||
@router.get("/stats/posts", response_model=YichensPostStats)
|
@router.get("/stats/posts", response_model=YichensPostStats)
|
||||||
# 更新:
|
|
||||||
def get_post_stats(days: int = Query(30, ge=1, le=365), db: Session = Depends(get_coolbot_db)):
|
def get_post_stats(days: int = Query(30, ge=1, le=365), db: Session = Depends(get_coolbot_db)):
|
||||||
# 更新:
|
|
||||||
"""获取帖子统计"""
|
"""获取帖子统计"""
|
||||||
# 更新:
|
|
||||||
result = db.execute(text("""
|
result = db.execute(text("""
|
||||||
# 更新:
|
|
||||||
SELECT
|
SELECT
|
||||||
# 更新:
|
|
||||||
COUNT(*) as total_posts,
|
COUNT(*) as total_posts,
|
||||||
# 更新:
|
|
||||||
COUNT(*) FILTER (WHERE post_type = 'deal') as total_deals,
|
COUNT(*) FILTER (WHERE post_type = 'deal') as total_deals,
|
||||||
# 更新:
|
|
||||||
COUNT(*) FILTER (WHERE post_type = 'want') as total_wants,
|
COUNT(*) FILTER (WHERE post_type = 'want') as total_wants,
|
||||||
# 更新:
|
|
||||||
COALESCE(SUM(reply_count), 0) as total_replies,
|
COALESCE(SUM(reply_count), 0) as total_replies,
|
||||||
# 更新:
|
|
||||||
COALESCE(SUM(view_count), 0) as total_views,
|
COALESCE(SUM(view_count), 0) as total_views,
|
||||||
# 更新:
|
|
||||||
AVG(price) as avg_price
|
AVG(price) as avg_price
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE post_time >= NOW() - INTERVAL '1 day' * :days
|
WHERE post_time >= NOW() - INTERVAL '1 day' * :days
|
||||||
# 更新:
|
|
||||||
"""), {"days": days}).fetchone()
|
"""), {"days": days}).fetchone()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
return YichensPostStats(
|
return YichensPostStats(
|
||||||
# 更新:
|
|
||||||
total_posts=result[0] or 0,
|
total_posts=result[0] or 0,
|
||||||
# 更新:
|
|
||||||
total_deals=result[1] or 0,
|
total_deals=result[1] or 0,
|
||||||
# 更新:
|
|
||||||
total_wants=result[2] or 0,
|
total_wants=result[2] or 0,
|
||||||
# 更新:
|
|
||||||
total_replies=result[3] or 0,
|
total_replies=result[3] or 0,
|
||||||
# 更新:
|
|
||||||
total_views=result[4] or 0,
|
total_views=result[4] or 0,
|
||||||
# 更新:
|
|
||||||
avg_price=float(result[5]) if result[5] else None
|
avg_price=float(result[5]) if result[5] else None
|
||||||
# 更新:
|
|
||||||
)
|
)
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.get("/stats/categories", response_model=List[CategoryStat])
|
@router.get("/stats/categories", response_model=List[CategoryStat])
|
||||||
# 更新:
|
|
||||||
def get_category_stats(days: int = Query(30, ge=1, le=365), db: Session = Depends(get_coolbot_db)):
|
def get_category_stats(days: int = Query(30, ge=1, le=365), db: Session = Depends(get_coolbot_db)):
|
||||||
# 更新:
|
|
||||||
"""按分类统计帖子数量"""
|
"""按分类统计帖子数量"""
|
||||||
# 更新:
|
|
||||||
results = db.execute(text("""
|
results = db.execute(text("""
|
||||||
# 更新:
|
|
||||||
SELECT category, COUNT(*) as count
|
SELECT category, COUNT(*) as count
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE post_time >= NOW() - INTERVAL '1 day' * :days
|
WHERE post_time >= NOW() - INTERVAL '1 day' * :days
|
||||||
# 更新:
|
|
||||||
GROUP BY category
|
GROUP BY category
|
||||||
# 更新:
|
|
||||||
ORDER BY count DESC
|
ORDER BY count DESC
|
||||||
# 更新:
|
|
||||||
"""), {"days": days}).fetchall()
|
"""), {"days": days}).fetchall()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
return [CategoryStat(category=r[0] or "未知", count=r[1]) for r in results]
|
return [CategoryStat(category=r[0] or "未知", count=r[1]) for r in results]
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.get("/stats/users", response_model=UserStat)
|
@router.get("/stats/users", response_model=UserStat)
|
||||||
# 更新:
|
|
||||||
def get_user_stats(db: Session = Depends(get_coolbot_db)):
|
def get_user_stats(db: Session = Depends(get_coolbot_db)):
|
||||||
# 更新:
|
|
||||||
"""获取用户统计"""
|
"""获取用户统计"""
|
||||||
# 更新:
|
|
||||||
result = db.execute(text("""
|
result = db.execute(text("""
|
||||||
# 更新:
|
|
||||||
SELECT
|
SELECT
|
||||||
# 更新:
|
|
||||||
COUNT(*) as total_users,
|
COUNT(*) as total_users,
|
||||||
# 更新:
|
|
||||||
COUNT(*) FILTER (WHERE created_at::date = CURRENT_DATE) as new_users_today,
|
COUNT(*) FILTER (WHERE created_at::date = CURRENT_DATE) as new_users_today,
|
||||||
# 更新:
|
|
||||||
COUNT(*) FILTER (WHERE is_seller = true) as sellers
|
COUNT(*) FILTER (WHERE is_seller = true) as sellers
|
||||||
# 更新:
|
|
||||||
FROM yichens_users
|
FROM yichens_users
|
||||||
# 更新:
|
|
||||||
""")).fetchone()
|
""")).fetchone()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
return UserStat(
|
return UserStat(
|
||||||
# 更新:
|
|
||||||
total_users=result[0] or 0,
|
total_users=result[0] or 0,
|
||||||
# 更新:
|
|
||||||
new_users_today=result[1] or 0,
|
new_users_today=result[1] or 0,
|
||||||
# 更新:
|
|
||||||
sellers=result[2] or 0
|
sellers=result[2] or 0
|
||||||
# 更新:
|
|
||||||
)
|
)
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.get("/posts")
|
@router.get("/posts")
|
||||||
# 更新:
|
|
||||||
def get_posts(
|
def get_posts(
|
||||||
# 更新:
|
|
||||||
limit: int = Query(20, ge=1, le=500),
|
limit: int = Query(20, ge=1, le=500),
|
||||||
# 更新:
|
|
||||||
offset: int = Query(0, ge=0),
|
offset: int = Query(0, ge=0),
|
||||||
# 更新:
|
|
||||||
category: Optional[str] = None,
|
category: Optional[str] = None,
|
||||||
# 更新:
|
|
||||||
post_type: Optional[str] = None,
|
post_type: Optional[str] = None,
|
||||||
# 更新:
|
|
||||||
keyword: Optional[str] = None,
|
keyword: Optional[str] = None,
|
||||||
# 更新:
|
|
||||||
db: Session = Depends(get_coolbot_db)
|
db: Session = Depends(get_coolbot_db)
|
||||||
# 更新:
|
|
||||||
):
|
):
|
||||||
# 更新:
|
|
||||||
"""获取帖子列表 - 支持全局搜索,返回总数和分页信息"""
|
"""获取帖子列表 - 支持全局搜索,返回总数和分页信息"""
|
||||||
# 更新:
|
|
||||||
# 构建WHERE条件
|
# 构建WHERE条件
|
||||||
# 更新:
|
|
||||||
where_clauses = ["1=1"]
|
where_clauses = ["1=1"]
|
||||||
# 更新:
|
|
||||||
params = {"limit": limit, "offset": offset}
|
params = {"limit": limit, "offset": offset}
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
if category:
|
if category:
|
||||||
# 更新:
|
|
||||||
where_clauses.append("category = :category")
|
where_clauses.append("category = :category")
|
||||||
# 更新:
|
|
||||||
params["category"] = category
|
params["category"] = category
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
if post_type:
|
if post_type:
|
||||||
# 更新:
|
|
||||||
where_clauses.append("post_type = :post_type")
|
where_clauses.append("post_type = :post_type")
|
||||||
# 更新:
|
|
||||||
params["post_type"] = post_type
|
params["post_type"] = post_type
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
# 全局搜索
|
# 全局搜索
|
||||||
# 更新:
|
|
||||||
if keyword:
|
if keyword:
|
||||||
# 更新:
|
|
||||||
where_clauses.append("(title ILIKE :keyword OR content ILIKE :keyword OR category ILIKE :keyword OR author_username ILIKE :keyword)")
|
where_clauses.append("(title ILIKE :keyword OR content ILIKE :keyword OR category ILIKE :keyword OR author_username ILIKE :keyword)")
|
||||||
# 更新:
|
|
||||||
params["keyword"] = f"%{keyword}%"
|
params["keyword"] = f"%{keyword}%"
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
where_sql = " AND ".join(where_clauses)
|
where_sql = " AND ".join(where_clauses)
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
# 查询总数
|
# 查询总数
|
||||||
# 更新:
|
|
||||||
count_query = f"SELECT COUNT(*) FROM yichens_posts WHERE {where_sql}"
|
count_query = f"SELECT COUNT(*) FROM yichens_posts WHERE {where_sql}"
|
||||||
# 更新:
|
|
||||||
total_count = db.execute(text(count_query), {k: v for k, v in params.items() if k not in ['limit', 'offset']}).scalar() or 0
|
total_count = db.execute(text(count_query), {k: v for k, v in params.items() if k not in ['limit', 'offset']}).scalar() or 0
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
# 查询数据 - 有post_time时按post_time排序,没有时按crawled_at排序
|
# 查询数据 - 有post_time时按post_time排序,没有时按crawled_at排序
|
||||||
# 更新:
|
|
||||||
data_query = f"""
|
data_query = f"""
|
||||||
# 更新:
|
|
||||||
SELECT post_id, title, content, category, post_type, price,
|
SELECT post_id, title, content, category, post_type, price,
|
||||||
# 更新:
|
|
||||||
author_username, post_time, reply_count, view_count, url
|
author_username, post_time, reply_count, view_count, url
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE {where_sql}
|
WHERE {where_sql}
|
||||||
# 更新:
|
|
||||||
ORDER BY COALESCE(post_time, crawled_at) DESC LIMIT :limit OFFSET :offset
|
ORDER BY COALESCE(post_time, crawled_at) DESC LIMIT :limit OFFSET :offset
|
||||||
# 更新:
|
|
||||||
"""
|
"""
|
||||||
# 更新:
|
|
||||||
results = db.execute(text(data_query), params).fetchall()
|
results = db.execute(text(data_query), params).fetchall()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
posts = [PostItem(
|
posts = [PostItem(
|
||||||
# 更新:
|
|
||||||
post_id=r[0],
|
post_id=r[0],
|
||||||
# 更新:
|
|
||||||
title=r[1] or "",
|
title=r[1] or "",
|
||||||
# 更新:
|
|
||||||
content=r[2] or "",
|
content=r[2] or "",
|
||||||
# 更新:
|
|
||||||
category=r[3],
|
category=r[3],
|
||||||
# 更新:
|
|
||||||
post_type=r[4] or "",
|
post_type=r[4] or "",
|
||||||
# 更新:
|
|
||||||
price=float(r[5]) if r[5] else None,
|
price=float(r[5]) if r[5] else None,
|
||||||
# 更新:
|
|
||||||
author_username=r[6] or "",
|
author_username=r[6] or "",
|
||||||
# 更新:
|
|
||||||
post_time=str(r[7]) if r[7] else "",
|
post_time=str(r[7]) if r[7] else "",
|
||||||
# 更新:
|
|
||||||
reply_count=r[8] or 0,
|
reply_count=r[8] or 0,
|
||||||
# 更新:
|
|
||||||
view_count=r[9] or 0,
|
view_count=r[9] or 0,
|
||||||
# 更新:
|
|
||||||
url=r[10]
|
url=r[10]
|
||||||
# 更新:
|
|
||||||
) for r in results]
|
) for r in results]
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
return {
|
return {
|
||||||
# 更新:
|
|
||||||
"posts": posts,
|
"posts": posts,
|
||||||
# 更新:
|
|
||||||
"total": total_count,
|
"total": total_count,
|
||||||
# 更新:
|
|
||||||
"page": offset // limit + 1,
|
"page": offset // limit + 1,
|
||||||
# 更新:
|
|
||||||
"page_size": limit
|
"page_size": limit
|
||||||
# 更新:
|
|
||||||
}
|
}
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.get("/users", response_model=List[UserItem])
|
@router.get("/users", response_model=List[UserItem])
|
||||||
# 更新:
|
|
||||||
def get_users(
|
def get_users(
|
||||||
# 更新:
|
|
||||||
limit: int = Query(20, ge=1, le=500),
|
limit: int = Query(20, ge=1, le=500),
|
||||||
# 更新:
|
|
||||||
offset: int = Query(0, ge=0),
|
offset: int = Query(0, ge=0),
|
||||||
# 更新:
|
|
||||||
is_seller: Optional[bool] = None,
|
is_seller: Optional[bool] = None,
|
||||||
# 更新:
|
|
||||||
db: Session = Depends(get_coolbot_db)
|
db: Session = Depends(get_coolbot_db)
|
||||||
# 更新:
|
|
||||||
):
|
):
|
||||||
# 更新:
|
|
||||||
"""获取用户列表"""
|
"""获取用户列表"""
|
||||||
# 更新:
|
|
||||||
query = """
|
query = """
|
||||||
# 更新:
|
|
||||||
SELECT user_id, username, avatar_url, credit_level, credit_score,
|
SELECT user_id, username, avatar_url, credit_level, credit_score,
|
||||||
# 更新:
|
|
||||||
post_count, is_seller, registration_date
|
post_count, is_seller, registration_date
|
||||||
# 更新:
|
|
||||||
FROM yichens_users
|
FROM yichens_users
|
||||||
# 更新:
|
|
||||||
WHERE 1=1
|
WHERE 1=1
|
||||||
# 更新:
|
|
||||||
"""
|
"""
|
||||||
# 更新:
|
|
||||||
params = {"limit": limit, "offset": offset}
|
params = {"limit": limit, "offset": offset}
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
if is_seller is not None:
|
if is_seller is not None:
|
||||||
# 更新:
|
|
||||||
query += " AND is_seller = :is_seller"
|
query += " AND is_seller = :is_seller"
|
||||||
# 更新:
|
|
||||||
params["is_seller"] = is_seller
|
params["is_seller"] = is_seller
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
query += " ORDER BY post_count DESC LIMIT :limit OFFSET :offset"
|
query += " ORDER BY post_count DESC LIMIT :limit OFFSET :offset"
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
results = db.execute(text(query), params).fetchall()
|
results = db.execute(text(query), params).fetchall()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
return [UserItem(
|
return [UserItem(
|
||||||
# 更新:
|
|
||||||
user_id=r[0],
|
user_id=r[0],
|
||||||
# 更新:
|
|
||||||
username=r[1] or "",
|
username=r[1] or "",
|
||||||
# 更新:
|
|
||||||
avatar_url=r[2],
|
avatar_url=r[2],
|
||||||
# 更新:
|
|
||||||
credit_level=r[3],
|
credit_level=r[3],
|
||||||
# 更新:
|
|
||||||
credit_score=r[4],
|
credit_score=r[4],
|
||||||
# 更新:
|
|
||||||
post_count=r[5] or 0,
|
post_count=r[5] or 0,
|
||||||
# 更新:
|
|
||||||
is_seller=r[6] or False,
|
is_seller=r[6] or False,
|
||||||
# 更新:
|
|
||||||
registration_date=str(r[7]) if r[7] else None
|
registration_date=str(r[7]) if r[7] else None
|
||||||
# 更新:
|
|
||||||
) for r in results]
|
) for r in results]
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.get("/stats/today")
|
@router.get("/stats/today")
|
||||||
# 更新:
|
|
||||||
async def get_today_stats(db: Session = Depends(get_coolbot_db)):
|
async def get_today_stats(db: Session = Depends(get_coolbot_db)):
|
||||||
# 更新:
|
|
||||||
"""获取今日新增帖子统计"""
|
"""获取今日新增帖子统计"""
|
||||||
# 更新:
|
|
||||||
query = """
|
query = """
|
||||||
# 更新:
|
|
||||||
SELECT
|
SELECT
|
||||||
# 更新:
|
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants,
|
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'normal' THEN 1 ELSE 0 END) as others,
|
SUM(CASE WHEN post_type = 'normal' THEN 1 ELSE 0 END) as others,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN category LIKE '%龙%' THEN 1 ELSE 0 END) as dragons,
|
SUM(CASE WHEN category LIKE '%龙%' THEN 1 ELSE 0 END) as dragons,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN category LIKE '%马%' THEN 1 ELSE 0 END) as horses,
|
SUM(CASE WHEN category LIKE '%马%' THEN 1 ELSE 0 END) as horses,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN category LIKE '%蛇%' THEN 1 ELSE 0 END) as snakes,
|
SUM(CASE WHEN category LIKE '%蛇%' THEN 1 ELSE 0 END) as snakes,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN title LIKE '%天马%' OR content LIKE '%天马%' THEN 1 ELSE 0 END) as tianma
|
SUM(CASE WHEN title LIKE '%天马%' OR content LIKE '%天马%' THEN 1 ELSE 0 END) as tianma
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE post_time >= CURRENT_DATE
|
WHERE post_time >= CURRENT_DATE
|
||||||
# 更新:
|
|
||||||
"""
|
"""
|
||||||
# 更新:
|
|
||||||
result = db.execute(text(query)).fetchone()
|
result = db.execute(text(query)).fetchone()
|
||||||
# 更新:
|
|
||||||
return {
|
return {
|
||||||
# 更新:
|
|
||||||
"total": result[0] or 0,
|
"total": result[0] or 0,
|
||||||
# 更新:
|
|
||||||
"deals": result[1] or 0,
|
"deals": result[1] or 0,
|
||||||
# 更新:
|
|
||||||
"wants": result[2] or 0,
|
"wants": result[2] or 0,
|
||||||
# 更新:
|
|
||||||
"others": result[3] or 0,
|
"others": result[3] or 0,
|
||||||
# 更新:
|
|
||||||
"dragons": result[4] or 0,
|
"dragons": result[4] or 0,
|
||||||
# 更新:
|
|
||||||
"horses": result[5] or 0,
|
"horses": result[5] or 0,
|
||||||
# 更新:
|
|
||||||
"snakes": result[6] or 0,
|
"snakes": result[6] or 0,
|
||||||
# 更新:
|
|
||||||
"tianma": result[7] or 0
|
"tianma": result[7] or 0
|
||||||
# 更新:
|
|
||||||
}
|
}
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.get("/stats/hour")
|
@router.get("/stats/hour")
|
||||||
# 更新:
|
|
||||||
async def get_hour_stats(db: Session = Depends(get_coolbot_db)):
|
async def get_hour_stats(db: Session = Depends(get_coolbot_db)):
|
||||||
# 更新:
|
|
||||||
"""获取近一个小时新增帖子统计"""
|
"""获取近一个小时新增帖子统计"""
|
||||||
# 更新:
|
|
||||||
query = """
|
query = """
|
||||||
# 更新:
|
|
||||||
SELECT
|
SELECT
|
||||||
# 更新:
|
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants,
|
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'normal' THEN 1 ELSE 0 END) as others,
|
SUM(CASE WHEN post_type = 'normal' THEN 1 ELSE 0 END) as others,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN category LIKE '%龙%' THEN 1 ELSE 0 END) as dragons,
|
SUM(CASE WHEN category LIKE '%龙%' THEN 1 ELSE 0 END) as dragons,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN category LIKE '%马%' THEN 1 ELSE 0 END) as horses,
|
SUM(CASE WHEN category LIKE '%马%' THEN 1 ELSE 0 END) as horses,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN category LIKE '%蛇%' THEN 1 ELSE 0 END) as snakes
|
SUM(CASE WHEN category LIKE '%蛇%' THEN 1 ELSE 0 END) as snakes
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE post_time >= NOW() - INTERVAL '1 hour'
|
WHERE post_time >= NOW() - INTERVAL '1 hour'
|
||||||
# 更新:
|
|
||||||
"""
|
"""
|
||||||
# 更新:
|
|
||||||
result = db.execute(text(query)).fetchone()
|
result = db.execute(text(query)).fetchone()
|
||||||
# 更新:
|
|
||||||
return {
|
return {
|
||||||
# 更新:
|
|
||||||
"total": result[0] or 0,
|
"total": result[0] or 0,
|
||||||
# 更新:
|
|
||||||
"deals": result[1] or 0,
|
"deals": result[1] or 0,
|
||||||
# 更新:
|
|
||||||
"wants": result[2] or 0,
|
"wants": result[2] or 0,
|
||||||
# 更新:
|
|
||||||
"others": result[3] or 0,
|
"others": result[3] or 0,
|
||||||
# 更新:
|
|
||||||
"dragons": result[3] or 0,
|
"dragons": result[3] or 0,
|
||||||
# 更新:
|
|
||||||
"horses": result[4] or 0,
|
"horses": result[4] or 0,
|
||||||
# 更新:
|
|
||||||
"snakes": result[5] or 0
|
"snakes": result[5] or 0
|
||||||
# 更新:
|
|
||||||
}
|
}
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.get("/stats/today-category")
|
@router.get("/stats/today-category")
|
||||||
# 更新:
|
|
||||||
async def get_today_category_stats(db: Session = Depends(get_coolbot_db)):
|
async def get_today_category_stats(db: Session = Depends(get_coolbot_db)):
|
||||||
# 更新:
|
|
||||||
"""获取今日帖子分类统计"""
|
"""获取今日帖子分类统计"""
|
||||||
# 更新:
|
|
||||||
query = """
|
query = """
|
||||||
# 更新:
|
|
||||||
SELECT category, COUNT(*) as count
|
SELECT category, COUNT(*) as count
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE post_time >= CURRENT_DATE
|
WHERE post_time >= CURRENT_DATE
|
||||||
# 更新:
|
|
||||||
GROUP BY category
|
GROUP BY category
|
||||||
# 更新:
|
|
||||||
ORDER BY count DESC
|
ORDER BY count DESC
|
||||||
# 更新:
|
|
||||||
"""
|
"""
|
||||||
# 更新:
|
|
||||||
results = db.execute(text(query)).fetchall()
|
results = db.execute(text(query)).fetchall()
|
||||||
# 更新:
|
|
||||||
return [{"category": r[0] or "未分类", "count": r[1]} for r in results]
|
return [{"category": r[0] or "未分类", "count": r[1]} for r in results]
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
@router.get("/stats/dragons-today")
|
@router.get("/stats/dragons-today")
|
||||||
# 更新:
|
|
||||||
def get_dragons_stats_today(
|
def get_dragons_stats_today(
|
||||||
# 更新:
|
|
||||||
db: Session = Depends(get_coolbot_db)
|
db: Session = Depends(get_coolbot_db)
|
||||||
# 更新:
|
|
||||||
):
|
):
|
||||||
# 更新:
|
|
||||||
"""获取今日龙钞详细统计数据(按号码分类)- 就高不就低"""
|
"""获取今日龙钞详细统计数据(按号码分类)- 就高不就低"""
|
||||||
# 更新:
|
|
||||||
from sqlalchemy import text
|
from sqlalchemy import text
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
# 1. 带4:包含"带4"、"带四"、"通货"
|
# 1. 带4:包含"带4"、"带四"、"通货"
|
||||||
# 更新:
|
|
||||||
dai4 = db.execute(text("""
|
dai4 = db.execute(text("""
|
||||||
# 更新:
|
|
||||||
SELECT
|
SELECT
|
||||||
# 更新:
|
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants
|
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE post_time >= CURRENT_DATE
|
WHERE post_time >= CURRENT_DATE
|
||||||
# 更新:
|
|
||||||
AND category LIKE '%龙%'
|
AND category LIKE '%龙%'
|
||||||
# 更新:
|
|
||||||
AND (
|
AND (
|
||||||
# 更新:
|
|
||||||
content LIKE '%带4%' OR title LIKE '%带4%'
|
content LIKE '%带4%' OR title LIKE '%带4%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%带四%' OR title LIKE '%带四%'
|
OR content LIKE '%带四%' OR title LIKE '%带四%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%通货%' OR title LIKE '%通货%'
|
OR content LIKE '%通货%' OR title LIKE '%通货%'
|
||||||
# 更新:
|
|
||||||
)
|
)
|
||||||
# 更新:
|
|
||||||
""")).fetchone()
|
""")).fetchone()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
# 2. 无4:包含"无4"、"无四",排除"无47"、"无247"、"无四七"、"永恒"
|
# 2. 无4:包含"无4"、"无四",排除"无47"、"无247"、"无四七"、"永恒"
|
||||||
# 更新:
|
|
||||||
wu4 = db.execute(text("""
|
wu4 = db.execute(text("""
|
||||||
# 更新:
|
|
||||||
SELECT
|
SELECT
|
||||||
# 更新:
|
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants
|
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE post_time >= CURRENT_DATE
|
WHERE post_time >= CURRENT_DATE
|
||||||
# 更新:
|
|
||||||
AND category LIKE '%龙%'
|
AND category LIKE '%龙%'
|
||||||
# 更新:
|
|
||||||
AND (
|
AND (
|
||||||
# 更新:
|
|
||||||
content LIKE '%无4%' OR title LIKE '%无4%'
|
content LIKE '%无4%' OR title LIKE '%无4%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%无四%' OR title LIKE '%无四%'
|
OR content LIKE '%无四%' OR title LIKE '%无四%'
|
||||||
# 更新:
|
|
||||||
)
|
)
|
||||||
# 更新:
|
|
||||||
AND content NOT LIKE '%无47%' AND title NOT LIKE '%无47%'
|
AND content NOT LIKE '%无47%' AND title NOT LIKE '%无47%'
|
||||||
# 更新:
|
|
||||||
AND content NOT LIKE '%无247%' AND title NOT LIKE '%无247%'
|
AND content NOT LIKE '%无247%' AND title NOT LIKE '%无247%'
|
||||||
# 更新:
|
|
||||||
AND content NOT LIKE '%永恒%' AND title NOT LIKE '%永恒%'
|
AND content NOT LIKE '%永恒%' AND title NOT LIKE '%永恒%'
|
||||||
# 更新:
|
|
||||||
AND content NOT LIKE '%无四七%' AND title NOT LIKE '%无四七%'
|
AND content NOT LIKE '%无四七%' AND title NOT LIKE '%无四七%'
|
||||||
# 更新:
|
|
||||||
""")).fetchone()
|
""")).fetchone()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
# 3. 无47:包含"无47"、"永恒"、"无四七",排除"无247"
|
# 3. 无47:包含"无47"、"永恒"、"无四七",排除"无247"
|
||||||
# 更新:
|
|
||||||
wu47 = db.execute(text("""
|
wu47 = db.execute(text("""
|
||||||
# 更新:
|
|
||||||
SELECT
|
SELECT
|
||||||
# 更新:
|
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants
|
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE post_time >= CURRENT_DATE
|
WHERE post_time >= CURRENT_DATE
|
||||||
# 更新:
|
|
||||||
AND category LIKE '%龙%'
|
AND category LIKE '%龙%'
|
||||||
# 更新:
|
|
||||||
AND (
|
AND (
|
||||||
# 更新:
|
|
||||||
content LIKE '%无47%' OR title LIKE '%无47%'
|
content LIKE '%无47%' OR title LIKE '%无47%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%永恒%' OR title LIKE '%永恒%'
|
OR content LIKE '%永恒%' OR title LIKE '%永恒%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%无四七%' OR title LIKE '%无四七%'
|
OR content LIKE '%无四七%' OR title LIKE '%无四七%'
|
||||||
# 更新:
|
|
||||||
)
|
)
|
||||||
# 更新:
|
|
||||||
AND content NOT LIKE '%无247%' AND title NOT LIKE '%无247%'
|
AND content NOT LIKE '%无247%' AND title NOT LIKE '%无247%'
|
||||||
# 更新:
|
|
||||||
""")).fetchone()
|
""")).fetchone()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
# 4. 无247:包含"无247"、"天马"、"金山",排除"无347"
|
# 4. 无247:包含"无247"、"天马"、"金山",排除"无347"
|
||||||
# 更新:
|
|
||||||
wu247 = db.execute(text("""
|
wu247 = db.execute(text("""
|
||||||
# 更新:
|
|
||||||
SELECT
|
SELECT
|
||||||
# 更新:
|
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants
|
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE post_time >= CURRENT_DATE
|
WHERE post_time >= CURRENT_DATE
|
||||||
# 更新:
|
|
||||||
AND category LIKE '%龙%'
|
AND category LIKE '%龙%'
|
||||||
# 更新:
|
|
||||||
AND (
|
AND (
|
||||||
# 更新:
|
|
||||||
content LIKE '%无247%' OR title LIKE '%无247%'
|
content LIKE '%无247%' OR title LIKE '%无247%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%天马%' OR title LIKE '%天马%'
|
OR content LIKE '%天马%' OR title LIKE '%天马%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%金山%' OR title LIKE '%金山%'
|
OR content LIKE '%金山%' OR title LIKE '%金山%'
|
||||||
# 更新:
|
|
||||||
)
|
)
|
||||||
# 更新:
|
|
||||||
AND content NOT LIKE '%无347%' AND title NOT LIKE '%无347%'
|
AND content NOT LIKE '%无347%' AND title NOT LIKE '%无347%'
|
||||||
# 更新:
|
|
||||||
""")).fetchone()
|
""")).fetchone()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
# 5. 无347:包含"无347"、"钻石"、"金马"、"魅力"、"朦胧"
|
# 5. 无347:包含"无347"、"钻石"、"金马"、"魅力"、"朦胧"
|
||||||
# 更新:
|
|
||||||
wu347 = db.execute(text("""
|
wu347 = db.execute(text("""
|
||||||
# 更新:
|
|
||||||
SELECT
|
SELECT
|
||||||
# 更新:
|
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
SUM(CASE WHEN post_type = 'deal' THEN 1 ELSE 0 END) as deals,
|
||||||
# 更新:
|
|
||||||
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants
|
SUM(CASE WHEN post_type = 'want' THEN 1 ELSE 0 END) as wants
|
||||||
# 更新:
|
|
||||||
FROM yichens_posts
|
FROM yichens_posts
|
||||||
# 更新:
|
|
||||||
WHERE post_time >= CURRENT_DATE
|
WHERE post_time >= CURRENT_DATE
|
||||||
# 更新:
|
|
||||||
AND category LIKE '%龙%'
|
AND category LIKE '%龙%'
|
||||||
# 更新:
|
|
||||||
AND (
|
AND (
|
||||||
# 更新:
|
|
||||||
content LIKE '%无347%' OR title LIKE '%无347%'
|
content LIKE '%无347%' OR title LIKE '%无347%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%钻石%' OR title LIKE '%钻石%'
|
OR content LIKE '%钻石%' OR title LIKE '%钻石%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%金马%' OR title LIKE '%金马%'
|
OR content LIKE '%金马%' OR title LIKE '%金马%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%魅力%' OR title LIKE '%魅力%'
|
OR content LIKE '%魅力%' OR title LIKE '%魅力%'
|
||||||
# 更新:
|
|
||||||
OR content LIKE '%朦胧%' OR title LIKE '%朦胧%'
|
OR content LIKE '%朦胧%' OR title LIKE '%朦胧%'
|
||||||
# 更新:
|
|
||||||
)
|
)
|
||||||
# 更新:
|
|
||||||
""")).fetchone()
|
""")).fetchone()
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
return {
|
return {
|
||||||
# 更新:
|
|
||||||
"dai4": {"total": dai4[0] or 0, "deals": dai4[1] or 0, "wants": dai4[2] or 0},
|
"dai4": {"total": dai4[0] or 0, "deals": dai4[1] or 0, "wants": dai4[2] or 0},
|
||||||
# 更新:
|
|
||||||
"wu4": {"total": wu4[0] or 0, "deals": wu4[1] or 0, "wants": wu4[2] or 0},
|
"wu4": {"total": wu4[0] or 0, "deals": wu4[1] or 0, "wants": wu4[2] or 0},
|
||||||
# 更新:
|
|
||||||
"wu47": {"total": wu47[0] or 0, "deals": wu47[1] or 0, "wants": wu47[2] or 0},
|
"wu47": {"total": wu47[0] or 0, "deals": wu47[1] or 0, "wants": wu47[2] or 0},
|
||||||
# 更新:
|
|
||||||
"wu247": {"total": wu247[0] or 0, "deals": wu247[1] or 0, "wants": wu247[2] or 0},
|
"wu247": {"total": wu247[0] or 0, "deals": wu247[1] or 0, "wants": wu247[2] or 0},
|
||||||
# 更新:
|
|
||||||
"wu347": {"total": wu347[0] or 0, "deals": wu347[1] or 0, "wants": wu347[2] or 0}
|
"wu347": {"total": wu347[0] or 0, "deals": wu347[1] or 0, "wants": wu347[2] or 0}
|
||||||
# 更新:
|
|
||||||
}
|
}
|
||||||
# 更新:
|
|
||||||
|
|
||||||
# 更新:
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Pydantic Schema - 使用字段编码并支持 camelCase
|
# Pydantic Schema - 使用字段编码并支持 camelCase
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
from pydantic import BaseModel, EmailStr, Field
|
from pydantic import BaseModel, EmailStr, Field, ConfigDict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,9 +14,7 @@ class UserBase(BaseModel):
|
||||||
address: Optional[str] = None
|
address: Optional[str] = None
|
||||||
bio: Optional[str] = None
|
bio: Optional[str] = None
|
||||||
|
|
||||||
class Config:
|
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
|
||||||
from_attributes = True
|
|
||||||
populate_by_name = True
|
|
||||||
|
|
||||||
|
|
||||||
class UserCreate(UserBase):
|
class UserCreate(UserBase):
|
||||||
|
|
@ -33,9 +31,7 @@ class UserUpdate(BaseModel):
|
||||||
bio: Optional[str] = None
|
bio: Optional[str] = None
|
||||||
password: Optional[str] = None
|
password: Optional[str] = None
|
||||||
|
|
||||||
class Config:
|
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
|
||||||
from_attributes = True
|
|
||||||
populate_by_name = True
|
|
||||||
|
|
||||||
|
|
||||||
class UserResponse(UserBase):
|
class UserResponse(UserBase):
|
||||||
|
|
@ -63,9 +59,7 @@ class UserResponse(UserBase):
|
||||||
f99_92_created_at: Optional[datetime] = Field(None, alias="created_at")
|
f99_92_created_at: Optional[datetime] = Field(None, alias="created_at")
|
||||||
f99_93_updated_at: Optional[datetime] = Field(None, alias="updated_at")
|
f99_93_updated_at: Optional[datetime] = Field(None, alias="updated_at")
|
||||||
|
|
||||||
class Config:
|
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
|
||||||
from_attributes = True
|
|
||||||
populate_by_name = True
|
|
||||||
|
|
||||||
|
|
||||||
# ============ 藏品相关 ============
|
# ============ 藏品相关 ============
|
||||||
|
|
@ -110,9 +104,7 @@ class CollectionBase(BaseModel):
|
||||||
# f06 其他信息
|
# f06 其他信息
|
||||||
f06_50_purpose: Optional[str] = Field(None, alias="purpose")
|
f06_50_purpose: Optional[str] = Field(None, alias="purpose")
|
||||||
|
|
||||||
class Config:
|
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
|
||||||
from_attributes = True
|
|
||||||
populate_by_name = True
|
|
||||||
|
|
||||||
|
|
||||||
class CollectionCreate(CollectionBase):
|
class CollectionCreate(CollectionBase):
|
||||||
|
|
@ -159,9 +151,7 @@ class CollectionUpdate(BaseModel):
|
||||||
# f06 其他信息
|
# f06 其他信息
|
||||||
f06_50_purpose: Optional[str] = Field(None, alias="purpose")
|
f06_50_purpose: Optional[str] = Field(None, alias="purpose")
|
||||||
|
|
||||||
class Config:
|
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
|
||||||
from_attributes = True
|
|
||||||
populate_by_name = True
|
|
||||||
|
|
||||||
|
|
||||||
class CollectionImageResponse(BaseModel):
|
class CollectionImageResponse(BaseModel):
|
||||||
|
|
@ -171,8 +161,7 @@ class CollectionImageResponse(BaseModel):
|
||||||
path: Optional[str] = None
|
path: Optional[str] = None
|
||||||
f99_92_created_at: Optional[datetime] = None
|
f99_92_created_at: Optional[datetime] = None
|
||||||
|
|
||||||
class Config:
|
model_config = ConfigDict(from_attributes=True)
|
||||||
from_attributes = True
|
|
||||||
|
|
||||||
|
|
||||||
class CollectionResponse(CollectionBase):
|
class CollectionResponse(CollectionBase):
|
||||||
|
|
@ -182,9 +171,7 @@ class CollectionResponse(CollectionBase):
|
||||||
f99_93_updated_at: Optional[datetime] = Field(None, alias="updatedAt")
|
f99_93_updated_at: Optional[datetime] = Field(None, alias="updatedAt")
|
||||||
images: List[CollectionImageResponse] = []
|
images: List[CollectionImageResponse] = []
|
||||||
|
|
||||||
class Config:
|
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
|
||||||
from_attributes = True
|
|
||||||
populate_by_name = True
|
|
||||||
|
|
||||||
|
|
||||||
class CollectionListResponse(BaseModel):
|
class CollectionListResponse(BaseModel):
|
||||||
|
|
@ -209,8 +196,7 @@ class OperationResponse(OperationBase):
|
||||||
f99_91_user_id: str
|
f99_91_user_id: str
|
||||||
f99_93_created_at: Optional[datetime] = None
|
f99_93_created_at: Optional[datetime] = None
|
||||||
|
|
||||||
class Config:
|
model_config = ConfigDict(from_attributes=True)
|
||||||
from_attributes = True
|
|
||||||
|
|
||||||
|
|
||||||
# ============ OCR 相关 ============
|
# ============ OCR 相关 ============
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
1.2.98
|
VERSION=v0.0.3
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const htmlPath = './index.html';
|
||||||
|
let html = fs.readFileSync(htmlPath, 'utf-8');
|
||||||
|
html = html.replace('v=0.0.3', 'v=0.0.4');
|
||||||
|
fs.writeFileSync(htmlPath, html);
|
||||||
|
console.log('Done');
|
||||||
|
|
@ -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>甲辰收藏 v=1.2.97</title>
|
<title>甲辰收藏 v=0.0.3</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" />
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
// 修改版本号只需修改 ../../VERSION 文件中的 VERSION=xxx
|
// 修改版本号只需修改 ../../VERSION 文件中的 VERSION=xxx
|
||||||
|
|
||||||
// 从环境变量读取(vite.config.js 注入)
|
// 从环境变量读取(vite.config.js 注入)
|
||||||
export const APP_VERSION = import.meta.env.APP_VERSION || '1.2.82'
|
export const APP_VERSION = import.meta.env.APP_VERSION || '0.0.3'
|
||||||
|
|
||||||
// 版本信息
|
// 版本信息
|
||||||
export const VERSION_INFO = {
|
export const VERSION_INFO = {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* Home - 首页
|
* Home - 首页
|
||||||
* Version: 0.0.3
|
* Version: 0.0.2
|
||||||
* 更新:修复寻配号stats接口调用(2026-04-20)
|
* 更新:快捷操作改为黑色背景(2026-04-20)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
|
|
@ -84,7 +84,7 @@ export default function Home() {
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
|
|
||||||
// 获取寻配号统计数据
|
// 获取寻配号统计数据
|
||||||
fetch('/api/information/seek/stats?_=1776700744').then(res => res.json()).then(data => {
|
fetch('/api/information/seek/stats').then(res => res.json()).then(data => {
|
||||||
setSeekStats(data || {})
|
setSeekStats(data || {})
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* News - 资讯列表页面
|
* News - 资讯列表页面
|
||||||
* Version: 0.0.2
|
* Version: 0.0.1
|
||||||
* 更新:修复寻配号API调用,使用/api/seek接口(2026-04-20)
|
* 更新:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
|
|
@ -330,7 +330,7 @@ export default function News() {
|
||||||
try {
|
try {
|
||||||
// 解析正文中的号码特征和联系方式
|
// 解析正文中的号码特征和联系方式
|
||||||
const content = (editingSeek.content || '') + '\n联系方式: ' + editingSeek.contact
|
const content = (editingSeek.content || '') + '\n联系方式: ' + editingSeek.contact
|
||||||
await fetch(`${API_BASE}/api/seek/${editingSeek.id}`, {
|
await fetch(`${API_BASE}/api/information/${editingSeek.id}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
|
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
|
@ -352,14 +352,16 @@ export default function News() {
|
||||||
const content = (seekForm.content ? seekForm.content + '\n' : '') + (seekForm.price ? `价格: ${seekForm.price}` : '') + (seekForm.features ? '\n号码特征: J0' + seekForm.features : '') + '\n联系方式: ' + finalContact
|
const content = (seekForm.content ? seekForm.content + '\n' : '') + (seekForm.price ? `价格: ${seekForm.price}` : '') + (seekForm.features ? '\n号码特征: J0' + seekForm.features : '') + '\n联系方式: ' + finalContact
|
||||||
try {
|
try {
|
||||||
const token = localStorage.getItem('token')
|
const token = localStorage.getItem('token')
|
||||||
// 调用 /api/seek 接口
|
// 从edition映射到category
|
||||||
const res = await fetch(`${API_BASE}/api/seek`, {
|
const categoryMap = { '龙钞': '龙钞', '马钞': '马钞', '蛇钞': '蛇钞' }
|
||||||
|
const res = await fetch(`${API_BASE}/api/information/`, {
|
||||||
method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
|
method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
title: seekForm.title,
|
title: seekForm.title,
|
||||||
content,
|
content,
|
||||||
|
info_type: 'seek',
|
||||||
expect_category: seekForm.edition,
|
expect_category: seekForm.edition,
|
||||||
expect_number: seekForm.features ? 'J0' + seekForm.features : null
|
expect_number: seekForm.features ? 'J0' + seekForm.features : None
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const data = await res.json()
|
const data = await res.json()
|
||||||
|
|
@ -368,7 +370,7 @@ export default function News() {
|
||||||
setShowSeekPublish(false)
|
setShowSeekPublish(false)
|
||||||
setSeekForm({ edition: '龙钞', type: '', category: '寻号', price: '', matchType: '模糊', features: '', content: '', title: '', contact: getUserPhone() || '' })
|
setSeekForm({ edition: '龙钞', type: '', category: '寻号', price: '', matchType: '模糊', features: '', content: '', title: '', contact: getUserPhone() || '' })
|
||||||
fetchInfoList()
|
fetchInfoList()
|
||||||
} else { alert(data.detail || data.message || '发布失败') }
|
} else { alert(data.message || '发布失败') }
|
||||||
} catch (e) { alert('发布失败: ' + e.message) }
|
} catch (e) { alert('发布失败: ' + e.message) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue